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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [binutils-2.18.50/] [opcodes/] [sh64-dis.c] - Blame information for rev 156

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 38 julius
/* Disassemble SH64 instructions.
2
   Copyright 2000, 2001, 2002, 2003, 2005, 2007 Free Software Foundation, Inc.
3
 
4
   This file is part of the GNU opcodes library.
5
 
6
   This library is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 3, or (at your option)
9
   any later version.
10
 
11
   It is distributed in the hope that it will be useful, but WITHOUT
12
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
14
   License for more details.
15
 
16
   You should have received a copy of the GNU General Public License
17
   along with this file; see the file COPYING.  If not, write to the
18
   Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
19
   MA 02110-1301, USA.  */
20
 
21
#include <stdio.h>
22
 
23
#include "dis-asm.h"
24
#include "sysdep.h"
25
#include "sh64-opc.h"
26
#include "libiberty.h"
27
/* We need to refer to the ELF header structure.  */
28
#include "elf-bfd.h"
29
#include "elf/sh.h"
30
#include "elf32-sh64.h"
31
 
32
#define ELF_MODE32_CODE_LABEL_P(SYM) \
33
 (((elf_symbol_type *) (SYM))->internal_elf_sym.st_other & STO_SH5_ISA32)
34
 
35
#define SAVED_MOVI_R(INFO) \
36
 (((struct sh64_disassemble_info *) ((INFO)->private_data))->address_reg)
37
 
38
#define SAVED_MOVI_IMM(INFO) \
39
 (((struct sh64_disassemble_info *) ((INFO)->private_data))->built_address)
40
 
41
struct sh64_disassemble_info
42
 {
43
   /* When we see a MOVI, we save the register and the value, and merge a
44
      subsequent SHORI and display the address, if there is one.  */
45
   unsigned int address_reg;
46
   bfd_signed_vma built_address;
47
 
48
   /* This is the range decriptor for the current address.  It is kept
49
      around for the next call.  */
50
   sh64_elf_crange crange;
51
 };
52
 
53
/* Each item in the table is a mask to indicate which bits to be set
54
   to determine an instruction's operator.
55
   The index is as same as the instruction in the opcode table.
56
   Note that some archs have this as a field in the opcode table.  */
57
static unsigned long *shmedia_opcode_mask_table;
58
 
59
/* Initialize the SH64 opcode mask table for each instruction in SHmedia
60
   mode.  */
61
 
62
static void
63
initialize_shmedia_opcode_mask_table (void)
64
{
65
  int n_opc;
66
  int n;
67
 
68
  /* Calculate number of opcodes.  */
69
  for (n_opc = 0; shmedia_table[n_opc].name != NULL; n_opc++)
70
    ;
71
 
72
  shmedia_opcode_mask_table
73
    = xmalloc (sizeof (shmedia_opcode_mask_table[0]) * n_opc);
74
 
75
  for (n = 0; n < n_opc; n++)
76
    {
77
      int i;
78
 
79
      unsigned long mask = 0;
80
 
81
      for (i = 0; shmedia_table[n].arg[i] != A_NONE; i++)
82
        {
83
          int offset = shmedia_table[n].nibbles[i];
84
          int length;
85
 
86
          switch (shmedia_table[n].arg[i])
87
            {
88
            case A_GREG_M:
89
            case A_GREG_N:
90
            case A_GREG_D:
91
            case A_CREG_K:
92
            case A_CREG_J:
93
            case A_FREG_G:
94
            case A_FREG_H:
95
            case A_FREG_F:
96
            case A_DREG_G:
97
            case A_DREG_H:
98
            case A_DREG_F:
99
            case A_FMREG_G:
100
            case A_FMREG_H:
101
            case A_FMREG_F:
102
            case A_FPREG_G:
103
            case A_FPREG_H:
104
            case A_FPREG_F:
105
            case A_FVREG_G:
106
            case A_FVREG_H:
107
            case A_FVREG_F:
108
            case A_REUSE_PREV:
109
              length = 6;
110
              break;
111
 
112
            case A_TREG_A:
113
            case A_TREG_B:
114
              length = 3;
115
              break;
116
 
117
            case A_IMMM:
118
              abort ();
119
              break;
120
 
121
            case A_IMMU5:
122
              length = 5;
123
              break;
124
 
125
            case A_IMMS6:
126
            case A_IMMU6:
127
            case A_IMMS6BY32:
128
              length = 6;
129
              break;
130
 
131
            case A_IMMS10:
132
            case A_IMMS10BY1:
133
            case A_IMMS10BY2:
134
            case A_IMMS10BY4:
135
            case A_IMMS10BY8:
136
              length = 10;
137
              break;
138
 
139
            case A_IMMU16:
140
            case A_IMMS16:
141
            case A_PCIMMS16BY4:
142
            case A_PCIMMS16BY4_PT:
143
              length = 16;
144
              break;
145
 
146
            default:
147
              abort ();
148
              length = 0;
149
              break;
150
            }
151
 
152
          if (length != 0)
153
            mask |= (0xffffffff >> (32 - length)) << offset;
154
        }
155
      shmedia_opcode_mask_table[n] = 0xffffffff & ~mask;
156
    }
157
}
158
 
159
/* Get a predefined control-register-name, or return NULL.  */
160
 
161
static const char *
162
creg_name (int cregno)
163
{
164
  const shmedia_creg_info *cregp;
165
 
166
  /* If control register usage is common enough, change this to search a
167
     hash-table.  */
168
  for (cregp = shmedia_creg_table; cregp->name != NULL; cregp++)
169
    if (cregp->cregno == cregno)
170
      return cregp->name;
171
 
172
  return NULL;
173
}
174
 
175
/* Main function to disassemble SHmedia instructions.  */
176
 
177
static int
178
print_insn_shmedia (bfd_vma memaddr, struct disassemble_info *info)
179
{
180
  fprintf_ftype fprintf_fn = info->fprintf_func;
181
  void *stream = info->stream;
182
  unsigned char insn[4];
183
  unsigned long instruction;
184
  int status;
185
  int n;
186
  const shmedia_opcode_info *op;
187
  int i;
188
  unsigned int r = 0;
189
  long imm = 0;
190
  bfd_vma disp_pc_addr;
191
 
192
  status = info->read_memory_func (memaddr, insn, 4, info);
193
 
194
  /* If we can't read four bytes, something is wrong.  Display any data we
195
     can get as .byte:s.  */
196
  if (status != 0)
197
    {
198
      int i;
199
 
200
      for (i = 0; i < 3; i++)
201
        {
202
          status = info->read_memory_func (memaddr + i, insn, 1, info);
203
          if (status != 0)
204
            break;
205
          (*fprintf_fn) (stream, "%s0x%02x",
206
                         i == 0 ? ".byte " : ", ",
207
                         insn[0]);
208
        }
209
 
210
      return i ? i : -1;
211
    }
212
 
213
  /* Rearrange the bytes to make up an instruction.  */
214
  if (info->endian == BFD_ENDIAN_LITTLE)
215
    instruction = bfd_getl32 (insn);
216
  else
217
    instruction = bfd_getb32 (insn);
218
 
219
  /* FIXME: Searching could be implemented using a hash on relevant
220
     fields.  */
221
  for (n = 0, op = shmedia_table;
222
       op->name != NULL
223
       && ((instruction & shmedia_opcode_mask_table[n]) != op->opcode_base);
224
       n++, op++)
225
    ;
226
 
227
  /* FIXME: We should also check register number constraints.  */
228
  if (op->name == NULL)
229
    {
230
      fprintf_fn (stream, ".long 0x%08lx", instruction);
231
      return 4;
232
    }
233
 
234
  fprintf_fn (stream, "%s\t", op->name);
235
 
236
  for (i = 0; i < 3 && op->arg[i] != A_NONE; i++)
237
    {
238
      unsigned long temp = instruction >> op->nibbles[i];
239
      int by_number = 0;
240
 
241
      if (i > 0 && op->arg[i] != A_REUSE_PREV)
242
        fprintf_fn (stream, ",");
243
 
244
      switch (op->arg[i])
245
        {
246
        case A_REUSE_PREV:
247
          continue;
248
 
249
        case A_GREG_M:
250
        case A_GREG_N:
251
        case A_GREG_D:
252
          r = temp & 0x3f;
253
          fprintf_fn (stream, "r%d", r);
254
          break;
255
 
256
        case A_FVREG_F:
257
        case A_FVREG_G:
258
        case A_FVREG_H:
259
          r = temp & 0x3f;
260
          fprintf_fn (stream, "fv%d", r);
261
          break;
262
 
263
        case A_FPREG_F:
264
        case A_FPREG_G:
265
        case A_FPREG_H:
266
          r = temp & 0x3f;
267
          fprintf_fn (stream, "fp%d", r);
268
          break;
269
 
270
        case A_FMREG_F:
271
        case A_FMREG_G:
272
        case A_FMREG_H:
273
          r = temp & 0x3f;
274
          fprintf_fn (stream, "mtrx%d", r);
275
          break;
276
 
277
        case A_CREG_K:
278
        case A_CREG_J:
279
          {
280
            const char *name;
281
 
282
            r = temp & 0x3f;
283
 
284
            name = creg_name (r);
285
 
286
            if (name != NULL)
287
              fprintf_fn (stream, "%s", name);
288
            else
289
              fprintf_fn (stream, "cr%d", r);
290
          }
291
          break;
292
 
293
        case A_FREG_G:
294
        case A_FREG_H:
295
        case A_FREG_F:
296
          r = temp & 0x3f;
297
          fprintf_fn (stream, "fr%d", r);
298
          break;
299
 
300
        case A_DREG_G:
301
        case A_DREG_H:
302
        case A_DREG_F:
303
          r = temp & 0x3f;
304
          fprintf_fn (stream, "dr%d", r);
305
          break;
306
 
307
        case A_TREG_A:
308
        case A_TREG_B:
309
          r = temp & 0x7;
310
          fprintf_fn (stream, "tr%d", r);
311
          break;
312
 
313
          /* A signed 6-bit number.  */
314
        case A_IMMS6:
315
          imm = temp & 0x3f;
316
          if (imm & (unsigned long) 0x20)
317
            imm |= ~(unsigned long) 0x3f;
318
          fprintf_fn (stream, "%ld", imm);
319
          break;
320
 
321
          /* A signed 6-bit number, multiplied by 32 when used.  */
322
        case A_IMMS6BY32:
323
          imm = temp & 0x3f;
324
          if (imm & (unsigned long) 0x20)
325
            imm |= ~(unsigned long) 0x3f;
326
          fprintf_fn (stream, "%ld", imm * 32);
327
          break;
328
 
329
          /* A signed 10-bit number, multiplied by 8 when used.  */
330
        case A_IMMS10BY8:
331
          by_number++;
332
          /* Fall through.  */
333
 
334
          /* A signed 10-bit number, multiplied by 4 when used.  */
335
        case A_IMMS10BY4:
336
          by_number++;
337
          /* Fall through.  */
338
 
339
          /* A signed 10-bit number, multiplied by 2 when used.  */
340
        case A_IMMS10BY2:
341
          by_number++;
342
          /* Fall through.  */
343
 
344
          /* A signed 10-bit number.  */
345
        case A_IMMS10:
346
        case A_IMMS10BY1:
347
          imm = temp & 0x3ff;
348
          if (imm & (unsigned long) 0x200)
349
            imm |= ~(unsigned long) 0x3ff;
350
          imm <<= by_number;
351
          fprintf_fn (stream, "%ld", imm);
352
          break;
353
 
354
          /* A signed 16-bit number.  */
355
        case A_IMMS16:
356
          imm = temp & 0xffff;
357
          if (imm & (unsigned long) 0x8000)
358
            imm |= ~((unsigned long) 0xffff);
359
          fprintf_fn (stream, "%ld", imm);
360
          break;
361
 
362
          /* A PC-relative signed 16-bit number, multiplied by 4 when
363
             used.  */
364
        case A_PCIMMS16BY4:
365
          imm = temp & 0xffff;  /* 16 bits */
366
          if (imm & (unsigned long) 0x8000)
367
            imm |= ~(unsigned long) 0xffff;
368
          imm <<= 2;
369
          disp_pc_addr = (bfd_vma) imm + memaddr;
370
          (*info->print_address_func) (disp_pc_addr, info);
371
          break;
372
 
373
          /* An unsigned 5-bit number.  */
374
        case A_IMMU5:
375
          imm = temp & 0x1f;
376
          fprintf_fn (stream, "%ld", imm);
377
          break;
378
 
379
          /* An unsigned 6-bit number.  */
380
        case A_IMMU6:
381
          imm = temp & 0x3f;
382
          fprintf_fn (stream, "%ld", imm);
383
          break;
384
 
385
          /* An unsigned 16-bit number.  */
386
        case A_IMMU16:
387
          imm = temp & 0xffff;
388
          fprintf_fn (stream, "%ld", imm);
389
          break;
390
 
391
        default:
392
          abort ();
393
          break;
394
        }
395
    }
396
 
397
  /* FIXME: Looks like 32-bit values only are handled.
398
     FIXME: PC-relative numbers aren't handled correctly.  */
399
  if (op->opcode_base == (unsigned long) SHMEDIA_SHORI_OPC
400
      && SAVED_MOVI_R (info) == r)
401
    {
402
      asection *section = info->section;
403
 
404
      /* Most callers do not set the section field correctly yet.  Revert
405
         to getting the section from symbols, if any. */
406
      if (section == NULL
407
          && info->symbols != NULL
408
          && bfd_asymbol_flavour (info->symbols[0]) == bfd_target_elf_flavour
409
          && ! bfd_is_und_section (bfd_get_section (info->symbols[0]))
410
          && ! bfd_is_abs_section (bfd_get_section (info->symbols[0])))
411
        section = bfd_get_section (info->symbols[0]);
412
 
413
      /* Only guess addresses when the contents of this section is fully
414
         relocated.  Otherwise, the value will be zero or perhaps even
415
         bogus.  */
416
      if (section == NULL
417
          || section->owner == NULL
418
          || elf_elfheader (section->owner)->e_type == ET_EXEC)
419
        {
420
          bfd_signed_vma shori_addr;
421
 
422
          shori_addr = SAVED_MOVI_IMM (info) << 16;
423
          shori_addr |= imm;
424
 
425
          fprintf_fn (stream, "\t! 0x");
426
          (*info->print_address_func) (shori_addr, info);
427
        }
428
    }
429
 
430
  if (op->opcode_base == SHMEDIA_MOVI_OPC)
431
    {
432
      SAVED_MOVI_IMM (info) = imm;
433
      SAVED_MOVI_R (info) = r;
434
    }
435
  else
436
    {
437
      SAVED_MOVI_IMM (info) = 0;
438
      SAVED_MOVI_R (info) = 255;
439
    }
440
 
441
  return 4;
442
}
443
 
444
/* Check the type of contents about to be disassembled.  This is like
445
   sh64_get_contents_type (which may be called from here), except that it
446
   takes the same arguments as print_insn_* and does what can be done if
447
   no section is available.  */
448
 
449
static enum sh64_elf_cr_type
450
sh64_get_contents_type_disasm (bfd_vma memaddr, struct disassemble_info *info)
451
{
452
  struct sh64_disassemble_info *sh64_infop = info->private_data;
453
 
454
  /* Perhaps we have a region from a previous probe and it still counts
455
     for this address?  */
456
  if (sh64_infop->crange.cr_type != CRT_NONE
457
      && memaddr >= sh64_infop->crange.cr_addr
458
      && memaddr < sh64_infop->crange.cr_addr + sh64_infop->crange.cr_size)
459
    return sh64_infop->crange.cr_type;
460
 
461
  /* If we have a section, try and use it.  */
462
  if (info->section
463
      && bfd_get_flavour (info->section->owner) == bfd_target_elf_flavour)
464
    {
465
      enum sh64_elf_cr_type cr_type
466
        = sh64_get_contents_type (info->section, memaddr,
467
                                  &sh64_infop->crange);
468
 
469
      if (cr_type != CRT_NONE)
470
        return cr_type;
471
    }
472
 
473
  /* If we have symbols, we can try and get at a section from *that*.  */
474
  if (info->symbols != NULL
475
      && bfd_asymbol_flavour (info->symbols[0]) == bfd_target_elf_flavour
476
      && ! bfd_is_und_section (bfd_get_section (info->symbols[0]))
477
      && ! bfd_is_abs_section (bfd_get_section (info->symbols[0])))
478
    {
479
      enum sh64_elf_cr_type cr_type
480
        = sh64_get_contents_type (bfd_get_section (info->symbols[0]),
481
                                  memaddr, &sh64_infop->crange);
482
 
483
      if (cr_type != CRT_NONE)
484
        return cr_type;
485
    }
486
 
487
  /* We can make a reasonable guess based on the st_other field of a
488
     symbol; for a BranchTarget this is marked as STO_SH5_ISA32 and then
489
     it's most probably code there.  */
490
  if (info->symbols
491
      && bfd_asymbol_flavour (info->symbols[0]) == bfd_target_elf_flavour
492
      && elf_symbol_from (bfd_asymbol_bfd (info->symbols[0]),
493
                          info->symbols[0])->internal_elf_sym.st_other
494
      == STO_SH5_ISA32)
495
    return CRT_SH5_ISA32;
496
 
497
  /* If all else fails, guess this is code and guess on the low bit set.  */
498
  return (memaddr & 1) == 1 ? CRT_SH5_ISA32 : CRT_SH5_ISA16;
499
}
500
 
501
/* Initialize static and dynamic disassembly state.  */
502
 
503
static bfd_boolean
504
init_sh64_disasm_info (struct disassemble_info *info)
505
{
506
  struct sh64_disassemble_info *sh64_infop
507
    = calloc (sizeof (*sh64_infop), 1);
508
 
509
  if (sh64_infop == NULL)
510
    return FALSE;
511
 
512
  info->private_data = sh64_infop;
513
 
514
  SAVED_MOVI_IMM (info) = 0;
515
  SAVED_MOVI_R (info) = 255;
516
 
517
  if (shmedia_opcode_mask_table == NULL)
518
    initialize_shmedia_opcode_mask_table ();
519
 
520
  return TRUE;
521
}
522
 
523
/* Main entry to disassemble SHmedia instructions, given an endian set in
524
   INFO.  Note that the simulator uses this as the main entry and does not
525
   use any of the functions further below.  */
526
 
527
int
528
print_insn_sh64x_media (bfd_vma memaddr, struct disassemble_info *info)
529
{
530
  if (info->private_data == NULL && ! init_sh64_disasm_info (info))
531
    return -1;
532
 
533
  /* Make reasonable output.  */
534
  info->bytes_per_line = 4;
535
  info->bytes_per_chunk = 4;
536
 
537
  return print_insn_shmedia (memaddr, info);
538
}
539
 
540
/* Main entry to disassemble SHmedia insns.
541
   If we see an SHcompact instruction, return -2.  */
542
 
543
int
544
print_insn_sh64 (bfd_vma memaddr, struct disassemble_info *info)
545
{
546
  enum bfd_endian endian = info->endian;
547
  enum sh64_elf_cr_type cr_type;
548
 
549
  if (info->private_data == NULL && ! init_sh64_disasm_info (info))
550
    return -1;
551
 
552
  cr_type = sh64_get_contents_type_disasm (memaddr, info);
553
  if (cr_type != CRT_SH5_ISA16)
554
    {
555
      int length = 4 - (memaddr % 4);
556
      info->display_endian = endian;
557
 
558
      /* If we got an uneven address to indicate SHmedia, adjust it.  */
559
      if (cr_type == CRT_SH5_ISA32 && length == 3)
560
        memaddr--, length = 4;
561
 
562
      /* Only disassemble on four-byte boundaries.  Addresses that are not
563
         a multiple of four can happen after a data region.  */
564
      if (cr_type == CRT_SH5_ISA32 && length == 4)
565
        return print_insn_sh64x_media (memaddr, info);
566
 
567
      /* We get CRT_DATA *only* for data regions in a mixed-contents
568
         section.  For sections with data only, we get indication of one
569
         of the ISA:s.  You may think that we shouldn't disassemble
570
         section with only data if we can figure that out.  However, the
571
         disassembly function is by default not called for data-only
572
         sections, so if the user explicitly specified disassembly of a
573
         data section, that's what we should do.  */
574
      if (cr_type == CRT_DATA || length != 4)
575
        {
576
          int status;
577
          unsigned char data[4];
578
          struct sh64_disassemble_info *sh64_infop = info->private_data;
579
 
580
          if (length == 4
581
              && sh64_infop->crange.cr_type != CRT_NONE
582
              && memaddr >= sh64_infop->crange.cr_addr
583
              && memaddr < (sh64_infop->crange.cr_addr
584
                            + sh64_infop->crange.cr_size))
585
            length
586
              = (sh64_infop->crange.cr_addr
587
                 + sh64_infop->crange.cr_size - memaddr);
588
 
589
          status
590
            = (*info->read_memory_func) (memaddr, data,
591
                                         length >= 4 ? 4 : length, info);
592
 
593
          if (status == 0 && length >= 4)
594
            {
595
              (*info->fprintf_func) (info->stream, ".long 0x%08lx",
596
                                     endian == BFD_ENDIAN_BIG
597
                                     ? (long) (bfd_getb32 (data))
598
                                     : (long) (bfd_getl32 (data)));
599
              return 4;
600
            }
601
          else
602
            {
603
              int i;
604
 
605
              for (i = 0; i < length; i++)
606
                {
607
                  status = info->read_memory_func (memaddr + i, data, 1, info);
608
                  if (status != 0)
609
                    break;
610
                  (*info->fprintf_func) (info->stream, "%s0x%02x",
611
                                         i == 0 ? ".byte " : ", ",
612
                                         data[0]);
613
                }
614
 
615
              return i ? i : -1;
616
            }
617
        }
618
    }
619
 
620
  /* SH1 .. SH4 instruction, let caller handle it.  */
621
  return -2;
622
}

powered by: WebSVN 2.1.0

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