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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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