version 1.1.1.2, 2016/10/26 17:03:38 |
version 1.1.1.3, 2018/04/14 15:37:33 |
|
|
/* Disassemble MSP430 instructions. |
/* Disassemble MSP430 instructions. |
Copyright (C) 2002-2015 Free Software Foundation, Inc. |
Copyright (C) 2002-2016 Free Software Foundation, Inc. |
|
|
Contributed by Dmitry Diky <diwil@mail.ru> |
Contributed by Dmitry Diky <diwil@mail.ru> |
|
|
|
|
#include <stdio.h> |
#include <stdio.h> |
#include <ctype.h> |
#include <ctype.h> |
#include <sys/types.h> |
#include <sys/types.h> |
|
#include <errno.h> |
|
|
#include "dis-asm.h" |
#include "dis-asm.h" |
#include "opintl.h" |
#include "opintl.h" |
|
|
|
|
#define PS(x) (0xffff & (x)) |
#define PS(x) (0xffff & (x)) |
|
|
static unsigned short |
static bfd_boolean |
msp430dis_opcode (bfd_vma addr, disassemble_info *info) |
msp430dis_read_two_bytes (bfd_vma addr, |
|
disassemble_info * info, |
|
bfd_byte * buffer, |
|
char * comm) |
{ |
{ |
bfd_byte buffer[2]; |
|
int status; |
int status; |
|
|
status = info->read_memory_func (addr, buffer, 2, info); |
status = info->read_memory_func (addr, buffer, 2, info); |
if (status != 0) |
if (status == 0) |
|
return TRUE; |
|
|
|
/* PR 20150: A status of EIO means that there were no more bytes left |
|
to read in the current section. This can happen when disassembling |
|
interrupt vectors for example. Avoid cluttering the output with |
|
unhelpful error messages in this case. */ |
|
if (status == EIO) |
|
{ |
|
if (comm) |
|
sprintf (comm, _("Warning: disassembly unreliable - not enough bytes available")); |
|
} |
|
else |
{ |
{ |
info->memory_error_func (status, addr, info); |
info->memory_error_func (status, addr, info); |
return -1; |
if (comm) |
|
sprintf (comm, _("Error: read from memory failed")); |
|
} |
|
|
|
return FALSE; |
|
} |
|
|
|
static bfd_boolean |
|
msp430dis_opcode_unsigned (bfd_vma addr, |
|
disassemble_info * info, |
|
unsigned short * return_val, |
|
char * comm) |
|
{ |
|
bfd_byte buffer[2]; |
|
|
|
if (msp430dis_read_two_bytes (addr, info, buffer, comm)) |
|
{ |
|
* return_val = bfd_getl16 (buffer); |
|
return TRUE; |
|
} |
|
else |
|
{ |
|
* return_val = 0; |
|
return FALSE; |
|
} |
|
} |
|
|
|
static bfd_boolean |
|
msp430dis_opcode_signed (bfd_vma addr, |
|
disassemble_info * info, |
|
signed int * return_val, |
|
char * comm) |
|
{ |
|
bfd_byte buffer[2]; |
|
|
|
if (msp430dis_read_two_bytes (addr, info, buffer, comm)) |
|
{ |
|
int status; |
|
|
|
status = bfd_getl_signed_16 (buffer); |
|
if (status & 0x8000) |
|
status |= -1U << 16; |
|
* return_val = status; |
|
return TRUE; |
|
} |
|
else |
|
{ |
|
* return_val = 0; |
|
return FALSE; |
} |
} |
return bfd_getl16 (buffer); |
|
} |
} |
|
|
static int |
static int |
Line 193 msp430_singleoperand (disassemble_info * |
|
Line 255 msp430_singleoperand (disassemble_info * |
|
if (regd == 0) |
if (regd == 0) |
{ |
{ |
/* PC relative. */ |
/* PC relative. */ |
dst = msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_signed (addr + 2, info, &dst, comm)) |
cmd_len += 2; |
|
*cycles = 4; |
|
sprintf (op, "0x%04x", dst); |
|
sprintf (comm, "PC rel. abs addr 0x%04x", |
|
PS ((short) (addr + 2) + dst)); |
|
if (extended_dst) |
|
{ |
{ |
dst |= extended_dst << 16; |
cmd_len += 2; |
sprintf (op, "0x%05x", dst); |
*cycles = 4; |
sprintf (comm, "PC rel. abs addr 0x%05lx", |
sprintf (op, "0x%04x", dst); |
(long)((addr + 2 + dst) & 0xfffff)); |
sprintf (comm, "PC rel. abs addr 0x%04x", |
|
PS ((short) (addr + 2) + dst)); |
|
if (extended_dst) |
|
{ |
|
dst |= extended_dst << 16; |
|
sprintf (op, "0x%05x", dst); |
|
sprintf (comm, "PC rel. abs addr 0x%05lx", |
|
(long)((addr + 2 + dst) & 0xfffff)); |
|
} |
} |
} |
} |
} |
else if (regd == 2) |
else if (regd == 2) |
{ |
{ |
/* Absolute. */ |
/* Absolute. */ |
dst = msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_signed (addr + 2, info, &dst, comm)) |
cmd_len += 2; |
|
*cycles = 4; |
|
sprintf (op, "&0x%04x", PS (dst)); |
|
if (extended_dst) |
|
{ |
{ |
dst |= extended_dst << 16; |
cmd_len += 2; |
sprintf (op, "&0x%05x", dst & 0xfffff); |
*cycles = 4; |
|
sprintf (op, "&0x%04x", PS (dst)); |
|
if (extended_dst) |
|
{ |
|
dst |= extended_dst << 16; |
|
sprintf (op, "&0x%05x", dst & 0xfffff); |
|
} |
} |
} |
} |
} |
else |
else |
{ |
{ |
dst = msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_signed (addr + 2, info, &dst, comm)) |
cmd_len += 2; |
|
*cycles = 4; |
|
if (extended_dst) |
|
{ |
{ |
dst |= extended_dst << 16; |
cmd_len += 2; |
if (dst & 0x80000) |
*cycles = 4; |
dst |= -1U << 20; |
if (extended_dst) |
|
{ |
|
dst |= extended_dst << 16; |
|
if (dst & 0x80000) |
|
dst |= -1U << 20; |
|
} |
|
sprintf (op, "%d(r%d)", dst, regd); |
} |
} |
else if (dst & 0x8000) |
|
dst |= -1U << 16; |
|
sprintf (op, "%d(r%d)", dst, regd); |
|
} |
} |
} |
} |
break; |
break; |
Line 264 msp430_singleoperand (disassemble_info * |
|
Line 330 msp430_singleoperand (disassemble_info * |
|
{ |
{ |
*cycles = 3; |
*cycles = 3; |
/* absolute. @pc+ */ |
/* absolute. @pc+ */ |
dst = msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_signed (addr + 2, info, &dst, comm)) |
cmd_len += 2; |
|
sprintf (op, "#%d", dst); |
|
if (dst > 9 || dst < 0) |
|
sprintf (comm, "#0x%04x", PS (dst)); |
|
if (extended_dst) |
|
{ |
{ |
dst |= extended_dst << 16; |
cmd_len += 2; |
if (dst & 0x80000) |
|
dst |= -1U << 20; |
|
sprintf (op, "#%d", dst); |
sprintf (op, "#%d", dst); |
if (dst > 9 || dst < 0) |
if (dst > 9 || dst < 0) |
sprintf (comm, "#0x%05x", dst); |
sprintf (comm, "#0x%04x", PS (dst)); |
|
if (extended_dst) |
|
{ |
|
dst |= extended_dst << 16; |
|
if (dst & 0x80000) |
|
dst |= -1U << 20; |
|
sprintf (op, "#%d", dst); |
|
if (dst > 9 || dst < 0) |
|
sprintf (comm, "#0x%05x", dst); |
|
} |
} |
} |
} |
} |
else |
else |
Line 288 msp430_singleoperand (disassemble_info * |
|
Line 356 msp430_singleoperand (disassemble_info * |
|
if (regd == 0) |
if (regd == 0) |
{ |
{ |
/* PC relative. */ |
/* PC relative. */ |
dst = msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_signed (addr + 2, info, &dst, comm)) |
cmd_len += 2; |
|
sprintf (op, "0x%04x", PS (dst)); |
|
sprintf (comm, "PC rel. 0x%04x", |
|
PS ((short) addr + 2 + dst)); |
|
if (extended_dst) |
|
{ |
{ |
dst |= extended_dst << 16; |
cmd_len += 2; |
sprintf (op, "0x%05x", dst & 0xffff); |
sprintf (op, "0x%04x", PS (dst)); |
sprintf (comm, "PC rel. 0x%05lx", |
sprintf (comm, "PC rel. 0x%04x", |
(long)((addr + 2 + dst) & 0xfffff)); |
PS ((short) addr + 2 + dst)); |
|
if (extended_dst) |
|
{ |
|
dst |= extended_dst << 16; |
|
sprintf (op, "0x%05x", dst & 0xffff); |
|
sprintf (comm, "PC rel. 0x%05lx", |
|
(long)((addr + 2 + dst) & 0xfffff)); |
|
} |
} |
} |
} |
} |
else if (regd == 2) |
else if (regd == 2) |
{ |
{ |
/* Absolute. */ |
/* Absolute. */ |
dst = msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_signed (addr + 2, info, &dst, comm)) |
cmd_len += 2; |
|
sprintf (op, "&0x%04x", PS (dst)); |
|
if (extended_dst) |
|
{ |
{ |
dst |= extended_dst << 16; |
cmd_len += 2; |
sprintf (op, "&0x%05x", dst & 0xfffff); |
sprintf (op, "&0x%04x", PS (dst)); |
|
if (extended_dst) |
|
{ |
|
dst |= extended_dst << 16; |
|
sprintf (op, "&0x%05x", dst & 0xfffff); |
|
} |
} |
} |
} |
} |
else if (regd == 3) |
else if (regd == 3) |
Line 322 msp430_singleoperand (disassemble_info * |
|
Line 394 msp430_singleoperand (disassemble_info * |
|
else |
else |
{ |
{ |
/* Indexed. */ |
/* Indexed. */ |
dst = msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_signed (addr + 2, info, &dst, comm)) |
cmd_len += 2; |
|
if (extended_dst) |
|
{ |
{ |
dst |= extended_dst << 16; |
cmd_len += 2; |
if (dst & 0x80000) |
if (extended_dst) |
dst |= -1U << 20; |
{ |
|
dst |= extended_dst << 16; |
|
if (dst & 0x80000) |
|
dst |= -1U << 20; |
|
} |
|
sprintf (op, "%d(r%d)", dst, regd); |
|
if (dst > 9 || dst < 0) |
|
sprintf (comm, "%05x", dst); |
} |
} |
else if (dst & 0x8000) |
|
dst |= -1U << 16; |
|
sprintf (op, "%d(r%d)", dst, regd); |
|
if (dst > 9 || dst < 0) |
|
sprintf (comm, "%05x", dst); |
|
} |
} |
} |
} |
break; |
break; |
Line 352 msp430_singleoperand (disassemble_info * |
|
Line 424 msp430_singleoperand (disassemble_info * |
|
*cycles = 2; |
*cycles = 2; |
return 2; |
return 2; |
break; |
break; |
|
|
default: |
default: |
cmd_len = 0; |
cmd_len = 0; |
} |
} |
Line 409 msp430_doubleoperand (disassemble_info * |
|
Line 482 msp430_doubleoperand (disassemble_info * |
|
/* Register mode. */ |
/* Register mode. */ |
if (regd == 3) |
if (regd == 3) |
{ |
{ |
strcpy (comm1, _("Illegal as emulation instr")); |
strcpy (comm1, _("Warning: illegal as emulation instr")); |
return -1; |
return -1; |
} |
} |
|
|
Line 421 msp430_doubleoperand (disassemble_info * |
|
Line 494 msp430_doubleoperand (disassemble_info * |
|
if (regd == 0) |
if (regd == 0) |
{ |
{ |
/* PC relative, Symbolic. */ |
/* PC relative, Symbolic. */ |
dst = msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1)) |
cmd_len += 4; |
|
*cycles = 6; |
|
sprintf (op1, "0x%04x", PS (dst)); |
|
sprintf (comm1, "PC rel. 0x%04x", |
|
PS ((short) addr + 2 + dst)); |
|
if (extension_word) |
|
{ |
{ |
dst |= extended_dst << 16; |
cmd_len += 4; |
if (dst & 0x80000) |
*cycles = 6; |
dst |= -1U << 20; |
sprintf (op1, "0x%04x", PS (dst)); |
sprintf (op1, "0x%05x", dst & 0xfffff); |
sprintf (comm1, "PC rel. 0x%04x", |
sprintf (comm1, "PC rel. 0x%05lx", |
PS ((short) addr + 2 + dst)); |
(long)((addr + 2 + dst) & 0xfffff)); |
if (extension_word) |
|
{ |
|
dst |= extended_dst << 16; |
|
if (dst & 0x80000) |
|
dst |= -1U << 20; |
|
sprintf (op1, "0x%05x", dst & 0xfffff); |
|
sprintf (comm1, "PC rel. 0x%05lx", |
|
(long)((addr + 2 + dst) & 0xfffff)); |
|
} |
} |
} |
} |
} |
else if (regd == 2) |
else if (regd == 2) |
{ |
{ |
/* Absolute. */ |
/* Absolute. */ |
dst = msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1)) |
/* If the 'src' field is not the same as the dst |
|
then this is not an rla instruction. */ |
|
if (dst != msp430dis_opcode (addr + 4, info)) |
|
return 0; |
|
cmd_len += 4; |
|
*cycles = 6; |
|
sprintf (op1, "&0x%04x", PS (dst)); |
|
if (extension_word) |
|
{ |
{ |
dst |= extended_dst << 16; |
int src; |
sprintf (op1, "&0x%05x", dst & 0xfffff); |
|
|
/* If the 'src' field is not the same as the dst |
|
then this is not an rla instruction. */ |
|
if (msp430dis_opcode_signed (addr + 4, info, &src, comm2)) |
|
{ |
|
if (src != dst) |
|
return 0; |
|
} |
|
cmd_len += 4; |
|
*cycles = 6; |
|
sprintf (op1, "&0x%04x", PS (dst)); |
|
if (extension_word) |
|
{ |
|
dst |= extended_dst << 16; |
|
sprintf (op1, "&0x%05x", dst & 0xfffff); |
|
} |
} |
} |
} |
} |
else |
else |
{ |
{ |
/* Indexed. */ |
/* Indexed. */ |
dst = msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1)) |
if (extension_word) |
|
{ |
{ |
dst |= extended_dst << 16; |
if (extension_word) |
if (dst & 0x80000) |
{ |
dst |= -1U << 20; |
dst |= extended_dst << 16; |
|
if (dst & 0x80000) |
|
dst |= -1U << 20; |
|
} |
|
cmd_len += 4; |
|
*cycles = 6; |
|
sprintf (op1, "%d(r%d)", dst, regd); |
|
if (dst > 9 || dst < -9) |
|
sprintf (comm1, "#0x%05x", dst); |
} |
} |
else if (dst & 0x8000) |
|
dst |= -1U << 16; |
|
cmd_len += 4; |
|
*cycles = 6; |
|
sprintf (op1, "%d(r%d)", dst, regd); |
|
if (dst > 9 || dst < -9) |
|
sprintf (comm1, "#0x%05x", dst); |
|
} |
} |
} |
} |
|
|
Line 484 msp430_doubleoperand (disassemble_info * |
|
Line 566 msp430_doubleoperand (disassemble_info * |
|
if (ad == 0 && regd == 3) |
if (ad == 0 && regd == 3) |
{ |
{ |
/* R2/R3 are illegal as dest: may be data section. */ |
/* R2/R3 are illegal as dest: may be data section. */ |
strcpy (comm1, _("Illegal as 2-op instr")); |
strcpy (comm1, _("Warning: illegal as 2-op instr")); |
return -1; |
return -1; |
} |
} |
|
|
Line 514 msp430_doubleoperand (disassemble_info * |
|
Line 596 msp430_doubleoperand (disassemble_info * |
|
{ |
{ |
*cycles = 3; |
*cycles = 3; |
/* Absolute. @pc+. */ |
/* Absolute. @pc+. */ |
dst = msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1)) |
cmd_len += 2; |
{ |
sprintf (op1, "#%d", dst); |
cmd_len += 2; |
if (dst > 9 || dst < 0) |
|
sprintf (comm1, "#0x%04x", PS (dst)); |
|
if (extension_word) |
|
{ |
|
dst |= extended_src << 16; |
|
if (dst & 0x80000) |
|
dst |= -1U << 20; |
|
sprintf (op1, "#%d", dst); |
sprintf (op1, "#%d", dst); |
if (dst > 9 || dst < 0) |
if (dst > 9 || dst < 0) |
sprintf (comm1, "0x%05x", dst & 0xfffff); |
sprintf (comm1, "#0x%04x", PS (dst)); |
|
if (extension_word) |
|
{ |
|
dst &= 0xffff; |
|
dst |= extended_src << 16; |
|
if (dst & 0x80000) |
|
dst |= -1U << 20; |
|
sprintf (op1, "#%d", dst); |
|
if (dst > 9 || dst < 0) |
|
sprintf (comm1, "0x%05x", dst & 0xfffff); |
|
} |
} |
} |
} |
} |
else |
else |
Line 538 msp430_doubleoperand (disassemble_info * |
|
Line 623 msp430_doubleoperand (disassemble_info * |
|
{ |
{ |
*cycles = 4; |
*cycles = 4; |
/* PC relative. */ |
/* PC relative. */ |
dst = msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1)) |
cmd_len += 2; |
{ |
sprintf (op1, "0x%04x", PS (dst)); |
cmd_len += 2; |
sprintf (comm1, "PC rel. 0x%04x", |
sprintf (op1, "0x%04x", PS (dst)); |
PS ((short) addr + 2 + dst)); |
sprintf (comm1, "PC rel. 0x%04x", |
if (extension_word) |
PS ((short) addr + 2 + dst)); |
{ |
if (extension_word) |
dst |= extended_src << 16; |
{ |
if (dst & 0x80000) |
dst &= 0xffff; |
dst |= -1U << 20; |
dst |= extended_src << 16; |
sprintf (op1, "0x%05x", dst & 0xfffff); |
if (dst & 0x80000) |
sprintf (comm1, "PC rel. 0x%05lx", |
dst |= -1U << 20; |
(long) ((addr + 2 + dst) & 0xfffff)); |
sprintf (op1, "0x%05x", dst & 0xfffff); |
|
sprintf (comm1, "PC rel. 0x%05lx", |
|
(long) ((addr + 2 + dst) & 0xfffff)); |
|
} |
} |
} |
} |
} |
else if (regs == 2) |
else if (regs == 2) |
{ |
{ |
*cycles = 2; |
*cycles = 2; |
/* Absolute. */ |
/* Absolute. */ |
dst = msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1)) |
cmd_len += 2; |
{ |
sprintf (op1, "&0x%04x", PS (dst)); |
cmd_len += 2; |
sprintf (comm1, "0x%04x", PS (dst)); |
sprintf (op1, "&0x%04x", PS (dst)); |
if (extension_word) |
sprintf (comm1, "0x%04x", PS (dst)); |
{ |
if (extension_word) |
dst |= extended_src << 16; |
{ |
sprintf (op1, "&0x%05x", dst & 0xfffff); |
dst &= 0xffff; |
* comm1 = 0; |
dst |= extended_src << 16; |
|
sprintf (op1, "&0x%05x", dst & 0xfffff); |
|
* comm1 = 0; |
|
} |
} |
} |
} |
} |
else if (regs == 3) |
else if (regs == 3) |
Line 578 msp430_doubleoperand (disassemble_info * |
|
Line 669 msp430_doubleoperand (disassemble_info * |
|
{ |
{ |
*cycles = 3; |
*cycles = 3; |
/* Indexed. */ |
/* Indexed. */ |
dst = msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1)) |
cmd_len += 2; |
|
if (extension_word) |
|
{ |
{ |
dst |= extended_src << 16; |
cmd_len += 2; |
if (dst & 0x80000) |
if (extension_word) |
dst |= -1U << 20; |
{ |
} |
dst &= 0xffff; |
else if (dst & 0x8000) |
dst |= extended_src << 16; |
dst |= -1U << 16; |
if (dst & 0x80000) |
sprintf (op1, "%d(r%d)", dst, regs); |
dst |= -1U << 20; |
if (dst > 9 || dst < -9) |
} |
sprintf (comm1, "0x%05x", dst); |
sprintf (op1, "%d(r%d)", dst, regs); |
|
if (dst > 9 || dst < -9) |
|
sprintf (comm1, "0x%05x", dst); |
|
} |
} |
} |
} |
} |
|
|
Line 621 msp430_doubleoperand (disassemble_info * |
|
Line 713 msp430_doubleoperand (disassemble_info * |
|
{ |
{ |
/* PC relative. */ |
/* PC relative. */ |
*cycles += 1; |
*cycles += 1; |
dst = msp430dis_opcode (addr + cmd_len, info); |
if (msp430dis_opcode_signed (addr + cmd_len, info, &dst, comm2)) |
sprintf (op2, "0x%04x", PS (dst)); |
{ |
sprintf (comm2, "PC rel. 0x%04x", |
sprintf (op2, "0x%04x", PS (dst)); |
PS ((short) addr + cmd_len + dst)); |
sprintf (comm2, "PC rel. 0x%04x", |
if (extension_word) |
PS ((short) addr + cmd_len + dst)); |
{ |
if (extension_word) |
dst |= extended_dst << 16; |
{ |
if (dst & 0x80000) |
dst |= extended_dst << 16; |
dst |= -1U << 20; |
if (dst & 0x80000) |
sprintf (op2, "0x%05x", dst & 0xfffff); |
dst |= -1U << 20; |
sprintf (comm2, "PC rel. 0x%05lx", |
sprintf (op2, "0x%05x", dst & 0xfffff); |
(long)((addr + cmd_len + dst) & 0xfffff)); |
sprintf (comm2, "PC rel. 0x%05lx", |
|
(long)((addr + cmd_len + dst) & 0xfffff)); |
|
} |
} |
} |
cmd_len += 2; |
cmd_len += 2; |
} |
} |
else if (regd == 2) |
else if (regd == 2) |
{ |
{ |
/* Absolute. */ |
/* Absolute. */ |
dst = msp430dis_opcode (addr + cmd_len, info); |
if (msp430dis_opcode_signed (addr + cmd_len, info, &dst, comm2)) |
cmd_len += 2; |
|
sprintf (op2, "&0x%04x", PS (dst)); |
|
if (extension_word) |
|
{ |
{ |
dst |= extended_dst << 16; |
cmd_len += 2; |
sprintf (op2, "&0x%05x", dst & 0xfffff); |
sprintf (op2, "&0x%04x", PS (dst)); |
|
if (extension_word) |
|
{ |
|
dst |= extended_dst << 16; |
|
sprintf (op2, "&0x%05x", dst & 0xfffff); |
|
} |
} |
} |
} |
} |
else |
else |
{ |
{ |
dst = msp430dis_opcode (addr + cmd_len, info); |
if (msp430dis_opcode_signed (addr + cmd_len, info, &dst, comm2)) |
cmd_len += 2; |
{ |
if (dst & 0x8000) |
cmd_len += 2; |
dst |= -1U << 16; |
|
if (dst > 9 || dst < 0) |
|
sprintf (comm2, "0x%04x", PS (dst)); |
|
if (extension_word) |
|
{ |
|
dst |= extended_dst << 16; |
|
if (dst & 0x80000) |
|
dst |= -1U << 20; |
|
if (dst > 9 || dst < 0) |
if (dst > 9 || dst < 0) |
sprintf (comm2, "0x%05x", dst & 0xfffff); |
sprintf (comm2, "0x%04x", PS (dst)); |
|
if (extension_word) |
|
{ |
|
dst |= extended_dst << 16; |
|
if (dst & 0x80000) |
|
dst |= -1U << 20; |
|
if (dst > 9 || dst < 0) |
|
sprintf (comm2, "0x%05x", dst & 0xfffff); |
|
} |
|
sprintf (op2, "%d(r%d)", dst, regd); |
} |
} |
sprintf (op2, "%d(r%d)", dst, regd); |
|
} |
} |
} |
} |
|
|
Line 683 msp430_branchinstr (disassemble_info *in |
|
Line 779 msp430_branchinstr (disassemble_info *in |
|
int regs = 0, regd = 0; |
int regs = 0, regd = 0; |
int as = 0; |
int as = 0; |
int cmd_len = 2; |
int cmd_len = 2; |
short dst = 0; |
int dst = 0; |
|
unsigned short udst = 0; |
|
|
regd = insn & 0x0f; |
regd = insn & 0x0f; |
regs = (insn & 0x0f00) >> 8; |
regs = (insn & 0x0f00) >> 8; |
Line 719 msp430_branchinstr (disassemble_info *in |
|
Line 816 msp430_branchinstr (disassemble_info *in |
|
{ |
{ |
/* Absolute. @pc+ */ |
/* Absolute. @pc+ */ |
*cycles = 3; |
*cycles = 3; |
dst = msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_unsigned (addr + 2, info, &udst, comm1)) |
cmd_len += 2; |
{ |
sprintf (op1, "#0x%04x", PS (dst)); |
cmd_len += 2; |
|
sprintf (op1, "#0x%04x", PS (udst)); |
|
} |
} |
} |
else |
else |
* cycles = print_as3_reg_name (regs, op1, comm1, 1, 1, 2); |
* cycles = print_as3_reg_name (regs, op1, comm1, 1, 1, 2); |
Line 733 msp430_branchinstr (disassemble_info *in |
|
Line 832 msp430_branchinstr (disassemble_info *in |
|
if (regs == 0) |
if (regs == 0) |
{ |
{ |
/* PC relative. */ |
/* PC relative. */ |
dst = msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1)) |
cmd_len += 2; |
{ |
(*cycles)++; |
cmd_len += 2; |
sprintf (op1, "0x%04x", PS (dst)); |
(*cycles)++; |
sprintf (comm1, "PC rel. 0x%04x", |
sprintf (op1, "0x%04x", PS (dst)); |
PS ((short) addr + 2 + dst)); |
sprintf (comm1, "PC rel. 0x%04x", |
|
PS ((short) addr + 2 + dst)); |
|
} |
} |
} |
else if (regs == 2) |
else if (regs == 2) |
{ |
{ |
/* Absolute. */ |
/* Absolute. */ |
dst = msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_unsigned (addr + 2, info, &udst, comm1)) |
cmd_len += 2; |
{ |
sprintf (op1, "&0x%04x", PS (dst)); |
cmd_len += 2; |
|
sprintf (op1, "&0x%04x", PS (udst)); |
|
} |
} |
} |
else if (regs == 3) |
else if (regs == 3) |
{ |
{ |
Line 756 msp430_branchinstr (disassemble_info *in |
|
Line 859 msp430_branchinstr (disassemble_info *in |
|
else |
else |
{ |
{ |
/* Indexed. */ |
/* Indexed. */ |
dst = msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1)) |
cmd_len += 2; |
{ |
if (dst & 0x8000) |
cmd_len += 2; |
dst |= -1U << 16; |
sprintf (op1, "%d(r%d)", dst, regs); |
sprintf (op1, "%d(r%d)", dst, regs); |
} |
} |
} |
} |
} |
|
|
Line 780 msp430x_calla_instr (disassemble_info * |
|
Line 883 msp430x_calla_instr (disassemble_info * |
|
int am = (insn & 0xf0) >> 4; |
int am = (insn & 0xf0) >> 4; |
int cmd_len = 2; |
int cmd_len = 2; |
unsigned short udst = 0; |
unsigned short udst = 0; |
short dst = 0; |
int dst = 0; |
|
|
switch (am) |
switch (am) |
{ |
{ |
Line 791 msp430x_calla_instr (disassemble_info * |
|
Line 894 msp430x_calla_instr (disassemble_info * |
|
|
|
case 5: /* CALLA x(Rdst) */ |
case 5: /* CALLA x(Rdst) */ |
*cycles = 3; |
*cycles = 3; |
dst = msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1)) |
cmd_len += 2; |
{ |
sprintf (op1, "%d(r%d)", dst, reg); |
cmd_len += 2; |
if (reg == 0) |
sprintf (op1, "%d(r%d)", dst, reg); |
sprintf (comm1, "PC rel. 0x%05lx", (long) (addr + 2 + dst)); |
if (reg == 0) |
else |
sprintf (comm1, "PC rel. 0x%05lx", (long) (addr + 2 + dst)); |
sprintf (comm1, "0x%05x", dst); |
else |
|
sprintf (comm1, "0x%05x", dst); |
|
} |
break; |
break; |
|
|
case 6: /* CALLA @Rdst */ |
case 6: /* CALLA @Rdst */ |
Line 811 msp430x_calla_instr (disassemble_info * |
|
Line 916 msp430x_calla_instr (disassemble_info * |
|
break; |
break; |
|
|
case 8: /* CALLA &abs20 */ |
case 8: /* CALLA &abs20 */ |
udst = msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_unsigned (addr + 2, info, &udst, comm1)) |
cmd_len += 2; |
{ |
*cycles = 4; |
cmd_len += 2; |
sprintf (op1, "&%d", (ureg << 16) + udst); |
*cycles = 4; |
sprintf (comm1, "0x%05x", (ureg << 16) + udst); |
sprintf (op1, "&%d", (ureg << 16) + udst); |
|
sprintf (comm1, "0x%05x", (ureg << 16) + udst); |
|
} |
break; |
break; |
|
|
case 9: /* CALLA pcrel-sym */ |
case 9: /* CALLA pcrel-sym */ |
dst = msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1)) |
cmd_len += 2; |
{ |
*cycles = 4; |
cmd_len += 2; |
sprintf (op1, "%d(PC)", (reg << 16) + dst); |
*cycles = 4; |
sprintf (comm1, "PC rel. 0x%05lx", |
sprintf (op1, "%d(PC)", (reg << 16) + dst); |
(long) (addr + 2 + dst + (reg << 16))); |
sprintf (comm1, "PC rel. 0x%05lx", |
|
(long) (addr + 2 + dst + (reg << 16))); |
|
} |
break; |
break; |
|
|
case 11: /* CALLA #imm20 */ |
case 11: /* CALLA #imm20 */ |
udst = msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_unsigned (addr + 2, info, &udst, comm1)) |
cmd_len += 2; |
{ |
*cycles = 4; |
cmd_len += 2; |
sprintf (op1, "#%d", (ureg << 16) + udst); |
*cycles = 4; |
sprintf (comm1, "0x%05x", (ureg << 16) + udst); |
sprintf (op1, "#%d", (ureg << 16) + udst); |
|
sprintf (comm1, "0x%05x", (ureg << 16) + udst); |
|
} |
break; |
break; |
|
|
default: |
default: |
strcpy (comm1, _("unrecognised CALLA addressing mode")); |
strcpy (comm1, _("Warning: unrecognised CALLA addressing mode")); |
return -1; |
return -1; |
} |
} |
|
|
Line 855 print_insn_msp430 (bfd_vma addr, disasse |
|
Line 966 print_insn_msp430 (bfd_vma addr, disasse |
|
int cycles = 0; |
int cycles = 0; |
char *bc = ""; |
char *bc = ""; |
unsigned short extension_word = 0; |
unsigned short extension_word = 0; |
|
unsigned short bits; |
|
|
insn = msp430dis_opcode (addr, info); |
if (! msp430dis_opcode_unsigned (addr, info, &insn, NULL)) |
if (insn == (unsigned short) -1) |
|
{ |
{ |
prin (stream, ".word 0xffff; ????"); |
prin (stream, ".word 0xffff; ????"); |
return 2; |
return 2; |
Line 877 print_insn_msp430 (bfd_vma addr, disasse |
|
Line 988 print_insn_msp430 (bfd_vma addr, disasse |
|
{ |
{ |
extension_word = insn; |
extension_word = insn; |
addr += 2; |
addr += 2; |
insn = msp430dis_opcode (addr, info); |
if (! msp430dis_opcode_unsigned (addr, info, &insn, NULL)) |
if (insn == (unsigned short) -1) |
|
{ |
{ |
prin (stream, ".word 0x%04x, 0xffff; ????", |
prin (stream, ".word 0x%04x, 0xffff; ????", |
extension_word); |
extension_word); |
Line 963 print_insn_msp430 (bfd_vma addr, disasse |
|
Line 1073 print_insn_msp430 (bfd_vma addr, disasse |
|
else |
else |
{ |
{ |
n <<= 16; |
n <<= 16; |
n |= msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_unsigned (addr + 2, info, &bits, comm1)) |
sprintf (op1, "#%d", n); |
{ |
if (n > 9 || n < 0) |
n |= bits; |
sprintf (comm1, "0x%05x", n); |
sprintf (op1, "#%d", n); |
|
if (n > 9 || n < 0) |
|
sprintf (comm1, "0x%05x", n); |
|
} |
cmd_len = 4; |
cmd_len = 4; |
} |
} |
sprintf (op2, "r%d", reg); |
sprintf (op2, "r%d", reg); |
Line 998 print_insn_msp430 (bfd_vma addr, disasse |
|
Line 1111 print_insn_msp430 (bfd_vma addr, disasse |
|
case 2: /* MOVA &abs20, Rdst */ |
case 2: /* MOVA &abs20, Rdst */ |
cmd_len = 4; |
cmd_len = 4; |
n <<= 16; |
n <<= 16; |
n |= msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_unsigned (addr + 2, info, &bits, comm1)) |
sprintf (op1, "&%d", n); |
{ |
if (n > 9 || n < 0) |
n |= bits; |
sprintf (comm1, "0x%05x", n); |
sprintf (op1, "&%d", n); |
if (strcmp (opcode->name, "bra") != 0) |
if (n > 9 || n < 0) |
sprintf (op2, "r%d", reg); |
sprintf (comm1, "0x%05x", n); |
|
if (strcmp (opcode->name, "bra") != 0) |
|
sprintf (op2, "r%d", reg); |
|
} |
break; |
break; |
|
|
case 3: /* MOVA x(Rsrc), Rdst */ |
case 3: /* MOVA x(Rsrc), Rdst */ |
Line 1011 print_insn_msp430 (bfd_vma addr, disasse |
|
Line 1127 print_insn_msp430 (bfd_vma addr, disasse |
|
if (strcmp (opcode->name, "bra") != 0) |
if (strcmp (opcode->name, "bra") != 0) |
sprintf (op2, "r%d", reg); |
sprintf (op2, "r%d", reg); |
reg = n; |
reg = n; |
n = msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_signed (addr + 2, info, &n, comm1)) |
if (n & 0x8000) |
{ |
n |= -1U << 16; |
sprintf (op1, "%d(r%d)", n, reg); |
sprintf (op1, "%d(r%d)", n, reg); |
if (n > 9 || n < 0) |
if (n > 9 || n < 0) |
{ |
{ |
if (reg == 0) |
if (reg == 0) |
sprintf (comm1, "PC rel. 0x%05lx", |
sprintf (comm1, "PC rel. 0x%05lx", |
(long) (addr + 2 + n)); |
(long) (addr + 2 + n)); |
else |
else |
sprintf (comm1, "0x%05x", n); |
sprintf (comm1, "0x%05x", n); |
} |
} |
} |
break; |
break; |
|
|
case 6: /* MOVA Rsrc, &abs20 */ |
case 6: /* MOVA Rsrc, &abs20 */ |
cmd_len = 4; |
cmd_len = 4; |
reg <<= 16; |
reg <<= 16; |
reg |= msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_unsigned (addr + 2, info, &bits, comm2)) |
sprintf (op1, "r%d", n); |
{ |
sprintf (op2, "&%d", reg); |
reg |= bits; |
if (reg > 9 || reg < 0) |
sprintf (op1, "r%d", n); |
sprintf (comm2, "0x%05x", reg); |
sprintf (op2, "&%d", reg); |
|
if (reg > 9 || reg < 0) |
|
sprintf (comm2, "0x%05x", reg); |
|
} |
break; |
break; |
|
|
case 7: /* MOVA Rsrc, x(Rdst) */ |
case 7: /* MOVA Rsrc, x(Rdst) */ |
cmd_len = 4; |
cmd_len = 4; |
sprintf (op1, "r%d", n); |
sprintf (op1, "r%d", n); |
n = msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_signed (addr + 2, info, &n, comm2)) |
if (n & 0x8000) |
{ |
n |= -1U << 16; |
sprintf (op2, "%d(r%d)", n, reg); |
sprintf (op2, "%d(r%d)", n, reg); |
if (n > 9 || n < 0) |
if (n > 9 || n < 0) |
{ |
{ |
if (reg == 0) |
if (reg == 0) |
sprintf (comm2, "PC rel. 0x%05lx", |
sprintf (comm2, "PC rel. 0x%05lx", |
(long) (addr + 2 + n)); |
(long) (addr + 2 + n)); |
else |
else |
sprintf (comm2, "0x%05x", n); |
sprintf (comm2, "0x%05x", n); |
} |
} |
} |
break; |
break; |
|
|
case 8: /* MOVA #imm20, Rdst */ |
case 8: /* MOVA #imm20, Rdst */ |
cmd_len = 4; |
cmd_len = 4; |
n <<= 16; |
n <<= 16; |
n |= msp430dis_opcode (addr + 2, info); |
if (msp430dis_opcode_unsigned (addr + 2, info, &bits, comm1)) |
if (n & 0x80000) |
{ |
n |= -1U << 20; |
n |= bits; |
sprintf (op1, "#%d", n); |
if (n & 0x80000) |
if (n > 9 || n < 0) |
n |= -1U << 20; |
sprintf (comm1, "0x%05x", n); |
sprintf (op1, "#%d", n); |
if (strcmp (opcode->name, "bra") != 0) |
if (n > 9 || n < 0) |
sprintf (op2, "r%d", reg); |
sprintf (comm1, "0x%05x", n); |
|
if (strcmp (opcode->name, "bra") != 0) |
|
sprintf (op2, "r%d", reg); |
|
} |
break; |
break; |
|
|
case 12: /* MOVA Rsrc, Rdst */ |
case 12: /* MOVA Rsrc, Rdst */ |
Line 1102 print_insn_msp430 (bfd_vma addr, disasse |
|
Line 1224 print_insn_msp430 (bfd_vma addr, disasse |
|
} |
} |
else if (extension_word) |
else if (extension_word) |
{ |
{ |
if (extension_word & (1 << 6)) |
if (extension_word & BYTE_OPERATION) |
bc = ".w"; |
bc = ".w"; |
else |
else |
{ |
{ |
bc = ".?"; |
bc = ".?"; |
sprintf (comm2, _("Reserved use of A/L and B/W bits detected")); |
sprintf (comm2, _("Warning: reserved use of A/L and B/W bits detected")); |
} |
} |
} |
} |
|
|
Line 1124 print_insn_msp430 (bfd_vma addr, disasse |
|
Line 1246 print_insn_msp430 (bfd_vma addr, disasse |
|
if (insn & BYTE_OPERATION) |
if (insn & BYTE_OPERATION) |
{ |
{ |
bc = ".?"; |
bc = ".?"; |
sprintf (comm2, _("Reserved use of A/L and B/W bits detected")); |
sprintf (comm2, _("Warning: reserved use of A/L and B/W bits detected")); |
} |
} |
else if (extension_word & BYTE_OPERATION) |
else if (extension_word & BYTE_OPERATION) |
bc = ".w"; |
bc = ".w"; |
Line 1145 print_insn_msp430 (bfd_vma addr, disasse |
|
Line 1267 print_insn_msp430 (bfd_vma addr, disasse |
|
else |
else |
{ |
{ |
bc = ".?"; |
bc = ".?"; |
sprintf (comm2, _("Reserved use of A/L and B/W bits detected")); |
sprintf (comm2, _("Warning: reserved use of A/L and B/W bits detected")); |
} |
} |
} |
} |
break; |
break; |
Line 1181 print_insn_msp430 (bfd_vma addr, disasse |
|
Line 1303 print_insn_msp430 (bfd_vma addr, disasse |
|
prin (stream, "rpt #%d { ", (extension_word & 0xf) + 1); |
prin (stream, "rpt #%d { ", (extension_word & 0xf) + 1); |
} |
} |
|
|
if (extension_word && opcode->name[strlen (opcode->name) - 1] != 'x') |
/* Special case: RRC with an extension word and the ZC bit set is actually RRU. */ |
|
if (extension_word |
|
&& (extension_word & IGNORE_CARRY_BIT) |
|
&& strcmp (opcode->name, "rrc") == 0) |
|
(*prin) (stream, "rrux%s", bc); |
|
else if (extension_word && opcode->name[strlen (opcode->name) - 1] != 'x') |
(*prin) (stream, "%sx%s", opcode->name, bc); |
(*prin) (stream, "%sx%s", opcode->name, bc); |
else |
else |
(*prin) (stream, "%s%s", opcode->name, bc); |
(*prin) (stream, "%s%s", opcode->name, bc); |