PPC: booke206: Check for min/max TLB entry size
[qemu.git] / cpu-exec.c
1 /*
2 * i386 emulator main execution loop
3 *
4 * Copyright (c) 2003-2005 Fabrice Bellard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 */
19 #include "config.h"
20 #include "cpu.h"
21 #include "disas.h"
22 #include "tcg.h"
23 #include "qemu-barrier.h"
24
25 int tb_invalidated_flag;
26
27 //#define CONFIG_DEBUG_EXEC
28
29 bool qemu_cpu_has_work(CPUState *env)
30 {
31 return cpu_has_work(env);
32 }
33
34 void cpu_loop_exit(CPUState *env)
35 {
36 env->current_tb = NULL;
37 longjmp(env->jmp_env, 1);
38 }
39
40 /* exit the current TB from a signal handler. The host registers are
41 restored in a state compatible with the CPU emulator
42 */
43 #if defined(CONFIG_SOFTMMU)
44 void cpu_resume_from_signal(CPUState *env, void *puc)
45 {
46 /* XXX: restore cpu registers saved in host registers */
47
48 env->exception_index = -1;
49 longjmp(env->jmp_env, 1);
50 }
51 #endif
52
53 /* Execute the code without caching the generated code. An interpreter
54 could be used if available. */
55 static void cpu_exec_nocache(CPUState *env, int max_cycles,
56 TranslationBlock *orig_tb)
57 {
58 unsigned long next_tb;
59 TranslationBlock *tb;
60
61 /* Should never happen.
62 We only end up here when an existing TB is too long. */
63 if (max_cycles > CF_COUNT_MASK)
64 max_cycles = CF_COUNT_MASK;
65
66 tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
67 max_cycles);
68 env->current_tb = tb;
69 /* execute the generated code */
70 next_tb = tcg_qemu_tb_exec(env, tb->tc_ptr);
71 env->current_tb = NULL;
72
73 if ((next_tb & 3) == 2) {
74 /* Restore PC. This may happen if async event occurs before
75 the TB starts executing. */
76 cpu_pc_from_tb(env, tb);
77 }
78 tb_phys_invalidate(tb, -1);
79 tb_free(tb);
80 }
81
82 static TranslationBlock *tb_find_slow(CPUState *env,
83 target_ulong pc,
84 target_ulong cs_base,
85 uint64_t flags)
86 {
87 TranslationBlock *tb, **ptb1;
88 unsigned int h;
89 tb_page_addr_t phys_pc, phys_page1;
90 target_ulong virt_page2;
91
92 tb_invalidated_flag = 0;
93
94 /* find translated block using physical mappings */
95 phys_pc = get_page_addr_code(env, pc);
96 phys_page1 = phys_pc & TARGET_PAGE_MASK;
97 h = tb_phys_hash_func(phys_pc);
98 ptb1 = &tb_phys_hash[h];
99 for(;;) {
100 tb = *ptb1;
101 if (!tb)
102 goto not_found;
103 if (tb->pc == pc &&
104 tb->page_addr[0] == phys_page1 &&
105 tb->cs_base == cs_base &&
106 tb->flags == flags) {
107 /* check next page if needed */
108 if (tb->page_addr[1] != -1) {
109 tb_page_addr_t phys_page2;
110
111 virt_page2 = (pc & TARGET_PAGE_MASK) +
112 TARGET_PAGE_SIZE;
113 phys_page2 = get_page_addr_code(env, virt_page2);
114 if (tb->page_addr[1] == phys_page2)
115 goto found;
116 } else {
117 goto found;
118 }
119 }
120 ptb1 = &tb->phys_hash_next;
121 }
122 not_found:
123 /* if no translated code available, then translate it now */
124 tb = tb_gen_code(env, pc, cs_base, flags, 0);
125
126 found:
127 /* Move the last found TB to the head of the list */
128 if (likely(*ptb1)) {
129 *ptb1 = tb->phys_hash_next;
130 tb->phys_hash_next = tb_phys_hash[h];
131 tb_phys_hash[h] = tb;
132 }
133 /* we add the TB in the virtual pc hash table */
134 env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
135 return tb;
136 }
137
138 static inline TranslationBlock *tb_find_fast(CPUState *env)
139 {
140 TranslationBlock *tb;
141 target_ulong cs_base, pc;
142 int flags;
143
144 /* we record a subset of the CPU state. It will
145 always be the same before a given translated block
146 is executed. */
147 cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
148 tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
149 if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
150 tb->flags != flags)) {
151 tb = tb_find_slow(env, pc, cs_base, flags);
152 }
153 return tb;
154 }
155
156 static CPUDebugExcpHandler *debug_excp_handler;
157
158 CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
159 {
160 CPUDebugExcpHandler *old_handler = debug_excp_handler;
161
162 debug_excp_handler = handler;
163 return old_handler;
164 }
165
166 static void cpu_handle_debug_exception(CPUState *env)
167 {
168 CPUWatchpoint *wp;
169
170 if (!env->watchpoint_hit) {
171 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
172 wp->flags &= ~BP_WATCHPOINT_HIT;
173 }
174 }
175 if (debug_excp_handler) {
176 debug_excp_handler(env);
177 }
178 }
179
180 /* main execution loop */
181
182 volatile sig_atomic_t exit_request;
183
184 int cpu_exec(CPUState *env)
185 {
186 int ret, interrupt_request;
187 TranslationBlock *tb;
188 uint8_t *tc_ptr;
189 unsigned long next_tb;
190
191 if (env->halted) {
192 if (!cpu_has_work(env)) {
193 return EXCP_HALTED;
194 }
195
196 env->halted = 0;
197 }
198
199 cpu_single_env = env;
200
201 if (unlikely(exit_request)) {
202 env->exit_request = 1;
203 }
204
205 #if defined(TARGET_I386)
206 /* put eflags in CPU temporary format */
207 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
208 DF = 1 - (2 * ((env->eflags >> 10) & 1));
209 CC_OP = CC_OP_EFLAGS;
210 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
211 #elif defined(TARGET_SPARC)
212 #elif defined(TARGET_M68K)
213 env->cc_op = CC_OP_FLAGS;
214 env->cc_dest = env->sr & 0xf;
215 env->cc_x = (env->sr >> 4) & 1;
216 #elif defined(TARGET_ALPHA)
217 #elif defined(TARGET_ARM)
218 #elif defined(TARGET_UNICORE32)
219 #elif defined(TARGET_PPC)
220 env->reserve_addr = -1;
221 #elif defined(TARGET_LM32)
222 #elif defined(TARGET_MICROBLAZE)
223 #elif defined(TARGET_MIPS)
224 #elif defined(TARGET_SH4)
225 #elif defined(TARGET_CRIS)
226 #elif defined(TARGET_S390X)
227 #elif defined(TARGET_XTENSA)
228 /* XXXXX */
229 #else
230 #error unsupported target CPU
231 #endif
232 env->exception_index = -1;
233
234 /* prepare setjmp context for exception handling */
235 for(;;) {
236 if (setjmp(env->jmp_env) == 0) {
237 /* if an exception is pending, we execute it here */
238 if (env->exception_index >= 0) {
239 if (env->exception_index >= EXCP_INTERRUPT) {
240 /* exit request from the cpu execution loop */
241 ret = env->exception_index;
242 if (ret == EXCP_DEBUG) {
243 cpu_handle_debug_exception(env);
244 }
245 break;
246 } else {
247 #if defined(CONFIG_USER_ONLY)
248 /* if user mode only, we simulate a fake exception
249 which will be handled outside the cpu execution
250 loop */
251 #if defined(TARGET_I386)
252 do_interrupt(env);
253 #endif
254 ret = env->exception_index;
255 break;
256 #else
257 do_interrupt(env);
258 env->exception_index = -1;
259 #endif
260 }
261 }
262
263 next_tb = 0; /* force lookup of first TB */
264 for(;;) {
265 interrupt_request = env->interrupt_request;
266 if (unlikely(interrupt_request)) {
267 if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
268 /* Mask out external interrupts for this step. */
269 interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
270 }
271 if (interrupt_request & CPU_INTERRUPT_DEBUG) {
272 env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
273 env->exception_index = EXCP_DEBUG;
274 cpu_loop_exit(env);
275 }
276 #if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
277 defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
278 defined(TARGET_MICROBLAZE) || defined(TARGET_LM32) || defined(TARGET_UNICORE32)
279 if (interrupt_request & CPU_INTERRUPT_HALT) {
280 env->interrupt_request &= ~CPU_INTERRUPT_HALT;
281 env->halted = 1;
282 env->exception_index = EXCP_HLT;
283 cpu_loop_exit(env);
284 }
285 #endif
286 #if defined(TARGET_I386)
287 if (interrupt_request & CPU_INTERRUPT_INIT) {
288 svm_check_intercept(env, SVM_EXIT_INIT);
289 do_cpu_init(env);
290 env->exception_index = EXCP_HALTED;
291 cpu_loop_exit(env);
292 } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
293 do_cpu_sipi(env);
294 } else if (env->hflags2 & HF2_GIF_MASK) {
295 if ((interrupt_request & CPU_INTERRUPT_SMI) &&
296 !(env->hflags & HF_SMM_MASK)) {
297 svm_check_intercept(env, SVM_EXIT_SMI);
298 env->interrupt_request &= ~CPU_INTERRUPT_SMI;
299 do_smm_enter(env);
300 next_tb = 0;
301 } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
302 !(env->hflags2 & HF2_NMI_MASK)) {
303 env->interrupt_request &= ~CPU_INTERRUPT_NMI;
304 env->hflags2 |= HF2_NMI_MASK;
305 do_interrupt_x86_hardirq(env, EXCP02_NMI, 1);
306 next_tb = 0;
307 } else if (interrupt_request & CPU_INTERRUPT_MCE) {
308 env->interrupt_request &= ~CPU_INTERRUPT_MCE;
309 do_interrupt_x86_hardirq(env, EXCP12_MCHK, 0);
310 next_tb = 0;
311 } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
312 (((env->hflags2 & HF2_VINTR_MASK) &&
313 (env->hflags2 & HF2_HIF_MASK)) ||
314 (!(env->hflags2 & HF2_VINTR_MASK) &&
315 (env->eflags & IF_MASK &&
316 !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
317 int intno;
318 svm_check_intercept(env, SVM_EXIT_INTR);
319 env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
320 intno = cpu_get_pic_interrupt(env);
321 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
322 do_interrupt_x86_hardirq(env, intno, 1);
323 /* ensure that no TB jump will be modified as
324 the program flow was changed */
325 next_tb = 0;
326 #if !defined(CONFIG_USER_ONLY)
327 } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
328 (env->eflags & IF_MASK) &&
329 !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
330 int intno;
331 /* FIXME: this should respect TPR */
332 svm_check_intercept(env, SVM_EXIT_VINTR);
333 intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
334 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
335 do_interrupt_x86_hardirq(env, intno, 1);
336 env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
337 next_tb = 0;
338 #endif
339 }
340 }
341 #elif defined(TARGET_PPC)
342 #if 0
343 if ((interrupt_request & CPU_INTERRUPT_RESET)) {
344 cpu_reset(env);
345 }
346 #endif
347 if (interrupt_request & CPU_INTERRUPT_HARD) {
348 ppc_hw_interrupt(env);
349 if (env->pending_interrupts == 0)
350 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
351 next_tb = 0;
352 }
353 #elif defined(TARGET_LM32)
354 if ((interrupt_request & CPU_INTERRUPT_HARD)
355 && (env->ie & IE_IE)) {
356 env->exception_index = EXCP_IRQ;
357 do_interrupt(env);
358 next_tb = 0;
359 }
360 #elif defined(TARGET_MICROBLAZE)
361 if ((interrupt_request & CPU_INTERRUPT_HARD)
362 && (env->sregs[SR_MSR] & MSR_IE)
363 && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
364 && !(env->iflags & (D_FLAG | IMM_FLAG))) {
365 env->exception_index = EXCP_IRQ;
366 do_interrupt(env);
367 next_tb = 0;
368 }
369 #elif defined(TARGET_MIPS)
370 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
371 cpu_mips_hw_interrupts_pending(env)) {
372 /* Raise it */
373 env->exception_index = EXCP_EXT_INTERRUPT;
374 env->error_code = 0;
375 do_interrupt(env);
376 next_tb = 0;
377 }
378 #elif defined(TARGET_SPARC)
379 if (interrupt_request & CPU_INTERRUPT_HARD) {
380 if (cpu_interrupts_enabled(env) &&
381 env->interrupt_index > 0) {
382 int pil = env->interrupt_index & 0xf;
383 int type = env->interrupt_index & 0xf0;
384
385 if (((type == TT_EXTINT) &&
386 cpu_pil_allowed(env, pil)) ||
387 type != TT_EXTINT) {
388 env->exception_index = env->interrupt_index;
389 do_interrupt(env);
390 next_tb = 0;
391 }
392 }
393 }
394 #elif defined(TARGET_ARM)
395 if (interrupt_request & CPU_INTERRUPT_FIQ
396 && !(env->uncached_cpsr & CPSR_F)) {
397 env->exception_index = EXCP_FIQ;
398 do_interrupt(env);
399 next_tb = 0;
400 }
401 /* ARMv7-M interrupt return works by loading a magic value
402 into the PC. On real hardware the load causes the
403 return to occur. The qemu implementation performs the
404 jump normally, then does the exception return when the
405 CPU tries to execute code at the magic address.
406 This will cause the magic PC value to be pushed to
407 the stack if an interrupt occurred at the wrong time.
408 We avoid this by disabling interrupts when
409 pc contains a magic address. */
410 if (interrupt_request & CPU_INTERRUPT_HARD
411 && ((IS_M(env) && env->regs[15] < 0xfffffff0)
412 || !(env->uncached_cpsr & CPSR_I))) {
413 env->exception_index = EXCP_IRQ;
414 do_interrupt(env);
415 next_tb = 0;
416 }
417 #elif defined(TARGET_UNICORE32)
418 if (interrupt_request & CPU_INTERRUPT_HARD
419 && !(env->uncached_asr & ASR_I)) {
420 do_interrupt(env);
421 next_tb = 0;
422 }
423 #elif defined(TARGET_SH4)
424 if (interrupt_request & CPU_INTERRUPT_HARD) {
425 do_interrupt(env);
426 next_tb = 0;
427 }
428 #elif defined(TARGET_ALPHA)
429 {
430 int idx = -1;
431 /* ??? This hard-codes the OSF/1 interrupt levels. */
432 switch (env->pal_mode ? 7 : env->ps & PS_INT_MASK) {
433 case 0 ... 3:
434 if (interrupt_request & CPU_INTERRUPT_HARD) {
435 idx = EXCP_DEV_INTERRUPT;
436 }
437 /* FALLTHRU */
438 case 4:
439 if (interrupt_request & CPU_INTERRUPT_TIMER) {
440 idx = EXCP_CLK_INTERRUPT;
441 }
442 /* FALLTHRU */
443 case 5:
444 if (interrupt_request & CPU_INTERRUPT_SMP) {
445 idx = EXCP_SMP_INTERRUPT;
446 }
447 /* FALLTHRU */
448 case 6:
449 if (interrupt_request & CPU_INTERRUPT_MCHK) {
450 idx = EXCP_MCHK;
451 }
452 }
453 if (idx >= 0) {
454 env->exception_index = idx;
455 env->error_code = 0;
456 do_interrupt(env);
457 next_tb = 0;
458 }
459 }
460 #elif defined(TARGET_CRIS)
461 if (interrupt_request & CPU_INTERRUPT_HARD
462 && (env->pregs[PR_CCS] & I_FLAG)
463 && !env->locked_irq) {
464 env->exception_index = EXCP_IRQ;
465 do_interrupt(env);
466 next_tb = 0;
467 }
468 if (interrupt_request & CPU_INTERRUPT_NMI
469 && (env->pregs[PR_CCS] & M_FLAG)) {
470 env->exception_index = EXCP_NMI;
471 do_interrupt(env);
472 next_tb = 0;
473 }
474 #elif defined(TARGET_M68K)
475 if (interrupt_request & CPU_INTERRUPT_HARD
476 && ((env->sr & SR_I) >> SR_I_SHIFT)
477 < env->pending_level) {
478 /* Real hardware gets the interrupt vector via an
479 IACK cycle at this point. Current emulated
480 hardware doesn't rely on this, so we
481 provide/save the vector when the interrupt is
482 first signalled. */
483 env->exception_index = env->pending_vector;
484 do_interrupt_m68k_hardirq(env);
485 next_tb = 0;
486 }
487 #elif defined(TARGET_S390X) && !defined(CONFIG_USER_ONLY)
488 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
489 (env->psw.mask & PSW_MASK_EXT)) {
490 do_interrupt(env);
491 next_tb = 0;
492 }
493 #elif defined(TARGET_XTENSA)
494 if (interrupt_request & CPU_INTERRUPT_HARD) {
495 env->exception_index = EXC_IRQ;
496 do_interrupt(env);
497 next_tb = 0;
498 }
499 #endif
500 /* Don't use the cached interrupt_request value,
501 do_interrupt may have updated the EXITTB flag. */
502 if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
503 env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
504 /* ensure that no TB jump will be modified as
505 the program flow was changed */
506 next_tb = 0;
507 }
508 }
509 if (unlikely(env->exit_request)) {
510 env->exit_request = 0;
511 env->exception_index = EXCP_INTERRUPT;
512 cpu_loop_exit(env);
513 }
514 #if defined(DEBUG_DISAS) || defined(CONFIG_DEBUG_EXEC)
515 if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
516 /* restore flags in standard format */
517 #if defined(TARGET_I386)
518 env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
519 | (DF & DF_MASK);
520 log_cpu_state(env, X86_DUMP_CCOP);
521 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
522 #elif defined(TARGET_M68K)
523 cpu_m68k_flush_flags(env, env->cc_op);
524 env->cc_op = CC_OP_FLAGS;
525 env->sr = (env->sr & 0xffe0)
526 | env->cc_dest | (env->cc_x << 4);
527 log_cpu_state(env, 0);
528 #else
529 log_cpu_state(env, 0);
530 #endif
531 }
532 #endif /* DEBUG_DISAS || CONFIG_DEBUG_EXEC */
533 spin_lock(&tb_lock);
534 tb = tb_find_fast(env);
535 /* Note: we do it here to avoid a gcc bug on Mac OS X when
536 doing it in tb_find_slow */
537 if (tb_invalidated_flag) {
538 /* as some TB could have been invalidated because
539 of memory exceptions while generating the code, we
540 must recompute the hash index here */
541 next_tb = 0;
542 tb_invalidated_flag = 0;
543 }
544 #ifdef CONFIG_DEBUG_EXEC
545 qemu_log_mask(CPU_LOG_EXEC, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
546 (long)tb->tc_ptr, tb->pc,
547 lookup_symbol(tb->pc));
548 #endif
549 /* see if we can patch the calling TB. When the TB
550 spans two pages, we cannot safely do a direct
551 jump. */
552 if (next_tb != 0 && tb->page_addr[1] == -1) {
553 tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
554 }
555 spin_unlock(&tb_lock);
556
557 /* cpu_interrupt might be called while translating the
558 TB, but before it is linked into a potentially
559 infinite loop and becomes env->current_tb. Avoid
560 starting execution if there is a pending interrupt. */
561 env->current_tb = tb;
562 barrier();
563 if (likely(!env->exit_request)) {
564 tc_ptr = tb->tc_ptr;
565 /* execute the generated code */
566 next_tb = tcg_qemu_tb_exec(env, tc_ptr);
567 if ((next_tb & 3) == 2) {
568 /* Instruction counter expired. */
569 int insns_left;
570 tb = (TranslationBlock *)(long)(next_tb & ~3);
571 /* Restore PC. */
572 cpu_pc_from_tb(env, tb);
573 insns_left = env->icount_decr.u32;
574 if (env->icount_extra && insns_left >= 0) {
575 /* Refill decrementer and continue execution. */
576 env->icount_extra += insns_left;
577 if (env->icount_extra > 0xffff) {
578 insns_left = 0xffff;
579 } else {
580 insns_left = env->icount_extra;
581 }
582 env->icount_extra -= insns_left;
583 env->icount_decr.u16.low = insns_left;
584 } else {
585 if (insns_left > 0) {
586 /* Execute remaining instructions. */
587 cpu_exec_nocache(env, insns_left, tb);
588 }
589 env->exception_index = EXCP_INTERRUPT;
590 next_tb = 0;
591 cpu_loop_exit(env);
592 }
593 }
594 }
595 env->current_tb = NULL;
596 /* reset soft MMU for next block (it can currently
597 only be set by a memory fault) */
598 } /* for(;;) */
599 } else {
600 /* Reload env after longjmp - the compiler may have smashed all
601 * local variables as longjmp is marked 'noreturn'. */
602 env = cpu_single_env;
603 }
604 } /* for(;;) */
605
606
607 #if defined(TARGET_I386)
608 /* restore flags in standard format */
609 env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
610 | (DF & DF_MASK);
611 #elif defined(TARGET_ARM)
612 /* XXX: Save/restore host fpu exception state?. */
613 #elif defined(TARGET_UNICORE32)
614 #elif defined(TARGET_SPARC)
615 #elif defined(TARGET_PPC)
616 #elif defined(TARGET_LM32)
617 #elif defined(TARGET_M68K)
618 cpu_m68k_flush_flags(env, env->cc_op);
619 env->cc_op = CC_OP_FLAGS;
620 env->sr = (env->sr & 0xffe0)
621 | env->cc_dest | (env->cc_x << 4);
622 #elif defined(TARGET_MICROBLAZE)
623 #elif defined(TARGET_MIPS)
624 #elif defined(TARGET_SH4)
625 #elif defined(TARGET_ALPHA)
626 #elif defined(TARGET_CRIS)
627 #elif defined(TARGET_S390X)
628 #elif defined(TARGET_XTENSA)
629 /* XXXXX */
630 #else
631 #error unsupported target CPU
632 #endif
633
634 /* fail safe : never use cpu_single_env outside cpu_exec() */
635 cpu_single_env = NULL;
636 return ret;
637 }