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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [opcodes/] [ip2k-dis.c] - Blame information for rev 1765

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 "ip2k-desc.h"
35
#include "ip2k-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
 
62
static void
63
print_fr (cd, dis_info, value, attrs, pc, length)
64
     CGEN_CPU_DESC cd;
65
     PTR dis_info;
66
     long value;
67
     unsigned int attrs;
68
     bfd_vma pc;
69
     int length;
70
{
71
  disassemble_info *info = (disassemble_info *) dis_info;
72
  const CGEN_KEYWORD_ENTRY *ke;
73
  extern CGEN_KEYWORD ip2k_cgen_opval_register_names;
74
  long offsettest;
75
  long offsetvalue;
76
 
77
  if ( value == 0 ) /* This is (IP) */
78
  {
79
      (*info->fprintf_func) (info->stream, "%s", "(IP)");
80
      return;
81
  }
82
 
83
  offsettest = value >> 7;
84
  offsetvalue = value & 0x7F;
85
 
86
  /* Check to see if first two bits are 10 -> (DP) */
87
  if ( offsettest == 2 )
88
  {
89
      if ( offsetvalue == 0 )
90
         (*info->fprintf_func) (info->stream, "%s","(DP)");
91
      else
92
         (*info->fprintf_func) (info->stream, "$%x%s",offsetvalue, "(DP)");
93
      return;
94
  }
95
 
96
  /* Check to see if first two bits are 11 -> (SP) */
97
  if ( offsettest == 3 )
98
  {
99
      if ( offsetvalue == 0 )
100
         (*info->fprintf_func) (info->stream, "%s", "(SP)");
101
      else
102
         (*info->fprintf_func) (info->stream, "$%x%s", offsetvalue,"(SP)");
103
      return;
104
  }
105
 
106
  /* Attempt to print as a register keyword. */
107
  ke = cgen_keyword_lookup_value (& ip2k_cgen_opval_register_names, value);
108
  if (ke != NULL)
109
    {
110
      (*info->fprintf_func) (info->stream, "%s", ke->name);
111
      return;
112
    }
113
 
114
  /* Print as an address literal. */
115
  (*info->fprintf_func) (info->stream, "$%02x", value);
116
}
117
 
118
static void
119
print_dollarhex (cd, dis_info, value, attrs, pc, length)
120
     CGEN_CPU_DESC cd;
121
     PTR dis_info;
122
     long value;
123
     unsigned int attrs;
124
     bfd_vma pc;
125
     int length;
126
{
127
  disassemble_info *info = (disassemble_info *) dis_info;
128
 
129
  (*info->fprintf_func) (info->stream, "$%x", value);
130
}
131
 
132
static void
133
print_dollarhex8 (cd, dis_info, value, attrs, pc, length)
134
     CGEN_CPU_DESC cd;
135
     PTR dis_info;
136
     long value;
137
     unsigned int attrs;
138
     bfd_vma pc;
139
     int length;
140
{
141
  disassemble_info *info = (disassemble_info *) dis_info;
142
 
143
  (*info->fprintf_func) (info->stream, "$%02x", value);
144
}
145
 
146
static void
147
print_dollarhex16 (cd, dis_info, value, attrs, pc, length)
148
     CGEN_CPU_DESC cd;
149
     PTR dis_info;
150
     long value;
151
     unsigned int attrs;
152
     bfd_vma pc;
153
     int length;
154
{
155
  disassemble_info *info = (disassemble_info *) dis_info;
156
 
157
  (*info->fprintf_func) (info->stream, "$%04x", value);
158
}
159
 
160
static void
161
print_dollarhex_addr16h (cd, dis_info, value, attrs, pc, length)
162
     CGEN_CPU_DESC cd;
163
     PTR dis_info;
164
     long value;
165
     unsigned int attrs;
166
     bfd_vma pc;
167
     int length;
168
{
169
  disassemble_info *info = (disassemble_info *) dis_info;
170
 
171
  /* This is a loadh instruction. Shift the value to the left      */
172
  /* by 8 bits so that disassembled code will reassemble properly. */
173
  value = ((value << 8) & 0xFF00);
174
 
175
  (*info->fprintf_func) (info->stream, "$%04x", value);
176
}
177
 
178
static void
179
print_dollarhex_addr16l (cd, dis_info, value, attrs, pc, length)
180
     CGEN_CPU_DESC cd;
181
     PTR dis_info;
182
     long value;
183
     unsigned int attrs;
184
     bfd_vma pc;
185
     int length;
186
{
187
  disassemble_info *info = (disassemble_info *) dis_info;
188
 
189
  (*info->fprintf_func) (info->stream, "$%04x", value);
190
}
191
 
192
static void
193
print_dollarhex_p (cd, dis_info, value, attrs, pc, length)
194
     CGEN_CPU_DESC cd;
195
     PTR dis_info;
196
     long value;
197
     unsigned int attrs;
198
     bfd_vma pc;
199
     int length;
200
{
201
  disassemble_info *info = (disassemble_info *) dis_info;
202
 
203
  value = ((value << 14) & 0x1C000);
204
  ;value = (value  & 0x1FFFF);
205
  (*info->fprintf_func) (info->stream, "$%05x", value);
206
}
207
 
208
static void
209
print_dollarhex_cj (cd, dis_info, value, attrs, pc, length)
210
     CGEN_CPU_DESC cd;
211
     PTR dis_info;
212
     long value;
213
     unsigned int attrs;
214
     bfd_vma pc;
215
     int length;
216
{
217
  disassemble_info *info = (disassemble_info *) dis_info;
218
 
219
  value = ((value << 1) & 0x1FFFF);
220
  (*info->fprintf_func) (info->stream, "$%05x", value);
221
}
222
 
223
 
224
static void
225
print_decimal (cd, dis_info, value, attrs, pc, length)
226
     CGEN_CPU_DESC cd;
227
     PTR dis_info;
228
     long value;
229
     unsigned int attrs;
230
     bfd_vma pc;
231
     int length;
232
{
233
  disassemble_info *info = (disassemble_info *) dis_info;
234
 
235
  (*info->fprintf_func) (info->stream, "%d", value);
236
}
237
 
238
 
239
 
240
/* -- */
241
 
242
void ip2k_cgen_print_operand
243
  PARAMS ((CGEN_CPU_DESC, int, PTR, CGEN_FIELDS *,
244
           void const *, bfd_vma, int));
245
 
246
/* Main entry point for printing operands.
247
   XINFO is a `void *' and not a `disassemble_info *' to not put a requirement
248
   of dis-asm.h on cgen.h.
249
 
250
   This function is basically just a big switch statement.  Earlier versions
251
   used tables to look up the function to use, but
252
   - if the table contains both assembler and disassembler functions then
253
     the disassembler contains much of the assembler and vice-versa,
254
   - there's a lot of inlining possibilities as things grow,
255
   - using a switch statement avoids the function call overhead.
256
 
257
   This function could be moved into `print_insn_normal', but keeping it
258
   separate makes clear the interface between `print_insn_normal' and each of
259
   the handlers.  */
260
 
261
void
262
ip2k_cgen_print_operand (cd, opindex, xinfo, fields, attrs, pc, length)
263
     CGEN_CPU_DESC cd;
264
     int opindex;
265
     PTR xinfo;
266
     CGEN_FIELDS *fields;
267
     void const *attrs ATTRIBUTE_UNUSED;
268
     bfd_vma pc;
269
     int length;
270
{
271
 disassemble_info *info = (disassemble_info *) xinfo;
272
 
273
  switch (opindex)
274
    {
275
    case IP2K_OPERAND_ADDR16CJP :
276
      print_dollarhex_cj (cd, info, fields->f_addr16cjp, 0|(1<<CGEN_OPERAND_ABS_ADDR), pc, length);
277
      break;
278
    case IP2K_OPERAND_ADDR16H :
279
      print_dollarhex_addr16h (cd, info, fields->f_imm8, 0, pc, length);
280
      break;
281
    case IP2K_OPERAND_ADDR16L :
282
      print_dollarhex_addr16l (cd, info, fields->f_imm8, 0, pc, length);
283
      break;
284
    case IP2K_OPERAND_ADDR16P :
285
      print_dollarhex_p (cd, info, fields->f_page3, 0, pc, length);
286
      break;
287
    case IP2K_OPERAND_BITNO :
288
      print_decimal (cd, info, fields->f_bitno, 0, pc, length);
289
      break;
290
    case IP2K_OPERAND_CBIT :
291
      print_normal (cd, info, 0, 0, pc, length);
292
      break;
293
    case IP2K_OPERAND_DCBIT :
294
      print_normal (cd, info, 0, 0, pc, length);
295
      break;
296
    case IP2K_OPERAND_FR :
297
      print_fr (cd, info, fields->f_reg, 0|(1<<CGEN_OPERAND_ABS_ADDR), pc, length);
298
      break;
299
    case IP2K_OPERAND_LIT8 :
300
      print_dollarhex8 (cd, info, fields->f_imm8, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
301
      break;
302
    case IP2K_OPERAND_PABITS :
303
      print_normal (cd, info, 0, 0, pc, length);
304
      break;
305
    case IP2K_OPERAND_RETI3 :
306
      print_dollarhex (cd, info, fields->f_reti3, 0, pc, length);
307
      break;
308
    case IP2K_OPERAND_ZBIT :
309
      print_normal (cd, info, 0, 0, pc, length);
310
      break;
311
 
312
    default :
313
      /* xgettext:c-format */
314
      fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
315
               opindex);
316
    abort ();
317
  }
318
}
319
 
320
cgen_print_fn * const ip2k_cgen_print_handlers[] =
321
{
322
  print_insn_normal,
323
};
324
 
325
 
326
void
327
ip2k_cgen_init_dis (cd)
328
     CGEN_CPU_DESC cd;
329
{
330
  ip2k_cgen_init_opcode_table (cd);
331
  ip2k_cgen_init_ibld_table (cd);
332
  cd->print_handlers = & ip2k_cgen_print_handlers[0];
333
  cd->print_operand = ip2k_cgen_print_operand;
334
}
335
 
336
 
337
/* Default print handler.  */
338
 
339
static void
340
print_normal (cd, dis_info, value, attrs, pc, length)
341
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
342
     PTR dis_info;
343
     long value;
344
     unsigned int attrs;
345
     bfd_vma pc ATTRIBUTE_UNUSED;
346
     int length ATTRIBUTE_UNUSED;
347
{
348
  disassemble_info *info = (disassemble_info *) dis_info;
349
 
350
#ifdef CGEN_PRINT_NORMAL
351
  CGEN_PRINT_NORMAL (cd, info, value, attrs, pc, length);
352
#endif
353
 
354
  /* Print the operand as directed by the attributes.  */
355
  if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
356
    ; /* nothing to do */
357
  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
358
    (*info->fprintf_func) (info->stream, "%ld", value);
359
  else
360
    (*info->fprintf_func) (info->stream, "0x%lx", value);
361
}
362
 
363
/* Default address handler.  */
364
 
365
static void
366
print_address (cd, dis_info, value, attrs, pc, length)
367
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
368
     PTR dis_info;
369
     bfd_vma value;
370
     unsigned int attrs;
371
     bfd_vma pc ATTRIBUTE_UNUSED;
372
     int length ATTRIBUTE_UNUSED;
373
{
374
  disassemble_info *info = (disassemble_info *) dis_info;
375
 
376
#ifdef CGEN_PRINT_ADDRESS
377
  CGEN_PRINT_ADDRESS (cd, info, value, attrs, pc, length);
378
#endif
379
 
380
  /* Print the operand as directed by the attributes.  */
381
  if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
382
    ; /* nothing to do */
383
  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
384
    (*info->print_address_func) (value, info);
385
  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
386
    (*info->print_address_func) (value, info);
387
  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
388
    (*info->fprintf_func) (info->stream, "%ld", (long) value);
389
  else
390
    (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
391
}
392
 
393
/* Keyword print handler.  */
394
 
395
static void
396
print_keyword (cd, dis_info, keyword_table, value, attrs)
397
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
398
     PTR dis_info;
399
     CGEN_KEYWORD *keyword_table;
400
     long value;
401
     unsigned int attrs ATTRIBUTE_UNUSED;
402
{
403
  disassemble_info *info = (disassemble_info *) dis_info;
404
  const CGEN_KEYWORD_ENTRY *ke;
405
 
406
  ke = cgen_keyword_lookup_value (keyword_table, value);
407
  if (ke != NULL)
408
    (*info->fprintf_func) (info->stream, "%s", ke->name);
409
  else
410
    (*info->fprintf_func) (info->stream, "???");
411
}
412
 
413
/* Default insn printer.
414
 
415
   DIS_INFO is defined as `PTR' so the disassembler needn't know anything
416
   about disassemble_info.  */
417
 
418
static void
419
print_insn_normal (cd, dis_info, insn, fields, pc, length)
420
     CGEN_CPU_DESC cd;
421
     PTR dis_info;
422
     const CGEN_INSN *insn;
423
     CGEN_FIELDS *fields;
424
     bfd_vma pc;
425
     int length;
426
{
427
  const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
428
  disassemble_info *info = (disassemble_info *) dis_info;
429
  const CGEN_SYNTAX_CHAR_TYPE *syn;
430
 
431
  CGEN_INIT_PRINT (cd);
432
 
433
  for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
434
    {
435
      if (CGEN_SYNTAX_MNEMONIC_P (*syn))
436
        {
437
          (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
438
          continue;
439
        }
440
      if (CGEN_SYNTAX_CHAR_P (*syn))
441
        {
442
          (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
443
          continue;
444
        }
445
 
446
      /* We have an operand.  */
447
      ip2k_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
448
                                 fields, CGEN_INSN_ATTRS (insn), pc, length);
449
    }
450
}
451
 
452
/* Subroutine of print_insn. Reads an insn into the given buffers and updates
453
   the extract info.
454
   Returns 0 if all is well, non-zero otherwise.  */
455
 
456
static int
457
read_insn (cd, pc, info, buf, buflen, ex_info, insn_value)
458
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
459
     bfd_vma pc;
460
     disassemble_info *info;
461
     char *buf;
462
     int buflen;
463
     CGEN_EXTRACT_INFO *ex_info;
464
     unsigned long *insn_value;
465
{
466
  int status = (*info->read_memory_func) (pc, buf, buflen, info);
467
  if (status != 0)
468
    {
469
      (*info->memory_error_func) (status, pc, info);
470
      return -1;
471
    }
472
 
473
  ex_info->dis_info = info;
474
  ex_info->valid = (1 << buflen) - 1;
475
  ex_info->insn_bytes = buf;
476
 
477
  *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
478
  return 0;
479
}
480
 
481
/* Utility to print an insn.
482
   BUF is the base part of the insn, target byte order, BUFLEN bytes long.
483
   The result is the size of the insn in bytes or zero for an unknown insn
484
   or -1 if an error occurs fetching data (memory_error_func will have
485
   been called).  */
486
 
487
static int
488
print_insn (cd, pc, info, buf, buflen)
489
     CGEN_CPU_DESC cd;
490
     bfd_vma pc;
491
     disassemble_info *info;
492
     char *buf;
493
     unsigned int buflen;
494
{
495
  CGEN_INSN_INT insn_value;
496
  const CGEN_INSN_LIST *insn_list;
497
  CGEN_EXTRACT_INFO ex_info;
498
  int basesize;
499
 
500
  /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
501
  basesize = cd->base_insn_bitsize < buflen * 8 ?
502
                                     cd->base_insn_bitsize : buflen * 8;
503
  insn_value = cgen_get_insn_value (cd, buf, basesize);
504
 
505
 
506
  /* Fill in ex_info fields like read_insn would.  Don't actually call
507
     read_insn, since the incoming buffer is already read (and possibly
508
     modified a la m32r).  */
509
  ex_info.valid = (1 << buflen) - 1;
510
  ex_info.dis_info = info;
511
  ex_info.insn_bytes = buf;
512
 
513
  /* The instructions are stored in hash lists.
514
     Pick the first one and keep trying until we find the right one.  */
515
 
516
  insn_list = CGEN_DIS_LOOKUP_INSN (cd, buf, insn_value);
517
  while (insn_list != NULL)
518
    {
519
      const CGEN_INSN *insn = insn_list->insn;
520
      CGEN_FIELDS fields;
521
      int length;
522
      unsigned long insn_value_cropped;
523
 
524
#ifdef CGEN_VALIDATE_INSN_SUPPORTED 
525
      /* Not needed as insn shouldn't be in hash lists if not supported.  */
526
      /* Supported by this cpu?  */
527
      if (! ip2k_cgen_insn_supported (cd, insn))
528
        {
529
          insn_list = CGEN_DIS_NEXT_INSN (insn_list);
530
          continue;
531
        }
532
#endif
533
 
534
      /* Basic bit mask must be correct.  */
535
      /* ??? May wish to allow target to defer this check until the extract
536
         handler.  */
537
 
538
      /* Base size may exceed this instruction's size.  Extract the
539
         relevant part from the buffer. */
540
      if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
541
          (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
542
        insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn),
543
                                           info->endian == BFD_ENDIAN_BIG);
544
      else
545
        insn_value_cropped = insn_value;
546
 
547
      if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
548
          == CGEN_INSN_BASE_VALUE (insn))
549
        {
550
          /* Printing is handled in two passes.  The first pass parses the
551
             machine insn and extracts the fields.  The second pass prints
552
             them.  */
553
 
554
          /* Make sure the entire insn is loaded into insn_value, if it
555
             can fit.  */
556
          if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
557
              (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
558
            {
559
              unsigned long full_insn_value;
560
              int rc = read_insn (cd, pc, info, buf,
561
                                  CGEN_INSN_BITSIZE (insn) / 8,
562
                                  & ex_info, & full_insn_value);
563
              if (rc != 0)
564
                return rc;
565
              length = CGEN_EXTRACT_FN (cd, insn)
566
                (cd, insn, &ex_info, full_insn_value, &fields, pc);
567
            }
568
          else
569
            length = CGEN_EXTRACT_FN (cd, insn)
570
              (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
571
 
572
          /* length < 0 -> error */
573
          if (length < 0)
574
            return length;
575
          if (length > 0)
576
            {
577
              CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
578
              /* length is in bits, result is in bytes */
579
              return length / 8;
580
            }
581
        }
582
 
583
      insn_list = CGEN_DIS_NEXT_INSN (insn_list);
584
    }
585
 
586
  return 0;
587
}
588
 
589
/* Default value for CGEN_PRINT_INSN.
590
   The result is the size of the insn in bytes or zero for an unknown insn
591
   or -1 if an error occured fetching bytes.  */
592
 
593
#ifndef CGEN_PRINT_INSN
594
#define CGEN_PRINT_INSN default_print_insn
595
#endif
596
 
597
static int
598
default_print_insn (cd, pc, info)
599
     CGEN_CPU_DESC cd;
600
     bfd_vma pc;
601
     disassemble_info *info;
602
{
603
  char buf[CGEN_MAX_INSN_SIZE];
604
  int buflen;
605
  int status;
606
 
607
  /* Attempt to read the base part of the insn.  */
608
  buflen = cd->base_insn_bitsize / 8;
609
  status = (*info->read_memory_func) (pc, buf, buflen, info);
610
 
611
  /* Try again with the minimum part, if min < base.  */
612
  if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
613
    {
614
      buflen = cd->min_insn_bitsize / 8;
615
      status = (*info->read_memory_func) (pc, buf, buflen, info);
616
    }
617
 
618
  if (status != 0)
619
    {
620
      (*info->memory_error_func) (status, pc, info);
621
      return -1;
622
    }
623
 
624
  return print_insn (cd, pc, info, buf, buflen);
625
}
626
 
627
/* Main entry point.
628
   Print one instruction from PC on INFO->STREAM.
629
   Return the size of the instruction (in bytes).  */
630
 
631
typedef struct cpu_desc_list {
632
  struct cpu_desc_list *next;
633
  int isa;
634
  int mach;
635
  int endian;
636
  CGEN_CPU_DESC cd;
637
} cpu_desc_list;
638
 
639
int
640
print_insn_ip2k (pc, info)
641
     bfd_vma pc;
642
     disassemble_info *info;
643
{
644
  static cpu_desc_list *cd_list = 0;
645
  cpu_desc_list *cl = 0;
646
  static CGEN_CPU_DESC cd = 0;
647
  static int prev_isa;
648
  static int prev_mach;
649
  static int prev_endian;
650
  int length;
651
  int isa,mach;
652
  int endian = (info->endian == BFD_ENDIAN_BIG
653
                ? CGEN_ENDIAN_BIG
654
                : CGEN_ENDIAN_LITTLE);
655
  enum bfd_architecture arch;
656
 
657
  /* ??? gdb will set mach but leave the architecture as "unknown" */
658
#ifndef CGEN_BFD_ARCH
659
#define CGEN_BFD_ARCH bfd_arch_ip2k
660
#endif
661
  arch = info->arch;
662
  if (arch == bfd_arch_unknown)
663
    arch = CGEN_BFD_ARCH;
664
 
665
  /* There's no standard way to compute the machine or isa number
666
     so we leave it to the target.  */
667
#ifdef CGEN_COMPUTE_MACH
668
  mach = CGEN_COMPUTE_MACH (info);
669
#else
670
  mach = info->mach;
671
#endif
672
 
673
#ifdef CGEN_COMPUTE_ISA
674
  isa = CGEN_COMPUTE_ISA (info);
675
#else
676
  isa = info->insn_sets;
677
#endif
678
 
679
  /* If we've switched cpu's, try to find a handle we've used before */
680
  if (cd
681
      && (isa != prev_isa
682
          || mach != prev_mach
683
          || endian != prev_endian))
684
    {
685
      cd = 0;
686
      for (cl = cd_list; cl; cl = cl->next)
687
        {
688
          if (cl->isa == isa &&
689
              cl->mach == mach &&
690
              cl->endian == endian)
691
            {
692
              cd = cl->cd;
693
              break;
694
            }
695
        }
696
    }
697
 
698
  /* If we haven't initialized yet, initialize the opcode table.  */
699
  if (! cd)
700
    {
701
      const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
702
      const char *mach_name;
703
 
704
      if (!arch_type)
705
        abort ();
706
      mach_name = arch_type->printable_name;
707
 
708
      prev_isa = isa;
709
      prev_mach = mach;
710
      prev_endian = endian;
711
      cd = ip2k_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
712
                                 CGEN_CPU_OPEN_BFDMACH, mach_name,
713
                                 CGEN_CPU_OPEN_ENDIAN, prev_endian,
714
                                 CGEN_CPU_OPEN_END);
715
      if (!cd)
716
        abort ();
717
 
718
      /* save this away for future reference */
719
      cl = xmalloc (sizeof (struct cpu_desc_list));
720
      cl->cd = cd;
721
      cl->isa = isa;
722
      cl->mach = mach;
723
      cl->endian = endian;
724
      cl->next = cd_list;
725
      cd_list = cl;
726
 
727
      ip2k_cgen_init_dis (cd);
728
    }
729
 
730
  /* We try to have as much common code as possible.
731
     But at this point some targets need to take over.  */
732
  /* ??? Some targets may need a hook elsewhere.  Try to avoid this,
733
     but if not possible try to move this hook elsewhere rather than
734
     have two hooks.  */
735
  length = CGEN_PRINT_INSN (cd, pc, info);
736
  if (length > 0)
737
    return length;
738
  if (length < 0)
739
    return -1;
740
 
741
  (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
742
  return cd->default_insn_bitsize / 8;
743
}

powered by: WebSVN 2.1.0

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