~ubuntu-branches/ubuntu/utopic/binutils-arm64-cross/utopic

« back to all changes in this revision

Viewing changes to binutils-2.23.52.20130611/opcodes/xc16x-dis.c

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2013-06-20 17:38:09 UTC
  • Revision ID: package-import@ubuntu.com-20130620173809-app8lzgvymy5fg6c
Tags: 0.7
Build-depend on binutils-source (>= 2.23.52.20130620-1~).

Show diffs side-by-side

added added

removed removed

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