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

Subversion Repositories or1k

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

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

Line No. Rev Author Line
1 1181 sfurman
/* Disassembler interface for targets using CGEN. -*- C -*-
2
   CGEN: Cpu tools GENerator
3
 
4
THIS FILE IS MACHINE GENERATED WITH CGEN.
5
- the resultant file is machine generated, cgen-dis.in isn't
6
 
7
Copyright 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
8
 
9
This file is part of the GNU Binutils and GDB, the GNU debugger.
10
 
11
This program is free software; you can redistribute it and/or modify
12
it under the terms of the GNU General Public License as published by
13
the Free Software Foundation; either version 2, or (at your option)
14
any later version.
15
 
16
This program is distributed in the hope that it will be useful,
17
but WITHOUT ANY WARRANTY; without even the implied warranty of
18
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
GNU General Public License for more details.
20
 
21
You should have received a copy of the GNU General Public License
22
along with this program; if not, write to the Free Software Foundation, Inc.,
23
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
24
 
25
/* ??? Eventually more and more of this stuff can go to cpu-independent files.
26
   Keep that in mind.  */
27
 
28
#include "sysdep.h"
29
#include <stdio.h>
30
#include "ansidecl.h"
31
#include "dis-asm.h"
32
#include "bfd.h"
33
#include "symcat.h"
34
#include "frv-desc.h"
35
#include "frv-opc.h"
36
#include "opintl.h"
37
 
38
/* Default text to print if an instruction isn't recognized.  */
39
#define UNKNOWN_INSN_MSG _("*unknown*")
40
 
41
static void print_normal
42
     PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned int, bfd_vma, int));
43
static void print_address
44
     PARAMS ((CGEN_CPU_DESC, PTR, bfd_vma, unsigned int, bfd_vma, int));
45
static void print_keyword
46
     PARAMS ((CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int));
47
static void print_insn_normal
48
     PARAMS ((CGEN_CPU_DESC, PTR, const CGEN_INSN *, CGEN_FIELDS *,
49
              bfd_vma, int));
50
static int print_insn
51
     PARAMS ((CGEN_CPU_DESC, bfd_vma,  disassemble_info *, char *, unsigned));
52
static int default_print_insn
53
     PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *));
54
static int read_insn
55
     PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *, char *, int,
56
              CGEN_EXTRACT_INFO *, unsigned long *));
57
 
58
/* -- disassembler routines inserted here */
59
 
60
/* -- dis.c */
61
static void print_spr
62
  PARAMS ((CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned));
63
static void print_hi
64
  PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
65
static void print_lo
66
  PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
67
 
68
static void
69
print_spr (cd, dis_info, names, regno, attrs)
70
     CGEN_CPU_DESC cd;
71
     PTR dis_info;
72
     CGEN_KEYWORD *names;
73
     long regno;
74
     unsigned int attrs;
75
{
76
  /* Use the register index format for any unnamed registers.  */
77
  if (cgen_keyword_lookup_value (names, regno) == NULL)
78
    {
79
      disassemble_info *info = (disassemble_info *) dis_info;
80
      (*info->fprintf_func) (info->stream, "spr[%ld]", regno);
81
    }
82
  else
83
    print_keyword (cd, dis_info, names, regno, attrs);
84
}
85
 
86
static void
87
print_hi (cd, dis_info, value, attrs, pc, length)
88
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
89
     PTR dis_info;
90
     long value;
91
     unsigned int attrs ATTRIBUTE_UNUSED;
92
     bfd_vma pc ATTRIBUTE_UNUSED;
93
     int length ATTRIBUTE_UNUSED;
94
{
95
  disassemble_info *info = (disassemble_info *) dis_info;
96
  if (value)
97
    (*info->fprintf_func) (info->stream, "0x%lx", value);
98
  else
99
    (*info->fprintf_func) (info->stream, "hi(0x%lx)", value);
100
}
101
 
102
static void
103
print_lo (cd, dis_info, value, attrs, pc, length)
104
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
105
     PTR dis_info;
106
     long value;
107
     unsigned int attrs ATTRIBUTE_UNUSED;
108
     bfd_vma pc ATTRIBUTE_UNUSED;
109
     int length ATTRIBUTE_UNUSED;
110
{
111
  disassemble_info *info = (disassemble_info *) dis_info;
112
  if (value)
113
    (*info->fprintf_func) (info->stream, "0x%lx", value);
114
  else
115
    (*info->fprintf_func) (info->stream, "lo(0x%lx)", value);
116
}
117
 
118
/* -- */
119
 
120
void frv_cgen_print_operand
121
  PARAMS ((CGEN_CPU_DESC, int, PTR, CGEN_FIELDS *,
122
           void const *, bfd_vma, int));
123
 
124
/* Main entry point for printing operands.
125
   XINFO is a `void *' and not a `disassemble_info *' to not put a requirement
126
   of dis-asm.h on cgen.h.
127
 
128
   This function is basically just a big switch statement.  Earlier versions
129
   used tables to look up the function to use, but
130
   - if the table contains both assembler and disassembler functions then
131
     the disassembler contains much of the assembler and vice-versa,
132
   - there's a lot of inlining possibilities as things grow,
133
   - using a switch statement avoids the function call overhead.
134
 
135
   This function could be moved into `print_insn_normal', but keeping it
136
   separate makes clear the interface between `print_insn_normal' and each of
137
   the handlers.  */
138
 
139
void
140
frv_cgen_print_operand (cd, opindex, xinfo, fields, attrs, pc, length)
141
     CGEN_CPU_DESC cd;
142
     int opindex;
143
     PTR xinfo;
144
     CGEN_FIELDS *fields;
145
     void const *attrs ATTRIBUTE_UNUSED;
146
     bfd_vma pc;
147
     int length;
148
{
149
 disassemble_info *info = (disassemble_info *) xinfo;
150
 
151
  switch (opindex)
152
    {
153
    case FRV_OPERAND_A :
154
      print_normal (cd, info, fields->f_A, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
155
      break;
156
    case FRV_OPERAND_ACC40SI :
157
      print_keyword (cd, info, & frv_cgen_opval_acc_names, fields->f_ACC40Si, 0);
158
      break;
159
    case FRV_OPERAND_ACC40SK :
160
      print_keyword (cd, info, & frv_cgen_opval_acc_names, fields->f_ACC40Sk, 0);
161
      break;
162
    case FRV_OPERAND_ACC40UI :
163
      print_keyword (cd, info, & frv_cgen_opval_acc_names, fields->f_ACC40Ui, 0);
164
      break;
165
    case FRV_OPERAND_ACC40UK :
166
      print_keyword (cd, info, & frv_cgen_opval_acc_names, fields->f_ACC40Uk, 0);
167
      break;
168
    case FRV_OPERAND_ACCGI :
169
      print_keyword (cd, info, & frv_cgen_opval_accg_names, fields->f_ACCGi, 0);
170
      break;
171
    case FRV_OPERAND_ACCGK :
172
      print_keyword (cd, info, & frv_cgen_opval_accg_names, fields->f_ACCGk, 0);
173
      break;
174
    case FRV_OPERAND_CCI :
175
      print_keyword (cd, info, & frv_cgen_opval_cccr_names, fields->f_CCi, 0);
176
      break;
177
    case FRV_OPERAND_CPRDOUBLEK :
178
      print_keyword (cd, info, & frv_cgen_opval_cpr_names, fields->f_CPRk, 0);
179
      break;
180
    case FRV_OPERAND_CPRI :
181
      print_keyword (cd, info, & frv_cgen_opval_cpr_names, fields->f_CPRi, 0);
182
      break;
183
    case FRV_OPERAND_CPRJ :
184
      print_keyword (cd, info, & frv_cgen_opval_cpr_names, fields->f_CPRj, 0);
185
      break;
186
    case FRV_OPERAND_CPRK :
187
      print_keyword (cd, info, & frv_cgen_opval_cpr_names, fields->f_CPRk, 0);
188
      break;
189
    case FRV_OPERAND_CRI :
190
      print_keyword (cd, info, & frv_cgen_opval_cccr_names, fields->f_CRi, 0);
191
      break;
192
    case FRV_OPERAND_CRJ :
193
      print_keyword (cd, info, & frv_cgen_opval_cccr_names, fields->f_CRj, 0);
194
      break;
195
    case FRV_OPERAND_CRJ_FLOAT :
196
      print_keyword (cd, info, & frv_cgen_opval_cccr_names, fields->f_CRj_float, 0);
197
      break;
198
    case FRV_OPERAND_CRJ_INT :
199
      print_keyword (cd, info, & frv_cgen_opval_cccr_names, fields->f_CRj_int, 0);
200
      break;
201
    case FRV_OPERAND_CRK :
202
      print_keyword (cd, info, & frv_cgen_opval_cccr_names, fields->f_CRk, 0);
203
      break;
204
    case FRV_OPERAND_FCCI_1 :
205
      print_keyword (cd, info, & frv_cgen_opval_fccr_names, fields->f_FCCi_1, 0);
206
      break;
207
    case FRV_OPERAND_FCCI_2 :
208
      print_keyword (cd, info, & frv_cgen_opval_fccr_names, fields->f_FCCi_2, 0);
209
      break;
210
    case FRV_OPERAND_FCCI_3 :
211
      print_keyword (cd, info, & frv_cgen_opval_fccr_names, fields->f_FCCi_3, 0);
212
      break;
213
    case FRV_OPERAND_FCCK :
214
      print_keyword (cd, info, & frv_cgen_opval_fccr_names, fields->f_FCCk, 0);
215
      break;
216
    case FRV_OPERAND_FRDOUBLEI :
217
      print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRi, 0);
218
      break;
219
    case FRV_OPERAND_FRDOUBLEJ :
220
      print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRj, 0);
221
      break;
222
    case FRV_OPERAND_FRDOUBLEK :
223
      print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRk, 0);
224
      break;
225
    case FRV_OPERAND_FRI :
226
      print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRi, 0);
227
      break;
228
    case FRV_OPERAND_FRINTI :
229
      print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRi, 0);
230
      break;
231
    case FRV_OPERAND_FRINTJ :
232
      print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRj, 0);
233
      break;
234
    case FRV_OPERAND_FRINTK :
235
      print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRk, 0);
236
      break;
237
    case FRV_OPERAND_FRJ :
238
      print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRj, 0);
239
      break;
240
    case FRV_OPERAND_FRK :
241
      print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRk, 0);
242
      break;
243
    case FRV_OPERAND_FRKHI :
244
      print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRk, 0);
245
      break;
246
    case FRV_OPERAND_FRKLO :
247
      print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRk, 0);
248
      break;
249
    case FRV_OPERAND_GRDOUBLEK :
250
      print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRk, 0);
251
      break;
252
    case FRV_OPERAND_GRI :
253
      print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRi, 0);
254
      break;
255
    case FRV_OPERAND_GRJ :
256
      print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRj, 0);
257
      break;
258
    case FRV_OPERAND_GRK :
259
      print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRk, 0);
260
      break;
261
    case FRV_OPERAND_GRKHI :
262
      print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRk, 0);
263
      break;
264
    case FRV_OPERAND_GRKLO :
265
      print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRk, 0);
266
      break;
267
    case FRV_OPERAND_ICCI_1 :
268
      print_keyword (cd, info, & frv_cgen_opval_iccr_names, fields->f_ICCi_1, 0);
269
      break;
270
    case FRV_OPERAND_ICCI_2 :
271
      print_keyword (cd, info, & frv_cgen_opval_iccr_names, fields->f_ICCi_2, 0);
272
      break;
273
    case FRV_OPERAND_ICCI_3 :
274
      print_keyword (cd, info, & frv_cgen_opval_iccr_names, fields->f_ICCi_3, 0);
275
      break;
276
    case FRV_OPERAND_LI :
277
      print_normal (cd, info, fields->f_LI, 0, pc, length);
278
      break;
279
    case FRV_OPERAND_AE :
280
      print_normal (cd, info, fields->f_ae, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
281
      break;
282
    case FRV_OPERAND_CCOND :
283
      print_normal (cd, info, fields->f_ccond, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
284
      break;
285
    case FRV_OPERAND_COND :
286
      print_normal (cd, info, fields->f_cond, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
287
      break;
288
    case FRV_OPERAND_D12 :
289
      print_normal (cd, info, fields->f_d12, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
290
      break;
291
    case FRV_OPERAND_DEBUG :
292
      print_normal (cd, info, fields->f_debug, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
293
      break;
294
    case FRV_OPERAND_EIR :
295
      print_normal (cd, info, fields->f_eir, 0, pc, length);
296
      break;
297
    case FRV_OPERAND_HINT :
298
      print_normal (cd, info, fields->f_hint, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
299
      break;
300
    case FRV_OPERAND_HINT_NOT_TAKEN :
301
      print_keyword (cd, info, & frv_cgen_opval_h_hint_not_taken, fields->f_hint, 0);
302
      break;
303
    case FRV_OPERAND_HINT_TAKEN :
304
      print_keyword (cd, info, & frv_cgen_opval_h_hint_taken, fields->f_hint, 0);
305
      break;
306
    case FRV_OPERAND_LABEL16 :
307
      print_address (cd, info, fields->f_label16, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
308
      break;
309
    case FRV_OPERAND_LABEL24 :
310
      print_address (cd, info, fields->f_label24, 0|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
311
      break;
312
    case FRV_OPERAND_LOCK :
313
      print_normal (cd, info, fields->f_lock, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
314
      break;
315
    case FRV_OPERAND_PACK :
316
      print_keyword (cd, info, & frv_cgen_opval_h_pack, fields->f_pack, 0);
317
      break;
318
    case FRV_OPERAND_S10 :
319
      print_normal (cd, info, fields->f_s10, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
320
      break;
321
    case FRV_OPERAND_S12 :
322
      print_normal (cd, info, fields->f_d12, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
323
      break;
324
    case FRV_OPERAND_S16 :
325
      print_normal (cd, info, fields->f_s16, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
326
      break;
327
    case FRV_OPERAND_S5 :
328
      print_normal (cd, info, fields->f_s5, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
329
      break;
330
    case FRV_OPERAND_S6 :
331
      print_normal (cd, info, fields->f_s6, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
332
      break;
333
    case FRV_OPERAND_S6_1 :
334
      print_normal (cd, info, fields->f_s6_1, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
335
      break;
336
    case FRV_OPERAND_SLO16 :
337
      print_lo (cd, info, fields->f_s16, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
338
      break;
339
    case FRV_OPERAND_SPR :
340
      print_spr (cd, info, & frv_cgen_opval_spr_names, fields->f_spr, 0|(1<<CGEN_OPERAND_VIRTUAL));
341
      break;
342
    case FRV_OPERAND_U12 :
343
      print_normal (cd, info, fields->f_u12, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
344
      break;
345
    case FRV_OPERAND_U16 :
346
      print_normal (cd, info, fields->f_u16, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
347
      break;
348
    case FRV_OPERAND_U6 :
349
      print_normal (cd, info, fields->f_u6, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
350
      break;
351
    case FRV_OPERAND_UHI16 :
352
      print_hi (cd, info, fields->f_u16, 0, pc, length);
353
      break;
354
    case FRV_OPERAND_ULO16 :
355
      print_lo (cd, info, fields->f_u16, 0, pc, length);
356
      break;
357
 
358
    default :
359
      /* xgettext:c-format */
360
      fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
361
               opindex);
362
    abort ();
363
  }
364
}
365
 
366
cgen_print_fn * const frv_cgen_print_handlers[] =
367
{
368
  print_insn_normal,
369
};
370
 
371
 
372
void
373
frv_cgen_init_dis (cd)
374
     CGEN_CPU_DESC cd;
375
{
376
  frv_cgen_init_opcode_table (cd);
377
  frv_cgen_init_ibld_table (cd);
378
  cd->print_handlers = & frv_cgen_print_handlers[0];
379
  cd->print_operand = frv_cgen_print_operand;
380
}
381
 
382
 
383
/* Default print handler.  */
384
 
385
static void
386
print_normal (cd, dis_info, value, attrs, pc, length)
387
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
388
     PTR dis_info;
389
     long value;
390
     unsigned int attrs;
391
     bfd_vma pc ATTRIBUTE_UNUSED;
392
     int length ATTRIBUTE_UNUSED;
393
{
394
  disassemble_info *info = (disassemble_info *) dis_info;
395
 
396
#ifdef CGEN_PRINT_NORMAL
397
  CGEN_PRINT_NORMAL (cd, info, value, attrs, pc, length);
398
#endif
399
 
400
  /* Print the operand as directed by the attributes.  */
401
  if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
402
    ; /* nothing to do */
403
  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
404
    (*info->fprintf_func) (info->stream, "%ld", value);
405
  else
406
    (*info->fprintf_func) (info->stream, "0x%lx", value);
407
}
408
 
409
/* Default address handler.  */
410
 
411
static void
412
print_address (cd, dis_info, value, attrs, pc, length)
413
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
414
     PTR dis_info;
415
     bfd_vma value;
416
     unsigned int attrs;
417
     bfd_vma pc ATTRIBUTE_UNUSED;
418
     int length ATTRIBUTE_UNUSED;
419
{
420
  disassemble_info *info = (disassemble_info *) dis_info;
421
 
422
#ifdef CGEN_PRINT_ADDRESS
423
  CGEN_PRINT_ADDRESS (cd, info, value, attrs, pc, length);
424
#endif
425
 
426
  /* Print the operand as directed by the attributes.  */
427
  if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
428
    ; /* nothing to do */
429
  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
430
    (*info->print_address_func) (value, info);
431
  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
432
    (*info->print_address_func) (value, info);
433
  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
434
    (*info->fprintf_func) (info->stream, "%ld", (long) value);
435
  else
436
    (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
437
}
438
 
439
/* Keyword print handler.  */
440
 
441
static void
442
print_keyword (cd, dis_info, keyword_table, value, attrs)
443
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
444
     PTR dis_info;
445
     CGEN_KEYWORD *keyword_table;
446
     long value;
447
     unsigned int attrs ATTRIBUTE_UNUSED;
448
{
449
  disassemble_info *info = (disassemble_info *) dis_info;
450
  const CGEN_KEYWORD_ENTRY *ke;
451
 
452
  ke = cgen_keyword_lookup_value (keyword_table, value);
453
  if (ke != NULL)
454
    (*info->fprintf_func) (info->stream, "%s", ke->name);
455
  else
456
    (*info->fprintf_func) (info->stream, "???");
457
}
458
 
459
/* Default insn printer.
460
 
461
   DIS_INFO is defined as `PTR' so the disassembler needn't know anything
462
   about disassemble_info.  */
463
 
464
static void
465
print_insn_normal (cd, dis_info, insn, fields, pc, length)
466
     CGEN_CPU_DESC cd;
467
     PTR dis_info;
468
     const CGEN_INSN *insn;
469
     CGEN_FIELDS *fields;
470
     bfd_vma pc;
471
     int length;
472
{
473
  const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
474
  disassemble_info *info = (disassemble_info *) dis_info;
475
  const CGEN_SYNTAX_CHAR_TYPE *syn;
476
 
477
  CGEN_INIT_PRINT (cd);
478
 
479
  for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
480
    {
481
      if (CGEN_SYNTAX_MNEMONIC_P (*syn))
482
        {
483
          (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
484
          continue;
485
        }
486
      if (CGEN_SYNTAX_CHAR_P (*syn))
487
        {
488
          (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
489
          continue;
490
        }
491
 
492
      /* We have an operand.  */
493
      frv_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
494
                                 fields, CGEN_INSN_ATTRS (insn), pc, length);
495
    }
496
}
497
 
498
/* Subroutine of print_insn. Reads an insn into the given buffers and updates
499
   the extract info.
500
   Returns 0 if all is well, non-zero otherwise.  */
501
 
502
static int
503
read_insn (cd, pc, info, buf, buflen, ex_info, insn_value)
504
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
505
     bfd_vma pc;
506
     disassemble_info *info;
507
     char *buf;
508
     int buflen;
509
     CGEN_EXTRACT_INFO *ex_info;
510
     unsigned long *insn_value;
511
{
512
  int status = (*info->read_memory_func) (pc, buf, buflen, info);
513
  if (status != 0)
514
    {
515
      (*info->memory_error_func) (status, pc, info);
516
      return -1;
517
    }
518
 
519
  ex_info->dis_info = info;
520
  ex_info->valid = (1 << buflen) - 1;
521
  ex_info->insn_bytes = buf;
522
 
523
  *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
524
  return 0;
525
}
526
 
527
/* Utility to print an insn.
528
   BUF is the base part of the insn, target byte order, BUFLEN bytes long.
529
   The result is the size of the insn in bytes or zero for an unknown insn
530
   or -1 if an error occurs fetching data (memory_error_func will have
531
   been called).  */
532
 
533
static int
534
print_insn (cd, pc, info, buf, buflen)
535
     CGEN_CPU_DESC cd;
536
     bfd_vma pc;
537
     disassemble_info *info;
538
     char *buf;
539
     unsigned int buflen;
540
{
541
  CGEN_INSN_INT insn_value;
542
  const CGEN_INSN_LIST *insn_list;
543
  CGEN_EXTRACT_INFO ex_info;
544
  int basesize;
545
 
546
  /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
547
  basesize = cd->base_insn_bitsize < buflen * 8 ?
548
                                     cd->base_insn_bitsize : buflen * 8;
549
  insn_value = cgen_get_insn_value (cd, buf, basesize);
550
 
551
 
552
  /* Fill in ex_info fields like read_insn would.  Don't actually call
553
     read_insn, since the incoming buffer is already read (and possibly
554
     modified a la m32r).  */
555
  ex_info.valid = (1 << buflen) - 1;
556
  ex_info.dis_info = info;
557
  ex_info.insn_bytes = buf;
558
 
559
  /* The instructions are stored in hash lists.
560
     Pick the first one and keep trying until we find the right one.  */
561
 
562
  insn_list = CGEN_DIS_LOOKUP_INSN (cd, buf, insn_value);
563
  while (insn_list != NULL)
564
    {
565
      const CGEN_INSN *insn = insn_list->insn;
566
      CGEN_FIELDS fields;
567
      int length;
568
      unsigned long insn_value_cropped;
569
 
570
#ifdef CGEN_VALIDATE_INSN_SUPPORTED 
571
      /* Not needed as insn shouldn't be in hash lists if not supported.  */
572
      /* Supported by this cpu?  */
573
      if (! frv_cgen_insn_supported (cd, insn))
574
        {
575
          insn_list = CGEN_DIS_NEXT_INSN (insn_list);
576
          continue;
577
        }
578
#endif
579
 
580
      /* Basic bit mask must be correct.  */
581
      /* ??? May wish to allow target to defer this check until the extract
582
         handler.  */
583
 
584
      /* Base size may exceed this instruction's size.  Extract the
585
         relevant part from the buffer. */
586
      if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
587
          (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
588
        insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn),
589
                                           info->endian == BFD_ENDIAN_BIG);
590
      else
591
        insn_value_cropped = insn_value;
592
 
593
      if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
594
          == CGEN_INSN_BASE_VALUE (insn))
595
        {
596
          /* Printing is handled in two passes.  The first pass parses the
597
             machine insn and extracts the fields.  The second pass prints
598
             them.  */
599
 
600
          /* Make sure the entire insn is loaded into insn_value, if it
601
             can fit.  */
602
          if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
603
              (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
604
            {
605
              unsigned long full_insn_value;
606
              int rc = read_insn (cd, pc, info, buf,
607
                                  CGEN_INSN_BITSIZE (insn) / 8,
608
                                  & ex_info, & full_insn_value);
609
              if (rc != 0)
610
                return rc;
611
              length = CGEN_EXTRACT_FN (cd, insn)
612
                (cd, insn, &ex_info, full_insn_value, &fields, pc);
613
            }
614
          else
615
            length = CGEN_EXTRACT_FN (cd, insn)
616
              (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
617
 
618
          /* length < 0 -> error */
619
          if (length < 0)
620
            return length;
621
          if (length > 0)
622
            {
623
              CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
624
              /* length is in bits, result is in bytes */
625
              return length / 8;
626
            }
627
        }
628
 
629
      insn_list = CGEN_DIS_NEXT_INSN (insn_list);
630
    }
631
 
632
  return 0;
633
}
634
 
635
/* Default value for CGEN_PRINT_INSN.
636
   The result is the size of the insn in bytes or zero for an unknown insn
637
   or -1 if an error occured fetching bytes.  */
638
 
639
#ifndef CGEN_PRINT_INSN
640
#define CGEN_PRINT_INSN default_print_insn
641
#endif
642
 
643
static int
644
default_print_insn (cd, pc, info)
645
     CGEN_CPU_DESC cd;
646
     bfd_vma pc;
647
     disassemble_info *info;
648
{
649
  char buf[CGEN_MAX_INSN_SIZE];
650
  int buflen;
651
  int status;
652
 
653
  /* Attempt to read the base part of the insn.  */
654
  buflen = cd->base_insn_bitsize / 8;
655
  status = (*info->read_memory_func) (pc, buf, buflen, info);
656
 
657
  /* Try again with the minimum part, if min < base.  */
658
  if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
659
    {
660
      buflen = cd->min_insn_bitsize / 8;
661
      status = (*info->read_memory_func) (pc, buf, buflen, info);
662
    }
663
 
664
  if (status != 0)
665
    {
666
      (*info->memory_error_func) (status, pc, info);
667
      return -1;
668
    }
669
 
670
  return print_insn (cd, pc, info, buf, buflen);
671
}
672
 
673
/* Main entry point.
674
   Print one instruction from PC on INFO->STREAM.
675
   Return the size of the instruction (in bytes).  */
676
 
677
typedef struct cpu_desc_list {
678
  struct cpu_desc_list *next;
679
  int isa;
680
  int mach;
681
  int endian;
682
  CGEN_CPU_DESC cd;
683
} cpu_desc_list;
684
 
685
int
686
print_insn_frv (pc, info)
687
     bfd_vma pc;
688
     disassemble_info *info;
689
{
690
  static cpu_desc_list *cd_list = 0;
691
  cpu_desc_list *cl = 0;
692
  static CGEN_CPU_DESC cd = 0;
693
  static int prev_isa;
694
  static int prev_mach;
695
  static int prev_endian;
696
  int length;
697
  int isa,mach;
698
  int endian = (info->endian == BFD_ENDIAN_BIG
699
                ? CGEN_ENDIAN_BIG
700
                : CGEN_ENDIAN_LITTLE);
701
  enum bfd_architecture arch;
702
 
703
  /* ??? gdb will set mach but leave the architecture as "unknown" */
704
#ifndef CGEN_BFD_ARCH
705
#define CGEN_BFD_ARCH bfd_arch_frv
706
#endif
707
  arch = info->arch;
708
  if (arch == bfd_arch_unknown)
709
    arch = CGEN_BFD_ARCH;
710
 
711
  /* There's no standard way to compute the machine or isa number
712
     so we leave it to the target.  */
713
#ifdef CGEN_COMPUTE_MACH
714
  mach = CGEN_COMPUTE_MACH (info);
715
#else
716
  mach = info->mach;
717
#endif
718
 
719
#ifdef CGEN_COMPUTE_ISA
720
  isa = CGEN_COMPUTE_ISA (info);
721
#else
722
  isa = info->insn_sets;
723
#endif
724
 
725
  /* If we've switched cpu's, try to find a handle we've used before */
726
  if (cd
727
      && (isa != prev_isa
728
          || mach != prev_mach
729
          || endian != prev_endian))
730
    {
731
      cd = 0;
732
      for (cl = cd_list; cl; cl = cl->next)
733
        {
734
          if (cl->isa == isa &&
735
              cl->mach == mach &&
736
              cl->endian == endian)
737
            {
738
              cd = cl->cd;
739
              break;
740
            }
741
        }
742
    }
743
 
744
  /* If we haven't initialized yet, initialize the opcode table.  */
745
  if (! cd)
746
    {
747
      const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
748
      const char *mach_name;
749
 
750
      if (!arch_type)
751
        abort ();
752
      mach_name = arch_type->printable_name;
753
 
754
      prev_isa = isa;
755
      prev_mach = mach;
756
      prev_endian = endian;
757
      cd = frv_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
758
                                 CGEN_CPU_OPEN_BFDMACH, mach_name,
759
                                 CGEN_CPU_OPEN_ENDIAN, prev_endian,
760
                                 CGEN_CPU_OPEN_END);
761
      if (!cd)
762
        abort ();
763
 
764
      /* save this away for future reference */
765
      cl = xmalloc (sizeof (struct cpu_desc_list));
766
      cl->cd = cd;
767
      cl->isa = isa;
768
      cl->mach = mach;
769
      cl->endian = endian;
770
      cl->next = cd_list;
771
      cd_list = cl;
772
 
773
      frv_cgen_init_dis (cd);
774
    }
775
 
776
  /* We try to have as much common code as possible.
777
     But at this point some targets need to take over.  */
778
  /* ??? Some targets may need a hook elsewhere.  Try to avoid this,
779
     but if not possible try to move this hook elsewhere rather than
780
     have two hooks.  */
781
  length = CGEN_PRINT_INSN (cd, pc, info);
782
  if (length > 0)
783
    return length;
784
  if (length < 0)
785
    return -1;
786
 
787
  (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
788
  return cd->default_insn_bitsize / 8;
789
}

powered by: WebSVN 2.1.0

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