simio: implemented instruction cycle counting.

This commit is contained in:
Daniel Beer 2011-03-10 12:43:08 +13:00
parent 37e7216a19
commit 981e691913
3 changed files with 71 additions and 11 deletions

78
sim.c
View File

@ -179,6 +179,26 @@ static int step_double(struct sim_device *dev, uint16_t ins)
uint32_t res_data; uint32_t res_data;
uint32_t msb = is_byte ? 0x80 : 0x8000; uint32_t msb = is_byte ? 0x80 : 0x8000;
uint32_t mask = is_byte ? 0xff : 0xffff; uint32_t mask = is_byte ? 0xff : 0xffff;
int cycles;
if (amode_dst == MSP430_AMODE_REGISTER && dreg == MSP430_REG_PC) {
if (amode_src == MSP430_AMODE_REGISTER ||
amode_src == MSP430_AMODE_INDIRECT)
cycles = 2;
else
cycles = 3;
} else {
if (amode_src == MSP430_AMODE_INDIRECT ||
amode_src == MSP430_AMODE_INDIRECT_INC)
cycles = 2;
else if (amode_src == MSP430_AMODE_INDEXED)
cycles = 3;
else
cycles = 1;
if (amode_dst == MSP430_AMODE_INDEXED)
cycles += 3;
}
if (fetch_operand(dev, amode_src, sreg, is_byte, NULL, &src_data) < 0) if (fetch_operand(dev, amode_src, sreg, is_byte, NULL, &src_data) < 0)
return -1; return -1;
@ -277,7 +297,7 @@ static int step_double(struct sim_device *dev, uint16_t ins)
dst_addr, res_data) < 0) dst_addr, res_data) < 0)
return -1; return -1;
return 0; return cycles;
} }
static int step_single(struct sim_device *dev, uint16_t ins) static int step_single(struct sim_device *dev, uint16_t ins)
@ -291,10 +311,18 @@ static int step_single(struct sim_device *dev, uint16_t ins)
uint16_t src_addr = 0; uint16_t src_addr = 0;
uint32_t src_data; uint32_t src_data;
uint32_t res_data = 0; uint32_t res_data = 0;
int cycles = 1;
if (fetch_operand(dev, amode, reg, is_byte, &src_addr, &src_data) < 0) if (fetch_operand(dev, amode, reg, is_byte, &src_addr, &src_data) < 0)
return -1; return -1;
if (amode == MSP430_AMODE_INDEXED)
cycles = 4;
else if (amode == MSP430_AMODE_REGISTER)
cycles = 1;
else
cycles = 5;
switch (opcode) { switch (opcode) {
case MSP430_OP_RRC: case MSP430_OP_RRC:
case MSP430_OP_RRA: case MSP430_OP_RRA:
@ -335,6 +363,15 @@ static int step_single(struct sim_device *dev, uint16_t ins)
case MSP430_OP_PUSH: case MSP430_OP_PUSH:
dev->regs[MSP430_REG_SP] -= 2; dev->regs[MSP430_REG_SP] -= 2;
MEM_SETW(dev, dev->regs[MSP430_REG_SP], src_data); MEM_SETW(dev, dev->regs[MSP430_REG_SP], src_data);
if (amode == MSP430_AMODE_REGISTER)
cycles = 3;
else if (amode == MSP430_AMODE_INDIRECT ||
(amode == MSP430_AMODE_INDIRECT_INC &&
reg == MSP430_REG_PC))
cycles = 4;
else
cycles = 5;
break; break;
case MSP430_OP_CALL: case MSP430_OP_CALL:
@ -342,6 +379,12 @@ static int step_single(struct sim_device *dev, uint16_t ins)
MEM_SETW(dev, dev->regs[MSP430_REG_SP], MEM_SETW(dev, dev->regs[MSP430_REG_SP],
dev->regs[MSP430_REG_PC]); dev->regs[MSP430_REG_PC]);
dev->regs[MSP430_REG_PC] = src_data; dev->regs[MSP430_REG_PC] = src_data;
if (amode == MSP430_AMODE_REGISTER ||
amode == MSP430_AMODE_INDIRECT)
cycles = 4;
else
cycles = 5;
break; break;
case MSP430_OP_RETI: case MSP430_OP_RETI:
@ -364,7 +407,7 @@ static int step_single(struct sim_device *dev, uint16_t ins)
store_operand(dev, amode, reg, is_byte, src_addr, res_data) < 0) store_operand(dev, amode, reg, is_byte, src_addr, res_data) < 0)
return -1; return -1;
return 0; return cycles;
} }
static int step_jump(struct sim_device *dev, uint16_t ins) static int step_jump(struct sim_device *dev, uint16_t ins)
@ -415,9 +458,12 @@ static int step_jump(struct sim_device *dev, uint16_t ins)
if (sr) if (sr)
dev->regs[MSP430_REG_PC] += pc_offset; dev->regs[MSP430_REG_PC] += pc_offset;
return 0; return 2;
} }
/* Fetch and execute one instruction. Return the number of CPU cycles
* it would have taken, or -1 if an error occurs.
*/
static int step_cpu(struct sim_device *dev) static int step_cpu(struct sim_device *dev)
{ {
uint16_t ins; uint16_t ins;
@ -443,6 +489,20 @@ static int step_cpu(struct sim_device *dev)
return ret; return ret;
} }
static int step_system(struct sim_device *dev)
{
int count = 1;
if (!(dev->regs[MSP430_REG_SR] & MSP430_SR_CPUOFF)) {
count = step_cpu(dev);
if (count < 0)
return -1;
}
simio_step(dev->regs[MSP430_REG_SR], count);
return 0;
}
/************************************************************************ /************************************************************************
* Device interface * Device interface
*/ */
@ -513,7 +573,9 @@ static int sim_ctl(device_t dev_base, device_ctl_t op)
case DEVICE_CTL_RESET: case DEVICE_CTL_RESET:
memset(dev->regs, 0, sizeof(dev->regs)); memset(dev->regs, 0, sizeof(dev->regs));
dev->regs[MSP430_REG_PC] = MEM_GETW(dev, 0xfffe); dev->regs[MSP430_REG_PC] = MEM_GETW(dev, 0xfffe);
dev->regs[MSP430_REG_SR] = 0;
simio_reset(); simio_reset();
simio_step(dev->regs[MSP430_REG_SR], 4);
return 0; return 0;
case DEVICE_CTL_HALT: case DEVICE_CTL_HALT:
@ -521,7 +583,7 @@ static int sim_ctl(device_t dev_base, device_ctl_t op)
return 0; return 0;
case DEVICE_CTL_STEP: case DEVICE_CTL_STEP:
return step_cpu(dev); return step_system(dev);
case DEVICE_CTL_RUN: case DEVICE_CTL_RUN:
dev->running = 1; dev->running = 1;
@ -578,13 +640,7 @@ static device_status_t sim_poll(device_t dev_base)
} }
} }
if (dev->regs[MSP430_REG_SR] & MSP430_SR_CPUOFF) { if (step_system(dev) < 0) {
printc("CPU disabled\n");
dev->running = 0;
return DEVICE_STATUS_HALTED;
}
if (step_cpu(dev) < 0) {
dev->running = 0; dev->running = 0;
return DEVICE_STATUS_ERROR; return DEVICE_STATUS_ERROR;
} }

View File

@ -361,6 +361,8 @@ void simio_step(uint16_t status_register, int cycles)
clocks[SIMIO_SMCLK] = cycles; clocks[SIMIO_SMCLK] = cycles;
clocks[SIMIO_ACLK] = aclk_counter >> 8; clocks[SIMIO_ACLK] = aclk_counter >> 8;
aclk_counter &= 0xff;
if (status_register & MSP430_SR_CPUOFF) if (status_register & MSP430_SR_CPUOFF)
clocks[SIMIO_MCLK] = 0; clocks[SIMIO_MCLK] = 0;

View File

@ -212,6 +212,8 @@ static int tracer_config(struct simio_device *dev,
else if (!strcasecmp(param, "clear")) { else if (!strcasecmp(param, "clear")) {
tr->head = 0; tr->head = 0;
tr->tail = 0; tr->tail = 0;
memset(tr->cycles, 0, sizeof(tr->cycles));
tr->inscount = 0;
} else if (!strcasecmp(param, "trigger")) { } else if (!strcasecmp(param, "trigger")) {
const char *irq_text = get_arg(arg_text); const char *irq_text = get_arg(arg_text);
address_t value; address_t value;