2009-11-16 23:52:10 +00:00
|
|
|
/* MSPDebug - debugging tool for the eZ430
|
2010-01-08 08:17:24 +00:00
|
|
|
* Copyright (C) 2009, 2010 Daniel Beer
|
2009-11-16 23:52:10 +00:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef DIS_H_
|
|
|
|
|
2010-05-13 00:57:21 +00:00
|
|
|
#include <stdint.h>
|
2010-08-10 00:21:16 +00:00
|
|
|
#include "util.h"
|
2009-11-16 23:52:10 +00:00
|
|
|
|
|
|
|
/* Addressing modes.
|
|
|
|
*
|
|
|
|
* Addressing modes are not determined solely by the address mode bits
|
|
|
|
* in an instruction. Rather, those bits specify one of four possible
|
|
|
|
* modes (REGISTER, INDEXED, INDIRECT and INDIRECT_INC). Using some of
|
|
|
|
* these modes in conjunction with special registers like PC or the
|
|
|
|
* constant generator registers results in extra modes. For example, the
|
|
|
|
* following code, written using INDIRECT_INC on PC:
|
|
|
|
*
|
|
|
|
* MOV @PC+, R5
|
|
|
|
* .word 0x5729
|
|
|
|
*
|
|
|
|
* can also be written as an instruction using IMMEDIATE addressing:
|
|
|
|
*
|
|
|
|
* MOV #0x5729, R5
|
|
|
|
*/
|
|
|
|
typedef enum {
|
|
|
|
MSP430_AMODE_REGISTER = 0x0,
|
|
|
|
MSP430_AMODE_INDEXED = 0x1,
|
|
|
|
MSP430_AMODE_SYMBOLIC = 0x81,
|
|
|
|
MSP430_AMODE_ABSOLUTE = 0x82,
|
|
|
|
MSP430_AMODE_INDIRECT = 0x2,
|
|
|
|
MSP430_AMODE_INDIRECT_INC = 0x3,
|
|
|
|
MSP430_AMODE_IMMEDIATE = 0x83
|
|
|
|
} msp430_amode_t;
|
|
|
|
|
|
|
|
/* MSP430 registers.
|
|
|
|
*
|
|
|
|
* These are divided into:
|
|
|
|
*
|
|
|
|
* PC/R0: program counter
|
|
|
|
* SP/R1: stack pointer
|
|
|
|
* SR/R2: status register/constant generator 1
|
|
|
|
* R3: constant generator 2
|
|
|
|
* R4-R15: general purpose registers
|
|
|
|
*/
|
|
|
|
typedef enum {
|
|
|
|
MSP430_REG_PC = 0,
|
|
|
|
MSP430_REG_SP = 1,
|
|
|
|
MSP430_REG_SR = 2,
|
|
|
|
MSP430_REG_R3 = 3,
|
|
|
|
MSP430_REG_R4 = 4,
|
|
|
|
MSP430_REG_R5 = 5,
|
|
|
|
MSP430_REG_R6 = 6,
|
|
|
|
MSP430_REG_R7 = 7,
|
|
|
|
MSP430_REG_R8 = 8,
|
|
|
|
MSP430_REG_R9 = 9,
|
|
|
|
MSP430_REG_R10 = 10,
|
|
|
|
MSP430_REG_R11 = 11,
|
|
|
|
MSP430_REG_R12 = 12,
|
|
|
|
MSP430_REG_R13 = 13,
|
|
|
|
MSP430_REG_R14 = 14,
|
|
|
|
MSP430_REG_R15 = 15,
|
|
|
|
} msp430_reg_t;
|
|
|
|
|
|
|
|
/* Status register bits. */
|
|
|
|
#define MSP430_SR_V 0x0100
|
|
|
|
#define MSP430_SR_SCG1 0x0080
|
|
|
|
#define MSP430_SR_SCG0 0x0040
|
|
|
|
#define MSP430_SR_OSCOFF 0x0020
|
|
|
|
#define MSP430_SR_CPUOFF 0x0010
|
|
|
|
#define MSP430_SR_GIE 0x0008
|
|
|
|
#define MSP430_SR_N 0x0004
|
|
|
|
#define MSP430_SR_Z 0x0002
|
|
|
|
#define MSP430_SR_C 0x0001
|
|
|
|
|
|
|
|
/* MSP430 instruction formats.
|
|
|
|
*
|
|
|
|
* NOARG is not an actual instruction format recognised by the CPU.
|
|
|
|
* It is used only for emulated instructions.
|
|
|
|
*/
|
|
|
|
typedef enum {
|
|
|
|
MSP430_ITYPE_NOARG,
|
|
|
|
MSP430_ITYPE_JUMP,
|
|
|
|
MSP430_ITYPE_DOUBLE,
|
|
|
|
MSP430_ITYPE_SINGLE
|
|
|
|
} msp430_itype_t;
|
|
|
|
|
2010-08-10 00:21:16 +00:00
|
|
|
/* MSP430(X) data sizes.
|
|
|
|
*
|
|
|
|
* An address-word is a 20-bit value. When stored in memory, they are
|
|
|
|
* stored as two 16-bit words in the following order:
|
|
|
|
*
|
|
|
|
* data[15:0], {12'b0, data[19:16]}
|
|
|
|
*/
|
|
|
|
typedef enum {
|
2010-08-10 03:57:25 +00:00
|
|
|
MSP430_DSIZE_WORD = 0,
|
|
|
|
MSP430_DSIZE_BYTE = 1,
|
|
|
|
MSP430_DSIZE_UNKNOWN = 2,
|
|
|
|
MSP430_DSIZE_AWORD = 3,
|
2010-08-10 00:21:16 +00:00
|
|
|
} msp430_dsize_t;
|
|
|
|
|
2009-11-16 23:52:10 +00:00
|
|
|
/* MSP430 operations.
|
|
|
|
*
|
|
|
|
* Some of these are emulated instructions. Emulated instructions are
|
|
|
|
* alternate mnemonics for combinations of some real opcodes with
|
|
|
|
* common operand values. For example, the following real instruction:
|
|
|
|
*
|
|
|
|
* MOV #0, R8
|
|
|
|
*
|
|
|
|
* can be written as the following emulated instruction:
|
|
|
|
*
|
|
|
|
* CLR R8
|
|
|
|
*/
|
|
|
|
typedef enum {
|
|
|
|
/* Single operand */
|
|
|
|
MSP430_OP_RRC = 0x1000,
|
|
|
|
MSP430_OP_SWPB = 0x1080,
|
|
|
|
MSP430_OP_RRA = 0x1100,
|
|
|
|
MSP430_OP_SXT = 0x1180,
|
|
|
|
MSP430_OP_PUSH = 0x1200,
|
|
|
|
MSP430_OP_CALL = 0x1280,
|
|
|
|
MSP430_OP_RETI = 0x1300,
|
|
|
|
|
|
|
|
/* Jump */
|
|
|
|
MSP430_OP_JNZ = 0x2000,
|
|
|
|
MSP430_OP_JZ = 0x2400,
|
|
|
|
MSP430_OP_JNC = 0x2800,
|
|
|
|
MSP430_OP_JC = 0x2C00,
|
|
|
|
MSP430_OP_JN = 0x3000,
|
|
|
|
MSP430_OP_JGE = 0x3400,
|
|
|
|
MSP430_OP_JL = 0x3800,
|
|
|
|
MSP430_OP_JMP = 0x3C00,
|
|
|
|
|
|
|
|
/* Double operand */
|
|
|
|
MSP430_OP_MOV = 0x4000,
|
|
|
|
MSP430_OP_ADD = 0x5000,
|
|
|
|
MSP430_OP_ADDC = 0x6000,
|
|
|
|
MSP430_OP_SUBC = 0x7000,
|
|
|
|
MSP430_OP_SUB = 0x8000,
|
|
|
|
MSP430_OP_CMP = 0x9000,
|
|
|
|
MSP430_OP_DADD = 0xA000,
|
|
|
|
MSP430_OP_BIT = 0xB000,
|
|
|
|
MSP430_OP_BIC = 0xC000,
|
|
|
|
MSP430_OP_BIS = 0xD000,
|
|
|
|
MSP430_OP_XOR = 0xE000,
|
|
|
|
MSP430_OP_AND = 0xF000,
|
|
|
|
|
|
|
|
/* Emulated instructions */
|
|
|
|
MSP430_OP_ADC = 0x10000,
|
|
|
|
MSP430_OP_BR = 0x10001,
|
|
|
|
MSP430_OP_CLR = 0x10002,
|
|
|
|
MSP430_OP_CLRC = 0x10003,
|
|
|
|
MSP430_OP_CLRN = 0x10004,
|
|
|
|
MSP430_OP_CLRZ = 0x10005,
|
|
|
|
MSP430_OP_DADC = 0x10006,
|
|
|
|
MSP430_OP_DEC = 0x10007,
|
|
|
|
MSP430_OP_DECD = 0x10008,
|
|
|
|
MSP430_OP_DINT = 0x10009,
|
|
|
|
MSP430_OP_EINT = 0x1000A,
|
|
|
|
MSP430_OP_INC = 0x1000B,
|
|
|
|
MSP430_OP_INCD = 0x1000C,
|
|
|
|
MSP430_OP_INV = 0x1000D,
|
|
|
|
MSP430_OP_NOP = 0x1000E,
|
|
|
|
MSP430_OP_POP = 0x1000F,
|
|
|
|
MSP430_OP_RET = 0x10010,
|
|
|
|
MSP430_OP_RLA = 0x10011,
|
|
|
|
MSP430_OP_RLC = 0x10012,
|
|
|
|
MSP430_OP_SBC = 0x10013,
|
|
|
|
MSP430_OP_SETC = 0x10014,
|
|
|
|
MSP430_OP_SETN = 0x10015,
|
|
|
|
MSP430_OP_SETZ = 0x10016,
|
2010-08-10 01:27:35 +00:00
|
|
|
MSP430_OP_TST = 0x10017,
|
|
|
|
|
2010-08-10 02:04:10 +00:00
|
|
|
/* MSP430X single operand (extension word) */
|
|
|
|
MSP430_OP_RRCX = 0x21000,
|
|
|
|
MSP430_OP_RRUX = 0x21001, /* note: ZC = 1 */
|
|
|
|
MSP430_OP_SWPBX = 0x21080,
|
|
|
|
MSP430_OP_RRAX = 0x21100,
|
|
|
|
MSP430_OP_SXTX = 0x21180,
|
|
|
|
MSP430_OP_PUSHX = 0x21200,
|
|
|
|
|
|
|
|
/* MSP430X double operand (extension word) */
|
2010-08-10 01:27:35 +00:00
|
|
|
MSP430_OP_MOVX = 0x24000,
|
|
|
|
MSP430_OP_ADDX = 0x25000,
|
|
|
|
MSP430_OP_ADDCX = 0x26000,
|
|
|
|
MSP430_OP_SUBCX = 0x27000,
|
|
|
|
MSP430_OP_SUBX = 0x28000,
|
|
|
|
MSP430_OP_CMPX = 0x29000,
|
|
|
|
MSP430_OP_DADDX = 0x2A000,
|
|
|
|
MSP430_OP_BITX = 0x2B000,
|
|
|
|
MSP430_OP_BICX = 0x2C000,
|
|
|
|
MSP430_OP_BISX = 0x2D000,
|
|
|
|
MSP430_OP_XORX = 0x2E000,
|
2010-08-10 02:20:25 +00:00
|
|
|
MSP430_OP_ANDX = 0x2F000,
|
|
|
|
|
2010-08-10 03:06:12 +00:00
|
|
|
/* MSP430X group 13xx */
|
|
|
|
MSP430_OP_CALLA = 0x21300,
|
|
|
|
|
2010-08-10 02:20:25 +00:00
|
|
|
/* MSP430X group 14xx */
|
|
|
|
MSP430_OP_PUSHM = 0x1400,
|
2010-08-10 02:32:38 +00:00
|
|
|
MSP430_OP_POPM = 0x1600,
|
|
|
|
|
2010-08-10 03:47:36 +00:00
|
|
|
/* MSP430X address instructions */
|
|
|
|
MSP430_OP_MOVA = 0x0000,
|
|
|
|
MSP430_OP_CMPA = 0x0090,
|
|
|
|
MSP430_OP_ADDA = 0x00A0,
|
|
|
|
MSP430_OP_SUBA = 0x00B0,
|
|
|
|
|
2010-08-10 02:32:38 +00:00
|
|
|
/* MSP430X group 00xx, non-address */
|
|
|
|
MSP430_OP_RRCM = 0x0040,
|
|
|
|
MSP430_OP_RRAM = 0x0140,
|
|
|
|
MSP430_OP_RLAM = 0x0240,
|
2010-08-10 04:26:45 +00:00
|
|
|
MSP430_OP_RRUM = 0x0340,
|
|
|
|
|
|
|
|
/* MSP430X emulated instructions */
|
|
|
|
MSP430_OP_ADCX = 0x40000,
|
|
|
|
MSP430_OP_BRA = 0x40001,
|
|
|
|
MSP430_OP_RETA = 0x40002,
|
|
|
|
MSP430_OP_CLRX = 0x40003,
|
|
|
|
MSP430_OP_DADCX = 0x40004,
|
|
|
|
MSP430_OP_DECX = 0x40005,
|
|
|
|
MSP430_OP_DECDA = 0x40006,
|
|
|
|
MSP430_OP_DECDX = 0x40007,
|
|
|
|
MSP430_OP_INCX = 0x40008,
|
|
|
|
MSP430_OP_INCDA = 0x40009,
|
|
|
|
MSP430_OP_INVX = 0x4000A,
|
|
|
|
MSP430_OP_RLAX = 0x4000B,
|
|
|
|
MSP430_OP_RLCX = 0x4000C,
|
|
|
|
MSP430_OP_SECX = 0x4000D,
|
|
|
|
MSP430_OP_TSTA = 0x4000E,
|
|
|
|
MSP430_OP_TSTX = 0x4000F,
|
|
|
|
MSP430_OP_POPX = 0x40010,
|
|
|
|
MSP430_OP_INCDX = 0x40011,
|
2009-11-16 23:52:10 +00:00
|
|
|
} msp430_op_t;
|
|
|
|
|
|
|
|
/* This represents a decoded instruction. All decoded addresses are
|
|
|
|
* absolute or register-indexed, depending on the addressing mode.
|
|
|
|
*
|
|
|
|
* For jump instructions, the target address is stored in dst_operand.
|
|
|
|
*/
|
|
|
|
struct msp430_instruction {
|
2010-08-10 00:21:16 +00:00
|
|
|
address_t offset;
|
2009-11-16 23:52:10 +00:00
|
|
|
int len;
|
|
|
|
|
|
|
|
msp430_op_t op;
|
|
|
|
msp430_itype_t itype;
|
2010-08-10 00:21:16 +00:00
|
|
|
msp430_dsize_t dsize;
|
2009-11-16 23:52:10 +00:00
|
|
|
|
|
|
|
msp430_amode_t src_mode;
|
2010-08-10 00:21:16 +00:00
|
|
|
address_t src_addr;
|
2009-11-16 23:52:10 +00:00
|
|
|
msp430_reg_t src_reg;
|
|
|
|
|
|
|
|
msp430_amode_t dst_mode;
|
2010-08-10 00:21:16 +00:00
|
|
|
address_t dst_addr;
|
2009-11-16 23:52:10 +00:00
|
|
|
msp430_reg_t dst_reg;
|
2010-08-10 01:27:35 +00:00
|
|
|
|
|
|
|
int rep_index;
|
|
|
|
int rep_register;
|
2020-09-05 02:56:37 +00:00
|
|
|
int ignore_cy;
|
2009-11-16 23:52:10 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Decode a single instruction.
|
|
|
|
*
|
|
|
|
* Returns the number of bytes consumed, or -1 if an error occured.
|
|
|
|
*
|
|
|
|
* The caller needs to pass a pointer to the bytes to be decoded, the
|
|
|
|
* virtual offset of those bytes, and the maximum number available. If
|
|
|
|
* successful, the decoded instruction is written into the structure
|
|
|
|
* pointed to by insn.
|
|
|
|
*/
|
2010-05-13 00:57:21 +00:00
|
|
|
int dis_decode(const uint8_t *code,
|
2010-08-10 00:21:16 +00:00
|
|
|
address_t offset, address_t len,
|
2009-11-16 23:52:10 +00:00
|
|
|
struct msp430_instruction *insn);
|
|
|
|
|
2010-04-21 04:56:56 +00:00
|
|
|
/* Look up names for registers and opcodes */
|
2010-05-22 04:17:06 +00:00
|
|
|
int dis_opcode_from_name(const char *name);
|
2010-04-21 04:56:56 +00:00
|
|
|
const char *dis_opcode_name(msp430_op_t op);
|
2010-05-22 04:17:06 +00:00
|
|
|
int dis_reg_from_name(const char *name);
|
2010-04-21 04:56:56 +00:00
|
|
|
const char *dis_reg_name(msp430_reg_t reg);
|
2010-04-10 02:35:36 +00:00
|
|
|
|
2009-11-16 23:52:10 +00:00
|
|
|
#endif
|