Fixed spurious IO reads from MOV instructions.

This commit is contained in:
Daniel Beer 2010-03-20 16:18:06 +13:00
parent b4d3b44fef
commit 4207badb6e
1 changed files with 46 additions and 22 deletions

68
sim.c
View File

@ -100,21 +100,29 @@ static void store_io(u_int16_t addr, int is_byte, u_int16_t data)
printf(" => 0x%04x\n", data); printf(" => 0x%04x\n", data);
} }
static u_int16_t fetch_operand(int amode, int reg, int is_byte, static void fetch_operand(int amode, int reg, int is_byte,
u_int16_t *addr_ret) u_int16_t *addr_ret, u_int32_t *data_ret)
{ {
u_int16_t addr = 0; u_int16_t addr = 0;
u_int32_t mask = is_byte ? 0xff : 0xffff; u_int32_t mask = is_byte ? 0xff : 0xffff;
switch (amode) { switch (amode) {
case MSP430_AMODE_REGISTER: case MSP430_AMODE_REGISTER:
if (reg == MSP430_REG_R3) if (reg == MSP430_REG_R3) {
return 0; if (data_ret)
return sim_regs[reg] & mask; *data_ret = 0;
return;
}
if (data_ret)
*data_ret = sim_regs[reg] & mask;
return;
case MSP430_AMODE_INDEXED: case MSP430_AMODE_INDEXED:
if (reg == MSP430_REG_R3) if (reg == MSP430_REG_R3) {
return 1; if (data_ret)
*data_ret = 1;
return;
}
addr = MEM_GETW(sim_regs[MSP430_REG_PC]); addr = MEM_GETW(sim_regs[MSP430_REG_PC]);
sim_regs[MSP430_REG_PC] += 2; sim_regs[MSP430_REG_PC] += 2;
@ -124,18 +132,31 @@ static u_int16_t fetch_operand(int amode, int reg, int is_byte,
break; break;
case MSP430_AMODE_INDIRECT: case MSP430_AMODE_INDIRECT:
if (reg == MSP430_REG_SR) if (reg == MSP430_REG_SR) {
return 4; if (data_ret)
if (reg == MSP430_REG_R3) *data_ret = 4;
return 2; return;
}
if (reg == MSP430_REG_R3) {
if (data_ret)
*data_ret = 2;
return;
}
addr = sim_regs[reg]; addr = sim_regs[reg];
break; break;
case MSP430_AMODE_INDIRECT_INC: case MSP430_AMODE_INDIRECT_INC:
if (reg == MSP430_REG_SR) if (reg == MSP430_REG_SR) {
return 8; if (data_ret)
if (reg == MSP430_REG_R3) *data_ret = 8;
return mask; return;
}
if (reg == MSP430_REG_R3) {
if (data_ret)
*data_ret = mask;
return;
}
addr = sim_regs[reg]; addr = sim_regs[reg];
sim_regs[reg] += 2; sim_regs[reg] += 2;
break; break;
@ -144,10 +165,12 @@ static u_int16_t fetch_operand(int amode, int reg, int is_byte,
if (addr_ret) if (addr_ret)
*addr_ret = addr; *addr_ret = addr;
if (addr < MEM_IO_END) if (data_ret) {
return fetch_io(addr, is_byte); if (addr < MEM_IO_END)
*data_ret = fetch_io(addr, is_byte);
return MEM_GETW(addr) & mask; else
*data_ret = MEM_GETW(addr) & mask;
}
} }
static void store_operand(int amode, int reg, int is_byte, static void store_operand(int amode, int reg, int is_byte,
@ -179,8 +202,9 @@ static int step_double(u_int16_t ins)
u_int32_t res_data; u_int32_t res_data;
u_int32_t msb = is_byte ? 0x80 : 0x8000; u_int32_t msb = is_byte ? 0x80 : 0x8000;
src_data = fetch_operand(amode_src, sreg, is_byte, NULL); fetch_operand(amode_src, sreg, is_byte, NULL, &src_data);
dst_data = fetch_operand(amode_dst, dreg, is_byte, &dst_addr); fetch_operand(amode_dst, dreg, is_byte, &dst_addr,
opcode == MSP430_OP_MOV ? NULL : &dst_data);
switch (opcode) { switch (opcode) {
case MSP430_OP_MOV: case MSP430_OP_MOV:
@ -285,7 +309,7 @@ static int step_single(u_int16_t ins)
u_int32_t src_data; u_int32_t src_data;
u_int32_t res_data; u_int32_t res_data;
src_data = fetch_operand(amode, reg, is_byte, &src_addr); fetch_operand(amode, reg, is_byte, &src_addr, &src_data);
switch (opcode) { switch (opcode) {
case MSP430_OP_RRC: case MSP430_OP_RRC: