Browse Source

simx: MSP430X simulator by Bruce Burns <bgb@alum.mit.edu>

master
Daniel Beer 1 year ago
parent
commit
6740d7d98b
  1. 3
      AUTHORS
  2. 1269
      drivers/sim.c
  3. 1
      drivers/sim.h
  4. 16
      simio/simio.c
  5. 75
      simio/simio_hwmult.c
  6. 5
      ui/main.c
  7. 31
      util/dis.c
  8. 1
      util/dis.h
  9. 3
      util/output_util.c

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)

1269
drivers/sim.c
File diff suppressed because it is too large
View File

1
drivers/sim.h

@ -23,5 +23,6 @@
/* Dummy/simulation implementation. */
extern const struct device_class device_sim;
extern const struct device_class device_simx;
#endif

16
simio/simio.c

@ -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;

75
simio/simio_hwmult.c

@ -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
};

5
ui/main.c

@ -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);

31
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;
insn->op = MSP430_OP_RRUX;
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)

1
util/dis.h

@ -270,6 +270,7 @@ struct msp430_instruction {
int rep_index;
int rep_register;
int ignore_cy;
};
/* Decode a single instruction.

3
util/output_util.c

@ -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…
Cancel
Save