~ubuntu-branches/ubuntu/hoary/binutils/hoary

« back to all changes in this revision

Viewing changes to opcodes/sh64-dis.c

  • Committer: Bazaar Package Importer
  • Author(s): James Troup
  • Date: 2004-05-19 10:35:44 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040519103544-17h3o6e8pwndydrg
Tags: 2.14.90.0.7-8
debian/rules: don't use gcc-2.95 on m68k.  Thanks to Adam Conrad for
pointing this out.

Show diffs side-by-side

added added

removed removed

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