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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [opcodes/] [xc16x-dis.c] - Blame information for rev 452

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

Line No. Rev Author Line
1 24 jeremybenn
/* 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 225 jeremybenn
   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007,
8
   2008  Free Software Foundation, Inc.
9 24 jeremybenn
 
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 "xc16x-desc.h"
37
#include "xc16x-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
#define CGEN_PRINT_NORMAL(cd, info, value, attrs, pc, length)   \
64
  do                                                            \
65
    {                                                           \
66
      if (CGEN_BOOL_ATTR ((attrs), CGEN_OPERAND_DOT_PREFIX))    \
67
        info->fprintf_func (info->stream, ".");                 \
68
      if (CGEN_BOOL_ATTR ((attrs), CGEN_OPERAND_POF_PREFIX))    \
69
        info->fprintf_func (info->stream, "#pof:");             \
70
      if (CGEN_BOOL_ATTR ((attrs), CGEN_OPERAND_PAG_PREFIX))    \
71
        info->fprintf_func (info->stream, "#pag:");             \
72
    }                                                           \
73
  while (0)
74
 
75
/* Print a 'pof:' prefix to an operand.  */
76
 
77
static void
78
print_pof (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
79
           void * dis_info ATTRIBUTE_UNUSED,
80
           long value ATTRIBUTE_UNUSED,
81
           unsigned int attrs ATTRIBUTE_UNUSED,
82
           bfd_vma pc ATTRIBUTE_UNUSED,
83
           int length ATTRIBUTE_UNUSED)
84
{
85
}
86
 
87
/* Print a 'pag:' prefix to an operand.  */
88
 
89
static void
90
print_pag (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
91
           void * dis_info ATTRIBUTE_UNUSED,
92
           long value ATTRIBUTE_UNUSED,
93
           unsigned int attrs ATTRIBUTE_UNUSED,
94
           bfd_vma pc ATTRIBUTE_UNUSED,
95
           int length ATTRIBUTE_UNUSED)
96
{
97
}
98
 
99
/* Print a 'sof:' prefix to an operand.  */
100
 
101
static void
102
print_sof (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
103
           void * dis_info,
104
           long value ATTRIBUTE_UNUSED,
105
           unsigned int attrs ATTRIBUTE_UNUSED,
106
           bfd_vma pc ATTRIBUTE_UNUSED,
107
           int length ATTRIBUTE_UNUSED)
108
{
109
  disassemble_info *info = (disassemble_info *) dis_info;
110
 
111
  info->fprintf_func (info->stream, "sof:");
112
}
113
 
114
/* Print a 'seg:' prefix to an operand.  */
115
 
116
static void
117
print_seg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
118
           void * dis_info,
119
           long value ATTRIBUTE_UNUSED,
120
           unsigned int attrs ATTRIBUTE_UNUSED,
121
           bfd_vma pc ATTRIBUTE_UNUSED,
122
           int length ATTRIBUTE_UNUSED)
123
{
124
  disassemble_info *info = (disassemble_info *) dis_info;
125
 
126
  info->fprintf_func (info->stream, "seg:");
127
}
128
 
129
/* Print a '#' prefix to an operand.  */
130
 
131
static void
132
print_hash (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
133
            void * dis_info,
134
            long value ATTRIBUTE_UNUSED,
135
            unsigned int attrs ATTRIBUTE_UNUSED,
136
            bfd_vma pc ATTRIBUTE_UNUSED,
137
            int length ATTRIBUTE_UNUSED)
138
{
139
  disassemble_info *info = (disassemble_info *) dis_info;
140
 
141
  info->fprintf_func (info->stream, "#");
142
}
143
 
144
/* Print a '.' prefix to an operand.  */
145
 
146
static void
147
print_dot (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
148
           void * dis_info ATTRIBUTE_UNUSED,
149
           long value ATTRIBUTE_UNUSED,
150
           unsigned int attrs ATTRIBUTE_UNUSED,
151
           bfd_vma pc ATTRIBUTE_UNUSED,
152
           int length ATTRIBUTE_UNUSED)
153
{
154
}
155
 
156
/* -- */
157
 
158
void xc16x_cgen_print_operand
159
  (CGEN_CPU_DESC, int, PTR, CGEN_FIELDS *, void const *, bfd_vma, int);
160
 
161
/* Main entry point for printing operands.
162
   XINFO is a `void *' and not a `disassemble_info *' to not put a requirement
163
   of dis-asm.h on cgen.h.
164
 
165
   This function is basically just a big switch statement.  Earlier versions
166
   used tables to look up the function to use, but
167
   - if the table contains both assembler and disassembler functions then
168
     the disassembler contains much of the assembler and vice-versa,
169
   - there's a lot of inlining possibilities as things grow,
170
   - using a switch statement avoids the function call overhead.
171
 
172
   This function could be moved into `print_insn_normal', but keeping it
173
   separate makes clear the interface between `print_insn_normal' and each of
174
   the handlers.  */
175
 
176
void
177
xc16x_cgen_print_operand (CGEN_CPU_DESC cd,
178
                           int opindex,
179
                           void * xinfo,
180
                           CGEN_FIELDS *fields,
181
                           void const *attrs ATTRIBUTE_UNUSED,
182
                           bfd_vma pc,
183
                           int length)
184
{
185
  disassemble_info *info = (disassemble_info *) xinfo;
186
 
187
  switch (opindex)
188
    {
189
    case XC16X_OPERAND_REGNAM :
190
      print_keyword (cd, info, & xc16x_cgen_opval_psw_names, fields->f_reg8, 0);
191
      break;
192
    case XC16X_OPERAND_BIT01 :
193
      print_normal (cd, info, fields->f_op_1bit, 0, pc, length);
194
      break;
195
    case XC16X_OPERAND_BIT1 :
196
      print_normal (cd, info, fields->f_op_bit1, 0, pc, length);
197
      break;
198
    case XC16X_OPERAND_BIT2 :
199
      print_normal (cd, info, fields->f_op_bit2, 0, pc, length);
200
      break;
201
    case XC16X_OPERAND_BIT4 :
202
      print_normal (cd, info, fields->f_op_bit4, 0, pc, length);
203
      break;
204
    case XC16X_OPERAND_BIT8 :
205
      print_normal (cd, info, fields->f_op_bit8, 0, pc, length);
206
      break;
207
    case XC16X_OPERAND_BITONE :
208
      print_normal (cd, info, fields->f_op_onebit, 0, pc, length);
209
      break;
210
    case XC16X_OPERAND_CADDR :
211
      print_address (cd, info, fields->f_offset16, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR), pc, length);
212
      break;
213
    case XC16X_OPERAND_COND :
214
      print_keyword (cd, info, & xc16x_cgen_opval_conditioncode_names, fields->f_condcode, 0);
215
      break;
216
    case XC16X_OPERAND_DATA8 :
217
      print_normal (cd, info, fields->f_data8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
218
      break;
219
    case XC16X_OPERAND_DATAHI8 :
220
      print_normal (cd, info, fields->f_datahi8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
221
      break;
222
    case XC16X_OPERAND_DOT :
223
      print_dot (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
224
      break;
225
    case XC16X_OPERAND_DR :
226
      print_keyword (cd, info, & xc16x_cgen_opval_gr_names, fields->f_r1, 0);
227
      break;
228
    case XC16X_OPERAND_DRB :
229
      print_keyword (cd, info, & xc16x_cgen_opval_grb_names, fields->f_r1, 0);
230
      break;
231
    case XC16X_OPERAND_DRI :
232
      print_keyword (cd, info, & xc16x_cgen_opval_gr_names, fields->f_r4, 0);
233
      break;
234
    case XC16X_OPERAND_EXTCOND :
235
      print_keyword (cd, info, & xc16x_cgen_opval_extconditioncode_names, fields->f_extccode, 0);
236
      break;
237
    case XC16X_OPERAND_GENREG :
238
      print_keyword (cd, info, & xc16x_cgen_opval_r8_names, fields->f_regb8, 0);
239
      break;
240
    case XC16X_OPERAND_HASH :
241
      print_hash (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
242
      break;
243
    case XC16X_OPERAND_ICOND :
244
      print_keyword (cd, info, & xc16x_cgen_opval_conditioncode_names, fields->f_icondcode, 0);
245
      break;
246
    case XC16X_OPERAND_LBIT2 :
247
      print_normal (cd, info, fields->f_op_lbit2, 0, pc, length);
248
      break;
249
    case XC16X_OPERAND_LBIT4 :
250
      print_normal (cd, info, fields->f_op_lbit4, 0, pc, length);
251
      break;
252
    case XC16X_OPERAND_MASK8 :
253
      print_normal (cd, info, fields->f_mask8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
254
      break;
255
    case XC16X_OPERAND_MASKLO8 :
256
      print_normal (cd, info, fields->f_datahi8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
257
      break;
258
    case XC16X_OPERAND_MEMGR8 :
259
      print_keyword (cd, info, & xc16x_cgen_opval_memgr8_names, fields->f_memgr8, 0);
260
      break;
261
    case XC16X_OPERAND_MEMORY :
262
      print_address (cd, info, fields->f_memory, 0, pc, length);
263
      break;
264
    case XC16X_OPERAND_PAG :
265
      print_pag (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
266
      break;
267
    case XC16X_OPERAND_PAGENUM :
268
      print_normal (cd, info, fields->f_pagenum, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
269
      break;
270
    case XC16X_OPERAND_POF :
271
      print_pof (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
272
      break;
273
    case XC16X_OPERAND_QBIT :
274
      print_normal (cd, info, fields->f_qbit, 0|(1<<CGEN_OPERAND_DOT_PREFIX), pc, length);
275
      break;
276
    case XC16X_OPERAND_QHIBIT :
277
      print_normal (cd, info, fields->f_qhibit, 0|(1<<CGEN_OPERAND_DOT_PREFIX), pc, length);
278
      break;
279
    case XC16X_OPERAND_QLOBIT :
280
      print_normal (cd, info, fields->f_qlobit, 0|(1<<CGEN_OPERAND_DOT_PREFIX), pc, length);
281
      break;
282
    case XC16X_OPERAND_REG8 :
283
      print_keyword (cd, info, & xc16x_cgen_opval_r8_names, fields->f_reg8, 0);
284
      break;
285
    case XC16X_OPERAND_REGB8 :
286
      print_keyword (cd, info, & xc16x_cgen_opval_grb8_names, fields->f_regb8, 0);
287
      break;
288
    case XC16X_OPERAND_REGBMEM8 :
289
      print_keyword (cd, info, & xc16x_cgen_opval_regbmem8_names, fields->f_regmem8, 0);
290
      break;
291
    case XC16X_OPERAND_REGHI8 :
292
      print_keyword (cd, info, & xc16x_cgen_opval_r8_names, fields->f_reghi8, 0);
293
      break;
294
    case XC16X_OPERAND_REGMEM8 :
295
      print_keyword (cd, info, & xc16x_cgen_opval_regmem8_names, fields->f_regmem8, 0);
296
      break;
297
    case XC16X_OPERAND_REGOFF8 :
298
      print_keyword (cd, info, & xc16x_cgen_opval_r8_names, fields->f_regoff8, 0);
299
      break;
300
    case XC16X_OPERAND_REL :
301
      print_normal (cd, info, fields->f_rel8, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
302
      break;
303
    case XC16X_OPERAND_RELHI :
304
      print_normal (cd, info, fields->f_relhi8, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
305
      break;
306
    case XC16X_OPERAND_SEG :
307
      print_normal (cd, info, fields->f_seg8, 0, pc, length);
308
      break;
309
    case XC16X_OPERAND_SEGHI8 :
310
      print_normal (cd, info, fields->f_segnum8, 0, pc, length);
311
      break;
312
    case XC16X_OPERAND_SEGM :
313
      print_seg (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
314
      break;
315
    case XC16X_OPERAND_SOF :
316
      print_sof (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
317
      break;
318
    case XC16X_OPERAND_SR :
319
      print_keyword (cd, info, & xc16x_cgen_opval_gr_names, fields->f_r2, 0);
320
      break;
321
    case XC16X_OPERAND_SR2 :
322
      print_keyword (cd, info, & xc16x_cgen_opval_gr_names, fields->f_r0, 0);
323
      break;
324
    case XC16X_OPERAND_SRB :
325
      print_keyword (cd, info, & xc16x_cgen_opval_grb_names, fields->f_r2, 0);
326
      break;
327
    case XC16X_OPERAND_SRC1 :
328
      print_keyword (cd, info, & xc16x_cgen_opval_gr_names, fields->f_r1, 0);
329
      break;
330
    case XC16X_OPERAND_SRC2 :
331
      print_keyword (cd, info, & xc16x_cgen_opval_gr_names, fields->f_r2, 0);
332
      break;
333
    case XC16X_OPERAND_SRDIV :
334
      print_keyword (cd, info, & xc16x_cgen_opval_regdiv8_names, fields->f_reg8, 0);
335
      break;
336
    case XC16X_OPERAND_U4 :
337
      print_keyword (cd, info, & xc16x_cgen_opval_reg0_name, fields->f_uimm4, 0);
338
      break;
339
    case XC16X_OPERAND_UIMM16 :
340
      print_normal (cd, info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
341
      break;
342
    case XC16X_OPERAND_UIMM2 :
343
      print_keyword (cd, info, & xc16x_cgen_opval_ext_names, fields->f_uimm2, 0|(1<<CGEN_OPERAND_HASH_PREFIX));
344
      break;
345
    case XC16X_OPERAND_UIMM3 :
346
      print_keyword (cd, info, & xc16x_cgen_opval_reg0_name1, fields->f_uimm3, 0|(1<<CGEN_OPERAND_HASH_PREFIX));
347
      break;
348
    case XC16X_OPERAND_UIMM4 :
349
      print_normal (cd, info, fields->f_uimm4, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
350
      break;
351
    case XC16X_OPERAND_UIMM7 :
352
      print_normal (cd, info, fields->f_uimm7, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
353
      break;
354
    case XC16X_OPERAND_UIMM8 :
355
      print_normal (cd, info, fields->f_uimm8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
356
      break;
357
    case XC16X_OPERAND_UPAG16 :
358
      print_normal (cd, info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_PAG_PREFIX), pc, length);
359
      break;
360
    case XC16X_OPERAND_UPOF16 :
361
      print_address (cd, info, fields->f_memory, 0|(1<<CGEN_OPERAND_POF_PREFIX), pc, length);
362
      break;
363
    case XC16X_OPERAND_USEG16 :
364
      print_normal (cd, info, fields->f_offset16, 0|(1<<CGEN_OPERAND_SEG_PREFIX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR), pc, length);
365
      break;
366
    case XC16X_OPERAND_USEG8 :
367
      print_normal (cd, info, fields->f_seg8, 0|(1<<CGEN_OPERAND_SEG_PREFIX), pc, length);
368
      break;
369
    case XC16X_OPERAND_USOF16 :
370
      print_normal (cd, info, fields->f_offset16, 0|(1<<CGEN_OPERAND_SOF_PREFIX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR), pc, length);
371
      break;
372
 
373
    default :
374
      /* xgettext:c-format */
375
      fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
376
               opindex);
377
    abort ();
378
  }
379
}
380
 
381
cgen_print_fn * const xc16x_cgen_print_handlers[] =
382
{
383
  print_insn_normal,
384
};
385
 
386
 
387
void
388
xc16x_cgen_init_dis (CGEN_CPU_DESC cd)
389
{
390
  xc16x_cgen_init_opcode_table (cd);
391
  xc16x_cgen_init_ibld_table (cd);
392
  cd->print_handlers = & xc16x_cgen_print_handlers[0];
393
  cd->print_operand = xc16x_cgen_print_operand;
394
}
395
 
396
 
397
/* Default print handler.  */
398
 
399
static void
400
print_normal (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
401
              void *dis_info,
402
              long value,
403
              unsigned int attrs,
404
              bfd_vma pc ATTRIBUTE_UNUSED,
405
              int length ATTRIBUTE_UNUSED)
406
{
407
  disassemble_info *info = (disassemble_info *) dis_info;
408
 
409
#ifdef CGEN_PRINT_NORMAL
410
  CGEN_PRINT_NORMAL (cd, info, value, attrs, pc, length);
411
#endif
412
 
413
  /* Print the operand as directed by the attributes.  */
414
  if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
415
    ; /* nothing to do */
416
  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
417
    (*info->fprintf_func) (info->stream, "%ld", value);
418
  else
419
    (*info->fprintf_func) (info->stream, "0x%lx", value);
420
}
421
 
422
/* Default address handler.  */
423
 
424
static void
425
print_address (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
426
               void *dis_info,
427
               bfd_vma value,
428
               unsigned int attrs,
429
               bfd_vma pc ATTRIBUTE_UNUSED,
430
               int length ATTRIBUTE_UNUSED)
431
{
432
  disassemble_info *info = (disassemble_info *) dis_info;
433
 
434
#ifdef CGEN_PRINT_ADDRESS
435
  CGEN_PRINT_ADDRESS (cd, info, value, attrs, pc, length);
436
#endif
437
 
438
  /* Print the operand as directed by the attributes.  */
439
  if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
440
    ; /* Nothing to do.  */
441
  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
442
    (*info->print_address_func) (value, info);
443
  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
444
    (*info->print_address_func) (value, info);
445
  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
446
    (*info->fprintf_func) (info->stream, "%ld", (long) value);
447
  else
448
    (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
449
}
450
 
451
/* Keyword print handler.  */
452
 
453
static void
454
print_keyword (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
455
               void *dis_info,
456
               CGEN_KEYWORD *keyword_table,
457
               long value,
458
               unsigned int attrs ATTRIBUTE_UNUSED)
459
{
460
  disassemble_info *info = (disassemble_info *) dis_info;
461
  const CGEN_KEYWORD_ENTRY *ke;
462
 
463
  ke = cgen_keyword_lookup_value (keyword_table, value);
464
  if (ke != NULL)
465
    (*info->fprintf_func) (info->stream, "%s", ke->name);
466
  else
467
    (*info->fprintf_func) (info->stream, "???");
468
}
469
 
470
/* Default insn printer.
471
 
472
   DIS_INFO is defined as `void *' so the disassembler needn't know anything
473
   about disassemble_info.  */
474
 
475
static void
476
print_insn_normal (CGEN_CPU_DESC cd,
477
                   void *dis_info,
478
                   const CGEN_INSN *insn,
479
                   CGEN_FIELDS *fields,
480
                   bfd_vma pc,
481
                   int length)
482
{
483
  const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
484
  disassemble_info *info = (disassemble_info *) dis_info;
485
  const CGEN_SYNTAX_CHAR_TYPE *syn;
486
 
487
  CGEN_INIT_PRINT (cd);
488
 
489
  for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
490
    {
491
      if (CGEN_SYNTAX_MNEMONIC_P (*syn))
492
        {
493
          (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
494
          continue;
495
        }
496
      if (CGEN_SYNTAX_CHAR_P (*syn))
497
        {
498
          (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
499
          continue;
500
        }
501
 
502
      /* We have an operand.  */
503
      xc16x_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
504
                                 fields, CGEN_INSN_ATTRS (insn), pc, length);
505
    }
506
}
507
 
508
/* Subroutine of print_insn. Reads an insn into the given buffers and updates
509
   the extract info.
510
   Returns 0 if all is well, non-zero otherwise.  */
511
 
512
static int
513
read_insn (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
514
           bfd_vma pc,
515
           disassemble_info *info,
516
           bfd_byte *buf,
517
           int buflen,
518
           CGEN_EXTRACT_INFO *ex_info,
519
           unsigned long *insn_value)
520
{
521
  int status = (*info->read_memory_func) (pc, buf, buflen, info);
522
 
523
  if (status != 0)
524
    {
525
      (*info->memory_error_func) (status, pc, info);
526
      return -1;
527
    }
528
 
529
  ex_info->dis_info = info;
530
  ex_info->valid = (1 << buflen) - 1;
531
  ex_info->insn_bytes = buf;
532
 
533
  *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
534
  return 0;
535
}
536
 
537
/* Utility to print an insn.
538
   BUF is the base part of the insn, target byte order, BUFLEN bytes long.
539
   The result is the size of the insn in bytes or zero for an unknown insn
540
   or -1 if an error occurs fetching data (memory_error_func will have
541
   been called).  */
542
 
543
static int
544
print_insn (CGEN_CPU_DESC cd,
545
            bfd_vma pc,
546
            disassemble_info *info,
547
            bfd_byte *buf,
548
            unsigned int buflen)
549
{
550
  CGEN_INSN_INT insn_value;
551
  const CGEN_INSN_LIST *insn_list;
552
  CGEN_EXTRACT_INFO ex_info;
553
  int basesize;
554
 
555
  /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
556
  basesize = cd->base_insn_bitsize < buflen * 8 ?
557
                                     cd->base_insn_bitsize : buflen * 8;
558
  insn_value = cgen_get_insn_value (cd, buf, basesize);
559
 
560
 
561
  /* Fill in ex_info fields like read_insn would.  Don't actually call
562
     read_insn, since the incoming buffer is already read (and possibly
563
     modified a la m32r).  */
564
  ex_info.valid = (1 << buflen) - 1;
565
  ex_info.dis_info = info;
566
  ex_info.insn_bytes = buf;
567
 
568
  /* The instructions are stored in hash lists.
569
     Pick the first one and keep trying until we find the right one.  */
570
 
571
  insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
572
  while (insn_list != NULL)
573
    {
574
      const CGEN_INSN *insn = insn_list->insn;
575
      CGEN_FIELDS fields;
576
      int length;
577
      unsigned long insn_value_cropped;
578
 
579
#ifdef CGEN_VALIDATE_INSN_SUPPORTED 
580
      /* Not needed as insn shouldn't be in hash lists if not supported.  */
581
      /* Supported by this cpu?  */
582
      if (! xc16x_cgen_insn_supported (cd, insn))
583
        {
584
          insn_list = CGEN_DIS_NEXT_INSN (insn_list);
585
          continue;
586
        }
587
#endif
588
 
589
      /* Basic bit mask must be correct.  */
590
      /* ??? May wish to allow target to defer this check until the extract
591
         handler.  */
592
 
593
      /* Base size may exceed this instruction's size.  Extract the
594
         relevant part from the buffer. */
595
      if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
596
          (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
597
        insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn),
598
                                           info->endian == BFD_ENDIAN_BIG);
599
      else
600
        insn_value_cropped = insn_value;
601
 
602
      if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
603
          == CGEN_INSN_BASE_VALUE (insn))
604
        {
605
          /* Printing is handled in two passes.  The first pass parses the
606
             machine insn and extracts the fields.  The second pass prints
607
             them.  */
608
 
609
          /* Make sure the entire insn is loaded into insn_value, if it
610
             can fit.  */
611
          if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
612
              (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
613
            {
614
              unsigned long full_insn_value;
615
              int rc = read_insn (cd, pc, info, buf,
616
                                  CGEN_INSN_BITSIZE (insn) / 8,
617
                                  & ex_info, & full_insn_value);
618
              if (rc != 0)
619
                return rc;
620
              length = CGEN_EXTRACT_FN (cd, insn)
621
                (cd, insn, &ex_info, full_insn_value, &fields, pc);
622
            }
623
          else
624
            length = CGEN_EXTRACT_FN (cd, insn)
625
              (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
626
 
627
          /* Length < 0 -> error.  */
628
          if (length < 0)
629
            return length;
630
          if (length > 0)
631
            {
632
              CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
633
              /* Length is in bits, result is in bytes.  */
634
              return length / 8;
635
            }
636
        }
637
 
638
      insn_list = CGEN_DIS_NEXT_INSN (insn_list);
639
    }
640
 
641
  return 0;
642
}
643
 
644
/* Default value for CGEN_PRINT_INSN.
645
   The result is the size of the insn in bytes or zero for an unknown insn
646
   or -1 if an error occured fetching bytes.  */
647
 
648
#ifndef CGEN_PRINT_INSN
649
#define CGEN_PRINT_INSN default_print_insn
650
#endif
651
 
652
static int
653
default_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
654
{
655
  bfd_byte buf[CGEN_MAX_INSN_SIZE];
656
  int buflen;
657
  int status;
658
 
659
  /* Attempt to read the base part of the insn.  */
660
  buflen = cd->base_insn_bitsize / 8;
661
  status = (*info->read_memory_func) (pc, buf, buflen, info);
662
 
663
  /* Try again with the minimum part, if min < base.  */
664
  if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
665
    {
666
      buflen = cd->min_insn_bitsize / 8;
667
      status = (*info->read_memory_func) (pc, buf, buflen, info);
668
    }
669
 
670
  if (status != 0)
671
    {
672
      (*info->memory_error_func) (status, pc, info);
673
      return -1;
674
    }
675
 
676
  return print_insn (cd, pc, info, buf, buflen);
677
}
678
 
679
/* Main entry point.
680
   Print one instruction from PC on INFO->STREAM.
681
   Return the size of the instruction (in bytes).  */
682
 
683
typedef struct cpu_desc_list
684
{
685
  struct cpu_desc_list *next;
686
  CGEN_BITSET *isa;
687
  int mach;
688
  int endian;
689
  CGEN_CPU_DESC cd;
690
} cpu_desc_list;
691
 
692
int
693
print_insn_xc16x (bfd_vma pc, disassemble_info *info)
694
{
695
  static cpu_desc_list *cd_list = 0;
696
  cpu_desc_list *cl = 0;
697
  static CGEN_CPU_DESC cd = 0;
698
  static CGEN_BITSET *prev_isa;
699
  static int prev_mach;
700
  static int prev_endian;
701
  int length;
702
  CGEN_BITSET *isa;
703
  int mach;
704
  int endian = (info->endian == BFD_ENDIAN_BIG
705
                ? CGEN_ENDIAN_BIG
706
                : CGEN_ENDIAN_LITTLE);
707
  enum bfd_architecture arch;
708
 
709
  /* ??? gdb will set mach but leave the architecture as "unknown" */
710
#ifndef CGEN_BFD_ARCH
711
#define CGEN_BFD_ARCH bfd_arch_xc16x
712
#endif
713
  arch = info->arch;
714
  if (arch == bfd_arch_unknown)
715
    arch = CGEN_BFD_ARCH;
716
 
717
  /* There's no standard way to compute the machine or isa number
718
     so we leave it to the target.  */
719
#ifdef CGEN_COMPUTE_MACH
720
  mach = CGEN_COMPUTE_MACH (info);
721
#else
722
  mach = info->mach;
723
#endif
724
 
725
#ifdef CGEN_COMPUTE_ISA
726
  {
727
    static CGEN_BITSET *permanent_isa;
728
 
729
    if (!permanent_isa)
730
      permanent_isa = cgen_bitset_create (MAX_ISAS);
731
    isa = permanent_isa;
732
    cgen_bitset_clear (isa);
733
    cgen_bitset_add (isa, CGEN_COMPUTE_ISA (info));
734
  }
735
#else
736
  isa = info->insn_sets;
737
#endif
738
 
739
  /* If we've switched cpu's, try to find a handle we've used before */
740
  if (cd
741
      && (cgen_bitset_compare (isa, prev_isa) != 0
742
          || mach != prev_mach
743
          || endian != prev_endian))
744
    {
745
      cd = 0;
746
      for (cl = cd_list; cl; cl = cl->next)
747
        {
748
          if (cgen_bitset_compare (cl->isa, isa) == 0 &&
749
              cl->mach == mach &&
750
              cl->endian == endian)
751
            {
752
              cd = cl->cd;
753
              prev_isa = cd->isas;
754
              break;
755
            }
756
        }
757
    }
758
 
759
  /* If we haven't initialized yet, initialize the opcode table.  */
760
  if (! cd)
761
    {
762
      const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
763
      const char *mach_name;
764
 
765
      if (!arch_type)
766
        abort ();
767
      mach_name = arch_type->printable_name;
768
 
769
      prev_isa = cgen_bitset_copy (isa);
770
      prev_mach = mach;
771
      prev_endian = endian;
772
      cd = xc16x_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
773
                                 CGEN_CPU_OPEN_BFDMACH, mach_name,
774
                                 CGEN_CPU_OPEN_ENDIAN, prev_endian,
775
                                 CGEN_CPU_OPEN_END);
776
      if (!cd)
777
        abort ();
778
 
779
      /* Save this away for future reference.  */
780
      cl = xmalloc (sizeof (struct cpu_desc_list));
781
      cl->cd = cd;
782
      cl->isa = prev_isa;
783
      cl->mach = mach;
784
      cl->endian = endian;
785
      cl->next = cd_list;
786
      cd_list = cl;
787
 
788
      xc16x_cgen_init_dis (cd);
789
    }
790
 
791
  /* We try to have as much common code as possible.
792
     But at this point some targets need to take over.  */
793
  /* ??? Some targets may need a hook elsewhere.  Try to avoid this,
794
     but if not possible try to move this hook elsewhere rather than
795
     have two hooks.  */
796
  length = CGEN_PRINT_INSN (cd, pc, info);
797
  if (length > 0)
798
    return length;
799
  if (length < 0)
800
    return -1;
801
 
802
  (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
803
  return cd->default_insn_bitsize / 8;
804
}

powered by: WebSVN 2.1.0

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