summaryrefslogtreecommitdiff
path: root/opcodes/sh-dis.c
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2004-07-29 05:19:27 +0000
committerAlexandre Oliva <aoliva@redhat.com>2004-07-29 05:19:27 +0000
commitb4cd7e841fc9595c7f21dd0b2883c26671ff338b (patch)
treed77208a1ba1445baa662941a53c8dec66d9bad1f /opcodes/sh-dis.c
parent05c67a55938a2c65717bfe77761f1285dfdfca0b (diff)
downloadgdb-b4cd7e841fc9595c7f21dd0b2883c26671ff338b.tar.gz
include/elf/ChangeLog:
Introduce SH2a support. 2004-02-18 Corinna Vinschen <vinschen@redhat.com> * sh.h (EF_SH2A_NOFPU): New. 2003-12-01 Michael Snyder <msnyder@redhat.com> * sh.h (EF_SH2A): New. bfd/ChangeLog: Introduce SH2a support. 2004-02-18 Corinna Vinschen <vinschen@redhat.com> * archures.c (bfd_mach_sh2a_nofpu): New. * bfd-in2.h: Rebuilt. * cpu-sh.c (SH2A_NOFPU_NEXT): New. (arch_info_struct): Add sh2a_nofpu. * elf32-sh.c (sh_elf_set_mach_from_flags): Handle sh2a_nofpu. 2003-12-29 DJ Delorie <dj@redhat.com> * reloc.c: Add relocs for sh2a. * bfd-in2.h: Regenerate. * libbfd.hh: Regenerate. 2003-12-01 Michael Snyder <msnyder@redhat.com> * archures.c (bfd_mach_sh2a): New. * bfd-in2.h: Rebuilt. * cpu-sh.c (SH_NEXT, SH2_NEXT, etc.): Change defines to enums. (SH2A_NEXT): New. (arch_info_struct): Add sh2a. * elf32-sh.c (sh_elf_set_mach_from_flags): Handle sh2a. binutils/ChangeLog: * readelf.c (get_machine_flags <EM_SH>): Handle EF_SH2A and EF_SH2A_NOFPU. gas/ChangeLog: Introduce SH2a support. 2004-02-24 Corinna Vinschen <vinschen@redhat.com> * config/tc-sh.c (get_specific): Change arch_sh2a_up to arch_sh2a_nofpu_up. 2004-02-24 Corinna Vinschen <vinschen@redhat.com> * config/tc-sh.c (md_parse_option): Add sh2a-nofpu ISA handling. 2004-02-20 Corinna Vinschen <vinschen@redhat.com> * config/tc-sh.c (sh_elf_final_processing): Move sh2a recognition to end of conditional expression. 2004-02-20 Corinna Vinschen <vinschen@redhat.com> * config/tc-sh.c: Add sh2a-nofpu support. 2003-12-29 DJ Delorie <dj@redhat.com> * tc-sh.c: Add sh2a support. (parse_reg): Add tbr. (parse_at): Support @@(disp,tbr). (get_specific): Support sh2a opcodes. (insert4): New, for 4 byte relocs. (build_Mytes): Support sh2a opcodes. (md_apply_fix3_Mytes): Support sh2a opcodes. 2003-12-02 Michael Snyder <msnyder@redhat.com> * config/tc-sh.c (md_parse_option): Handle sh2a. (sh_elf_final_processing): Ditto. gas/testsuite/ChangeLog: 2003-12-30 DJ Delorie <dj@redhat.com> * gas/sh/sh2a.s: New. * gas/sh/sh2a.d: New. * gas/sh/basic.exp: Add it. opcodes/ChangeLog: Introduce SH2a support. * sh-opc.h (arch_sh2a_base): Renumber. (arch_sh2a_nofpu_base): Remove. (arch_sh_base_mask): Adjust. (arch_opann_mask): New. (arch_sh2a, arch_sh2a_nofpu): Adjust. (arch_sh2a_up, arch_sh2a_nofpu_up): Likewise. (sh_table): Adjust whitespace. 2004-02-24 Corinna Vinschen <vinschen@redhat.com> * sh-opc.h (arch_sh2a_nofpu_up): New. Use instead of arch_sh2a_up in instruction list throughout. (arch_sh2a_up): Redefine to include fpu instruction set. Use instead of arch_sh2a in instruction list throughout. (arch_sh2e_up): Accomodate above changes. (arch_sh2_up): Ditto. 2004-02-20 Corinna Vinschen <vinschen@redhat.com> * sh-opc.h: Add arch_sh2a_nofpu to arch_sh2_up. 2004-02-18 Corinna Vinschen <vinschen@redhat.com> * sh-dis.c (print_insn_sh): Add bfd_mach_sh2a_nofpu handling. * sh-opc.h (arch_sh2a_nofpu): New. (arch_sh2a_up): New, defines sh2a and sh2a_nofpu. (sh_table): Change all arch_sh2a to arch_sh2a_up unless FPU instruction. 2004-01-20 DJ Delorie <dj@redhat.com> * sh-dis.c (print_insn_sh): SH2A does not have 'X' fp regs. 2003-12-29 DJ Delorie <dj@redhat.com> * sh-opc.c (sh_nibble_type, sh_arg_type, arch_2a, arch_2e_up, sh_opcode_info, sh_table): Add sh2a support. (arch_op32): New, to tag 32-bit opcodes. * sh-dis.c (print_insn_sh): Support sh2a opcodes. 2003-12-02 Michael Snyder <msnyder@redhat.com> * sh-opc.h (arch_sh2a): Add. * sh-dis.c (arch_sh2a): Handle. * sh-opc.h (arch_sh2_up): Fix up to include arch_sh2a.
Diffstat (limited to 'opcodes/sh-dis.c')
-rw-r--r--opcodes/sh-dis.c130
1 files changed, 123 insertions, 7 deletions
diff --git a/opcodes/sh-dis.c b/opcodes/sh-dis.c
index 3ca5130968b..34e84d2940a 100644
--- a/opcodes/sh-dis.c
+++ b/opcodes/sh-dis.c
@@ -390,6 +390,8 @@ print_insn_ppi (field_b, info)
fprintf_fn (stream, ".word 0x%x", field_b);
}
+/* FIXME mvs: movx insns print as ".word 0x%03x", insn & 0xfff
+ (ie. the upper nibble is missing). */
int
print_insn_sh (memaddr, info)
bfd_vma memaddr;
@@ -398,11 +400,12 @@ print_insn_sh (memaddr, info)
fprintf_ftype fprintf_fn = info->fprintf_func;
void *stream = info->stream;
unsigned char insn[4];
- unsigned char nibs[4];
+ unsigned char nibs[8];
int status;
bfd_vma relmask = ~(bfd_vma) 0;
const sh_opcode_info *op;
unsigned int target_arch;
+ int allow_op32;
switch (info->mach)
{
@@ -453,6 +456,30 @@ print_insn_sh (memaddr, info)
nibs[2] = (insn[1] >> 4) & 0xf;
nibs[3] = insn[1] & 0xf;
}
+ status = info->read_memory_func (memaddr + 2, insn + 2, 2, info);
+ if (status != 0)
+ allow_op32 = 0;
+ else
+ {
+ allow_op32 = 1;
+
+ if (info->endian == BFD_ENDIAN_LITTLE)
+ {
+ nibs[4] = (insn[3] >> 4) & 0xf;
+ nibs[5] = insn[3] & 0xf;
+
+ nibs[6] = (insn[2] >> 4) & 0xf;
+ nibs[7] = insn[2] & 0xf;
+ }
+ else
+ {
+ nibs[4] = (insn[2] >> 4) & 0xf;
+ nibs[5] = insn[2] & 0xf;
+
+ nibs[6] = (insn[3] >> 4) & 0xf;
+ nibs[7] = insn[3] & 0xf;
+ }
+ }
if (nibs[0] == 0xf && (nibs[1] & 4) == 0
&& SH_MERGE_ARCH_SET_VALID (target_arch, arch_sh_dsp_up))
@@ -490,10 +517,17 @@ print_insn_sh (memaddr, info)
int rb = 0;
int disp_pc;
bfd_vma disp_pc_addr = 0;
+ int disp = 0;
+ int has_disp = 0;
+ int max_n = SH_MERGE_ARCH_SET (op->arch, arch_op32) ? 8 : 4;
+
+ if (!allow_op32
+ && SH_MERGE_ARCH_SET (op->arch, arch_op32))
+ goto fail;
if (!SH_MERGE_ARCH_SET_VALID (op->arch, target_arch))
goto fail;
- for (n = 0; n < 4; n++)
+ for (n = 0; n < max_n; n++)
{
int i = op->nibbles[n];
@@ -517,6 +551,64 @@ print_insn_sh (memaddr, info)
imm |= ~0xfff;
imm = imm * 2 + 4;
goto ok;
+ case IMM0_3c:
+ if (nibs[3] & 0x8)
+ goto fail;
+ imm = nibs[3] & 0x7;
+ break;
+ case IMM0_3s:
+ if (!(nibs[3] & 0x8))
+ goto fail;
+ imm = nibs[3] & 0x7;
+ break;
+ case IMM0_3Uc:
+ if (nibs[2] & 0x8)
+ goto fail;
+ imm = nibs[2] & 0x7;
+ break;
+ case IMM0_3Us:
+ if (!(nibs[2] & 0x8))
+ goto fail;
+ imm = nibs[2] & 0x7;
+ break;
+ case DISP0_12:
+ case DISP1_12:
+ disp = (nibs[5] << 8) | (nibs[6] << 4) | nibs[7];
+ has_disp = 1;
+ goto ok;
+ case DISP0_12BY2:
+ case DISP1_12BY2:
+ disp = ((nibs[5] << 8) | (nibs[6] << 4) | nibs[7]) << 1;
+ relmask = ~(bfd_vma) 1;
+ has_disp = 1;
+ goto ok;
+ case DISP0_12BY4:
+ case DISP1_12BY4:
+ disp = ((nibs[5] << 8) | (nibs[6] << 4) | nibs[7]) << 2;
+ relmask = ~(bfd_vma) 3;
+ has_disp = 1;
+ goto ok;
+ case DISP0_12BY8:
+ case DISP1_12BY8:
+ disp = ((nibs[5] << 8) | (nibs[6] << 4) | nibs[7]) << 3;
+ relmask = ~(bfd_vma) 7;
+ has_disp = 1;
+ goto ok;
+ case IMM0_20_4:
+ break;
+ case IMM0_20:
+ imm = ((nibs[2] << 16) | (nibs[4] << 12) | (nibs[5] << 8)
+ | (nibs[6] << 4) | nibs[7]);
+ if (imm & 0x80000)
+ imm -= 0x100000;
+ goto ok;
+ case IMM0_20BY8:
+ imm = ((nibs[2] << 16) | (nibs[4] << 12) | (nibs[5] << 8)
+ | (nibs[6] << 4) | nibs[7]);
+ imm <<= 8;
+ if (imm & 0x8000000)
+ imm -= 0x10000000;
+ goto ok;
case IMM0_4:
case IMM1_4:
imm = nibs[3];
@@ -532,6 +624,10 @@ print_insn_sh (memaddr, info)
case IMM0_8:
case IMM1_8:
imm = (nibs[2] << 4) | nibs[3];
+ disp = imm;
+ has_disp = 1;
+ if (imm & 0x80)
+ imm -= 0x100;
goto ok;
case PCRELIMM_8BY2:
imm = ((nibs[2] << 4) | nibs[3]) << 1;
@@ -588,6 +684,14 @@ print_insn_sh (memaddr, info)
}
ok:
+ /* sh2a has D_REG but not X_REG. We don't know the pattern
+ doesn't match unless we check the output args to see if they
+ make sense. */
+ if (target_arch == arch_sh2a
+ && ((op->arg[0] == DX_REG_M && (rm & 1) != 0)
+ || (op->arg[1] == DX_REG_N && (rn & 1) != 0)))
+ goto fail;
+
fprintf_fn (stream, "%s\t", op->name);
disp_pc = 0;
for (n = 0; n < 3 && op->arg[n] != A_END; n++)
@@ -597,7 +701,7 @@ print_insn_sh (memaddr, info)
switch (op->arg[n])
{
case A_IMM:
- fprintf_fn (stream, "#%d", (char) (imm));
+ fprintf_fn (stream, "#%d", imm);
break;
case A_R0:
fprintf_fn (stream, "r0");
@@ -618,7 +722,7 @@ print_insn_sh (memaddr, info)
fprintf_fn (stream, "@r%d", rn);
break;
case A_DISP_REG_N:
- fprintf_fn (stream, "@(%d,r%d)", imm, rn);
+ fprintf_fn (stream, "@(%d,r%d)", has_disp?disp:imm, rn);
break;
case AS_PMOD_N:
fprintf_fn (stream, "@r%d+r8", rn);
@@ -636,7 +740,7 @@ print_insn_sh (memaddr, info)
fprintf_fn (stream, "@r%d", rm);
break;
case A_DISP_REG_M:
- fprintf_fn (stream, "@(%d,r%d)", imm, rm);
+ fprintf_fn (stream, "@(%d,r%d)", has_disp?disp:imm, rm);
break;
case A_REG_B:
fprintf_fn (stream, "r%d_bank", rb);
@@ -653,7 +757,19 @@ print_insn_sh (memaddr, info)
fprintf_fn (stream, "@(r0,r%d)", rm);
break;
case A_DISP_GBR:
- fprintf_fn (stream, "@(%d,gbr)", imm);
+ fprintf_fn (stream, "@(%d,gbr)", has_disp?disp:imm);
+ break;
+ case A_TBR:
+ fprintf_fn (stream, "tbr");
+ break;
+ case A_DISP2_TBR:
+ fprintf_fn (stream, "@@(%d,tbr)", has_disp?disp:imm);
+ break;
+ case A_INC_R15:
+ fprintf_fn (stream, "@r15+");
+ break;
+ case A_DEC_R15:
+ fprintf_fn (stream, "@-r15");
break;
case A_R0_GBR:
fprintf_fn (stream, "@(r0,gbr)");
@@ -832,7 +948,7 @@ print_insn_sh (memaddr, info)
}
}
- return 2;
+ return SH_MERGE_ARCH_SET (op->arch, arch_op32) ? 4 : 2;
fail:
;