simio: integrated programmed IO interface with CPU simulator.

This commit is contained in:
Daniel Beer 2011-03-10 12:06:05 +13:00
parent 1cf7385364
commit 37e7216a19
3 changed files with 35 additions and 111 deletions

71
main.c
View File

@ -51,75 +51,6 @@
#include "olimex.h"
#include "rf2500.h"
static void io_prefix(const char *prefix, uint16_t pc,
uint16_t addr, int is_byte)
{
char name[64];
address_t offset;
if (!stab_nearest(stab_default, pc, name, sizeof(name), &offset)) {
printf("%s", name);
if (offset)
printf("+0x%x", offset);
} else {
printf("0x%04x", pc);
}
printf(": IO %s.%c: 0x%04x", prefix, is_byte ? 'B' : 'W', addr);
if (!stab_nearest(stab_default, addr, name, sizeof(name), &offset)) {
printf(" (%s", name);
if (offset)
printf("+0x%x", offset);
printf(")");
}
}
static int fetch_io(void *user_data, uint16_t pc,
uint16_t addr, int is_byte, uint16_t *data_ret)
{
io_prefix("READ", pc, addr, is_byte);
for (;;) {
char text[128];
int len;
address_t data;
printf("? ");
fflush(stdout);
if (!fgets(text, sizeof(text), stdin)) {
printf("\nAborted IO request\n");
return -1;
}
len = strlen(text);
while (len && isspace(text[len - 1]))
len--;
text[len] = 0;
if (!len)
return 0;
if (!expr_eval(stab_default, text, &data)) {
if (data_ret)
*data_ret = data;
return 0;
}
}
return 0;
}
static void store_io(void *user_data, uint16_t pc,
uint16_t addr, int is_byte, uint16_t data)
{
io_prefix("WRITE", pc, addr, is_byte);
if (is_byte)
printf(" => 0x%02x\n", data & 0xff);
else
printf(" => 0x%04x\n", data);
}
struct cmdline_args {
const char *driver_name;
const char *serial_device;
@ -204,7 +135,7 @@ static device_t driver_open_olimex_iso(const struct cmdline_args *args)
static device_t driver_open_sim(const struct cmdline_args *args)
{
return sim_open(fetch_io, store_io, NULL);
return sim_open();
}
static device_t driver_open_uif(const struct cmdline_args *args)

56
sim.c
View File

@ -25,6 +25,7 @@
#include "util.h"
#include "output.h"
#include "sim.h"
#include "simio_cpu.h"
#define MEM_SIZE 65536
#define MEM_IO_END 0x200
@ -32,10 +33,6 @@
struct sim_device {
struct device base;
sim_fetch_func_t fetch_func;
sim_store_func_t store_func;
void *user_data;
uint8_t memory[MEM_SIZE];
uint16_t regs[DEVICE_NUM_REGS];
@ -123,14 +120,21 @@ static int fetch_operand(struct sim_device *dev,
if (data_ret) {
*data_ret = MEM_GETW(dev, addr) & mask;
if (addr < MEM_IO_END && dev->fetch_func) {
uint16_t data16 = *data_ret;
if (addr < MEM_IO_END) {
int ret;
ret = dev->fetch_func(dev->user_data,
dev->current_insn,
addr, is_byte, &data16);
*data_ret = data16;
if (is_byte) {
uint8_t x = *data_ret;
ret = simio_read_b(addr, &x);
*data_ret = x;
} else {
uint16_t x = *data_ret;
ret = simio_read(addr, &x);
*data_ret = x;
}
return ret;
}
}
@ -138,7 +142,7 @@ static int fetch_operand(struct sim_device *dev,
return 0;
}
static void store_operand(struct sim_device *dev,
static int store_operand(struct sim_device *dev,
int amode, int reg, int is_byte,
uint16_t addr, uint16_t data)
{
@ -149,9 +153,14 @@ static void store_operand(struct sim_device *dev,
if (amode == MSP430_AMODE_REGISTER)
dev->regs[reg] = data;
else if (addr < MEM_IO_END && dev->store_func)
dev->store_func(dev->user_data, dev->current_insn,
addr, is_byte, data);
else if (addr < MEM_IO_END) {
if (is_byte)
return simio_write_b(addr, data);
return simio_write(addr, data);
}
return 0;
}
#define ARITH_BITS (MSP430_SR_V | MSP430_SR_N | MSP430_SR_Z | MSP430_SR_C)
@ -263,9 +272,10 @@ static int step_double(struct sim_device *dev, uint16_t ins)
return -1;
}
if (opcode != MSP430_OP_CMP && opcode != MSP430_OP_BIT)
if (opcode != MSP430_OP_CMP && opcode != MSP430_OP_BIT &&
store_operand(dev, amode_dst, dreg, is_byte,
dst_addr, res_data);
dst_addr, res_data) < 0)
return -1;
return 0;
}
@ -350,8 +360,9 @@ static int step_single(struct sim_device *dev, uint16_t ins)
}
if (opcode != MSP430_OP_PUSH && opcode != MSP430_OP_CALL &&
opcode != MSP430_OP_RETI)
store_operand(dev, amode, reg, is_byte, src_addr, res_data);
opcode != MSP430_OP_RETI &&
store_operand(dev, amode, reg, is_byte, src_addr, res_data) < 0)
return -1;
return 0;
}
@ -502,6 +513,7 @@ static int sim_ctl(device_t dev_base, device_ctl_t op)
case DEVICE_CTL_RESET:
memset(dev->regs, 0, sizeof(dev->regs));
dev->regs[MSP430_REG_PC] = MEM_GETW(dev, 0xfffe);
simio_reset();
return 0;
case DEVICE_CTL_HALT:
@ -586,9 +598,7 @@ static device_status_t sim_poll(device_t dev_base)
return DEVICE_STATUS_RUNNING;
}
device_t sim_open(sim_fetch_func_t fetch_func,
sim_store_func_t store_func,
void *user_data)
device_t sim_open(void)
{
struct sim_device *dev = malloc(sizeof(*dev));
@ -609,10 +619,6 @@ device_t sim_open(sim_fetch_func_t fetch_func,
dev->base.ctl = sim_ctl;
dev->base.poll = sim_poll;
dev->fetch_func = fetch_func;
dev->store_func = store_func;
dev->user_data = user_data;
memset(dev->memory, 0xff, sizeof(dev->memory));
memset(dev->regs, 0xff, sizeof(dev->regs));

15
sim.h
View File

@ -21,20 +21,7 @@
#include "device.h"
/* These function pointers should be supplied in order to allow
* the simulator to perform IO operations. If they're left blank, IO
* addresses just map to RAM.
*/
typedef int (*sim_fetch_func_t)(void *user_data,
uint16_t pc, uint16_t addr,
int is_byte, uint16_t *data);
typedef void (*sim_store_func_t)(void *user_data,
uint16_t pc, uint16_t addr,
int is_byte, uint16_t data);
/* Dummy/simulation implementation. */
device_t sim_open(sim_fetch_func_t fetch, sim_store_func_t store,
void *user_data);
device_t sim_open(void);
#endif