simx: MSP430X simulator by Bruce Burns <bgb@alum.mit.edu>
This commit is contained in:
parent
e65bc6910a
commit
6740d7d98b
3
AUTHORS
3
AUTHORS
|
@ -87,3 +87,6 @@ Paolo Zebelloni <p.zebelloni@c-labs.it>:
|
|||
|
||||
Jan Willeke <willeke@smartmote.de>:
|
||||
* GPIO JTAG driver.
|
||||
|
||||
Bruce Burns <bgb@alum.mit.edu>
|
||||
* CPUX support in simulation driver (simx)
|
||||
|
|
997
drivers/sim.c
997
drivers/sim.c
File diff suppressed because it is too large
Load Diff
|
@ -23,5 +23,6 @@
|
|||
|
||||
/* Dummy/simulation implementation. */
|
||||
extern const struct device_class device_sim;
|
||||
extern const struct device_class device_simx;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -355,6 +355,12 @@ int simio_read(address_t addr, uint16_t *data)
|
|||
*data = ((uint16_t)sfr_data[addr]) |
|
||||
(((uint16_t)sfr_data[addr + 1]) << 8);
|
||||
return 0;
|
||||
|
||||
} else if (addr >= 0x100 && addr < 0x110) {
|
||||
/* most MSPs map SFR at 0x100 */
|
||||
*data = ((uint16_t)sfr_data[addr - 0x100]) |
|
||||
(((uint16_t)sfr_data[addr - 0x100 + 1]) << 8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*data = 0;
|
||||
|
@ -366,6 +372,11 @@ int simio_write_b(address_t addr, uint8_t data)
|
|||
if (addr < 16) {
|
||||
sfr_data[addr] = data;
|
||||
return 0;
|
||||
|
||||
} else if (addr >= 0x100 && addr < 0x110) {
|
||||
/* most MSPs map SFR at 0x100 */
|
||||
sfr_data[addr - 0x100] = data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return simio_write_b_device(addr, data);
|
||||
|
@ -376,6 +387,11 @@ int simio_read_b(address_t addr, uint8_t *data)
|
|||
if (addr < 16) {
|
||||
*data = sfr_data[addr];
|
||||
return 0;
|
||||
|
||||
} else if (addr >= 0x100 && addr < 0x110) {
|
||||
/* most MSPs map SFR at 0x100 */
|
||||
*data = sfr_data[addr - 0x100];
|
||||
return 0;
|
||||
}
|
||||
|
||||
*data = 0;
|
||||
|
|
|
@ -24,21 +24,23 @@
|
|||
#include "output.h"
|
||||
#include "expr.h"
|
||||
|
||||
/* Multiplier register addresses - taken from mspgcc */
|
||||
#define MPY 0x0130 /* Multiply Unsigned/Operand 1 */
|
||||
#define MPYS 0x0132 /* Multiply Signed/Operand 1 */
|
||||
#define MAC 0x0134 /* Multiply Unsigned and Accumulate/Operand 1 */
|
||||
#define MACS 0x0136 /* Multiply Signed and Accumulate/Operand 1 */
|
||||
#define OP2 0x0138 /* Operand 2 */
|
||||
#define RESLO 0x013A /* Result Low Word */
|
||||
#define RESHI 0x013C /* Result High Word */
|
||||
#define SUMEXT 0x013E /* Sum Extend */
|
||||
/* Multiplier register offsets from base addr */
|
||||
#define MPY 0x0 /* Multiply Unsigned/Operand 1 */
|
||||
#define MPYS 0x2 /* Multiply Signed/Operand 1 */
|
||||
#define MAC 0x4 /* Multiply Unsigned and Accumulate/Operand 1 */
|
||||
#define MACS 0x6 /* Multiply Signed and Accumulate/Operand 1 */
|
||||
#define OP2 0x8 /* Operand 2 */
|
||||
#define RESLO 0xA /* Result Low Word */
|
||||
#define RESHI 0xC /* Result High Word */
|
||||
#define SUMEXT 0xE /* Sum Extend */
|
||||
|
||||
struct hwmult {
|
||||
struct simio_device base;
|
||||
|
||||
int mode;
|
||||
|
||||
address_t base_addr;
|
||||
|
||||
uint16_t op1;
|
||||
uint16_t op2;
|
||||
uint32_t result;
|
||||
|
@ -59,6 +61,8 @@ struct simio_device *hwmult_create(char **arg_text)
|
|||
memset(h, 0, sizeof(*h));
|
||||
h->base.type = &simio_hwmult;
|
||||
|
||||
h->base_addr = 0x130;
|
||||
|
||||
return (struct simio_device *)h;
|
||||
}
|
||||
|
||||
|
@ -67,6 +71,44 @@ static void hwmult_destroy(struct simio_device *dev)
|
|||
free(dev);
|
||||
}
|
||||
|
||||
static int config_addr(address_t *addr, char **arg_text)
|
||||
{
|
||||
char *text = get_arg(arg_text);
|
||||
|
||||
if (!text) {
|
||||
printc_err("hwmult: config: expected address\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (expr_eval(text, addr) < 0) {
|
||||
printc_err("hwmult: can't parse address: %s\n", text);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hwmult_config(struct simio_device *dev,
|
||||
const char *param, char **arg_text)
|
||||
{
|
||||
struct hwmult *h = (struct hwmult *)dev;
|
||||
|
||||
if (!strcasecmp(param, "base"))
|
||||
return config_addr(&h->base_addr, arg_text);
|
||||
|
||||
printc_err("hwmult: config: unknown parameter: %s\n", param);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int hwmult_info(struct simio_device *dev)
|
||||
{
|
||||
struct hwmult *h = (struct hwmult *)dev;
|
||||
|
||||
printc("Base address: 0x%04x\n\n", h->base_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void do_multiply(struct hwmult *h)
|
||||
{
|
||||
uint32_t im;
|
||||
|
@ -100,6 +142,10 @@ static int hwmult_write(struct simio_device *dev, address_t addr, uint16_t data)
|
|||
{
|
||||
struct hwmult *h = (struct hwmult *)dev;
|
||||
|
||||
if (addr < h->base_addr) return 1;
|
||||
|
||||
addr -= h->base_addr;
|
||||
|
||||
switch (addr) {
|
||||
case RESHI:
|
||||
h->result = (h->result & 0xffff) | ((uint32_t)data << 16);
|
||||
|
@ -130,6 +176,10 @@ static int hwmult_read(struct simio_device *dev, address_t addr, uint16_t *data)
|
|||
{
|
||||
struct hwmult *h = (struct hwmult *)dev;
|
||||
|
||||
if (addr < h->base_addr) return 1;
|
||||
|
||||
addr -= h->base_addr;
|
||||
|
||||
switch (addr) {
|
||||
case MPY:
|
||||
case MPYS:
|
||||
|
@ -161,9 +211,14 @@ static int hwmult_read(struct simio_device *dev, address_t addr, uint16_t *data)
|
|||
const struct simio_class simio_hwmult = {
|
||||
.name = "hwmult",
|
||||
.help =
|
||||
"This module simulates the hardware multiplier.\n",
|
||||
"This module simulates the hardware multiplier.\n"
|
||||
"Config arguments are:\n"
|
||||
" base <address>\n"
|
||||
" Set the peripheral base address.\n",
|
||||
.create = hwmult_create,
|
||||
.destroy = hwmult_destroy,
|
||||
.config = hwmult_config,
|
||||
.info = hwmult_info,
|
||||
.write = hwmult_write,
|
||||
.read = hwmult_read
|
||||
};
|
||||
|
|
|
@ -80,6 +80,7 @@ static const struct device_class *const driver_table[] = {
|
|||
&device_olimex_iso,
|
||||
&device_olimex_iso_mk2,
|
||||
&device_sim,
|
||||
&device_simx,
|
||||
&device_uif,
|
||||
&device_bsl,
|
||||
&device_flash_bsl,
|
||||
|
@ -550,11 +551,11 @@ int main(int argc, char **argv)
|
|||
goto fail_driver;
|
||||
}
|
||||
|
||||
simio_init();
|
||||
|
||||
if (device_probe_id(device_default, args.devarg.forced_chip_id) < 0)
|
||||
printc_err("warning: device ID probe failed\n");
|
||||
|
||||
simio_init();
|
||||
|
||||
if (!(args.flags & OPT_NO_RC))
|
||||
process_rc_file(args.alt_config);
|
||||
|
||||
|
|
29
util/dis.c
29
util/dis.c
|
@ -249,14 +249,24 @@ static int decode_14xx(const uint8_t *code,
|
|||
* valid single-operand instruction could not be found.
|
||||
*/
|
||||
static int decode_single(const uint8_t *code, address_t offset,
|
||||
address_t size, struct msp430_instruction *insn)
|
||||
address_t size, struct msp430_instruction *insn,
|
||||
uint16_t ex_word)
|
||||
{
|
||||
uint16_t op = (code[1] << 8) | code[0];
|
||||
int need_arg = 0;
|
||||
|
||||
insn->itype = MSP430_ITYPE_SINGLE;
|
||||
insn->op = op & 0xff80;
|
||||
insn->dsize = (op & 0x0040) ? MSP430_DSIZE_BYTE : MSP430_DSIZE_WORD;
|
||||
|
||||
/* length encoding is based on AL bit (if ex_word present) and BW bit;
|
||||
SWPB and SXT have non-standard encodings */
|
||||
insn->dsize = (insn->op != MSP430_OP_SWPB && insn->op != MSP430_OP_SXT)
|
||||
? ((!ex_word || (ex_word & 0x0040))
|
||||
? ((op & 0x0040) ? MSP430_DSIZE_BYTE : MSP430_DSIZE_WORD)
|
||||
: ((op & 0x0040) ? MSP430_DSIZE_AWORD : MSP430_DSIZE_UNKNOWN))
|
||||
: ((op & 0x0040)
|
||||
? MSP430_DSIZE_UNKNOWN
|
||||
: (!ex_word || (ex_word & 0x0040)) ? MSP430_DSIZE_WORD : MSP430_DSIZE_AWORD);
|
||||
|
||||
insn->dst_mode = (op >> 4) & 0x3;
|
||||
insn->dst_reg = op & 0xf;
|
||||
|
@ -317,7 +327,9 @@ static int decode_double(const uint8_t *code, address_t offset,
|
|||
/* Decode and consume opcode */
|
||||
insn->itype = MSP430_ITYPE_DOUBLE;
|
||||
insn->op = op & 0xf000;
|
||||
insn->dsize = (op & 0x0040) ? MSP430_DSIZE_BYTE : MSP430_DSIZE_WORD;
|
||||
insn->dsize = (!ex_word || (ex_word & 0x0040))
|
||||
? ((op & 0x0040) ? MSP430_DSIZE_BYTE : MSP430_DSIZE_WORD)
|
||||
: ((op & 0x0040) ? MSP430_DSIZE_AWORD : MSP430_DSIZE_UNKNOWN);
|
||||
|
||||
insn->src_mode = (op >> 4) & 0x3;
|
||||
insn->src_reg = (op >> 8) & 0xf;
|
||||
|
@ -785,7 +797,7 @@ int dis_decode(const uint8_t *code, address_t offset, address_t len,
|
|||
if ((op & 0xf000) >= 0x4000)
|
||||
ret = decode_double(code, offset, len, insn, ex_word);
|
||||
else if ((op & 0xf000) == 0x1000 && (op & 0xfc00) < 0x1280)
|
||||
ret = decode_single(code, offset, len, insn);
|
||||
ret = decode_single(code, offset, len, insn, ex_word);
|
||||
else
|
||||
return -1;
|
||||
|
||||
|
@ -796,16 +808,15 @@ int dis_decode(const uint8_t *code, address_t offset, address_t len,
|
|||
(insn->itype == MSP430_ITYPE_SINGLE ||
|
||||
insn->src_mode == MSP430_AMODE_REGISTER)) {
|
||||
if ((ex_word >> 8) & 1) {
|
||||
if (insn->op != MSP430_OP_RRCX)
|
||||
return -1;
|
||||
if (insn->op == MSP430_OP_RRCX)
|
||||
insn->op = MSP430_OP_RRUX;
|
||||
else
|
||||
insn->ignore_cy = 1;
|
||||
}
|
||||
insn->rep_register = (ex_word >> 7) & 1;
|
||||
insn->rep_index = ex_word & 0xf;
|
||||
}
|
||||
|
||||
if (!(ex_word & 0x40))
|
||||
insn->dsize |= 2;
|
||||
} else {
|
||||
if ((op & 0xf000) == 0x0000)
|
||||
ret = decode_00xx(code, len, insn);
|
||||
|
@ -814,7 +825,7 @@ int dis_decode(const uint8_t *code, address_t offset, address_t len,
|
|||
else if ((op & 0xff00) == 0x1300)
|
||||
ret = decode_13xx(code, len, insn);
|
||||
else if ((op & 0xf000) == 0x1000)
|
||||
ret = decode_single(code, offset, len, insn);
|
||||
ret = decode_single(code, offset, len, insn, 0);
|
||||
else if ((op & 0xf000) >= 0x2000 && (op & 0xf000) < 0x4000)
|
||||
ret = decode_jump(code, offset, insn);
|
||||
else if ((op & 0xf000) >= 0x4000)
|
||||
|
|
|
@ -270,6 +270,7 @@ struct msp430_instruction {
|
|||
|
||||
int rep_index;
|
||||
int rep_register;
|
||||
int ignore_cy;
|
||||
};
|
||||
|
||||
/* Decode a single instruction.
|
||||
|
|
|
@ -202,6 +202,9 @@ static int dis_format(const struct msp430_instruction *insn)
|
|||
else if (insn->rep_index)
|
||||
len += printc(" [repeat %d]", insn->rep_index + 1);
|
||||
|
||||
if (insn->ignore_cy)
|
||||
len += printc(" [ignore carry]");
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue