| 253 | // |
| 254 | //************************************************************************************* |
| 255 | CFragment * CFragment::Simulate() |
| 256 | { |
| 257 | #ifdef DAEDALUS_ENABLE_ASSERTS |
| 258 | DAEDALUS_ASSERT( gCPUState.GetStuffToDo() == 0, "Entering when there is stuff to do?" ); |
| 259 | DAEDALUS_ASSERT( gCPUState.CurrentPC == mEntryAddress, "Why are we entering at the wrong address?" ); |
| 260 | DAEDALUS_ASSERT( gCPUState.Delay == NO_DELAY, "Why are we entering with a delay slot active?" ); |
| 261 | #endif |
| 262 | #ifdef FRAGMENT_RETAIN_ADDITIONAL_INFO |
| 263 | mHitCount++; |
| 264 | #endif |
| 265 | |
| 266 | // |
| 267 | // Keep executing ops until we take a branch |
| 268 | // |
| 269 | u32 instructions_executed( 0 ); |
| 270 | |
| 271 | u32 branch_idx_taken( INVALID_IDX ); // Index into mBranchBuffer of the taken branch |
| 272 | u32 branch_taken_address( 0 ); |
| 273 | bool checked_cop1_usable( false ); |
| 274 | |
| 275 | u32 count_entry( gCPUState.CPUControl[C0_COUNT]._u32_0 ); |
| 276 | |
| 277 | OpCode last_executed_op; |
| 278 | |
| 279 | for( auto i {}; i < mTraceBuffer.size(); ++i) |
| 280 | { |
| 281 | const STraceEntry & ti( mTraceBuffer[ i ] ); |
| 282 | OpCode op_code( ti.OpCode ); |
| 283 | u32 branch_idx( ti.BranchIdx ); |
| 284 | |
| 285 | #ifdef DAEDALUS_ENABLE_ASSERTS |
| 286 | DAEDALUS_ASSERT( op_code._u32 == *(u32*)ReadAddress( ti.Address ), "Self modifying code detected but not handled" ); |
| 287 | #endif |
| 288 | bool branch_taken; |
| 289 | |
| 290 | if( ti.BranchDelaySlot ) |
| 291 | { |
| 292 | gCPUState.Delay = EXEC_DELAY; |
| 293 | } |
| 294 | |
| 295 | DAEDALUS_ASSERT( gCPUState.Delay == (ti.BranchDelaySlot ? EXEC_DELAY : NO_DELAY), "Delay doesn't match expectations" ); |
| 296 | |
| 297 | // Check the cop1 usable flag. Do this only once (theoretically it could be toggled mid-fragment but this is unlikely) |
| 298 | if( op_code.op == OP_COPRO1 && !checked_cop1_usable ) |
| 299 | { |
| 300 | checked_cop1_usable = true; |
| 301 | CheckCop1Usable(); |
| 302 | if(gCPUState.GetStuffToDo() != 0) |
| 303 | { |
| 304 | UpdateCountAndHandleException_Counter( instructions_executed ); |
| 305 | return nullptr; |
| 306 | } |
| 307 | } |
| 308 | |
| 309 | last_executed_op = op_code; |
| 310 | |
| 311 | CPU_ExecuteOpRaw( count_entry+instructions_executed, ti.Address, op_code, R4300_GetInstructionHandler( op_code ), &branch_taken ); |
| 312 |
no test coverage detected