1
/* Disassemble SH64 instructions.
2
Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
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.
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.
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. */
23
#include "libiberty.h"
25
/* We need to refer to the ELF header structure. */
28
#include "elf32-sh64.h"
30
#define ELF_MODE32_CODE_LABEL_P(SYM) \
31
(((elf_symbol_type *) (SYM))->internal_elf_sym.st_other & STO_SH5_ISA32)
33
#define SAVED_MOVI_R(INFO) \
34
(((struct sh64_disassemble_info *) ((INFO)->private_data))->address_reg)
36
#define SAVED_MOVI_IMM(INFO) \
37
(((struct sh64_disassemble_info *) ((INFO)->private_data))->built_address)
39
struct sh64_disassemble_info
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;
46
/* This is the range decriptor for the current address. It is kept
47
around for the next call. */
48
sh64_elf_crange crange;
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;
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 *));
64
/* Initialize the SH64 opcode mask table for each instruction in SHmedia
68
initialize_shmedia_opcode_mask_table ()
73
/* Calculate number of opcodes. */
74
for (n_opc = 0; shmedia_table[n_opc].name != NULL; n_opc++)
77
shmedia_opcode_mask_table
78
= xmalloc (sizeof (shmedia_opcode_mask_table[0]) * n_opc);
80
for (n = 0; n < n_opc; n++)
84
unsigned long mask = 0;
86
for (i = 0; shmedia_table[n].arg[i] != A_NONE; i++)
88
int offset = shmedia_table[n].nibbles[i];
91
switch (shmedia_table[n].arg[i])
147
case A_PCIMMS16BY4_PT:
158
mask |= (0xffffffff >> (32 - length)) << offset;
160
shmedia_opcode_mask_table[n] = 0xffffffff & ~mask;
164
/* Get a predefined control-register-name, or return NULL. */
170
const shmedia_creg_info *cregp;
172
/* If control register usage is common enough, change this to search a
174
for (cregp = shmedia_creg_table; cregp->name != NULL; cregp++)
176
if (cregp->cregno == cregno)
183
/* Main function to disassemble SHmedia instructions. */
186
print_insn_shmedia (memaddr, info)
188
struct disassemble_info *info;
190
fprintf_ftype fprintf_fn = info->fprintf_func;
191
void *stream = info->stream;
193
unsigned char insn[4];
194
unsigned long instruction;
197
const shmedia_opcode_info *op;
201
bfd_vma disp_pc_addr;
203
status = info->read_memory_func (memaddr, insn, 4, info);
205
/* If we can't read four bytes, something is wrong. Display any data we
206
can get as .byte:s. */
211
for (i = 0; i < 3; i++)
213
status = info->read_memory_func (memaddr + i, insn, 1, info);
216
(*fprintf_fn) (stream, "%s0x%02x",
217
i == 0 ? ".byte " : ", ",
224
/* Rearrange the bytes to make up an instruction. */
225
if (info->endian == BFD_ENDIAN_LITTLE)
226
instruction = bfd_getl32 (insn);
228
instruction = bfd_getb32 (insn);
230
/* FIXME: Searching could be implemented using a hash on relevant
232
for (n = 0, op = shmedia_table;
234
&& ((instruction & shmedia_opcode_mask_table[n]) != op->opcode_base);
238
/* FIXME: We should also check register number constraints. */
239
if (op->name == NULL)
241
fprintf_fn (stream, ".long 0x%08x", instruction);
245
fprintf_fn (stream, "%s\t", op->name);
247
for (i = 0; i < 3 && op->arg[i] != A_NONE; i++)
249
unsigned long temp = instruction >> op->nibbles[i];
252
if (i > 0 && op->arg[i] != A_REUSE_PREV)
253
fprintf_fn (stream, ",");
264
fprintf_fn (stream, "r%d", r);
271
fprintf_fn (stream, "fv%d", r);
278
fprintf_fn (stream, "fp%d", r);
285
fprintf_fn (stream, "mtrx%d", r);
294
name = creg_name (r);
297
fprintf_fn (stream, "%s", name);
299
fprintf_fn (stream, "cr%d", r);
307
fprintf_fn (stream, "fr%d", r);
314
fprintf_fn (stream, "dr%d", r);
320
fprintf_fn (stream, "tr%d", r);
323
/* A signed 6-bit number. */
326
if (imm & (unsigned long) 0x20)
327
imm |= ~(unsigned long) 0x3f;
328
fprintf_fn (stream, "%d", imm);
331
/* A signed 6-bit number, multiplied by 32 when used. */
334
if (imm & (unsigned long) 0x20)
335
imm |= ~(unsigned long) 0x3f;
336
fprintf_fn (stream, "%d", imm * 32);
339
/* A signed 10-bit number, multiplied by 8 when used. */
344
/* A signed 10-bit number, multiplied by 4 when used. */
349
/* A signed 10-bit number, multiplied by 2 when used. */
354
/* A signed 10-bit number. */
358
if (imm & (unsigned long) 0x200)
359
imm |= ~(unsigned long) 0x3ff;
361
fprintf_fn (stream, "%d", imm);
364
/* A signed 16-bit number. */
367
if (imm & (unsigned long) 0x8000)
368
imm |= ~((unsigned long) 0xffff);
369
fprintf_fn (stream, "%d", imm);
372
/* A PC-relative signed 16-bit number, multiplied by 4 when
375
imm = temp & 0xffff; /* 16 bits */
376
if (imm & (unsigned long) 0x8000)
377
imm |= ~(unsigned long) 0xffff;
379
disp_pc_addr = (bfd_vma) imm + memaddr;
380
(*info->print_address_func) (disp_pc_addr, info);
383
/* An unsigned 5-bit number. */
386
fprintf_fn (stream, "%d", imm);
389
/* An unsigned 6-bit number. */
392
fprintf_fn (stream, "%d", imm);
395
/* An unsigned 16-bit number. */
398
fprintf_fn (stream, "%d", imm);
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)
412
asection *section = info->section;
414
/* Most callers do not set the section field correctly yet. Revert
415
to getting the section from symbols, if any. */
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]);
423
/* Only guess addresses when the contents of this section is fully
424
relocated. Otherwise, the value will be zero or perhaps even
427
|| section->owner == NULL
428
|| elf_elfheader (section->owner)->e_type == ET_EXEC)
430
bfd_signed_vma shori_addr;
432
shori_addr = SAVED_MOVI_IMM (info) << 16;
435
fprintf_fn (stream, "\t! 0x");
436
(*info->print_address_func) (shori_addr, info);
440
if (op->opcode_base == SHMEDIA_MOVI_OPC)
442
SAVED_MOVI_IMM (info) = imm;
443
SAVED_MOVI_R (info) = r;
447
SAVED_MOVI_IMM (info) = 0;
448
SAVED_MOVI_R (info) = 255;
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. */
459
static enum sh64_elf_cr_type
460
sh64_get_contents_type_disasm (memaddr, info)
462
struct disassemble_info *info;
464
struct sh64_disassemble_info *sh64_infop = info->private_data;
466
/* Perhaps we have a region from a previous probe and it still counts
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;
473
/* If we have a section, try and use it. */
475
&& bfd_get_flavour (info->section->owner) == bfd_target_elf_flavour)
477
enum sh64_elf_cr_type cr_type
478
= sh64_get_contents_type (info->section, memaddr,
479
&sh64_infop->crange);
481
if (cr_type != CRT_NONE)
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])))
491
enum sh64_elf_cr_type cr_type
492
= sh64_get_contents_type (bfd_get_section (info->symbols[0]),
493
memaddr, &sh64_infop->crange);
495
if (cr_type != CRT_NONE)
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. */
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
507
return CRT_SH5_ISA32;
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;
513
/* Initialize static and dynamic disassembly state. */
516
init_sh64_disasm_info (info)
517
struct disassemble_info *info;
519
struct sh64_disassemble_info *sh64_infop
520
= calloc (sizeof (*sh64_infop), 1);
522
if (sh64_infop == NULL)
525
info->private_data = sh64_infop;
527
SAVED_MOVI_IMM (info) = 0;
528
SAVED_MOVI_R (info) = 255;
530
if (shmedia_opcode_mask_table == NULL)
531
initialize_shmedia_opcode_mask_table ();
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. */
541
print_insn_sh64x_media (memaddr, info)
543
struct disassemble_info *info;
545
if (info->private_data == NULL && ! init_sh64_disasm_info (info))
548
/* Make reasonable output. */
549
info->bytes_per_line = 4;
550
info->bytes_per_chunk = 4;
552
return print_insn_shmedia (memaddr, info);
555
/* Main entry to disassemble SHmedia insns.
556
If we see an SHcompact instruction, return -2. */
559
print_insn_sh64 (memaddr, info)
561
struct disassemble_info *info;
563
enum bfd_endian endian = info->endian;
564
enum sh64_elf_cr_type cr_type;
566
if (info->private_data == NULL && ! init_sh64_disasm_info (info))
569
cr_type = sh64_get_contents_type_disasm (memaddr, info);
570
if (cr_type != CRT_SH5_ISA16)
572
int length = 4 - (memaddr % 4);
573
info->display_endian = endian;
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;
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);
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)
594
unsigned char data[4];
595
struct sh64_disassemble_info *sh64_infop = info->private_data;
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))
603
= (sh64_infop->crange.cr_addr
604
+ sh64_infop->crange.cr_size - memaddr);
607
= (*info->read_memory_func) (memaddr, data,
608
length >= 4 ? 4 : length, info);
610
if (status == 0 && length >= 4)
612
(*info->fprintf_func) (info->stream, ".long 0x%08lx",
613
endian == BFD_ENDIAN_BIG
614
? (long) (bfd_getb32 (data))
615
: (long) (bfd_getl32 (data)));
622
for (i = 0; i < length; i++)
624
status = info->read_memory_func (memaddr + i, data, 1, info);
627
(*info->fprintf_func) (info->stream, "%s0x%02x",
628
i == 0 ? ".byte " : ", ",
637
/* SH1 .. SH4 instruction, let caller handle it. */