Changeset 13301
- Timestamp:
- 10/15/08 22:17:20 (3 months ago)
- Files:
-
- trunk/src/recompiler_new/cpu-exec.c (modified) (47 diffs)
- trunk/src/recompiler_new/exec.c (modified) (49 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/src/recompiler_new/cpu-exec.c
r13117 r13301 28 28 */ 29 29 #include "config.h" 30 #define CPU_NO_GLOBAL_REGS 30 31 #include "exec.h" 31 32 #include "disas.h" 33 #include "tcg.h" 32 34 33 35 #if !defined(CONFIG_SOFTMMU) … … 45 47 #endif 46 48 49 #if defined(__sparc__) && !defined(HOST_SOLARIS) 50 // Work around ugly bugs in glibc that mangle global register contents 51 #undef env 52 #define env cpu_single_env 53 #endif 54 47 55 int tb_invalidated_flag; 48 56 … … 50 58 //#define DEBUG_SIGNAL 51 59 52 #if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_M68K) 53 /* XXX: unify with i386 target */ 60 54 61 void cpu_loop_exit(void) 55 62 { 63 /* NOTE: the register at this point must be saved by hand because 64 longjmp restore them */ 65 regs_to_env(); 56 66 longjmp(env->jmp_env, 1); 57 67 } 58 #endif 68 59 69 #if !(defined(TARGET_SPARC) || defined(TARGET_SH4) || defined(TARGET_M68K)) 60 70 #define reg_T2 … … 83 93 } 84 94 95 /* Execute the code without caching the generated code. An interpreter 96 could be used if available. */ 97 static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb) 98 { 99 unsigned long next_tb; 100 TranslationBlock *tb; 101 102 /* Should never happen. 103 We only end up here when an existing TB is too long. */ 104 if (max_cycles > CF_COUNT_MASK) 105 max_cycles = CF_COUNT_MASK; 106 107 tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags, 108 max_cycles); 109 env->current_tb = tb; 110 /* execute the generated code */ 111 next_tb = tcg_qemu_tb_exec(tb->tc_ptr); 112 113 if ((next_tb & 3) == 2) { 114 /* Restore PC. This may happen if async event occurs before 115 the TB starts executing. */ 116 CPU_PC_FROM_TB(env, tb); 117 } 118 tb_phys_invalidate(tb, -1); 119 tb_free(tb); 120 } 85 121 86 122 static TranslationBlock *tb_find_slow(target_ulong pc, 87 123 target_ulong cs_base, 88 u nsigned int flags)124 uint64_t flags) 89 125 { 90 126 TranslationBlock *tb, **ptb1; 91 int code_gen_size;92 127 unsigned int h; 93 128 target_ulong phys_pc, phys_page1, phys_page2, virt_page2; 94 uint8_t *tc_ptr;95 96 spin_lock(&tb_lock);97 129 98 130 tb_invalidated_flag = 0; … … 128 160 } 129 161 not_found: 130 /* if no translated code available, then translate it now */ 131 tb = tb_alloc(pc); 132 if (!tb) { 133 /* flush must be done */ 134 tb_flush(env); 135 /* cannot fail at this point */ 136 tb = tb_alloc(pc); 137 /* don't forget to invalidate previous TB info */ 138 tb_invalidated_flag = 1; 139 } 140 tc_ptr = code_gen_ptr; 141 tb->tc_ptr = tc_ptr; 142 tb->cs_base = cs_base; 143 tb->flags = flags; 144 cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE, &code_gen_size); 145 code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1)); 146 147 /* check next page if needed */ 148 virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK; 149 phys_page2 = -1; 150 if ((pc & TARGET_PAGE_MASK) != virt_page2) { 151 phys_page2 = get_phys_addr_code(env, virt_page2); 152 } 153 tb_link_phys(tb, phys_pc, phys_page2); 162 /* if no translated code available, then translate it now */ 163 tb = tb_gen_code(env, pc, cs_base, flags, 0); 154 164 155 165 found: 156 166 /* we add the TB in the virtual pc hash table */ 157 167 env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb; 158 spin_unlock(&tb_lock);159 168 return tb; 160 169 } … … 164 173 TranslationBlock *tb; 165 174 target_ulong cs_base, pc; 166 u nsigned int flags;175 uint64_t flags; 167 176 168 177 /* we record a subset of the CPU state. It will … … 181 190 if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) 182 191 flags |= (1 << 7); 192 flags |= (env->condexec_bits << 8); 183 193 cs_base = 0; 184 194 pc = env->regs[15]; 185 195 #elif defined(TARGET_SPARC) 186 196 #ifdef TARGET_SPARC64 187 // Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled 188 flags = (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2)) 197 // AM . Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled 198 flags = ((env->pstate & PS_AM) << 2) 199 | (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2)) 189 200 | (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2); 190 201 #else 191 // FPU enable . MMU enabled . MMU no-fault . Supervisor 192 flags = (env->psref << 3) | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1) 193 | env->psrs; 202 // FPU enable . Supervisor 203 flags = (env->psref << 4) | env->psrs; 194 204 #endif 195 205 cs_base = env->npc; 196 206 pc = env->pc; 197 207 #elif defined(TARGET_PPC) 198 flags = (msr_pr << MSR_PR) | (msr_fp << MSR_FP) | 199 (msr_se << MSR_SE) | (msr_le << MSR_LE); 208 flags = env->hflags; 200 209 cs_base = 0; 201 210 pc = env->nip; … … 203 212 flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK); 204 213 cs_base = 0; 205 pc = env-> PC;214 pc = env->active_tc.PC; 206 215 #elif defined(TARGET_M68K) 207 flags = env->fpcr & M68K_FPCR_PREC; 216 flags = (env->fpcr & M68K_FPCR_PREC) /* Bit 6 */ 217 | (env->sr & SR_S) /* Bit 13 */ 218 | ((env->macsr >> 4) & 0xf); /* Bits 0-3 */ 208 219 cs_base = 0; 209 220 pc = env->pc; 210 221 #elif defined(TARGET_SH4) 211 flags = env->sr & (SR_MD | SR_RB); 212 cs_base = 0; /* XXXXX */ 222 flags = (env->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL 223 | DELAY_SLOT_TRUE | DELAY_SLOT_CLEARME)) /* Bits 0- 3 */ 224 | (env->fpscr & (FPSCR_FR | FPSCR_SZ | FPSCR_PR)) /* Bits 19-21 */ 225 | (env->sr & (SR_MD | SR_RB)); /* Bits 29-30 */ 226 cs_base = 0; 227 pc = env->pc; 228 #elif defined(TARGET_ALPHA) 229 flags = env->ps; 230 cs_base = 0; 231 pc = env->pc; 232 #elif defined(TARGET_CRIS) 233 flags = env->pregs[PR_CCS] & (S_FLAG | P_FLAG | U_FLAG | X_FLAG); 234 flags |= env->dslot; 235 cs_base = 0; 213 236 pc = env->pc; 214 237 #else … … 216 239 #endif 217 240 tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)]; 218 if ( __builtin_expect(!tb || tb->pc != pc || tb->cs_base != cs_base ||219 tb->flags != flags, 0)) {241 if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base || 242 tb->flags != flags)) { 220 243 tb = tb_find_slow(pc, cs_base, flags); 221 /* Note: we do it here to avoid a gcc bug on Mac OS X when222 doing it in tb_find_slow */223 if (tb_invalidated_flag) {224 /* as some TB could have been invalidated because225 of memory exceptions while generating the code, we226 must recompute the hash index here */227 T0 = 0;228 }229 244 } 230 245 return tb; 231 246 } 232 233 247 234 248 /* main execution loop */ … … 241 255 #include "hostregs_helper.h" 242 256 int ret, interrupt_request; 243 void (*gen_func)(void);244 257 TranslationBlock *tb; 245 258 uint8_t *tc_ptr; 246 247 #if defined(TARGET_I386) 248 /* handle exit of HALTED state */ 249 if (env1->hflags & HF_HALTED_MASK) { 250 /* disable halt condition */ 251 if ((env1->interrupt_request & CPU_INTERRUPT_HARD) && 252 (env1->eflags & IF_MASK)) { 253 env1->hflags &= ~HF_HALTED_MASK; 254 } else { 255 return EXCP_HALTED; 256 } 257 } 258 #elif defined(TARGET_PPC) 259 if (env1->halted) { 260 if (env1->msr[MSR_EE] && 261 (env1->interrupt_request & 262 (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER))) { 263 env1->halted = 0; 264 } else { 265 return EXCP_HALTED; 266 } 267 } 268 #elif defined(TARGET_SPARC) 269 if (env1->halted) { 270 if ((env1->interrupt_request & CPU_INTERRUPT_HARD) && 271 (env1->psret != 0)) { 272 env1->halted = 0; 273 } else { 274 return EXCP_HALTED; 275 } 276 } 277 #elif defined(TARGET_ARM) 278 if (env1->halted) { 279 /* An interrupt wakes the CPU even if the I and F CPSR bits are 280 set. */ 281 if (env1->interrupt_request 282 & (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD)) { 283 env1->halted = 0; 284 } else { 285 return EXCP_HALTED; 286 } 287 } 288 #elif defined(TARGET_MIPS) 289 if (env1->halted) { 290 if (env1->interrupt_request & 291 (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER)) { 292 env1->halted = 0; 293 } else { 294 return EXCP_HALTED; 295 } 296 } 297 #endif 259 unsigned long next_tb; 260 261 if (cpu_halted(env1) == EXCP_HALTED) 262 return EXCP_HALTED; 298 263 299 264 cpu_single_env = env1; … … 303 268 #include "hostregs_helper.h" 304 269 env = env1; 305 #if defined(__sparc__) && !defined(HOST_SOLARIS) 306 /* we also save i7 because longjmp may not restore it */ 307 asm volatile ("mov %%i7, %0" : "=r" (saved_i7)); 308 #endif 309 270 271 env_to_regs(); 310 272 #if defined(TARGET_I386) 311 312 env_to_regs();313 273 /* put eflags in CPU temporary format */ 314 274 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); … … 316 276 CC_OP = CC_OP_EFLAGS; 317 277 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); 278 #elif defined(TARGET_SPARC) 279 #elif defined(TARGET_M68K) 280 env->cc_op = CC_OP_FLAGS; 281 env->cc_dest = env->sr & 0xf; 282 env->cc_x = (env->sr >> 4) & 1; 283 #elif defined(TARGET_ALPHA) 318 284 #elif defined(TARGET_ARM) 319 #elif defined(TARGET_SPARC)320 #if defined(reg_REGWPTR)321 saved_regwptr = REGWPTR;322 #endif323 285 #elif defined(TARGET_PPC) 324 286 #elif defined(TARGET_MIPS) 325 287 #elif defined(TARGET_SH4) 288 #elif defined(TARGET_CRIS) 326 289 /* XXXXX */ 327 290 #else … … 345 308 if (env->interrupt_request & CPU_INTERRUPT_RC) { 346 309 env->exception_index = EXCP_RC; 347 ASMAtomicAndS32( &env->interrupt_request, ~CPU_INTERRUPT_RC);310 ASMAtomicAndS32((int32_t volatile *)&env->interrupt_request, ~CPU_INTERRUPT_RC); 348 311 ret = env->exception_index; 349 312 cpu_loop_exit(); … … 367 330 env->error_code, 368 331 env->exception_next_eip, 0); 332 /* successfully delivered */ 333 env->old_exception = -1; 369 334 RAWEx_ProfileStop(env, STATS_IRQ_HANDLING); 370 335 } … … 372 337 } 373 338 374 T0= 0; /* force lookup of first TB */339 next_tb = 0; /* force lookup of first TB */ 375 340 for(;;) 376 341 { … … 378 343 if (__builtin_expect(interrupt_request, 0)) 379 344 { 345 /** @todo: reconscille with what QEMU really does */ 346 380 347 /* Single instruction exec request, we execute it and return (one way or the other). 381 348 The caller will always reschedule after doing this operation! */ … … 385 352 if (!(env->interrupt_request & CPU_INTERRUPT_SINGLE_INSTR_IN_FLIGHT)) 386 353 { 387 ASMAtomicOrS32( &env->interrupt_request, CPU_INTERRUPT_SINGLE_INSTR_IN_FLIGHT);354 ASMAtomicOrS32((int32_t volatile *)&env->interrupt_request, CPU_INTERRUPT_SINGLE_INSTR_IN_FLIGHT); 388 355 env->exception_index = EXCP_SINGLE_INSTR; 389 356 if (emulate_single_instr(env) == -1) … … 405 372 } 406 373 /* Clear CPU_INTERRUPT_SINGLE_INSTR and leave CPU_INTERRUPT_SINGLE_INSTR_IN_FLIGHT set. */ 407 ASMAtomicAndS32( &env->interrupt_request, ~CPU_INTERRUPT_SINGLE_INSTR);374 ASMAtomicAndS32((int32_t volatile *)&env->interrupt_request, ~CPU_INTERRUPT_SINGLE_INSTR); 408 375 } 409 376 … … 413 380 env->interrupt_request &= ~CPU_INTERRUPT_SMI; 414 381 do_smm_enter(); 415 T0= 0;382 next_tb = 0; 416 383 } 417 384 else if ((interrupt_request & CPU_INTERRUPT_HARD) && … … 421 388 /* if hardware interrupt pending, we execute it */ 422 389 int intno; 423 ASMAtomicAndS32( &env->interrupt_request, ~CPU_INTERRUPT_HARD);390 ASMAtomicAndS32((int32_t volatile *)&env->interrupt_request, ~CPU_INTERRUPT_HARD); 424 391 intno = cpu_get_pic_interrupt(env); 425 392 if (intno >= 0) … … 430 397 /* ensure that no TB jump will be modified as 431 398 the program flow was changed */ 432 T0= 0;399 next_tb = 0; 433 400 } 434 401 if (env->interrupt_request & CPU_INTERRUPT_EXITTB) 435 402 { 436 ASMAtomicAndS32( &env->interrupt_request, ~CPU_INTERRUPT_EXITTB);403 ASMAtomicAndS32((int32_t volatile *)&env->interrupt_request, ~CPU_INTERRUPT_EXITTB); 437 404 /* ensure that no TB jump will be modified as 438 405 the program flow was changed */ 439 T0= 0;406 next_tb = 0; 440 407 } 441 408 RAWEx_ProfileStop(env, STATS_IRQ_HANDLING); … … 443 410 { 444 411 env->exception_index = EXCP_INTERRUPT; 445 ASMAtomicAndS32( &env->interrupt_request, ~CPU_INTERRUPT_EXIT);412 ASMAtomicAndS32((int32_t volatile *)&env->interrupt_request, ~CPU_INTERRUPT_EXIT); 446 413 ret = env->exception_index; 447 414 cpu_loop_exit(); … … 450 417 { 451 418 env->exception_index = EXCP_RC; 452 ASMAtomicAndS32( &env->interrupt_request, ~CPU_INTERRUPT_RC);419 ASMAtomicAndS32((int32_t volatile *)&env->interrupt_request, ~CPU_INTERRUPT_RC); 453 420 ret = env->exception_index; 454 421 cpu_loop_exit(); … … 472 439 473 440 RAWEx_ProfileStart(env, STATS_TLB_LOOKUP); 441 spin_lock(&tb_lock); 474 442 tb = tb_find_fast(); 443 /* Note: we do it here to avoid a gcc bug on Mac OS X when 444 doing it in tb_find_slow */ 445 if (tb_invalidated_flag) { 446 /* as some TB could have been invalidated because 447 of memory exceptions while generating the code, we 448 must recompute the hash index here */ 449 next_tb = 0; 450 tb_invalidated_flag = 0; 451 } 475 452 476 453 /* see if we can patch the calling TB. When the TB 477 454 spans two pages, we cannot safely do a direct 478 455 jump. */ 479 if ( T0!= 0456 if (next_tb != 0 480 457 && !(tb->cflags & CF_RAW_MODE) 481 458 && tb->page_addr[1] == -1) 482 459 { 483 spin_lock(&tb_lock); 484 tb_add_jump((TranslationBlock *)(long)(T0 & ~3), T0 & 3, tb); 485 spin_unlock(&tb_lock); 460 tb_add_jump((TranslationBlock *)(long)(next_tb & ~3), next_tb & 3, tb); 486 461 } 487 tc_ptr = tb->tc_ptr; 462 spin_unlock(&tb_lock); 463 RAWEx_ProfileStop(env, STATS_TLB_LOOKUP); 464 488 465 env->current_tb = tb; 489 /* execute the generated code */ 490 gen_func = (void *)tc_ptr; 491 RAWEx_ProfileStop(env, STATS_TLB_LOOKUP); 492 493 #if defined(DEBUG) && defined(VBOX) && !defined(DEBUG_dmik) 494 #if !defined(DEBUG_bird) 495 if (((env->hflags >> HF_CPL_SHIFT) & 3) == 0 && (env->hflags & HF_PE_MASK) && (env->cr[0] & CR0_PG_MASK)) 496 { 497 if(!(env->state & CPU_EMULATE_SINGLE_STEP)) 498 { 499 Log(("EMR0: %VGv ESP=%VGv IF=%d TF=%d CPL=%d\n", env->eip, ESP, (env->eflags & IF_MASK) ? 1 : 0, (env->eflags & TF_MASK) ? 1 : 0, (env->hflags >> HF_CPL_SHIFT) & 3)); 500 } 466 while (env->current_tb) { 467 tc_ptr = tb->tc_ptr; 468 /* execute the generated code */ 469 RAWEx_ProfileStart(env, STATS_QEMU_RUN_EMULATED_CODE); 470 next_tb = tcg_qemu_tb_exec(tc_ptr); 471 RAWEx_ProfileStop(env, STATS_QEMU_RUN_EMULATED_CODE); 472 env->current_tb = NULL; 473 if ((next_tb & 3) == 2) { 474 /* Instruction counter expired. */ 475 int insns_left; 476 tb = (TranslationBlock *)(long)(next_tb & ~3); 477 /* Restore PC. */ 478 CPU_PC_FROM_TB(env, tb); 479 insns_left = env->icount_decr.u32; 480 if (env->icount_extra && insns_left >= 0) { 481 /* Refill decrementer and continue execution. */ 482 env->icount_extra += insns_left; 483 if (env->icount_extra > 0xffff) { 484 insns_left = 0xffff; 485 } else { 486 insns_left = env->icount_extra; 487 } 488 env->icount_extra -= insns_left; 489 env->icount_decr.u16.low = insns_left; 490 } else { 491 if (insns_left > 0) { 492 /* Execute remaining instructions. */ 493 cpu_exec_nocache(insns_left, tb); 494 } 495 env->exception_index = EXCP_INTERRUPT; 496 next_tb = 0; 497 cpu_loop_exit(); 498 } 499 } 501 500 } 502 else 503 if (((env->hflags >> HF_CPL_SHIFT) & 3) == 3 && (env->hflags & HF_PE_MASK) && (env->cr[0] & CR0_PG_MASK)) 504 { 505 if(!(env->state & CPU_EMULATE_SINGLE_STEP)) 506 { 507 if(env->eflags & VM_MASK) 508 { 509 Log(("EMV86: %04X:%VGv IF=%d TF=%d CPL=%d CR0=%RGr\n", env->segs[R_CS].selector, env->eip, (env->eflags & IF_MASK) ? 1 : 0, (env->eflags & TF_MASK) ? 1 : 0, (env->hflags >> HF_CPL_SHIFT) & 3, env->cr[0])); 510 } 511 else 512 { 513 Log(("EMR3: %VGv ESP=%VGv IF=%d TF=%d CPL=%d IOPL=%d CR0=%RGr\n", env->eip, ESP, (env->eflags & IF_MASK) ? 1 : 0, (env->eflags & TF_MASK) ? 1 : 0, (env->hflags >> HF_CPL_SHIFT) & 3, ((env->eflags >> IOPL_SHIFT) & 3), env->cr[0])); 514 } 515 } 516 } 517 else 518 { 519 /* Seriously slows down realmode booting. */ 520 LogFlow(("EMRM: %04X:%VGv SS:ESP=%04X:%VGv IF=%d TF=%d CPL=%d PE=%d PG=%d\n", env->segs[R_CS].selector, env->eip, env->segs[R_SS].selector, ESP, (env->eflags & IF_MASK) ? 1 : 0, (env->eflags & TF_MASK) ? 1 : 0, (env->hflags >> HF_CPL_SHIFT) & 3, env->cr[0] & X86_CR0_PE, env->cr[0] & X86_CR0_PG)); 521 } 522 #endif /* !DEBUG_bird */ 523 if(env->state & CPU_EMULATE_SINGLE_STEP) 524 { 525 #ifdef DEBUG_bird 526 static int s_cTimes = 0; 527 if (s_cTimes++ > 1000000) 528 { 529 RTLogPrintf("Enough stepping!\n"); 530 #if 0 531 env->exception_index = EXCP_DEBUG; 532 ret = env->exception_index; 533 cpu_loop_exit(); 534 #else 535 env->state &= ~CPU_EMULATE_SINGLE_STEP; 536 #endif 537 } 538 #endif 539 TMCpuTickPause(env->pVM); 540 remR3DisasInstr(env, -1, NULL); 541 TMCpuTickResume(env->pVM); 542 if(emulate_single_instr(env) == -1) 543 { 544 Log(("emulate_single_instr failed for EIP=%VGv!!\n", env->eip)); 545 } 546 } 547 else 548 { 549 RAWEx_ProfileStart(env, STATS_QEMU_RUN_EMULATED_CODE); 550 gen_func(); 551 RAWEx_ProfileStop(env, STATS_QEMU_RUN_EMULATED_CODE); 552 } 553 #else /* !DEBUG || !VBOX || DEBUG_dmik */ 554 555 RAWEx_ProfileStart(env, STATS_QEMU_RUN_EMULATED_CODE); 556 gen_func(); 557 RAWEx_ProfileStop(env, STATS_QEMU_RUN_EMULATED_CODE); 558 559 #endif /* !DEBUG || !VBOX || DEBUG_dmik */ 560 env->current_tb = NULL; 501 561 502 /* reset soft MMU for next block (it can currently 562 503 only be set by a memory fault) */ … … 565 506 env->hflags &= ~HF_SOFTMMU_MASK; 566 507 /* do not allow linking to another block */ 567 T0= 0;508 next_tb = 0; 568 509 } 569 510 #endif 570 } 511 } /* for(;;) */ 571 512 } else { 572 513 env_to_regs(); … … 590 531 } 591 532 592 593 533 #else /* !VBOX */ 594 595 596 534 int cpu_exec(CPUState *env1) 597 535 { 598 536 #define DECLARE_HOST_REGS 1 599 537 #include "hostregs_helper.h" 600 #if defined(__sparc__) && !defined(HOST_SOLARIS)601 int saved_i7;602 target_ulong tmp_T0;603 #endif604 538 int ret, interrupt_request; 605 void (*gen_func)(void);606 539 TranslationBlock *tb; 607 540 uint8_t *tc_ptr; 608 609 #if defined(TARGET_I386) 610 /* handle exit of HALTED state */ 611 if (env1->hflags & HF_HALTED_MASK) { 612 /* disable halt condition */ 613 if ((env1->interrupt_request & CPU_INTERRUPT_HARD) && 614 (env1->eflags & IF_MASK)) { 615 env1->hflags &= ~HF_HALTED_MASK; 616 } else { 617 return EXCP_HALTED; 618 } 619 } 620 #elif defined(TARGET_PPC) 621 if (env1->halted) { 622 if (env1->msr[MSR_EE] && 623 (env1->interrupt_request & 624 (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER))) { 625 env1->halted = 0; 626 } else { 627 return EXCP_HALTED; 628 } 629 } 630 #elif defined(TARGET_SPARC) 631 if (env1->halted) { 632 if ((env1->interrupt_request & CPU_INTERRUPT_HARD) && 633 (env1->psret != 0)) { 634 env1->halted = 0; 635 } else { 636 return EXCP_HALTED; 637 } 638 } 639 #elif defined(TARGET_ARM) 640 if (env1->halted) { 641 /* An interrupt wakes the CPU even if the I and F CPSR bits are 642 set. */ 643 if (env1->interrupt_request 644 & (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD)) { 645 env1->halted = 0; 646 } else { 647 return EXCP_HALTED; 648 } 649 } 650 #elif defined(TARGET_MIPS) 651 if (env1->halted) { 652 if (env1->interrupt_request & 653 (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER)) { 654 env1->halted = 0; 655 } else { 656 return EXCP_HALTED; 657 } 658 } 659 #endif 541 unsigned long next_tb; 542 543 if (cpu_halted(env1) == EXCP_HALTED) 544 return EXCP_HALTED; 660 545 661 546 cpu_single_env = env1; … … 665 550 #include "hostregs_helper.h" 666 551 env = env1; 667 #if defined(__sparc__) && !defined(HOST_SOLARIS) 668 /* we also save i7 because longjmp may not restore it */ 669 asm volatile ("mov %%i7, %0" : "=r" (saved_i7)); 670 #endif 671 552 553 env_to_regs(); 672 554 #if defined(TARGET_I386) 673 env_to_regs();674 555 /* put eflags in CPU temporary format */ 675 556 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); … … 677 558 CC_OP = CC_OP_EFLAGS; 678 559 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); 679 #elif defined(TARGET_ARM)680 560 #elif defined(TARGET_SPARC) 681 #if defined(reg_REGWPTR)682 saved_regwptr = REGWPTR;683 #endif684 #elif defined(TARGET_PPC)685 561 #elif defined(TARGET_M68K) 686 562 env->cc_op = CC_OP_FLAGS; 687 563 env->cc_dest = env->sr & 0xf; 688 564 env->cc_x = (env->sr >> 4) & 1; 565 #elif defined(TARGET_ALPHA) 566 #elif defined(TARGET_ARM) 567 #elif defined(TARGET_PPC) 689 568 #elif defined(TARGET_MIPS) 690 569 #elif defined(TARGET_SH4) 570 #elif defined(TARGET_CRIS) 691 571 /* XXXXX */ 692 572 #else 693 573 #error unsupported target CPU 694 574 #endif 695 #ifndef VBOX /* VBOX: We need to raise traps and suchlike from the outside. */696 575 env->exception_index = -1; 697 #endif698 576 699 577 /* prepare setjmp context for exception handling */ … … 701 579 if (setjmp(env->jmp_env) == 0) { 702 580 env->current_tb = NULL; 703 #ifdef VBOX704 VMMR3Unlock(env->pVM);705 VMMR3Lock(env->pVM);706 707 /* Check for high priority requests first (like fatal708 errors). */709 if (env->interrupt_request & CPU_INTERRUPT_RC) {710 env->exception_index = EXCP_RC;711 ASMAtomicAndS32(&env->interrupt_request, ~CPU_INTERRUPT_RC);712 ret = env->exception_index;713 cpu_loop_exit();714 }715 #endif /* VBOX */716 717 718 581 /* if an exception is pending, we execute it here */ 719 582 if (env->exception_index >= 0) { … … 731 594 env->error_code, 732 595 env->exception_next_eip); 596 /* successfully delivered */ 597 env->old_exception = -1; 733 598 #endif 734 599 ret = env->exception_index; … … 743 608 env->error_code, 744 609 env->exception_next_eip, 0); 610 /* successfully delivered */ 611 env->old_exception = -1; 745 612 #elif defined(TARGET_PPC) 746 613 do_interrupt(env); … … 748 615 do_interrupt(env); 749 616 #elif defined(TARGET_SPARC) 750 do_interrupt(env ->exception_index);617 do_interrupt(env); 751 618 #elif defined(TARGET_ARM) 752 619 do_interrupt(env); 753 620 #elif defined(TARGET_SH4) 754 621 do_interrupt(env); 622 #elif defined(TARGET_ALPHA) 623 do_interrupt(env); 624 #elif defined(TARGET_CRIS) 625 do_interrupt(env); 626 #elif defined(TARGET_M68K) 627 do_interrupt(0); 755 628 #endif 756 629 } … … 783 656 #endif 784 657 785 T0= 0; /* force lookup of first TB */658 next_tb = 0; /* force lookup of first TB */ 786 659 for(;;) { 787 #if defined(__sparc__) && !defined(HOST_SOLARIS)788 /* g1 can be modified by some libc? functions */789 tmp_T0 = T0;790 #endif791 660 interrupt_request = env->interrupt_request; 792 if (__builtin_expect(interrupt_request, 0)) { 793 #ifdef VBOX 794 /* Single instruction exec request, we execute it and return (one way or the other). 795 The caller will always reschedule after doing this operation! */ 796 if (interrupt_request & CPU_INTERRUPT_SINGLE_INSTR) 797 { 798 /* not in flight are we? */ 799 if (!(env->interrupt_request & CPU_INTERRUPT_SINGLE_INSTR_IN_FLIGHT)) 800 { 801 ASMAtomicOrS32(&env->interrupt_request, CPU_INTERRUPT_SINGLE_INSTR_IN_FLIGHT); 802 env->exception_index = EXCP_SINGLE_INSTR; 803 if (emulate_single_instr(env) == -1) 804 AssertMsgFailed(("REM: emulate_single_instr failed for EIP=%VGv!!\n", env->eip)); 805 806 /* When we receive an external interrupt during execution of this single 807 instruction, then we should stay here. We will leave when we're ready 808 for raw-mode or when interrupted by pending EMT requests. */ 809 interrupt_request = env->interrupt_request; /* reload this! */ 810 if ( !(interrupt_request & CPU_INTERRUPT_HARD) 811 || !(env->eflags & IF_MASK) 812 || (env->hflags & HF_INHIBIT_IRQ_MASK) 813 ) 814 { 815 env->exception_index = ret = EXCP_SINGLE_INSTR; 816 cpu_loop_exit(); 661 if (unlikely(interrupt_request) && 662 likely(!(env->singlestep_enabled & SSTEP_NOIRQ))) { 663 if (interrupt_request & CPU_INTERRUPT_DEBUG) { 664 env->interrupt_request &= ~CPU_INTERRUPT_DEBUG; 665 env->exception_index = EXCP_DEBUG; 666 cpu_loop_exit(); 667 } 668 #if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \ 669 defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) 670 if (interrupt_request & CPU_INTERRUPT_HALT) { 671 env->interrupt_request &= ~CPU_INTERRUPT_HALT; 672 env->halted = 1; 673 env->exception_index = EXCP_HLT; 674 cpu_loop_exit(); 675 } 676 #endif 677 #if defined(TARGET_I386) 678 if (env->hflags2 & HF2_GIF_MASK) { 679 if ((interrupt_request & CPU_INTERRUPT_SMI) && 680 !(env->hflags & HF_SMM_MASK)) { 681 svm_check_intercept(SVM_EXIT_SMI); 682 env->interrupt_request &= ~CPU_INTERRUPT_SMI; 683 do_smm_enter(); 684 next_tb = 0; 685 } else if ((interrupt_request & CPU_INTERRUPT_NMI) && 686 !(env->hflags2 & HF2_NMI_MASK)) { 687 env->interrupt_request &= ~CPU_INTERRUPT_NMI; 688 env->hflags2 |= HF2_NMI_MASK; 689 do_interrupt(EXCP02_NMI, 0, 0, 0, 1); 690 next_tb = 0; 691 } else if ((interrupt_request & CPU_INTERRUPT_HARD) && 692 (((env->hflags2 & HF2_VINTR_MASK) && 693 (env->hflags2 & HF2_HIF_MASK)) || 694 (!(env->hflags2 & HF2_VINTR_MASK) && 695 (env->eflags & IF_MASK && 696 !(env->hflags & HF_INHIBIT_IRQ_MASK))))) { 697 int intno; 698 svm_check_intercept(SVM_EXIT_INTR); 699 env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ); 700 intno = cpu_get_pic_interrupt(env); 701 if (loglevel & CPU_LOG_TB_IN_ASM) { 702 fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno); 817 703 } 704 do_interrupt(intno, 0, 0, 0, 1); 705 /* ensure that no TB jump will be modified as 706 the program flow was changed */ 707 next_tb = 0; 708 #if !defined(CONFIG_USER_ONLY) 709 } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) && 710 (env->eflags & IF_MASK) && 711 !(env->hflags & HF_INHIBIT_IRQ_MASK)) { 712 int intno; 713 /* FIXME: this should respect TPR */ 714 svm_check_intercept(SVM_EXIT_VINTR); 715 env->interrupt_request &= ~CPU_INTERRUPT_VIRQ; 716 intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector)); 717 if (loglevel & CPU_LOG_TB_IN_ASM) 718 fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno); 719 do_interrupt(intno, 0, 0, 0, 1); 720 next_tb = 0; 721 #endif 818 722 } 819 env->exception_index = EXCP_SINGLE_INSTR;820 cpu_loop_exit();821 }822 823 RAWEx_ProfileStart(env, STATS_IRQ_HANDLING);824 #endif /* VBOX */825 #if defined(TARGET_I386)826 if ((interrupt_request & CPU_INTERRUPT_SMI) &&827 !(env->hflags & HF_SMM_MASK)) {828 env->interrupt_request &= ~CPU_INTERRUPT_SMI;829 do_smm_enter();830 #if defined(__sparc__) && !defined(HOST_SOLARIS)831 tmp_T0 = 0;832 #else833 T0 = 0;834 #endif835 } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&836 (env->eflags & IF_MASK) &&837 !(env->hflags & HF_INHIBIT_IRQ_MASK)) {838 int intno;839 #if defined(VBOX)840 ASMAtomicAndS32(&env->interrupt_request, ~CPU_INTERRUPT_HARD);841 #else842 env->interrupt_request &= ~CPU_INTERRUPT_HARD;843 #endif844 intno = cpu_get_pic_interrupt(env);845 if (loglevel & CPU_LOG_TB_IN_ASM) {846 fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);847 }848 #if defined(VBOX)849 if (intno >= 0)850 #endif851 do_interrupt(intno, 0, 0, 0, 1);852 /* ensure that no TB jump will be modified as853 the program flow was changed */854 #if defined(__sparc__) && !defined(HOST_SOLARIS)855 tmp_T0 = 0;856 #else857 T0 = 0;858 #endif859 723 } 860 724 #elif defined(TARGET_PPC) … … 864 728 } 865 729 #endif 866 if (msr_ee != 0) { 867 if ((interrupt_request & CPU_INTERRUPT_HARD)) { 868 /* Raise it */ 869 env->exception_index = EXCP_EXTERNAL; 870

