/* Disassemble SH instructions.
- Copyright (C) 1993, 94, 95, 96, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1993, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
unsigned char insn[2];
unsigned char nibs[4];
int status;
- int relmask = ~0;
+ bfd_vma relmask = ~ (bfd_vma) 0;
sh_opcode_info *op;
status = info->read_memory_func (memaddr, insn, 2, info);
for (op = sh_table; op->name; op++)
{
int n;
- int imm;
- int rn;
- int rm;
- int rb;
+ int imm = 0;
+ int rn = 0;
+ int rm = 0;
+ int rb = 0;
+ int disp_pc;
+ bfd_vma disp_pc_addr = 0;
for (n = 0; n < 4; n++)
{
goto ok;
case PCRELIMM_8BY2:
imm = ((nibs[2] << 4) | nibs[3]) <<1;
- relmask = ~1;
+ relmask = ~ (bfd_vma) 1;
goto ok;
case PCRELIMM_8BY4:
imm = ((nibs[2] << 4) | nibs[3]) <<2;
- relmask = ~3;
+ relmask = ~ (bfd_vma) 3;
goto ok;
case IMM_8BY2:
imm = ((nibs[2] << 4) | nibs[3]) <<1;
case REG_M:
rm = nibs[n];
break;
+ case REG_NM:
+ rn = (nibs[n] & 0xc) >> 2;
+ rm = (nibs[n] & 0x3);
+ break;
case REG_B:
rb = nibs[n] & 0x07;
break;
ok:
fprintf_fn (stream,"%s\t", op->name);
+ disp_pc = 0;
for (n = 0; n < 3 && op->arg[n] != A_END; n++)
{
if (n && op->arg[1] != A_END)
case A_DISP_REG_M:
fprintf_fn (stream, "@(%d,r%d)", imm, rm);
break;
- case A_REG_B:
- fprintf_fn (stream, "r%d_bank", rb);
+ case A_REG_B:
+ fprintf_fn (stream, "r%d_bank", rb);
break;
case A_DISP_PC:
- fprintf_fn (stream, "0x%0x", imm + 4 + (memaddr & relmask));
+ disp_pc = 1;
+ disp_pc_addr = imm + 4 + (memaddr & relmask);
+ (*info->print_address_func) (disp_pc_addr, info);
break;
case A_IND_R0_REG_N:
fprintf_fn (stream, "@(r0,r%d)", rn);
case A_PR:
fprintf_fn (stream, "pr");
break;
+ case A_SGR:
+ fprintf_fn (stream, "sgr");
+ break;
+ case A_DBR:
+ fprintf_fn (stream, "dbr");
+ break;
+ case FD_REG_N:
+ if (0)
+ goto d_reg_n;
case F_REG_N:
fprintf_fn (stream, "fr%d", rn);
break;
case F_REG_M:
fprintf_fn (stream, "fr%d", rm);
break;
+ case DX_REG_N:
+ if (rn & 1)
+ {
+ fprintf_fn (stream, "xd%d", rn & ~1);
+ break;
+ }
+ d_reg_n:
+ case D_REG_N:
+ fprintf_fn (stream, "dr%d", rn);
+ break;
+ case DX_REG_M:
+ if (rm & 1)
+ {
+ fprintf_fn (stream, "xd%d", rm & ~1);
+ break;
+ }
+ case D_REG_M:
+ fprintf_fn (stream, "dr%d", rm);
+ break;
case FPSCR_M:
case FPSCR_N:
fprintf_fn (stream, "fpscr");
case F_FR0:
fprintf_fn (stream, "fr0");
break;
+ case V_REG_N:
+ fprintf_fn (stream, "fv%d", rn*4);
+ break;
+ case V_REG_M:
+ fprintf_fn (stream, "fv%d", rm*4);
+ break;
+ case XMTRX_M4:
+ fprintf_fn (stream, "xmtrx");
+ break;
default:
abort();
}
-
}
+#if 0
+ /* This code prints instructions in delay slots on the same line
+ as the instruction which needs the delay slots. This can be
+ confusing, since other disassembler don't work this way, and
+ it means that the instructions are not all in a line. So I
+ disabled it. Ian. */
if (!(info->flags & 1)
&& (op->name[0] == 'j'
|| (op->name[0] == 'b'
fprintf_fn (stream, ")");
return 4;
}
+#endif
+
+ if (disp_pc && strcmp (op->name, "mova") != 0)
+ {
+ int size;
+ bfd_byte bytes[4];
+
+ if (relmask == ~ (bfd_vma) 1)
+ size = 2;
+ else
+ size = 4;
+ status = info->read_memory_func (disp_pc_addr, bytes, size, info);
+ if (status == 0)
+ {
+ unsigned int val;
+
+ if (size == 2)
+ {
+ if ((info->flags & LITTLE_BIT) != 0)
+ val = bfd_getl16 (bytes);
+ else
+ val = bfd_getb16 (bytes);
+ }
+ else
+ {
+ if ((info->flags & LITTLE_BIT) != 0)
+ val = bfd_getl32 (bytes);
+ else
+ val = bfd_getb32 (bytes);
+ }
+ fprintf_fn (stream, "\t! 0x%x", val);
+ }
+ }
return 2;
fail: