unsigned arm_dasm(char *buffer, unsigned int pc) { #ifdef MAME_DEBUG arm_disasm( buffer, pc, cpu_read32(pc&ADDRESS_MASK) ); return 4; #else sprintf(buffer, "$%08x", READ32(pc)); return 4; #endif }
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 */
void arm2_execute_run(int tube_cycles) { #ifdef TRACE int i; #endif UINT32 pc; UINT32 insn; //int m_icount = number; do { //debugger_instruction_hook(this, R15 & ADDRESS_MASK); /* load instruction */ pc = R15; #ifdef INCLUDE_DEBUGGER if (arm2_debug_enabled) { debug_preexec(&arm2_cpu_debug, pc & ADDRESS_MASK); } #endif insn = cpu_read32( pc & ADDRESS_MASK ); #ifdef TRACE if ((pc & ADDRESS_MASK) == 0xa060) { m_trace = 1; } if (m_trace) { printf("%08X %08X ", pc, insn); for (i = eR0; i <= eR7; i++) { printf("%08X ", m_sArmRegister[i]); } if(darm_armv7_disasm(&d, insn) == 0 && darm_str2(&d, &str, 0) == 0) { printf("%s\r\n", str.total); } else { printf("***\r\n"); } } if ((pc & ADDRESS_MASK) == 0xa0c0) { m_trace = 0; } if ((pc & ADDRESS_MASK) == 0xa2ac) { m_trace = 0; } if ((insn & 0x0D900000) == 0x01000000) { printf("S bit not set in %08x at %08x\r\n", insn, pc & ADDRESS_MASK); insn |= INSN_S; } #endif switch (insn >> INSN_COND_SHIFT) { case COND_EQ: if (Z_IS_CLEAR(pc)) goto L_Next; break; case COND_NE: if (Z_IS_SET(pc)) goto L_Next; break; case COND_CS: if (C_IS_CLEAR(pc)) goto L_Next; break; case COND_CC: if (C_IS_SET(pc)) goto L_Next; break; case COND_MI: if (N_IS_CLEAR(pc)) goto L_Next; break; case COND_PL: if (N_IS_SET(pc)) goto L_Next; break; case COND_VS: if (V_IS_CLEAR(pc)) goto L_Next; break; case COND_VC: if (V_IS_SET(pc)) goto L_Next; break; case COND_HI: if (C_IS_CLEAR(pc) || Z_IS_SET(pc)) goto L_Next; break; case COND_LS: if (C_IS_SET(pc) && Z_IS_CLEAR(pc)) goto L_Next; break; case COND_GE: if (!(pc & N_MASK) != !(pc & V_MASK)) goto L_Next; /* Use x ^ (x >> ...) method */ break; case COND_LT: if (!(pc & N_MASK) == !(pc & V_MASK)) goto L_Next; break; case COND_GT: if (Z_IS_SET(pc) || (!(pc & N_MASK) != !(pc & V_MASK))) goto L_Next; break; case COND_LE: if (Z_IS_CLEAR(pc) && (!(pc & N_MASK) == !(pc & V_MASK))) goto L_Next; break; case COND_NV: goto L_Next; } /* Condition satisfied, so decode the instruction */ if ((insn & 0x0fc000f0u) == 0x00000090u) /* Multiplication */ { HandleMul(insn); R15 += 4; } else if (!(insn & 0x0c000000u)) /* Data processing */ { HandleALU(insn); } else if ((insn & 0x0c000000u) == 0x04000000u) /* Single data access */ { HandleMemSingle(insn); R15 += 4; } else if ((insn & 0x0e000000u) == 0x08000000u ) /* Block data access */ { HandleMemBlock(insn); R15 += 4; } else if ((insn & 0x0e000000u) == 0x0a000000u) /* Branch */ { HandleBranch(insn); } else if ((insn & 0x0f000000u) == 0x0e000000u) /* Coprocessor */ { if (m_copro_type == ARM_COPRO_TYPE_VL86C020) HandleCoProVL86C020(insn); else HandleCoPro(insn); R15 += 4; } else if ((insn & 0x0f000000u) == 0x0f000000u) /* Software interrupt */ { pc=R15+4; R15 = eARM_MODE_SVC; /* Set SVC mode so PC is saved to correct R14 bank */ SetRegister( 14, pc ); /* save PC */ R15 = (pc&PSR_MASK)|(pc&IRQ_MASK)|0x8|eARM_MODE_SVC|I_MASK|(pc&MODE_MASK); CYCLE_COUNT(2 * S_CYCLE + N_CYCLE); } else /* Undefined */ { logerror("%08x: Undefined instruction\n",R15); L_Next: CYCLE_COUNT(S_CYCLE); R15 += 4; } //arm2_check_irq_state(); tubeUseCycles(1); } while (tubeContinueRunning()); //while( m_icount > 0 ); //while (number--); } /* arm_execute */