arm7: revert previous changes, explicit masking and rotating was unneeded (except for POP {Rlist} which is correct),

handle v5 behavior (lsb address bit is ignored in 16bit loads) in arm946es_cpu_device::arm7_cpu_read16 instead,
manually handle v4 and v5 difference for LDRSH signed halfword load.

note: it looks like all? v5 cores ignore least significant address bit during 16bit loads, so we should add something like
virtual uint32_t arm7_cpu_read16(uint32_t addr) override { return base_class::arm7_cpu_read16(addr & ~1)};
into theirs class declaration.
This commit is contained in:
MetalliC 2017-12-25 14:18:56 +02:00
parent cca12e5a32
commit 779f50511c
3 changed files with 26 additions and 55 deletions

View File

@ -1425,29 +1425,20 @@ uint32_t arm946es_cpu_device::arm7_cpu_read32(uint32_t addr)
uint32_t arm946es_cpu_device::arm7_cpu_read16(uint32_t addr)
{
uint32_t result;
addr &= ~1;
if ((addr >= cp15_itcm_base) && (addr <= cp15_itcm_end))
{
uint16_t *wp = (uint16_t *)&ITCM[(addr & ~1)&0x7fff];
result = *wp;
uint16_t *wp = (uint16_t *)&ITCM[addr & 0x7fff];
return *wp;
}
else if ((addr >= cp15_dtcm_base) && (addr <= cp15_dtcm_end))
{
uint16_t *wp = (uint16_t *)&DTCM[(addr & ~1)&0x3fff];
result = *wp;
}
else
{
result = m_program->read_word(addr & ~1);
uint16_t *wp = (uint16_t *)&DTCM[addr &0x3fff];
return *wp;
}
if (addr & 1)
{
result = ((result >> 8) & 0xff) | ((result & 0xff) << 24);
}
return result;
return m_program->read_word(addr);
}
uint8_t arm946es_cpu_device::arm7_cpu_read8(uint32_t addr)

View File

@ -648,10 +648,10 @@ void arm7_cpu_device::HandleHalfWordDT(uint32_t insn)
// Signed Half Word?
if (insn & 0x20) {
uint32_t databyte = READ16(rnv);
uint32_t mask = 0x0000ffff;
mask >>= (rnv & 1) ? 8 : 0;
newval = databyte | ((databyte & ((mask + 1) >> 1)) ? ~mask : 0);
int32_t data = (int32_t)(int16_t)(uint16_t)READ16(rnv & ~1);
if ((rnv & 1) && m_archRev < 5)
data >>= 8;
newval = (uint32_t)data;
}
// Signed Byte
else {

View File

@ -977,7 +977,7 @@ void arm7_cpu_device::tg05_0(uint32_t pc, uint32_t op) /* STR Rd, [Rn, Rm] */
uint32_t rn = (op & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT;
uint32_t rd = (op & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT;
uint32_t addr = GetRegister(rn) + GetRegister(rm);
WRITE32(addr & ~3, GetRegister(rd));
WRITE32(addr, GetRegister(rd));
R15 += 2;
}
@ -987,7 +987,7 @@ void arm7_cpu_device::tg05_1(uint32_t pc, uint32_t op) /* STRH Rd, [Rn, Rm] */
uint32_t rn = (op & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT;
uint32_t rd = (op & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT;
uint32_t addr = GetRegister(rn) + GetRegister(rm);
WRITE16(addr & ~1, GetRegister(rd));
WRITE16(addr, GetRegister(rd));
R15 += 2;
}
@ -1022,9 +1022,8 @@ void arm7_cpu_device::tg05_4(uint32_t pc, uint32_t op) /* LDR Rd, [Rn, Rm] */
uint32_t rn = (op & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT;
uint32_t rd = (op & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT;
uint32_t addr = GetRegister(rn) + GetRegister(rm);
uint32_t tmp = READ32(addr & ~3);
addr = (addr & 3) << 3;
SetRegister(rd, ROR(tmp, addr));
uint32_t op2 = READ32(addr);
SetRegister(rd, op2);
R15 += 2;
}
@ -1034,12 +1033,7 @@ void arm7_cpu_device::tg05_5(uint32_t pc, uint32_t op) /* LDRH Rd, [Rn, Rm] */
uint32_t rn = (op & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT;
uint32_t rd = (op & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT;
uint32_t addr = GetRegister(rn) + GetRegister(rm);
uint32_t op2 = READ16(addr & ~1);
if (m_archRev < 5)
{
addr = (addr & 1) << 3;
op2 = ROR(op2, addr);
}
uint32_t op2 = READ16(addr);
SetRegister(rd, op2);
R15 += 2;
}
@ -1061,14 +1055,9 @@ void arm7_cpu_device::tg05_7(uint32_t pc, uint32_t op) /* LDSH Rd, [Rn, Rm] */
uint32_t rn = (op & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT;
uint32_t rd = (op & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT;
uint32_t addr = GetRegister(rn) + GetRegister(rm);
uint32_t op2 = READ16(addr & ~1);
int32_t op2 = (int32_t)(int16_t)(uint16_t)READ16(addr & ~1);
if ((addr & 1) && m_archRev < 5)
op2 = (uint32_t)(((int32_t)(op2 << 16)) >> 24);
else
if (op2 & 0x00008000)
{
op2 |= 0xffff0000;
}
op2 >>= 8;
SetRegister(rd, op2);
R15 += 2;
}
@ -1080,7 +1069,7 @@ void arm7_cpu_device::tg06_0(uint32_t pc, uint32_t op) /* Store */
uint32_t rn = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
uint32_t rd = op & THUMB_ADDSUB_RD;
int32_t offs = ((op & THUMB_LSOP_OFFS) >> THUMB_LSOP_OFFS_SHIFT) << 2;
WRITE32((GetRegister(rn) + offs) & ~3, GetRegister(rd));
WRITE32(GetRegister(rn) + offs, GetRegister(rd));
R15 += 2;
}
@ -1088,10 +1077,8 @@ void arm7_cpu_device::tg06_1(uint32_t pc, uint32_t op) /* Load */
{
uint32_t rn = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
uint32_t rd = op & THUMB_ADDSUB_RD;
uint32_t addr = GetRegister(rn) + (((op & THUMB_LSOP_OFFS) >> THUMB_LSOP_OFFS_SHIFT) << 2);
uint32_t tmp = READ32(addr & ~3);
addr = (addr & 3) << 3;
SetRegister(rd, ROR(tmp, addr));
int32_t offs = ((op & THUMB_LSOP_OFFS) >> THUMB_LSOP_OFFS_SHIFT) << 2;
SetRegister(rd, READ32(GetRegister(rn) + offs)); // fix
R15 += 2;
}
@ -1122,7 +1109,7 @@ void arm7_cpu_device::tg08_0(uint32_t pc, uint32_t op) /* Store */
uint32_t imm = (op & THUMB_HALFOP_OFFS) >> THUMB_HALFOP_OFFS_SHIFT;
uint32_t rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
uint32_t rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
WRITE16((GetRegister(rs) + (imm << 1)) & ~1, GetRegister(rd));
WRITE16(GetRegister(rs) + (imm << 1), GetRegister(rd));
R15 += 2;
}
@ -1131,14 +1118,7 @@ void arm7_cpu_device::tg08_1(uint32_t pc, uint32_t op) /* Load */
uint32_t imm = (op & THUMB_HALFOP_OFFS) >> THUMB_HALFOP_OFFS_SHIFT;
uint32_t rs = (op & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
uint32_t rd = (op & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
uint32_t addr = GetRegister(rs) + (imm << 1);
uint32_t op2 = READ16(addr & ~1);
if (m_archRev < 5)
{
addr = (addr & 1) << 3;
op2 = ROR(op2, addr);
}
SetRegister(rd, op2);
SetRegister(rd, READ16(GetRegister(rs) + (imm << 1)));
R15 += 2;
}
@ -1148,7 +1128,7 @@ void arm7_cpu_device::tg09_0(uint32_t pc, uint32_t op) /* Store */
{
uint32_t rd = (op & THUMB_STACKOP_RD) >> THUMB_STACKOP_RD_SHIFT;
int32_t offs = (uint8_t)(op & THUMB_INSN_IMM);
WRITE32((GetRegister(13) + ((uint32_t)offs << 2)) & ~3, GetRegister(rd));
WRITE32(GetRegister(13) + ((uint32_t)offs << 2), GetRegister(rd));
R15 += 2;
}
@ -1211,7 +1191,7 @@ void arm7_cpu_device::tg0b_4(uint32_t pc, uint32_t op) /* PUSH {Rlist} */
if (op & (1 << offs))
{
SetRegister(13, GetRegister(13) - 4);
WRITE32(GetRegister(13) & ~3, GetRegister(offs));
WRITE32(GetRegister(13), GetRegister(offs));
}
}
R15 += 2;
@ -1220,13 +1200,13 @@ void arm7_cpu_device::tg0b_4(uint32_t pc, uint32_t op) /* PUSH {Rlist} */
void arm7_cpu_device::tg0b_5(uint32_t pc, uint32_t op) /* PUSH {Rlist}{LR} */
{
SetRegister(13, GetRegister(13) - 4);
WRITE32(GetRegister(13) & ~3, GetRegister(14));
WRITE32(GetRegister(13), GetRegister(14));
for (int32_t offs = 7; offs >= 0; offs--)
{
if (op & (1 << offs))
{
SetRegister(13, GetRegister(13) - 4);
WRITE32(GetRegister(13) & ~3, GetRegister(offs));
WRITE32(GetRegister(13), GetRegister(offs));
}
}
R15 += 2;