void arm_cpu_device::HandleMemSingle( UINT32 insn ) { UINT32 rn, rnv, off, rd; /* Fetch the offset */ if (insn & INSN_I) { off = decodeShift(insn, NULL); } else { off = insn & INSN_SDT_IMM; } /* Calculate Rn, accounting for PC */ rn = (insn & INSN_RN) >> INSN_RN_SHIFT; // if (rn==0xf) logerror("%08x: Source R15\n",R15); if (insn & INSN_SDT_P) { /* Pre-indexed addressing */ if (insn & INSN_SDT_U) { if (rn != eR15) rnv = (GetRegister(rn) + off); else rnv = (R15 & ADDRESS_MASK) + off; } else { if (rn != eR15) rnv = (GetRegister(rn) - off); else rnv = (R15 & ADDRESS_MASK) - off; } if (insn & INSN_SDT_W) { SetRegister(rn,rnv); if (ARM_DEBUG_CORE && rn == eR15) logerror("writeback R15 %08x\n", R15); } else if (rn == eR15) { rnv = rnv + 8; } } else { /* Post-indexed addressing */ if (rn == eR15) { rnv = (R15 & ADDRESS_MASK) + 8; } else { rnv = GetRegister(rn); } } /* Do the transfer */ rd = (insn & INSN_RD) >> INSN_RD_SHIFT; if (insn & INSN_SDT_L) { /* Load */ m_icount -= S_CYCLE + I_CYCLE + N_CYCLE; if (insn & INSN_SDT_B) { if (ARM_DEBUG_CORE && rd == eR15) logerror("read byte R15 %08x\n", R15); SetRegister(rd,(UINT32) cpu_read8(rnv) ); } else { if (rd == eR15) { R15 = (cpu_read32(rnv) & ADDRESS_MASK) | (R15 & PSR_MASK) | (R15 & MODE_MASK); /* The docs are explicit in that the bottom bits should be masked off when writing to R15 in this way, however World Cup Volleyball 95 has an example of an unaligned jump (bottom bits = 2) where execution should definitely continue from the rounded up address. In other cases, 4 is subracted from R15 here to account for pipelining. */ if ((cpu_read32(rnv)&3)==0) R15 -= 4; m_icount -= S_CYCLE + N_CYCLE; } else { SetRegister(rd, cpu_read32(rnv)); } } } else { /* Store */ m_icount -= 2 * N_CYCLE; if (insn & INSN_SDT_B) { if (ARM_DEBUG_CORE && rd==eR15) logerror("Wrote R15 in byte mode\n"); cpu_write8(rnv, (UINT8) GetRegister(rd) & 0xffu); } else { if (ARM_DEBUG_CORE && rd==eR15) logerror("Wrote R15 in 32bit mode\n"); cpu_write32(rnv, rd == eR15 ? R15 + 8 : GetRegister(rd)); } } /* Do post-indexing writeback */ if (!(insn & INSN_SDT_P)/* && (insn&INSN_SDT_W)*/) { if (insn & INSN_SDT_U) { /* Writeback is applied in pipeline, before value is read from mem, so writeback is effectively ignored */ if (rd==rn) { SetRegister(rn,GetRegister(rd)); } else { if ((insn&INSN_SDT_W)!=0) logerror("%08x: RegisterWritebackIncrement %d %d %d\n",R15,(insn & INSN_SDT_P)!=0,(insn&INSN_SDT_W)!=0,(insn & INSN_SDT_U)!=0); SetRegister(rn,(rnv + off)); } } else { /* Writeback is applied in pipeline, before value is read from mem, so writeback is effectively ignored */ if (rd==rn) { SetRegister(rn,GetRegister(rd)); } else { SetRegister(rn,(rnv - off)); if ((insn&INSN_SDT_W)!=0) logerror("%08x: RegisterWritebackDecrement %d %d %d\n",R15,(insn & INSN_SDT_P)!=0,(insn&INSN_SDT_W)!=0,(insn & INSN_SDT_U)!=0); } } } } /* HandleMemSingle */
static void HandleMemSingle( data32_t insn ) { data32_t rn, rnv, off, rd; /* Fetch the offset */ if (insn & INSN_I) { off = decodeShift(insn, NULL); } else { off = insn & INSN_SDT_IMM; } /* Calculate Rn, accounting for PC */ rn = (insn & INSN_RN) >> INSN_RN_SHIFT; // if (rn==0xf) logerror("%08x: Source R15\n",R15); if (insn & INSN_SDT_P) { /* Pre-indexed addressing */ if (insn & INSN_SDT_U) { rnv = (GetRegister(rn) + off); } else { rnv = (GetRegister(rn) - off); } if (insn & INSN_SDT_W) { SetRegister(rn,rnv); //check writeback??? } else if (rn == eR15) { rnv = (rnv & ADDRESS_MASK) + 8; } } else { /* Post-indexed addressing */ if (rn == eR15) { rnv = (R15 & ADDRESS_MASK) + 8; } else { rnv = GetRegister(rn); } } /* Do the transfer */ rd = (insn & INSN_RD) >> INSN_RD_SHIFT; if (insn & INSN_SDT_L) { /* Load */ if (insn & INSN_SDT_B) { SetRegister(rd,(data32_t) READ8(rnv)); } else { if (rd == eR15) { if (ARM_DEBUG_CORE) logerror("%08x: LDR to R15\n",R15); R15 = (READ32(rnv) & ADDRESS_MASK) | (R15 & PSR_MASK) | (R15 & MODE_MASK); R15 -= 4; } else { SetRegister(rd,READ32(rnv)); } } } else { /* Store */ if (insn & INSN_SDT_B) { if (ARM_DEBUG_CORE && rd==eR15) logerror("Wrote R15 in byte mode\n"); WRITE8(rnv, (data8_t) GetRegister(rd) & 0xffu); } else { if (ARM_DEBUG_CORE && rd==eR15) logerror("Wrote R15 in 32bit mode\n"); WRITE32(rnv, rd == eR15 ? R15 + 8 : GetRegister(rd)); } } /* Do post-indexing writeback */ if (!(insn & INSN_SDT_P)/* && (insn&INSN_SDT_W)*/) { if (insn & INSN_SDT_U) { /* Writeback is applied in pipeline, before value is read from mem, so writeback is effectively ignored */ if (rd==rn) { SetRegister(rn,GetRegister(rd)); //todo: check for offs... ? } else { if ((insn&INSN_SDT_W)!=0) logerror("%08x: RegisterWritebackIncrement %d %d %d\n",R15,(insn & INSN_SDT_P)!=0,(insn&INSN_SDT_W)!=0,(insn & INSN_SDT_U)!=0); SetRegister(rn,(rnv + off)); } } else { /* Writeback is applied in pipeline, before value is read from mem, so writeback is effectively ignored */ if (rd==rn) { SetRegister(rn,GetRegister(rd)); // logerror("Arm %08x: LDR style with rn==rn\n",R15); } else { SetRegister(rn,(rnv - off)); if ((insn&INSN_SDT_W)!=0) logerror("%08x: RegisterWritebackDecrement %d %d %d\n",R15,(insn & INSN_SDT_P)!=0,(insn&INSN_SDT_W)!=0,(insn & INSN_SDT_U)!=0); } } } // arm_check_irq_state() } /* HandleMemSingle */
static void HandleMemSingle( UINT32 insn ) { UINT32 rn, rnv, off, rd; /* Fetch the offset */ if (insn & INSN_I) { off = decodeShift(insn, NULL); } else { off = insn & INSN_SDT_IMM; } /* Calculate Rn, accounting for PC */ rn = (insn & INSN_RN) >> INSN_RN_SHIFT; if (insn & INSN_SDT_P) { /* Pre-indexed addressing */ if (insn & INSN_SDT_U) { rnv = (GetRegister(rn) + off); } else { rnv = (GetRegister(rn) - off); } if (insn & INSN_SDT_W) { SetRegister(rn,rnv); } else if (rn == eR15) { rnv = (rnv & ADDRESS_MASK) + 8; } } else { /* Post-indexed addressing */ if (rn == eR15) { rnv = (R15 & ADDRESS_MASK) + 8; } else { rnv = GetRegister(rn); } } /* Do the transfer */ rd = (insn & INSN_RD) >> INSN_RD_SHIFT; if (insn & INSN_SDT_L) { /* Load */ arm_icount -= S_CYCLE + I_CYCLE + N_CYCLE; if (insn & INSN_SDT_B) { SetRegister(rd,(UINT32) READ8(rnv)); } else { if (rd == eR15) { R15 = (READ32(rnv) & ADDRESS_MASK) | (R15 & PSR_MASK) | (R15 & MODE_MASK); change_pc(R15 & ADDRESS_MASK); /* The docs are explicit in that the bottom bits should be masked off when writing to R15 in this way, however World Cup Volleyball 95 has an example of an unaligned jump (bottom bits = 2) where execution should definitely continue from the rounded up address. In other cases, 4 is subracted from R15 here to account for pipelining. */ if ((READ32(rnv)&3)==0) R15 -= 4; arm_icount -= S_CYCLE + N_CYCLE; } else { SetRegister(rd,READ32(rnv)); } } } else { /* Store */ arm_icount -= 2 * N_CYCLE; if (insn & INSN_SDT_B) { WRITE8(rnv, (UINT8) GetRegister(rd) & 0xffu); } else { WRITE32(rnv, rd == eR15 ? R15 + 8 : GetRegister(rd)); } } /* Do post-indexing writeback */ if (!(insn & INSN_SDT_P)/* && (insn&INSN_SDT_W)*/) { if (insn & INSN_SDT_U) { /* Writeback is applied in pipeline, before value is read from mem, so writeback is effectively ignored */ if (rd==rn) { SetRegister(rn,GetRegister(rd)); } else { SetRegister(rn,(rnv + off)); } } else { /* Writeback is applied in pipeline, before value is read from mem, so writeback is effectively ignored */ if (rd==rn) { SetRegister(rn,GetRegister(rd)); } else { SetRegister(rn,(rnv - off)); } } } } /* HandleMemSingle */