1 /* Disassemble SH64 instructions.
2 Copyright (C) 2000, 2001 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. */
29 #define ELF_MODE32_CODE_LABEL_P(SYM) \
30 (((elf_symbol_type *) (SYM))->internal_elf_sym.st_other & STO_SH5_ISA32)
32 #define SAVED_MOVI_R(INFO) \
33 (((struct sh64_disassemble_info *) ((INFO)->private_data))->address_reg)
35 #define SAVED_MOVI_IMM(INFO) \
36 (((struct sh64_disassemble_info *) ((INFO)->private_data))->built_address)
38 struct sh64_disassemble_info
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;
45 /* This is the range decriptor for the current address. It is kept
46 around for the next call. */
47 sh64_elf_crange crange;
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;
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 *));
63 /* Initialize the SH64 opcode mask table for each instruction in SHmedia
67 initialize_shmedia_opcode_mask_table ()
72 /* Calculate number of opcodes. */
73 for (n_opc = 0; shmedia_table[n_opc].name != NULL; n_opc++)
76 shmedia_opcode_mask_table
77 = xmalloc (sizeof (shmedia_opcode_mask_table[0]) * n_opc);
79 for (n = 0; n < n_opc; n++)
83 unsigned long mask = 0;
85 for (i = 0; shmedia_table[n].arg[i] != A_NONE; i++)
87 int offset = shmedia_table[n].nibbles[i];
90 switch (shmedia_table[n].arg[i])
146 case A_PCIMMS16BY4_PT:
157 mask |= (0xffffffff >> (32 - length)) << offset;
159 shmedia_opcode_mask_table[n] = 0xffffffff & ~mask;
163 /* Get a predefined control-register-name, or return NULL. */
169 const shmedia_creg_info *cregp;
171 /* If control register usage is common enough, change this to search a
173 for (cregp = shmedia_creg_table; cregp->name != NULL; cregp++)
175 if (cregp->cregno == cregno)
182 /* Main function to disassemble SHmedia instructions. */
185 print_insn_shmedia (memaddr, info)
187 struct disassemble_info *info;
189 fprintf_ftype fprintf_fn = info->fprintf_func;
190 void *stream = info->stream;
192 unsigned char insn[4];
193 unsigned long instruction;
196 const shmedia_opcode_info *op;
200 bfd_vma disp_pc_addr;
202 status = info->read_memory_func (memaddr, insn, 4, info);
204 /* If we can't read four bytes, something is wrong. Display any data we
205 can get as .byte:s. */
210 for (i = 0; i < 3; i++)
212 status = info->read_memory_func (memaddr + i, insn, 1, info);
215 (*fprintf_fn) (stream, "%s0x%02x",
216 i == 0 ? ".byte " : ", ",
223 /* Rearrange the bytes to make up an instruction. */
224 if (info->endian == BFD_ENDIAN_LITTLE)
225 instruction = bfd_getl32 (insn);
227 instruction = bfd_getb32 (insn);
229 /* FIXME: Searching could be implemented using a hash on relevant
231 for (n = 0, op = shmedia_table;
233 && ((instruction & shmedia_opcode_mask_table[n]) != op->opcode_base);
237 /* FIXME: We should also check register number constraints. */
238 if (op->name == NULL)
240 fprintf_fn (stream, ".long 0x%08x", instruction);
244 fprintf_fn (stream, "%s\t", op->name);
246 for (i = 0; i < 3 && op->arg[i] != A_NONE; i++)
248 unsigned long temp = instruction >> op->nibbles[i];
251 if (i > 0 && op->arg[i] != A_REUSE_PREV)
252 fprintf_fn (stream, ",");
263 fprintf_fn (stream, "r%d", r);
270 fprintf_fn (stream, "fv%d", r);
277 fprintf_fn (stream, "fp%d", r);
284 fprintf_fn (stream, "mtrx%d", r);
293 name = creg_name (r);
296 fprintf_fn (stream, "%s", name);
298 fprintf_fn (stream, "cr%d", r);
306 fprintf_fn (stream, "fr%d", r);
313 fprintf_fn (stream, "dr%d", r);
319 fprintf_fn (stream, "tr%d", r);
322 /* A signed 6-bit number. */
325 if (imm & (unsigned long) 0x20)
326 imm |= ~(unsigned long) 0x3f;
327 fprintf_fn (stream, "%d", imm);
330 /* A signed 6-bit number, multiplied by 32 when used. */
333 if (imm & (unsigned long) 0x20)
334 imm |= ~(unsigned long) 0x3f;
335 fprintf_fn (stream, "%d", imm * 32);
338 /* A signed 10-bit number, multiplied by 8 when used. */
343 /* A signed 10-bit number, multiplied by 4 when used. */
348 /* A signed 10-bit number, multiplied by 2 when used. */
353 /* A signed 10-bit number. */
357 if (imm & (unsigned long) 0x200)
358 imm |= ~(unsigned long) 0x3ff;
360 fprintf_fn (stream, "%d", imm);
363 /* A signed 16-bit number. */
366 if (imm & (unsigned long) 0x8000)
367 imm |= ~((unsigned long) 0xffff);
368 fprintf_fn (stream, "%d", imm);
371 /* A PC-relative signed 16-bit number, multiplied by 4 when
374 imm = temp & 0xffff; /* 16 bits */
375 if (imm & (unsigned long) 0x8000)
376 imm |= ~(unsigned long) 0xffff;
378 disp_pc_addr = (bfd_vma) imm + memaddr;
379 (*info->print_address_func) (disp_pc_addr, info);
382 /* An unsigned 5-bit number. */
385 fprintf_fn (stream, "%d", imm);
388 /* An unsigned 6-bit number. */
391 fprintf_fn (stream, "%d", imm);
394 /* An unsigned 16-bit number. */
397 fprintf_fn (stream, "%d", imm);
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)
411 asection *section = info->section;
413 /* Most callers do not set the section field correctly yet. Revert
414 to getting the section from symbols, if any. */
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]);
422 /* Only guess addresses when the contents of this section is fully
423 relocated. Otherwise, the value will be zero or perhaps even
426 || section->owner == NULL
427 || elf_elfheader (section->owner)->e_type == ET_EXEC)
429 bfd_signed_vma shori_addr;
431 shori_addr = SAVED_MOVI_IMM (info) << 16;
434 fprintf_fn (stream, "\t! 0x");
435 (*info->print_address_func) (shori_addr, info);
439 if (op->opcode_base == SHMEDIA_MOVI_OPC)
441 SAVED_MOVI_IMM (info) = imm;
442 SAVED_MOVI_R (info) = r;
446 SAVED_MOVI_IMM (info) = 0;
447 SAVED_MOVI_R (info) = 255;
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. */
458 static enum sh64_elf_cr_type
459 sh64_get_contents_type_disasm (memaddr, info)
461 struct disassemble_info *info;
463 struct sh64_disassemble_info *sh64_infop = info->private_data;
465 /* Perhaps we have a region from a previous probe and it still counts
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;
472 /* If we have a section, try and use it. */
474 && bfd_get_flavour (info->section->owner) == bfd_target_elf_flavour)
476 enum sh64_elf_cr_type cr_type
477 = sh64_get_contents_type (info->section, memaddr,
478 &sh64_infop->crange);
480 if (cr_type != CRT_NONE)
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])))
490 enum sh64_elf_cr_type cr_type
491 = sh64_get_contents_type (bfd_get_section (info->symbols[0]),
492 memaddr, &sh64_infop->crange);
494 if (cr_type != CRT_NONE)
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. */
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
506 return CRT_SH5_ISA32;
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;
512 /* Initialize static and dynamic disassembly state. */
515 init_sh64_disasm_info (info)
516 struct disassemble_info *info;
518 struct sh64_disassemble_info *sh64_infop
519 = calloc (sizeof (*sh64_infop), 1);
521 if (sh64_infop == NULL)
524 info->private_data = sh64_infop;
526 SAVED_MOVI_IMM (info) = 0;
527 SAVED_MOVI_R (info) = 255;
529 if (shmedia_opcode_mask_table == NULL)
530 initialize_shmedia_opcode_mask_table ();
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. */
540 print_insn_sh64x_media (memaddr, info)
542 struct disassemble_info *info;
544 if (info->private_data == NULL && ! init_sh64_disasm_info (info))
547 /* Make reasonable output. */
548 info->bytes_per_line = 4;
549 info->bytes_per_chunk = 4;
551 return print_insn_shmedia (memaddr, info);
554 /* Main entry to disassemble SHmedia insns.
555 If we see an SHcompact instruction, return -2. */
558 print_insn_sh64 (memaddr, info)
560 struct disassemble_info *info;
562 enum bfd_endian endian = info->endian;
563 enum sh64_elf_cr_type cr_type;
565 if (info->private_data == NULL && ! init_sh64_disasm_info (info))
568 cr_type = sh64_get_contents_type_disasm (memaddr, info);
569 if (cr_type != CRT_SH5_ISA16)
571 int length = 4 - (memaddr % 4);
572 info->display_endian = endian;
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;
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);
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)
593 unsigned char data[4];
594 struct sh64_disassemble_info *sh64_infop = info->private_data;
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))
602 = (sh64_infop->crange.cr_addr
603 + sh64_infop->crange.cr_size - memaddr);
606 = (*info->read_memory_func) (memaddr, data,
607 length >= 4 ? 4 : length, info);
609 if (status == 0 && length >= 4)
611 (*info->fprintf_func) (info->stream, ".long 0x%08lx",
612 endian == BFD_ENDIAN_BIG
613 ? (long) (bfd_getb32 (data))
614 : (long) (bfd_getl32 (data)));
621 for (i = 0; i < length; i++)
623 status = info->read_memory_func (memaddr + i, data, 1, info);
626 (*info->fprintf_func) (info->stream, "%s0x%02x",
627 i == 0 ? ".byte " : ", ",
636 /* SH1 .. SH4 instruction, let caller handle it. */