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

Subversion Repositories or1k

[/] [or1k/] [tags/] [VER_5_3/] [gdb-5.3/] [opcodes/] [fr30-dis.c] - Blame information for rev 1778

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

Line No. Rev Author Line
1 1181 sfurman
/* 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
51
     PARAMS ((CGEN_CPU_DESC, bfd_vma,  disassemble_info *, char *, unsigned));
52
static int default_print_insn
53
     PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *));
54
static int read_insn
55
     PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *, char *, int,
56
              CGEN_EXTRACT_INFO *, unsigned long *));
57
 
58
/* -- disassembler routines inserted here */
59
 
60
/* -- dis.c */
61
static void print_register_list
62
  PARAMS ((PTR, long, long, int));
63
static void print_hi_register_list_ld
64
  PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
65
static void print_low_register_list_ld
66
  PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
67
static void print_hi_register_list_st
68
  PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
69
static void print_low_register_list_st
70
  PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
71
static void print_m4
72
  PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
73
 
74
static void
75
print_register_list (dis_info, value, offset, load_store)
76
     PTR dis_info;
77
     long value;
78
     long offset;
79
     int load_store; /* 0 == load, 1 == store */
80
{
81
  disassemble_info *info = dis_info;
82
  int mask;
83
  int index = 0;
84
  char* comma = "";
85
 
86
  if (load_store)
87
    mask = 0x80;
88
  else
89
    mask = 1;
90
 
91
  if (value & mask)
92
    {
93
      (*info->fprintf_func) (info->stream, "r%i", index + offset);
94
      comma = ",";
95
    }
96
 
97
  for (index = 1; index <= 7; ++index)
98
    {
99
      if (load_store)
100
        mask >>= 1;
101
      else
102
        mask <<= 1;
103
 
104
      if (value & mask)
105
        {
106
          (*info->fprintf_func) (info->stream, "%sr%i", comma, index + offset);
107
          comma = ",";
108
        }
109
    }
110
}
111
 
112
static void
113
print_hi_register_list_ld (cd, dis_info, value, attrs, pc, length)
114
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
115
     PTR dis_info;
116
     long value;
117
     unsigned int attrs ATTRIBUTE_UNUSED;
118
     bfd_vma pc ATTRIBUTE_UNUSED;
119
     int length ATTRIBUTE_UNUSED;
120
{
121
  print_register_list (dis_info, value, 8, 0/*load*/);
122
}
123
 
124
static void
125
print_low_register_list_ld (cd, dis_info, value, attrs, pc, length)
126
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
127
     PTR dis_info;
128
     long value;
129
     unsigned int attrs ATTRIBUTE_UNUSED;
130
     bfd_vma pc ATTRIBUTE_UNUSED;
131
     int length ATTRIBUTE_UNUSED;
132
{
133
  print_register_list (dis_info, value, 0, 0/*load*/);
134
}
135
 
136
static void
137
print_hi_register_list_st (cd, dis_info, value, attrs, pc, length)
138
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
139
     PTR dis_info;
140
     long value;
141
     unsigned int attrs ATTRIBUTE_UNUSED;
142
     bfd_vma pc ATTRIBUTE_UNUSED;
143
     int length ATTRIBUTE_UNUSED;
144
{
145
  print_register_list (dis_info, value, 8, 1/*store*/);
146
}
147
 
148
static void
149
print_low_register_list_st (cd, dis_info, value, attrs, pc, length)
150
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
151
     PTR dis_info;
152
     long value;
153
     unsigned int attrs ATTRIBUTE_UNUSED;
154
     bfd_vma pc ATTRIBUTE_UNUSED;
155
     int length ATTRIBUTE_UNUSED;
156
{
157
  print_register_list (dis_info, value, 0, 1/*store*/);
158
}
159
 
160
static void
161
print_m4 (cd, dis_info, value, attrs, pc, length)
162
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
163
     PTR dis_info;
164
     long value;
165
     unsigned int attrs ATTRIBUTE_UNUSED;
166
     bfd_vma pc ATTRIBUTE_UNUSED;
167
     int length ATTRIBUTE_UNUSED;
168
{
169
  disassemble_info *info = (disassemble_info *) dis_info;
170
  (*info->fprintf_func) (info->stream, "%ld", value);
171
}
172
/* -- */
173
 
174
void fr30_cgen_print_operand
175
  PARAMS ((CGEN_CPU_DESC, int, PTR, CGEN_FIELDS *,
176
           void const *, bfd_vma, int));
177
 
178
/* Main entry point for printing operands.
179
   XINFO is a `void *' and not a `disassemble_info *' to not put a requirement
180
   of dis-asm.h on cgen.h.
181
 
182
   This function is basically just a big switch statement.  Earlier versions
183
   used tables to look up the function to use, but
184
   - if the table contains both assembler and disassembler functions then
185
     the disassembler contains much of the assembler and vice-versa,
186
   - there's a lot of inlining possibilities as things grow,
187
   - using a switch statement avoids the function call overhead.
188
 
189
   This function could be moved into `print_insn_normal', but keeping it
190
   separate makes clear the interface between `print_insn_normal' and each of
191
   the handlers.  */
192
 
193
void
194
fr30_cgen_print_operand (cd, opindex, xinfo, fields, attrs, pc, length)
195
     CGEN_CPU_DESC cd;
196
     int opindex;
197
     PTR xinfo;
198
     CGEN_FIELDS *fields;
199
     void const *attrs ATTRIBUTE_UNUSED;
200
     bfd_vma pc;
201
     int length;
202
{
203
 disassemble_info *info = (disassemble_info *) xinfo;
204
 
205
  switch (opindex)
206
    {
207
    case FR30_OPERAND_CRI :
208
      print_keyword (cd, info, & fr30_cgen_opval_cr_names, fields->f_CRi, 0);
209
      break;
210
    case FR30_OPERAND_CRJ :
211
      print_keyword (cd, info, & fr30_cgen_opval_cr_names, fields->f_CRj, 0);
212
      break;
213
    case FR30_OPERAND_R13 :
214
      print_keyword (cd, info, & fr30_cgen_opval_h_r13, 0, 0);
215
      break;
216
    case FR30_OPERAND_R14 :
217
      print_keyword (cd, info, & fr30_cgen_opval_h_r14, 0, 0);
218
      break;
219
    case FR30_OPERAND_R15 :
220
      print_keyword (cd, info, & fr30_cgen_opval_h_r15, 0, 0);
221
      break;
222
    case FR30_OPERAND_RI :
223
      print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Ri, 0);
224
      break;
225
    case FR30_OPERAND_RIC :
226
      print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Ric, 0);
227
      break;
228
    case FR30_OPERAND_RJ :
229
      print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Rj, 0);
230
      break;
231
    case FR30_OPERAND_RJC :
232
      print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Rjc, 0);
233
      break;
234
    case FR30_OPERAND_RS1 :
235
      print_keyword (cd, info, & fr30_cgen_opval_dr_names, fields->f_Rs1, 0);
236
      break;
237
    case FR30_OPERAND_RS2 :
238
      print_keyword (cd, info, & fr30_cgen_opval_dr_names, fields->f_Rs2, 0);
239
      break;
240
    case FR30_OPERAND_CC :
241
      print_normal (cd, info, fields->f_cc, 0, pc, length);
242
      break;
243
    case FR30_OPERAND_CCC :
244
      print_normal (cd, info, fields->f_ccc, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
245
      break;
246
    case FR30_OPERAND_DIR10 :
247
      print_normal (cd, info, fields->f_dir10, 0, pc, length);
248
      break;
249
    case FR30_OPERAND_DIR8 :
250
      print_normal (cd, info, fields->f_dir8, 0, pc, length);
251
      break;
252
    case FR30_OPERAND_DIR9 :
253
      print_normal (cd, info, fields->f_dir9, 0, pc, length);
254
      break;
255
    case FR30_OPERAND_DISP10 :
256
      print_normal (cd, info, fields->f_disp10, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
257
      break;
258
    case FR30_OPERAND_DISP8 :
259
      print_normal (cd, info, fields->f_disp8, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
260
      break;
261
    case FR30_OPERAND_DISP9 :
262
      print_normal (cd, info, fields->f_disp9, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
263
      break;
264
    case FR30_OPERAND_I20 :
265
      print_normal (cd, info, fields->f_i20, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
266
      break;
267
    case FR30_OPERAND_I32 :
268
      print_normal (cd, info, fields->f_i32, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGN_OPT), pc, length);
269
      break;
270
    case FR30_OPERAND_I8 :
271
      print_normal (cd, info, fields->f_i8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
272
      break;
273
    case FR30_OPERAND_LABEL12 :
274
      print_address (cd, info, fields->f_rel12, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
275
      break;
276
    case FR30_OPERAND_LABEL9 :
277
      print_address (cd, info, fields->f_rel9, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
278
      break;
279
    case FR30_OPERAND_M4 :
280
      print_m4 (cd, info, fields->f_m4, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
281
      break;
282
    case FR30_OPERAND_PS :
283
      print_keyword (cd, info, & fr30_cgen_opval_h_ps, 0, 0);
284
      break;
285
    case FR30_OPERAND_REGLIST_HI_LD :
286
      print_hi_register_list_ld (cd, info, fields->f_reglist_hi_ld, 0, pc, length);
287
      break;
288
    case FR30_OPERAND_REGLIST_HI_ST :
289
      print_hi_register_list_st (cd, info, fields->f_reglist_hi_st, 0, pc, length);
290
      break;
291
    case FR30_OPERAND_REGLIST_LOW_LD :
292
      print_low_register_list_ld (cd, info, fields->f_reglist_low_ld, 0, pc, length);
293
      break;
294
    case FR30_OPERAND_REGLIST_LOW_ST :
295
      print_low_register_list_st (cd, info, fields->f_reglist_low_st, 0, pc, length);
296
      break;
297
    case FR30_OPERAND_S10 :
298
      print_normal (cd, info, fields->f_s10, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
299
      break;
300
    case FR30_OPERAND_U10 :
301
      print_normal (cd, info, fields->f_u10, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
302
      break;
303
    case FR30_OPERAND_U4 :
304
      print_normal (cd, info, fields->f_u4, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
305
      break;
306
    case FR30_OPERAND_U4C :
307
      print_normal (cd, info, fields->f_u4c, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
308
      break;
309
    case FR30_OPERAND_U8 :
310
      print_normal (cd, info, fields->f_u8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
311
      break;
312
    case FR30_OPERAND_UDISP6 :
313
      print_normal (cd, info, fields->f_udisp6, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
314
      break;
315
 
316
    default :
317
      /* xgettext:c-format */
318
      fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
319
               opindex);
320
    abort ();
321
  }
322
}
323
 
324
cgen_print_fn * const fr30_cgen_print_handlers[] =
325
{
326
  print_insn_normal,
327
};
328
 
329
 
330
void
331
fr30_cgen_init_dis (cd)
332
     CGEN_CPU_DESC cd;
333
{
334
  fr30_cgen_init_opcode_table (cd);
335
  fr30_cgen_init_ibld_table (cd);
336
  cd->print_handlers = & fr30_cgen_print_handlers[0];
337
  cd->print_operand = fr30_cgen_print_operand;
338
}
339
 
340
 
341
/* Default print handler.  */
342
 
343
static void
344
print_normal (cd, dis_info, value, attrs, pc, length)
345
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
346
     PTR dis_info;
347
     long value;
348
     unsigned int attrs;
349
     bfd_vma pc ATTRIBUTE_UNUSED;
350
     int length ATTRIBUTE_UNUSED;
351
{
352
  disassemble_info *info = (disassemble_info *) dis_info;
353
 
354
#ifdef CGEN_PRINT_NORMAL
355
  CGEN_PRINT_NORMAL (cd, info, value, attrs, pc, length);
356
#endif
357
 
358
  /* Print the operand as directed by the attributes.  */
359
  if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
360
    ; /* nothing to do */
361
  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
362
    (*info->fprintf_func) (info->stream, "%ld", value);
363
  else
364
    (*info->fprintf_func) (info->stream, "0x%lx", value);
365
}
366
 
367
/* Default address handler.  */
368
 
369
static void
370
print_address (cd, dis_info, value, attrs, pc, length)
371
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
372
     PTR dis_info;
373
     bfd_vma value;
374
     unsigned int attrs;
375
     bfd_vma pc ATTRIBUTE_UNUSED;
376
     int length ATTRIBUTE_UNUSED;
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
 
460
static int
461
read_insn (cd, pc, info, buf, buflen, ex_info, insn_value)
462
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
463
     bfd_vma pc;
464
     disassemble_info *info;
465
     char *buf;
466
     int buflen;
467
     CGEN_EXTRACT_INFO *ex_info;
468
     unsigned long *insn_value;
469
{
470
  int status = (*info->read_memory_func) (pc, buf, buflen, info);
471
  if (status != 0)
472
    {
473
      (*info->memory_error_func) (status, pc, info);
474
      return -1;
475
    }
476
 
477
  ex_info->dis_info = info;
478
  ex_info->valid = (1 << buflen) - 1;
479
  ex_info->insn_bytes = buf;
480
 
481
  *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
482
  return 0;
483
}
484
 
485
/* Utility to print an insn.
486
   BUF is the base part of the insn, target byte order, BUFLEN bytes long.
487
   The result is the size of the insn in bytes or zero for an unknown insn
488
   or -1 if an error occurs fetching data (memory_error_func will have
489
   been called).  */
490
 
491
static int
492
print_insn (cd, pc, info, buf, buflen)
493
     CGEN_CPU_DESC cd;
494
     bfd_vma pc;
495
     disassemble_info *info;
496
     char *buf;
497
     unsigned int buflen;
498
{
499
  CGEN_INSN_INT insn_value;
500
  const CGEN_INSN_LIST *insn_list;
501
  CGEN_EXTRACT_INFO ex_info;
502
  int basesize;
503
 
504
  /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
505
  basesize = cd->base_insn_bitsize < buflen * 8 ?
506
                                     cd->base_insn_bitsize : buflen * 8;
507
  insn_value = cgen_get_insn_value (cd, buf, basesize);
508
 
509
 
510
  /* Fill in ex_info fields like read_insn would.  Don't actually call
511
     read_insn, since the incoming buffer is already read (and possibly
512
     modified a la m32r).  */
513
  ex_info.valid = (1 << buflen) - 1;
514
  ex_info.dis_info = info;
515
  ex_info.insn_bytes = buf;
516
 
517
  /* The instructions are stored in hash lists.
518
     Pick the first one and keep trying until we find the right one.  */
519
 
520
  insn_list = CGEN_DIS_LOOKUP_INSN (cd, buf, insn_value);
521
  while (insn_list != NULL)
522
    {
523
      const CGEN_INSN *insn = insn_list->insn;
524
      CGEN_FIELDS fields;
525
      int length;
526
      unsigned long insn_value_cropped;
527
 
528
#ifdef CGEN_VALIDATE_INSN_SUPPORTED 
529
      /* Not needed as insn shouldn't be in hash lists if not supported.  */
530
      /* Supported by this cpu?  */
531
      if (! fr30_cgen_insn_supported (cd, insn))
532
        {
533
          insn_list = CGEN_DIS_NEXT_INSN (insn_list);
534
          continue;
535
        }
536
#endif
537
 
538
      /* Basic bit mask must be correct.  */
539
      /* ??? May wish to allow target to defer this check until the extract
540
         handler.  */
541
 
542
      /* Base size may exceed this instruction's size.  Extract the
543
         relevant part from the buffer. */
544
      if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
545
          (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
546
        insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn),
547
                                           info->endian == BFD_ENDIAN_BIG);
548
      else
549
        insn_value_cropped = insn_value;
550
 
551
      if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
552
          == CGEN_INSN_BASE_VALUE (insn))
553
        {
554
          /* Printing is handled in two passes.  The first pass parses the
555
             machine insn and extracts the fields.  The second pass prints
556
             them.  */
557
 
558
          /* Make sure the entire insn is loaded into insn_value, if it
559
             can fit.  */
560
          if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
561
              (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
562
            {
563
              unsigned long full_insn_value;
564
              int rc = read_insn (cd, pc, info, buf,
565
                                  CGEN_INSN_BITSIZE (insn) / 8,
566
                                  & ex_info, & full_insn_value);
567
              if (rc != 0)
568
                return rc;
569
              length = CGEN_EXTRACT_FN (cd, insn)
570
                (cd, insn, &ex_info, full_insn_value, &fields, pc);
571
            }
572
          else
573
            length = CGEN_EXTRACT_FN (cd, insn)
574
              (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
575
 
576
          /* length < 0 -> error */
577
          if (length < 0)
578
            return length;
579
          if (length > 0)
580
            {
581
              CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
582
              /* length is in bits, result is in bytes */
583
              return length / 8;
584
            }
585
        }
586
 
587
      insn_list = CGEN_DIS_NEXT_INSN (insn_list);
588
    }
589
 
590
  return 0;
591
}
592
 
593
/* Default value for CGEN_PRINT_INSN.
594
   The result is the size of the insn in bytes or zero for an unknown insn
595
   or -1 if an error occured fetching bytes.  */
596
 
597
#ifndef CGEN_PRINT_INSN
598
#define CGEN_PRINT_INSN default_print_insn
599
#endif
600
 
601
static int
602
default_print_insn (cd, pc, info)
603
     CGEN_CPU_DESC cd;
604
     bfd_vma pc;
605
     disassemble_info *info;
606
{
607
  char buf[CGEN_MAX_INSN_SIZE];
608
  int buflen;
609
  int status;
610
 
611
  /* Attempt to read the base part of the insn.  */
612
  buflen = cd->base_insn_bitsize / 8;
613
  status = (*info->read_memory_func) (pc, buf, buflen, info);
614
 
615
  /* Try again with the minimum part, if min < base.  */
616
  if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
617
    {
618
      buflen = cd->min_insn_bitsize / 8;
619
      status = (*info->read_memory_func) (pc, buf, buflen, info);
620
    }
621
 
622
  if (status != 0)
623
    {
624
      (*info->memory_error_func) (status, pc, info);
625
      return -1;
626
    }
627
 
628
  return print_insn (cd, pc, info, buf, buflen);
629
}
630
 
631
/* Main entry point.
632
   Print one instruction from PC on INFO->STREAM.
633
   Return the size of the instruction (in bytes).  */
634
 
635
typedef struct cpu_desc_list {
636
  struct cpu_desc_list *next;
637
  int isa;
638
  int mach;
639
  int endian;
640
  CGEN_CPU_DESC cd;
641
} cpu_desc_list;
642
 
643
int
644
print_insn_fr30 (pc, info)
645
     bfd_vma pc;
646
     disassemble_info *info;
647
{
648
  static cpu_desc_list *cd_list = 0;
649
  cpu_desc_list *cl = 0;
650
  static CGEN_CPU_DESC cd = 0;
651
  static int prev_isa;
652
  static int prev_mach;
653
  static int prev_endian;
654
  int length;
655
  int isa,mach;
656
  int endian = (info->endian == BFD_ENDIAN_BIG
657
                ? CGEN_ENDIAN_BIG
658
                : CGEN_ENDIAN_LITTLE);
659
  enum bfd_architecture arch;
660
 
661
  /* ??? gdb will set mach but leave the architecture as "unknown" */
662
#ifndef CGEN_BFD_ARCH
663
#define CGEN_BFD_ARCH bfd_arch_fr30
664
#endif
665
  arch = info->arch;
666
  if (arch == bfd_arch_unknown)
667
    arch = CGEN_BFD_ARCH;
668
 
669
  /* There's no standard way to compute the machine or isa number
670
     so we leave it to the target.  */
671
#ifdef CGEN_COMPUTE_MACH
672
  mach = CGEN_COMPUTE_MACH (info);
673
#else
674
  mach = info->mach;
675
#endif
676
 
677
#ifdef CGEN_COMPUTE_ISA
678
  isa = CGEN_COMPUTE_ISA (info);
679
#else
680
  isa = info->insn_sets;
681
#endif
682
 
683
  /* If we've switched cpu's, try to find a handle we've used before */
684
  if (cd
685
      && (isa != prev_isa
686
          || mach != prev_mach
687
          || endian != prev_endian))
688
    {
689
      cd = 0;
690
      for (cl = cd_list; cl; cl = cl->next)
691
        {
692
          if (cl->isa == isa &&
693
              cl->mach == mach &&
694
              cl->endian == endian)
695
            {
696
              cd = cl->cd;
697
              break;
698
            }
699
        }
700
    }
701
 
702
  /* If we haven't initialized yet, initialize the opcode table.  */
703
  if (! cd)
704
    {
705
      const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
706
      const char *mach_name;
707
 
708
      if (!arch_type)
709
        abort ();
710
      mach_name = arch_type->printable_name;
711
 
712
      prev_isa = isa;
713
      prev_mach = mach;
714
      prev_endian = endian;
715
      cd = fr30_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
716
                                 CGEN_CPU_OPEN_BFDMACH, mach_name,
717
                                 CGEN_CPU_OPEN_ENDIAN, prev_endian,
718
                                 CGEN_CPU_OPEN_END);
719
      if (!cd)
720
        abort ();
721
 
722
      /* save this away for future reference */
723
      cl = xmalloc (sizeof (struct cpu_desc_list));
724
      cl->cd = cd;
725
      cl->isa = isa;
726
      cl->mach = mach;
727
      cl->endian = endian;
728
      cl->next = cd_list;
729
      cd_list = cl;
730
 
731
      fr30_cgen_init_dis (cd);
732
    }
733
 
734
  /* We try to have as much common code as possible.
735
     But at this point some targets need to take over.  */
736
  /* ??? Some targets may need a hook elsewhere.  Try to avoid this,
737
     but if not possible try to move this hook elsewhere rather than
738
     have two hooks.  */
739
  length = CGEN_PRINT_INSN (cd, pc, info);
740
  if (length > 0)
741
    return length;
742
  if (length < 0)
743
    return -1;
744
 
745
  (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
746
  return cd->default_insn_bitsize / 8;
747
}

powered by: WebSVN 2.1.0

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