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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [opcodes/] [cgen-dis.in] - 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 
30
#include "ansidecl.h"
31
#include "dis-asm.h"
32
#include "bfd.h"
33
#include "symcat.h"
34
#include "@prefix@-desc.h"
35
#include "@prefix@-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
/* Default print handler.  */
58
 
59
static void
60
print_normal (cd, dis_info, value, attrs, pc, length)
61
#ifdef CGEN_PRINT_NORMAL
62
     CGEN_CPU_DESC cd;
63
#else
64
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
65
#endif
66
     PTR dis_info;
67
     long value;
68
     unsigned int attrs;
69
#ifdef CGEN_PRINT_NORMAL
70
     bfd_vma pc;
71
     int length;
72
#else
73
     bfd_vma pc ATTRIBUTE_UNUSED;
74
     int length ATTRIBUTE_UNUSED;
75
#endif
76
{
77
  disassemble_info *info = (disassemble_info *) dis_info;
78
 
79
#ifdef CGEN_PRINT_NORMAL
80
  CGEN_PRINT_NORMAL (cd, info, value, attrs, pc, length);
81
#endif
82
 
83
  /* Print the operand as directed by the attributes.  */
84
  if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
85
    ; /* nothing to do */
86
  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
87
    (*info->fprintf_func) (info->stream, "%ld", value);
88
  else
89
    (*info->fprintf_func) (info->stream, "0x%lx", value);
90
}
91
 
92
/* Default address handler.  */
93
 
94
static void
95
print_address (cd, dis_info, value, attrs, pc, length)
96
#ifdef CGEN_PRINT_NORMAL
97
     CGEN_CPU_DESC cd;
98
#else
99
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
100
#endif
101
     PTR dis_info;
102
     bfd_vma value;
103
     unsigned int attrs;
104
#ifdef CGEN_PRINT_NORMAL
105
     bfd_vma pc;
106
     int length;
107
#else
108
     bfd_vma pc ATTRIBUTE_UNUSED;
109
     int length ATTRIBUTE_UNUSED;
110
#endif
111
{
112
  disassemble_info *info = (disassemble_info *) dis_info;
113
 
114
#ifdef CGEN_PRINT_ADDRESS
115
  CGEN_PRINT_ADDRESS (cd, info, value, attrs, pc, length);
116
#endif
117
 
118
  /* Print the operand as directed by the attributes.  */
119
  if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
120
    ; /* nothing to do */
121
  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
122
    (*info->print_address_func) (value, info);
123
  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
124
    (*info->print_address_func) (value, info);
125
  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
126
    (*info->fprintf_func) (info->stream, "%ld", (long) value);
127
  else
128
    (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
129
}
130
 
131
/* Keyword print handler.  */
132
 
133
static void
134
print_keyword (cd, dis_info, keyword_table, value, attrs)
135
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
136
     PTR dis_info;
137
     CGEN_KEYWORD *keyword_table;
138
     long value;
139
     unsigned int attrs ATTRIBUTE_UNUSED;
140
{
141
  disassemble_info *info = (disassemble_info *) dis_info;
142
  const CGEN_KEYWORD_ENTRY *ke;
143
 
144
  ke = cgen_keyword_lookup_value (keyword_table, value);
145
  if (ke != NULL)
146
    (*info->fprintf_func) (info->stream, "%s", ke->name);
147
  else
148
    (*info->fprintf_func) (info->stream, "???");
149
}
150
 
151
/* Default insn printer.
152
 
153
   DIS_INFO is defined as `PTR' so the disassembler needn't know anything
154
   about disassemble_info.  */
155
 
156
static void
157
print_insn_normal (cd, dis_info, insn, fields, pc, length)
158
     CGEN_CPU_DESC cd;
159
     PTR dis_info;
160
     const CGEN_INSN *insn;
161
     CGEN_FIELDS *fields;
162
     bfd_vma pc;
163
     int length;
164
{
165
  const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
166
  disassemble_info *info = (disassemble_info *) dis_info;
167
  const CGEN_SYNTAX_CHAR_TYPE *syn;
168
 
169
  CGEN_INIT_PRINT (cd);
170
 
171
  for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
172
    {
173
      if (CGEN_SYNTAX_MNEMONIC_P (*syn))
174
        {
175
          (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
176
          continue;
177
        }
178
      if (CGEN_SYNTAX_CHAR_P (*syn))
179
        {
180
          (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
181
          continue;
182
        }
183
 
184
      /* We have an operand.  */
185
      @arch@_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
186
                                 fields, CGEN_INSN_ATTRS (insn), pc, length);
187
    }
188
}
189
 
190
/* Subroutine of print_insn. Reads an insn into the given buffers and updates
191
   the extract info.
192
   Returns 0 if all is well, non-zero otherwise.  */
193
static int
194
read_insn (cd, pc, info, buf, buflen, ex_info, insn_value)
195
     CGEN_CPU_DESC cd;
196
     bfd_vma pc;
197
     disassemble_info *info;
198
     char *buf;
199
     int buflen;
200
     CGEN_EXTRACT_INFO *ex_info;
201
     unsigned long *insn_value;
202
{
203
  int status = (*info->read_memory_func) (pc, buf, buflen, info);
204
  if (status != 0)
205
    {
206
      (*info->memory_error_func) (status, pc, info);
207
      return -1;
208
    }
209
 
210
  ex_info->dis_info = info;
211
  ex_info->valid = (1 << buflen) - 1;
212
  ex_info->insn_bytes = buf;
213
 
214
  *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
215
  return 0;
216
}
217
 
218
/* Utility to print an insn.
219
   BUF is the base part of the insn, target byte order, BUFLEN bytes long.
220
   The result is the size of the insn in bytes or zero for an unknown insn
221
   or -1 if an error occurs fetching data (memory_error_func will have
222
   been called).  */
223
 
224
static int
225
print_insn (cd, pc, info, buf, buflen)
226
     CGEN_CPU_DESC cd;
227
     bfd_vma pc;
228
     disassemble_info *info;
229
     char *buf;
230
     int buflen;
231
{
232
  unsigned long insn_value;
233
  const CGEN_INSN_LIST *insn_list;
234
  CGEN_EXTRACT_INFO ex_info;
235
 
236
  /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
237
  insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
238
 
239
  /* Fill in ex_info fields like read_insn would.  Don't actually call
240
     read_insn, since the incoming buffer is already read (and possibly
241
     modified a la m32r).  */
242
  ex_info.valid = (1 << buflen) - 1;
243
  ex_info.dis_info = info;
244
  ex_info.insn_bytes = buf;
245
 
246
  /* The instructions are stored in hash lists.
247
     Pick the first one and keep trying until we find the right one.  */
248
 
249
  insn_list = CGEN_DIS_LOOKUP_INSN (cd, buf, insn_value);
250
  while (insn_list != NULL)
251
    {
252
      const CGEN_INSN *insn = insn_list->insn;
253
      CGEN_FIELDS fields;
254
      int length;
255
      unsigned long insn_value_cropped;
256
 
257
#ifdef CGEN_VALIDATE_INSN_SUPPORTED
258
      /* not needed as insn shouldn't be in hash lists if not supported */
259
      /* Supported by this cpu?  */
260
      if (! @arch@_cgen_insn_supported (cd, insn))
261
        {
262
          insn_list = CGEN_DIS_NEXT_INSN (insn_list);
263
          continue;
264
        }
265
#endif
266
 
267
      /* Basic bit mask must be correct.  */
268
      /* ??? May wish to allow target to defer this check until the extract
269
         handler.  */
270
 
271
      /* Base size may exceed this instruction's size.  Extract the
272
         relevant part from the buffer. */
273
      if ((CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
274
          (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
275
        insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn),
276
                                           info->endian == BFD_ENDIAN_BIG);
277
      else
278
        insn_value_cropped = insn_value;
279
 
280
      if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
281
          == CGEN_INSN_BASE_VALUE (insn))
282
        {
283
          /* Printing is handled in two passes.  The first pass parses the
284
             machine insn and extracts the fields.  The second pass prints
285
             them.  */
286
 
287
          /* Make sure the entire insn is loaded into insn_value, if it
288
             can fit.  */
289
          if (CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize &&
290
              (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
291
            {
292
              unsigned long full_insn_value;
293
              int rc = read_insn (cd, pc, info, buf,
294
                                  CGEN_INSN_BITSIZE (insn) / 8,
295
                                  & ex_info, & full_insn_value);
296
              if (rc != 0)
297
                return rc;
298
              length = CGEN_EXTRACT_FN (cd, insn)
299
                (cd, insn, &ex_info, full_insn_value, &fields, pc);
300
            }
301
          else
302
            length = CGEN_EXTRACT_FN (cd, insn)
303
              (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
304
 
305
          /* length < 0 -> error */
306
          if (length < 0)
307
            return length;
308
          if (length > 0)
309
            {
310
              CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
311
              /* length is in bits, result is in bytes */
312
              return length / 8;
313
            }
314
        }
315
 
316
      insn_list = CGEN_DIS_NEXT_INSN (insn_list);
317
    }
318
 
319
  return 0;
320
}
321
 
322
/* Default value for CGEN_PRINT_INSN.
323
   The result is the size of the insn in bytes or zero for an unknown insn
324
   or -1 if an error occured fetching bytes.  */
325
 
326
#ifndef CGEN_PRINT_INSN
327
#define CGEN_PRINT_INSN default_print_insn
328
#endif
329
 
330
static int
331
default_print_insn (cd, pc, info)
332
     CGEN_CPU_DESC cd;
333
     bfd_vma pc;
334
     disassemble_info *info;
335
{
336
  char buf[CGEN_MAX_INSN_SIZE];
337
  int buflen;
338
  int status;
339
 
340
  /* Attempt to read the base part of the insn.  */
341
  buflen = cd->base_insn_bitsize / 8;
342
  status = (*info->read_memory_func) (pc, buf, buflen, info);
343
 
344
  /* Try again with the minimum part, if min < base.  */
345
  if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
346
    {
347
      buflen = cd->min_insn_bitsize / 8;
348
      status = (*info->read_memory_func) (pc, buf, buflen, info);
349
    }
350
 
351
  if (status != 0)
352
    {
353
      (*info->memory_error_func) (status, pc, info);
354
      return -1;
355
    }
356
 
357
  return print_insn (cd, pc, info, buf, buflen);
358
}
359
 
360
/* Main entry point.
361
   Print one instruction from PC on INFO->STREAM.
362
   Return the size of the instruction (in bytes).  */
363
 
364
int
365
print_insn_@arch@ (pc, info)
366
     bfd_vma pc;
367
     disassemble_info *info;
368
{
369
  static CGEN_CPU_DESC cd = 0;
370
  static int prev_isa;
371
  static int prev_mach;
372
  static int prev_endian;
373
  int length;
374
  int isa,mach;
375
  int endian = (info->endian == BFD_ENDIAN_BIG
376
                ? CGEN_ENDIAN_BIG
377
                : CGEN_ENDIAN_LITTLE);
378
  enum bfd_architecture arch;
379
 
380
  /* ??? gdb will set mach but leave the architecture as "unknown" */
381
#ifndef CGEN_BFD_ARCH
382
#define CGEN_BFD_ARCH bfd_arch_@arch@
383
#endif
384
  arch = info->arch;
385
  if (arch == bfd_arch_unknown)
386
    arch = CGEN_BFD_ARCH;
387
 
388
  /* There's no standard way to compute the machine or isa number
389
     so we leave it to the target.  */
390
#ifdef CGEN_COMPUTE_MACH
391
  mach = CGEN_COMPUTE_MACH (info);
392
#else
393
  mach = info->mach;
394
#endif
395
 
396
#ifdef CGEN_COMPUTE_ISA
397
  isa = CGEN_COMPUTE_ISA (info);
398
#else
399
  isa = 0;
400
#endif
401
 
402
  /* If we've switched cpu's, close the current table and open a new one.  */
403
  if (cd
404
      && (isa != prev_isa
405
          || mach != prev_mach
406
          || endian != prev_endian))
407
    {
408
      @arch@_cgen_cpu_close (cd);
409
      cd = 0;
410
    }
411
 
412
  /* If we haven't initialized yet, initialize the opcode table.  */
413
  if (! cd)
414
    {
415
      const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
416
      const char *mach_name;
417
 
418
      if (!arch_type)
419
        abort ();
420
      mach_name = arch_type->printable_name;
421
 
422
      prev_isa = isa;
423
      prev_mach = mach;
424
      prev_endian = endian;
425
      cd = @arch@_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
426
                                 CGEN_CPU_OPEN_BFDMACH, mach_name,
427
                                 CGEN_CPU_OPEN_ENDIAN, prev_endian,
428
                                 CGEN_CPU_OPEN_END);
429
      if (!cd)
430
        abort ();
431
      @arch@_cgen_init_dis (cd);
432
    }
433
 
434
  /* We try to have as much common code as possible.
435
     But at this point some targets need to take over.  */
436
  /* ??? Some targets may need a hook elsewhere.  Try to avoid this,
437
     but if not possible try to move this hook elsewhere rather than
438
     have two hooks.  */
439
  length = CGEN_PRINT_INSN (cd, pc, info);
440
  if (length > 0)
441
    return length;
442
  if (length < 0)
443
    return -1;
444
 
445
  (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
446
  return cd->default_insn_bitsize / 8;
447
}

powered by: WebSVN 2.1.0

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