qemu/cpu-exec.c
<<
>>
Prefs
   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 "exec.h"
  21#include "disas.h"
  22#include "tcg.h"
  23#include "kvm.h"
  24#include "qemu-barrier.h"
  25
  26#if !defined(CONFIG_SOFTMMU)
  27#undef EAX
  28#undef ECX
  29#undef EDX
  30#undef EBX
  31#undef ESP
  32#undef EBP
  33#undef ESI
  34#undef EDI
  35#undef EIP
  36#include <signal.h>
  37#ifdef __linux__
  38#include <sys/ucontext.h>
  39#endif
  40#endif
  41
  42#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
  43// Work around ugly bugs in glibc that mangle global register contents
  44#undef env
  45#define env cpu_single_env
  46#endif
  47
  48int tb_invalidated_flag;
  49
  50//#define CONFIG_DEBUG_EXEC
  51//#define DEBUG_SIGNAL
  52
  53int qemu_cpu_has_work(CPUState *env)
  54{
  55    return cpu_has_work(env);
  56}
  57
  58void cpu_loop_exit(void)
  59{
  60    env->current_tb = NULL;
  61    longjmp(env->jmp_env, 1);
  62}
  63
  64/* exit the current TB from a signal handler. The host registers are
  65   restored in a state compatible with the CPU emulator
  66 */
  67void cpu_resume_from_signal(CPUState *env1, void *puc)
  68{
  69#if !defined(CONFIG_SOFTMMU)
  70#ifdef __linux__
  71    struct ucontext *uc = puc;
  72#elif defined(__OpenBSD__)
  73    struct sigcontext *uc = puc;
  74#endif
  75#endif
  76
  77    env = env1;
  78
  79    /* XXX: restore cpu registers saved in host registers */
  80
  81#if !defined(CONFIG_SOFTMMU)
  82    if (puc) {
  83        /* XXX: use siglongjmp ? */
  84#ifdef __linux__
  85#ifdef __ia64
  86        sigprocmask(SIG_SETMASK, (sigset_t *)&uc->uc_sigmask, NULL);
  87#else
  88        sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
  89#endif
  90#elif defined(__OpenBSD__)
  91        sigprocmask(SIG_SETMASK, &uc->sc_mask, NULL);
  92#endif
  93    }
  94#endif
  95    env->exception_index = -1;
  96    longjmp(env->jmp_env, 1);
  97}
  98
  99/* Execute the code without caching the generated code. An interpreter
 100   could be used if available. */
 101static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
 102{
 103    unsigned long next_tb;
 104    TranslationBlock *tb;
 105
 106    /* Should never happen.
 107       We only end up here when an existing TB is too long.  */
 108    if (max_cycles > CF_COUNT_MASK)
 109        max_cycles = CF_COUNT_MASK;
 110
 111    tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
 112                     max_cycles);
 113    env->current_tb = tb;
 114    /* execute the generated code */
 115    next_tb = tcg_qemu_tb_exec(tb->tc_ptr);
 116    env->current_tb = NULL;
 117
 118    if ((next_tb & 3) == 2) {
 119        /* Restore PC.  This may happen if async event occurs before
 120           the TB starts executing.  */
 121        cpu_pc_from_tb(env, tb);
 122    }
 123    tb_phys_invalidate(tb, -1);
 124    tb_free(tb);
 125}
 126
 127static TranslationBlock *tb_find_slow(target_ulong pc,
 128                                      target_ulong cs_base,
 129                                      uint64_t flags)
 130{
 131    TranslationBlock *tb, **ptb1;
 132    unsigned int h;
 133    tb_page_addr_t phys_pc, phys_page1, phys_page2;
 134    target_ulong virt_page2;
 135
 136    tb_invalidated_flag = 0;
 137
 138    /* find translated block using physical mappings */
 139    phys_pc = get_page_addr_code(env, pc);
 140    phys_page1 = phys_pc & TARGET_PAGE_MASK;
 141    phys_page2 = -1;
 142    h = tb_phys_hash_func(phys_pc);
 143    ptb1 = &tb_phys_hash[h];
 144    for(;;) {
 145        tb = *ptb1;
 146        if (!tb)
 147            goto not_found;
 148        if (tb->pc == pc &&
 149            tb->page_addr[0] == phys_page1 &&
 150            tb->cs_base == cs_base &&
 151            tb->flags == flags) {
 152            /* check next page if needed */
 153            if (tb->page_addr[1] != -1) {
 154                virt_page2 = (pc & TARGET_PAGE_MASK) +
 155                    TARGET_PAGE_SIZE;
 156                phys_page2 = get_page_addr_code(env, virt_page2);
 157                if (tb->page_addr[1] == phys_page2)
 158                    goto found;
 159            } else {
 160                goto found;
 161            }
 162        }
 163        ptb1 = &tb->phys_hash_next;
 164    }
 165 not_found:
 166   /* if no translated code available, then translate it now */
 167    tb = tb_gen_code(env, pc, cs_base, flags, 0);
 168
 169 found:
 170    /* Move the last found TB to the head of the list */
 171    if (likely(*ptb1)) {
 172        *ptb1 = tb->phys_hash_next;
 173        tb->phys_hash_next = tb_phys_hash[h];
 174        tb_phys_hash[h] = tb;
 175    }
 176    /* we add the TB in the virtual pc hash table */
 177    env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
 178    return tb;
 179}
 180
 181static inline TranslationBlock *tb_find_fast(void)
 182{
 183    TranslationBlock *tb;
 184    target_ulong cs_base, pc;
 185    int flags;
 186
 187    /* we record a subset of the CPU state. It will
 188       always be the same before a given translated block
 189       is executed. */
 190    cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
 191    tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
 192    if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
 193                 tb->flags != flags)) {
 194        tb = tb_find_slow(pc, cs_base, flags);
 195    }
 196    return tb;
 197}
 198
 199static CPUDebugExcpHandler *debug_excp_handler;
 200
 201CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
 202{
 203    CPUDebugExcpHandler *old_handler = debug_excp_handler;
 204
 205    debug_excp_handler = handler;
 206    return old_handler;
 207}
 208
 209static void cpu_handle_debug_exception(CPUState *env)
 210{
 211    CPUWatchpoint *wp;
 212
 213    if (!env->watchpoint_hit)
 214        QTAILQ_FOREACH(wp, &env->watchpoints, entry)
 215            wp->flags &= ~BP_WATCHPOINT_HIT;
 216
 217    if (debug_excp_handler)
 218        debug_excp_handler(env);
 219}
 220
 221/* main execution loop */
 222
 223volatile sig_atomic_t exit_request;
 224
 225int cpu_exec(CPUState *env1)
 226{
 227    volatile host_reg_t saved_env_reg;
 228    int ret, interrupt_request;
 229    TranslationBlock *tb;
 230    uint8_t *tc_ptr;
 231    unsigned long next_tb;
 232
 233    if (cpu_halted(env1) == EXCP_HALTED)
 234        return EXCP_HALTED;
 235
 236    cpu_single_env = env1;
 237
 238    /* the access to env below is actually saving the global register's
 239       value, so that files not including target-xyz/exec.h are free to
 240       use it.  */
 241    QEMU_BUILD_BUG_ON (sizeof (saved_env_reg) != sizeof (env));
 242    saved_env_reg = (host_reg_t) env;
 243    barrier();
 244    env = env1;
 245
 246    if (unlikely(exit_request)) {
 247        env->exit_request = 1;
 248    }
 249
 250#if defined(TARGET_I386)
 251    if (!kvm_enabled()) {
 252        /* put eflags in CPU temporary format */
 253        CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
 254        DF = 1 - (2 * ((env->eflags >> 10) & 1));
 255        CC_OP = CC_OP_EFLAGS;
 256        env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
 257    }
 258#elif defined(TARGET_SPARC)
 259#elif defined(TARGET_M68K)
 260    env->cc_op = CC_OP_FLAGS;
 261    env->cc_dest = env->sr & 0xf;
 262    env->cc_x = (env->sr >> 4) & 1;
 263#elif defined(TARGET_ALPHA)
 264#elif defined(TARGET_ARM)
 265#elif defined(TARGET_PPC)
 266#elif defined(TARGET_MICROBLAZE)
 267#elif defined(TARGET_MIPS)
 268#elif defined(TARGET_SH4)
 269#elif defined(TARGET_CRIS)
 270#elif defined(TARGET_S390X)
 271    /* XXXXX */
 272#else
 273#error unsupported target CPU
 274#endif
 275    env->exception_index = -1;
 276
 277    /* prepare setjmp context for exception handling */
 278    for(;;) {
 279        if (setjmp(env->jmp_env) == 0) {
 280#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
 281#undef env
 282                    env = cpu_single_env;
 283#define env cpu_single_env
 284#endif
 285            /* if an exception is pending, we execute it here */
 286            if (env->exception_index >= 0) {
 287                if (env->exception_index >= EXCP_INTERRUPT) {
 288                    /* exit request from the cpu execution loop */
 289                    ret = env->exception_index;
 290                    if (ret == EXCP_DEBUG)
 291                        cpu_handle_debug_exception(env);
 292                    break;
 293                } else {
 294#if defined(CONFIG_USER_ONLY)
 295                    /* if user mode only, we simulate a fake exception
 296                       which will be handled outside the cpu execution
 297                       loop */
 298#if defined(TARGET_I386)
 299                    do_interrupt_user(env->exception_index,
 300                                      env->exception_is_int,
 301                                      env->error_code,
 302                                      env->exception_next_eip);
 303                    /* successfully delivered */
 304                    env->old_exception = -1;
 305#endif
 306                    ret = env->exception_index;
 307                    break;
 308#else
 309#if defined(TARGET_I386)
 310                    /* simulate a real cpu exception. On i386, it can
 311                       trigger new exceptions, but we do not handle
 312                       double or triple faults yet. */
 313                    do_interrupt(env->exception_index,
 314                                 env->exception_is_int,
 315                                 env->error_code,
 316                                 env->exception_next_eip, 0);
 317                    /* successfully delivered */
 318                    env->old_exception = -1;
 319#elif defined(TARGET_PPC)
 320                    do_interrupt(env);
 321#elif defined(TARGET_MICROBLAZE)
 322                    do_interrupt(env);
 323#elif defined(TARGET_MIPS)
 324                    do_interrupt(env);
 325#elif defined(TARGET_SPARC)
 326                    do_interrupt(env);
 327#elif defined(TARGET_ARM)
 328                    do_interrupt(env);
 329#elif defined(TARGET_SH4)
 330                    do_interrupt(env);
 331#elif defined(TARGET_ALPHA)
 332                    do_interrupt(env);
 333#elif defined(TARGET_CRIS)
 334                    do_interrupt(env);
 335#elif defined(TARGET_M68K)
 336                    do_interrupt(0);
 337#endif
 338                    env->exception_index = -1;
 339#endif
 340                }
 341            }
 342
 343            if (kvm_enabled()) {
 344                kvm_cpu_exec(env);
 345                longjmp(env->jmp_env, 1);
 346            }
 347
 348            next_tb = 0; /* force lookup of first TB */
 349            for(;;) {
 350                interrupt_request = env->interrupt_request;
 351                if (unlikely(interrupt_request)) {
 352                    if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
 353                        /* Mask out external interrupts for this step. */
 354                        interrupt_request &= ~(CPU_INTERRUPT_HARD |
 355                                               CPU_INTERRUPT_FIQ |
 356                                               CPU_INTERRUPT_SMI |
 357                                               CPU_INTERRUPT_NMI);
 358                    }
 359                    if (interrupt_request & CPU_INTERRUPT_DEBUG) {
 360                        env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
 361                        env->exception_index = EXCP_DEBUG;
 362                        cpu_loop_exit();
 363                    }
 364#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
 365    defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
 366    defined(TARGET_MICROBLAZE)
 367                    if (interrupt_request & CPU_INTERRUPT_HALT) {
 368                        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
 369                        env->halted = 1;
 370                        env->exception_index = EXCP_HLT;
 371                        cpu_loop_exit();
 372                    }
 373#endif
 374#if defined(TARGET_I386)
 375                    if (interrupt_request & CPU_INTERRUPT_INIT) {
 376                            svm_check_intercept(SVM_EXIT_INIT);
 377                            do_cpu_init(env);
 378                            env->exception_index = EXCP_HALTED;
 379                            cpu_loop_exit();
 380                    } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
 381                            do_cpu_sipi(env);
 382                    } else if (env->hflags2 & HF2_GIF_MASK) {
 383                        if ((interrupt_request & CPU_INTERRUPT_SMI) &&
 384                            !(env->hflags & HF_SMM_MASK)) {
 385                            svm_check_intercept(SVM_EXIT_SMI);
 386                            env->interrupt_request &= ~CPU_INTERRUPT_SMI;
 387                            do_smm_enter();
 388                            next_tb = 0;
 389                        } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
 390                                   !(env->hflags2 & HF2_NMI_MASK)) {
 391                            env->interrupt_request &= ~CPU_INTERRUPT_NMI;
 392                            env->hflags2 |= HF2_NMI_MASK;
 393                            do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
 394                            next_tb = 0;
 395                        } else if (interrupt_request & CPU_INTERRUPT_MCE) {
 396                            env->interrupt_request &= ~CPU_INTERRUPT_MCE;
 397                            do_interrupt(EXCP12_MCHK, 0, 0, 0, 0);
 398                            next_tb = 0;
 399                        } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
 400                                   (((env->hflags2 & HF2_VINTR_MASK) && 
 401                                     (env->hflags2 & HF2_HIF_MASK)) ||
 402                                    (!(env->hflags2 & HF2_VINTR_MASK) && 
 403                                     (env->eflags & IF_MASK && 
 404                                      !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
 405                            int intno;
 406                            svm_check_intercept(SVM_EXIT_INTR);
 407                            env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
 408                            intno = cpu_get_pic_interrupt(env);
 409                            qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
 410#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
 411#undef env
 412                    env = cpu_single_env;
 413#define env cpu_single_env
 414#endif
 415                            do_interrupt(intno, 0, 0, 0, 1);
 416                            /* ensure that no TB jump will be modified as
 417                               the program flow was changed */
 418                            next_tb = 0;
 419#if !defined(CONFIG_USER_ONLY)
 420                        } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
 421                                   (env->eflags & IF_MASK) && 
 422                                   !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
 423                            int intno;
 424                            /* FIXME: this should respect TPR */
 425                            svm_check_intercept(SVM_EXIT_VINTR);
 426                            intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
 427                            qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
 428                            do_interrupt(intno, 0, 0, 0, 1);
 429                            env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
 430                            next_tb = 0;
 431#endif
 432                        }
 433                    }
 434#elif defined(TARGET_PPC)
 435#if 0
 436                    if ((interrupt_request & CPU_INTERRUPT_RESET)) {
 437                        cpu_reset(env);
 438                    }
 439#endif
 440                    if (interrupt_request & CPU_INTERRUPT_HARD) {
 441                        ppc_hw_interrupt(env);
 442                        if (env->pending_interrupts == 0)
 443                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
 444                        next_tb = 0;
 445                    }
 446#elif defined(TARGET_MICROBLAZE)
 447                    if ((interrupt_request & CPU_INTERRUPT_HARD)
 448                        && (env->sregs[SR_MSR] & MSR_IE)
 449                        && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
 450                        && !(env->iflags & (D_FLAG | IMM_FLAG))) {
 451                        env->exception_index = EXCP_IRQ;
 452                        do_interrupt(env);
 453                        next_tb = 0;
 454                    }
 455#elif defined(TARGET_MIPS)
 456                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
 457                        cpu_mips_hw_interrupts_pending(env)) {
 458                        /* Raise it */
 459                        env->exception_index = EXCP_EXT_INTERRUPT;
 460                        env->error_code = 0;
 461                        do_interrupt(env);
 462                        next_tb = 0;
 463                    }
 464#elif defined(TARGET_SPARC)
 465                    if (interrupt_request & CPU_INTERRUPT_HARD) {
 466                        if (cpu_interrupts_enabled(env) &&
 467                            env->interrupt_index > 0) {
 468                            int pil = env->interrupt_index & 0xf;
 469                            int type = env->interrupt_index & 0xf0;
 470
 471                            if (((type == TT_EXTINT) &&
 472                                  cpu_pil_allowed(env, pil)) ||
 473                                  type != TT_EXTINT) {
 474                                env->exception_index = env->interrupt_index;
 475                                do_interrupt(env);
 476                                next_tb = 0;
 477                            }
 478                        }
 479                    } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
 480                        //do_interrupt(0, 0, 0, 0, 0);
 481                        env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
 482                    }
 483#elif defined(TARGET_ARM)
 484                    if (interrupt_request & CPU_INTERRUPT_FIQ
 485                        && !(env->uncached_cpsr & CPSR_F)) {
 486                        env->exception_index = EXCP_FIQ;
 487                        do_interrupt(env);
 488                        next_tb = 0;
 489                    }
 490                    /* ARMv7-M interrupt return works by loading a magic value
 491                       into the PC.  On real hardware the load causes the
 492                       return to occur.  The qemu implementation performs the
 493                       jump normally, then does the exception return when the
 494                       CPU tries to execute code at the magic address.
 495                       This will cause the magic PC value to be pushed to
 496                       the stack if an interrupt occured at the wrong time.
 497                       We avoid this by disabling interrupts when
 498                       pc contains a magic address.  */
 499                    if (interrupt_request & CPU_INTERRUPT_HARD
 500                        && ((IS_M(env) && env->regs[15] < 0xfffffff0)
 501                            || !(env->uncached_cpsr & CPSR_I))) {
 502                        env->exception_index = EXCP_IRQ;
 503                        do_interrupt(env);
 504                        next_tb = 0;
 505                    }
 506#elif defined(TARGET_SH4)
 507                    if (interrupt_request & CPU_INTERRUPT_HARD) {
 508                        do_interrupt(env);
 509                        next_tb = 0;
 510                    }
 511#elif defined(TARGET_ALPHA)
 512                    if (interrupt_request & CPU_INTERRUPT_HARD) {
 513                        do_interrupt(env);
 514                        next_tb = 0;
 515                    }
 516#elif defined(TARGET_CRIS)
 517                    if (interrupt_request & CPU_INTERRUPT_HARD
 518                        && (env->pregs[PR_CCS] & I_FLAG)
 519                        && !env->locked_irq) {
 520                        env->exception_index = EXCP_IRQ;
 521                        do_interrupt(env);
 522                        next_tb = 0;
 523                    }
 524                    if (interrupt_request & CPU_INTERRUPT_NMI
 525                        && (env->pregs[PR_CCS] & M_FLAG)) {
 526                        env->exception_index = EXCP_NMI;
 527                        do_interrupt(env);
 528                        next_tb = 0;
 529                    }
 530#elif defined(TARGET_M68K)
 531                    if (interrupt_request & CPU_INTERRUPT_HARD
 532                        && ((env->sr & SR_I) >> SR_I_SHIFT)
 533                            < env->pending_level) {
 534                        /* Real hardware gets the interrupt vector via an
 535                           IACK cycle at this point.  Current emulated
 536                           hardware doesn't rely on this, so we
 537                           provide/save the vector when the interrupt is
 538                           first signalled.  */
 539                        env->exception_index = env->pending_vector;
 540                        do_interrupt(1);
 541                        next_tb = 0;
 542                    }
 543#endif
 544                   /* Don't use the cached interupt_request value,
 545                      do_interrupt may have updated the EXITTB flag. */
 546                    if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
 547                        env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
 548                        /* ensure that no TB jump will be modified as
 549                           the program flow was changed */
 550                        next_tb = 0;
 551                    }
 552                }
 553                if (unlikely(env->exit_request)) {
 554                    env->exit_request = 0;
 555                    env->exception_index = EXCP_INTERRUPT;
 556                    cpu_loop_exit();
 557                }
 558#if defined(DEBUG_DISAS) || defined(CONFIG_DEBUG_EXEC)
 559                if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
 560                    /* restore flags in standard format */
 561#if defined(TARGET_I386)
 562                    env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
 563                    log_cpu_state(env, X86_DUMP_CCOP);
 564                    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
 565#elif defined(TARGET_M68K)
 566                    cpu_m68k_flush_flags(env, env->cc_op);
 567                    env->cc_op = CC_OP_FLAGS;
 568                    env->sr = (env->sr & 0xffe0)
 569                              | env->cc_dest | (env->cc_x << 4);
 570                    log_cpu_state(env, 0);
 571#else
 572                    log_cpu_state(env, 0);
 573#endif
 574                }
 575#endif /* DEBUG_DISAS || CONFIG_DEBUG_EXEC */
 576                spin_lock(&tb_lock);
 577                tb = tb_find_fast();
 578                /* Note: we do it here to avoid a gcc bug on Mac OS X when
 579                   doing it in tb_find_slow */
 580                if (tb_invalidated_flag) {
 581                    /* as some TB could have been invalidated because
 582                       of memory exceptions while generating the code, we
 583                       must recompute the hash index here */
 584                    next_tb = 0;
 585                    tb_invalidated_flag = 0;
 586                }
 587#ifdef CONFIG_DEBUG_EXEC
 588                qemu_log_mask(CPU_LOG_EXEC, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
 589                             (long)tb->tc_ptr, tb->pc,
 590                             lookup_symbol(tb->pc));
 591#endif
 592                /* see if we can patch the calling TB. When the TB
 593                   spans two pages, we cannot safely do a direct
 594                   jump. */
 595                if (next_tb != 0 && tb->page_addr[1] == -1) {
 596                    tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
 597                }
 598                spin_unlock(&tb_lock);
 599
 600                /* cpu_interrupt might be called while translating the
 601                   TB, but before it is linked into a potentially
 602                   infinite loop and becomes env->current_tb. Avoid
 603                   starting execution if there is a pending interrupt. */
 604                env->current_tb = tb;
 605                barrier();
 606                if (likely(!env->exit_request)) {
 607                    tc_ptr = tb->tc_ptr;
 608                /* execute the generated code */
 609#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
 610#undef env
 611                    env = cpu_single_env;
 612#define env cpu_single_env
 613#endif
 614                    next_tb = tcg_qemu_tb_exec(tc_ptr);
 615                    if ((next_tb & 3) == 2) {
 616                        /* Instruction counter expired.  */
 617                        int insns_left;
 618                        tb = (TranslationBlock *)(long)(next_tb & ~3);
 619                        /* Restore PC.  */
 620                        cpu_pc_from_tb(env, tb);
 621                        insns_left = env->icount_decr.u32;
 622                        if (env->icount_extra && insns_left >= 0) {
 623                            /* Refill decrementer and continue execution.  */
 624                            env->icount_extra += insns_left;
 625                            if (env->icount_extra > 0xffff) {
 626                                insns_left = 0xffff;
 627                            } else {
 628                                insns_left = env->icount_extra;
 629                            }
 630                            env->icount_extra -= insns_left;
 631                            env->icount_decr.u16.low = insns_left;
 632                        } else {
 633                            if (insns_left > 0) {
 634                                /* Execute remaining instructions.  */
 635                                cpu_exec_nocache(insns_left, tb);
 636                            }
 637                            env->exception_index = EXCP_INTERRUPT;
 638                            next_tb = 0;
 639                            cpu_loop_exit();
 640                        }
 641                    }
 642                }
 643                env->current_tb = NULL;
 644                /* reset soft MMU for next block (it can currently
 645                   only be set by a memory fault) */
 646            } /* for(;;) */
 647        }
 648    } /* for(;;) */
 649
 650
 651#if defined(TARGET_I386)
 652    /* restore flags in standard format */
 653    env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
 654#elif defined(TARGET_ARM)
 655    /* XXX: Save/restore host fpu exception state?.  */
 656#elif defined(TARGET_SPARC)
 657#elif defined(TARGET_PPC)
 658#elif defined(TARGET_M68K)
 659    cpu_m68k_flush_flags(env, env->cc_op);
 660    env->cc_op = CC_OP_FLAGS;
 661    env->sr = (env->sr & 0xffe0)
 662              | env->cc_dest | (env->cc_x << 4);
 663#elif defined(TARGET_MICROBLAZE)
 664#elif defined(TARGET_MIPS)
 665#elif defined(TARGET_SH4)
 666#elif defined(TARGET_ALPHA)
 667#elif defined(TARGET_CRIS)
 668#elif defined(TARGET_S390X)
 669    /* XXXXX */
 670#else
 671#error unsupported target CPU
 672#endif
 673
 674    /* restore global registers */
 675    barrier();
 676    env = (void *) saved_env_reg;
 677
 678    /* fail safe : never use cpu_single_env outside cpu_exec() */
 679    cpu_single_env = NULL;
 680    return ret;
 681}
 682
 683/* must only be called from the generated code as an exception can be
 684   generated */
 685void tb_invalidate_page_range(target_ulong start, target_ulong end)
 686{
 687    /* XXX: cannot enable it yet because it yields to MMU exception
 688       where NIP != read address on PowerPC */
 689#if 0
 690    target_ulong phys_addr;
 691    phys_addr = get_phys_addr_code(env, start);
 692    tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
 693#endif
 694}
 695
 696#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
 697
 698void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
 699{
 700    CPUX86State *saved_env;
 701
 702    saved_env = env;
 703    env = s;
 704    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
 705        selector &= 0xffff;
 706        cpu_x86_load_seg_cache(env, seg_reg, selector,
 707                               (selector << 4), 0xffff, 0);
 708    } else {
 709        helper_load_seg(seg_reg, selector);
 710    }
 711    env = saved_env;
 712}
 713
 714void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
 715{
 716    CPUX86State *saved_env;
 717
 718    saved_env = env;
 719    env = s;
 720
 721    helper_fsave(ptr, data32);
 722
 723    env = saved_env;
 724}
 725
 726void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
 727{
 728    CPUX86State *saved_env;
 729
 730    saved_env = env;
 731    env = s;
 732
 733    helper_frstor(ptr, data32);
 734
 735    env = saved_env;
 736}
 737
 738#endif /* TARGET_I386 */
 739
 740#if !defined(CONFIG_SOFTMMU)
 741
 742#if defined(TARGET_I386)
 743#define EXCEPTION_ACTION raise_exception_err(env->exception_index, env->error_code)
 744#else
 745#define EXCEPTION_ACTION cpu_loop_exit()
 746#endif
 747
 748/* 'pc' is the host PC at which the exception was raised. 'address' is
 749   the effective address of the memory exception. 'is_write' is 1 if a
 750   write caused the exception and otherwise 0'. 'old_set' is the
 751   signal set which should be restored */
 752static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
 753                                    int is_write, sigset_t *old_set,
 754                                    void *puc)
 755{
 756    TranslationBlock *tb;
 757    int ret;
 758
 759    if (cpu_single_env)
 760        env = cpu_single_env; /* XXX: find a correct solution for multithread */
 761#if defined(DEBUG_SIGNAL)
 762    qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
 763                pc, address, is_write, *(unsigned long *)old_set);
 764#endif
 765    /* XXX: locking issue */
 766    if (is_write && page_unprotect(h2g(address), pc, puc)) {
 767        return 1;
 768    }
 769
 770    /* see if it is an MMU fault */
 771    ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
 772    if (ret < 0)
 773        return 0; /* not an MMU fault */
 774    if (ret == 0)
 775        return 1; /* the MMU fault was handled without causing real CPU fault */
 776    /* now we have a real cpu fault */
 777    tb = tb_find_pc(pc);
 778    if (tb) {
 779        /* the PC is inside the translated code. It means that we have
 780           a virtual CPU fault */
 781        cpu_restore_state(tb, env, pc, puc);
 782    }
 783
 784    /* we restore the process signal mask as the sigreturn should
 785       do it (XXX: use sigsetjmp) */
 786    sigprocmask(SIG_SETMASK, old_set, NULL);
 787    EXCEPTION_ACTION;
 788
 789    /* never comes here */
 790    return 1;
 791}
 792
 793#if defined(__i386__)
 794
 795#if defined(__APPLE__)
 796# include <sys/ucontext.h>
 797
 798# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
 799# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
 800# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
 801# define MASK_sig(context)    ((context)->uc_sigmask)
 802#elif defined (__NetBSD__)
 803# include <ucontext.h>
 804
 805# define EIP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_EIP])
 806# define TRAP_sig(context)    ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
 807# define ERROR_sig(context)   ((context)->uc_mcontext.__gregs[_REG_ERR])
 808# define MASK_sig(context)    ((context)->uc_sigmask)
 809#elif defined (__FreeBSD__) || defined(__DragonFly__)
 810# include <ucontext.h>
 811
 812# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_eip))
 813# define TRAP_sig(context)    ((context)->uc_mcontext.mc_trapno)
 814# define ERROR_sig(context)   ((context)->uc_mcontext.mc_err)
 815# define MASK_sig(context)    ((context)->uc_sigmask)
 816#elif defined(__OpenBSD__)
 817# define EIP_sig(context)     ((context)->sc_eip)
 818# define TRAP_sig(context)    ((context)->sc_trapno)
 819# define ERROR_sig(context)   ((context)->sc_err)
 820# define MASK_sig(context)    ((context)->sc_mask)
 821#else
 822# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
 823# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
 824# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
 825# define MASK_sig(context)    ((context)->uc_sigmask)
 826#endif
 827
 828int cpu_signal_handler(int host_signum, void *pinfo,
 829                       void *puc)
 830{
 831    siginfo_t *info = pinfo;
 832#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
 833    ucontext_t *uc = puc;
 834#elif defined(__OpenBSD__)
 835    struct sigcontext *uc = puc;
 836#else
 837    struct ucontext *uc = puc;
 838#endif
 839    unsigned long pc;
 840    int trapno;
 841
 842#ifndef REG_EIP
 843/* for glibc 2.1 */
 844#define REG_EIP    EIP
 845#define REG_ERR    ERR
 846#define REG_TRAPNO TRAPNO
 847#endif
 848    pc = EIP_sig(uc);
 849    trapno = TRAP_sig(uc);
 850    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
 851                             trapno == 0xe ?
 852                             (ERROR_sig(uc) >> 1) & 1 : 0,
 853                             &MASK_sig(uc), puc);
 854}
 855
 856#elif defined(__x86_64__)
 857
 858#ifdef __NetBSD__
 859#define PC_sig(context)       _UC_MACHINE_PC(context)
 860#define TRAP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
 861#define ERROR_sig(context)    ((context)->uc_mcontext.__gregs[_REG_ERR])
 862#define MASK_sig(context)     ((context)->uc_sigmask)
 863#elif defined(__OpenBSD__)
 864#define PC_sig(context)       ((context)->sc_rip)
 865#define TRAP_sig(context)     ((context)->sc_trapno)
 866#define ERROR_sig(context)    ((context)->sc_err)
 867#define MASK_sig(context)     ((context)->sc_mask)
 868#elif defined (__FreeBSD__) || defined(__DragonFly__)
 869#include <ucontext.h>
 870
 871#define PC_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_rip))
 872#define TRAP_sig(context)     ((context)->uc_mcontext.mc_trapno)
 873#define ERROR_sig(context)    ((context)->uc_mcontext.mc_err)
 874#define MASK_sig(context)     ((context)->uc_sigmask)
 875#else
 876#define PC_sig(context)       ((context)->uc_mcontext.gregs[REG_RIP])
 877#define TRAP_sig(context)     ((context)->uc_mcontext.gregs[REG_TRAPNO])
 878#define ERROR_sig(context)    ((context)->uc_mcontext.gregs[REG_ERR])
 879#define MASK_sig(context)     ((context)->uc_sigmask)
 880#endif
 881
 882int cpu_signal_handler(int host_signum, void *pinfo,
 883                       void *puc)
 884{
 885    siginfo_t *info = pinfo;
 886    unsigned long pc;
 887#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
 888    ucontext_t *uc = puc;
 889#elif defined(__OpenBSD__)
 890    struct sigcontext *uc = puc;
 891#else
 892    struct ucontext *uc = puc;
 893#endif
 894
 895    pc = PC_sig(uc);
 896    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
 897                             TRAP_sig(uc) == 0xe ?
 898                             (ERROR_sig(uc) >> 1) & 1 : 0,
 899                             &MASK_sig(uc), puc);
 900}
 901
 902#elif defined(_ARCH_PPC)
 903
 904/***********************************************************************
 905 * signal context platform-specific definitions
 906 * From Wine
 907 */
 908#ifdef linux
 909/* All Registers access - only for local access */
 910# define REG_sig(reg_name, context)             ((context)->uc_mcontext.regs->reg_name)
 911/* Gpr Registers access  */
 912# define GPR_sig(reg_num, context)              REG_sig(gpr[reg_num], context)
 913# define IAR_sig(context)                       REG_sig(nip, context)   /* Program counter */
 914# define MSR_sig(context)                       REG_sig(msr, context)   /* Machine State Register (Supervisor) */
 915# define CTR_sig(context)                       REG_sig(ctr, context)   /* Count register */
 916# define XER_sig(context)                       REG_sig(xer, context) /* User's integer exception register */
 917# define LR_sig(context)                        REG_sig(link, context) /* Link register */
 918# define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
 919/* Float Registers access  */
 920# define FLOAT_sig(reg_num, context)            (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
 921# define FPSCR_sig(context)                     (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
 922/* Exception Registers access */
 923# define DAR_sig(context)                       REG_sig(dar, context)
 924# define DSISR_sig(context)                     REG_sig(dsisr, context)
 925# define TRAP_sig(context)                      REG_sig(trap, context)
 926#endif /* linux */
 927
 928#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
 929#include <ucontext.h>
 930# define IAR_sig(context)               ((context)->uc_mcontext.mc_srr0)
 931# define MSR_sig(context)               ((context)->uc_mcontext.mc_srr1)
 932# define CTR_sig(context)               ((context)->uc_mcontext.mc_ctr)
 933# define XER_sig(context)               ((context)->uc_mcontext.mc_xer)
 934# define LR_sig(context)                ((context)->uc_mcontext.mc_lr)
 935# define CR_sig(context)                ((context)->uc_mcontext.mc_cr)
 936/* Exception Registers access */
 937# define DAR_sig(context)               ((context)->uc_mcontext.mc_dar)
 938# define DSISR_sig(context)             ((context)->uc_mcontext.mc_dsisr)
 939# define TRAP_sig(context)              ((context)->uc_mcontext.mc_exc)
 940#endif /* __FreeBSD__|| __FreeBSD_kernel__ */
 941
 942#ifdef __APPLE__
 943# include <sys/ucontext.h>
 944typedef struct ucontext SIGCONTEXT;
 945/* All Registers access - only for local access */
 946# define REG_sig(reg_name, context)             ((context)->uc_mcontext->ss.reg_name)
 947# define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
 948# define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
 949# define VECREG_sig(reg_name, context)          ((context)->uc_mcontext->vs.reg_name)
 950/* Gpr Registers access */
 951# define GPR_sig(reg_num, context)              REG_sig(r##reg_num, context)
 952# define IAR_sig(context)                       REG_sig(srr0, context)  /* Program counter */
 953# define MSR_sig(context)                       REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
 954# define CTR_sig(context)                       REG_sig(ctr, context)
 955# define XER_sig(context)                       REG_sig(xer, context) /* Link register */
 956# define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
 957# define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
 958/* Float Registers access */
 959# define FLOAT_sig(reg_num, context)            FLOATREG_sig(fpregs[reg_num], context)
 960# define FPSCR_sig(context)                     ((double)FLOATREG_sig(fpscr, context))
 961/* Exception Registers access */
 962# define DAR_sig(context)                       EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
 963# define DSISR_sig(context)                     EXCEPREG_sig(dsisr, context)
 964# define TRAP_sig(context)                      EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
 965#endif /* __APPLE__ */
 966
 967int cpu_signal_handler(int host_signum, void *pinfo,
 968                       void *puc)
 969{
 970    siginfo_t *info = pinfo;
 971#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
 972    ucontext_t *uc = puc;
 973#else
 974    struct ucontext *uc = puc;
 975#endif
 976    unsigned long pc;
 977    int is_write;
 978
 979    pc = IAR_sig(uc);
 980    is_write = 0;
 981#if 0
 982    /* ppc 4xx case */
 983    if (DSISR_sig(uc) & 0x00800000)
 984        is_write = 1;
 985#else
 986    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
 987        is_write = 1;
 988#endif
 989    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
 990                             is_write, &uc->uc_sigmask, puc);
 991}
 992
 993#elif defined(__alpha__)
 994
 995int cpu_signal_handler(int host_signum, void *pinfo,
 996                           void *puc)
 997{
 998    siginfo_t *info = pinfo;
 999    struct ucontext *uc = puc;
1000    uint32_t *pc = uc->uc_mcontext.sc_pc;
1001    uint32_t insn = *pc;
1002    int is_write = 0;
1003
1004    /* XXX: need kernel patch to get write flag faster */
1005    switch (insn >> 26) {
1006    case 0x0d: // stw
1007    case 0x0e: // stb
1008    case 0x0f: // stq_u
1009    case 0x24: // stf
1010    case 0x25: // stg
1011    case 0x26: // sts
1012    case 0x27: // stt
1013    case 0x2c: // stl
1014    case 0x2d: // stq
1015    case 0x2e: // stl_c
1016    case 0x2f: // stq_c
1017        is_write = 1;
1018    }
1019
1020    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1021                             is_write, &uc->uc_sigmask, puc);
1022}
1023#elif defined(__sparc__)
1024
1025int cpu_signal_handler(int host_signum, void *pinfo,
1026                       void *puc)
1027{
1028    siginfo_t *info = pinfo;
1029    int is_write;
1030    uint32_t insn;
1031#if !defined(__arch64__) || defined(CONFIG_SOLARIS)
1032    uint32_t *regs = (uint32_t *)(info + 1);
1033    void *sigmask = (regs + 20);
1034    /* XXX: is there a standard glibc define ? */
1035    unsigned long pc = regs[1];
1036#else
1037#ifdef __linux__
1038    struct sigcontext *sc = puc;
1039    unsigned long pc = sc->sigc_regs.tpc;
1040    void *sigmask = (void *)sc->sigc_mask;
1041#elif defined(__OpenBSD__)
1042    struct sigcontext *uc = puc;
1043    unsigned long pc = uc->sc_pc;
1044    void *sigmask = (void *)(long)uc->sc_mask;
1045#endif
1046#endif
1047
1048    /* XXX: need kernel patch to get write flag faster */
1049    is_write = 0;
1050    insn = *(uint32_t *)pc;
1051    if ((insn >> 30) == 3) {
1052      switch((insn >> 19) & 0x3f) {
1053      case 0x05: // stb
1054      case 0x15: // stba
1055      case 0x06: // sth
1056      case 0x16: // stha
1057      case 0x04: // st
1058      case 0x14: // sta
1059      case 0x07: // std
1060      case 0x17: // stda
1061      case 0x0e: // stx
1062      case 0x1e: // stxa
1063      case 0x24: // stf
1064      case 0x34: // stfa
1065      case 0x27: // stdf
1066      case 0x37: // stdfa
1067      case 0x26: // stqf
1068      case 0x36: // stqfa
1069      case 0x25: // stfsr
1070      case 0x3c: // casa
1071      case 0x3e: // casxa
1072        is_write = 1;
1073        break;
1074      }
1075    }
1076    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1077                             is_write, sigmask, NULL);
1078}
1079
1080#elif defined(__arm__)
1081
1082int cpu_signal_handler(int host_signum, void *pinfo,
1083                       void *puc)
1084{
1085    siginfo_t *info = pinfo;
1086    struct ucontext *uc = puc;
1087    unsigned long pc;
1088    int is_write;
1089
1090#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
1091    pc = uc->uc_mcontext.gregs[R15];
1092#else
1093    pc = uc->uc_mcontext.arm_pc;
1094#endif
1095    /* XXX: compute is_write */
1096    is_write = 0;
1097    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1098                             is_write,
1099                             &uc->uc_sigmask, puc);
1100}
1101
1102#elif defined(__mc68000)
1103
1104int cpu_signal_handler(int host_signum, void *pinfo,
1105                       void *puc)
1106{
1107    siginfo_t *info = pinfo;
1108    struct ucontext *uc = puc;
1109    unsigned long pc;
1110    int is_write;
1111
1112    pc = uc->uc_mcontext.gregs[16];
1113    /* XXX: compute is_write */
1114    is_write = 0;
1115    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1116                             is_write,
1117                             &uc->uc_sigmask, puc);
1118}
1119
1120#elif defined(__ia64)
1121
1122#ifndef __ISR_VALID
1123  /* This ought to be in <bits/siginfo.h>... */
1124# define __ISR_VALID    1
1125#endif
1126
1127int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1128{
1129    siginfo_t *info = pinfo;
1130    struct ucontext *uc = puc;
1131    unsigned long ip;
1132    int is_write = 0;
1133
1134    ip = uc->uc_mcontext.sc_ip;
1135    switch (host_signum) {
1136      case SIGILL:
1137      case SIGFPE:
1138      case SIGSEGV:
1139      case SIGBUS:
1140      case SIGTRAP:
1141          if (info->si_code && (info->si_segvflags & __ISR_VALID))
1142              /* ISR.W (write-access) is bit 33:  */
1143              is_write = (info->si_isr >> 33) & 1;
1144          break;
1145
1146      default:
1147          break;
1148    }
1149    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1150                             is_write,
1151                             (sigset_t *)&uc->uc_sigmask, puc);
1152}
1153
1154#elif defined(__s390__)
1155
1156int cpu_signal_handler(int host_signum, void *pinfo,
1157                       void *puc)
1158{
1159    siginfo_t *info = pinfo;
1160    struct ucontext *uc = puc;
1161    unsigned long pc;
1162    uint16_t *pinsn;
1163    int is_write = 0;
1164
1165    pc = uc->uc_mcontext.psw.addr;
1166
1167    /* ??? On linux, the non-rt signal handler has 4 (!) arguments instead
1168       of the normal 2 arguments.  The 3rd argument contains the "int_code"
1169       from the hardware which does in fact contain the is_write value.
1170       The rt signal handler, as far as I can tell, does not give this value
1171       at all.  Not that we could get to it from here even if it were.  */
1172    /* ??? This is not even close to complete, since it ignores all
1173       of the read-modify-write instructions.  */
1174    pinsn = (uint16_t *)pc;
1175    switch (pinsn[0] >> 8) {
1176    case 0x50: /* ST */
1177    case 0x42: /* STC */
1178    case 0x40: /* STH */
1179        is_write = 1;
1180        break;
1181    case 0xc4: /* RIL format insns */
1182        switch (pinsn[0] & 0xf) {
1183        case 0xf: /* STRL */
1184        case 0xb: /* STGRL */
1185        case 0x7: /* STHRL */
1186            is_write = 1;
1187        }
1188        break;
1189    case 0xe3: /* RXY format insns */
1190        switch (pinsn[2] & 0xff) {
1191        case 0x50: /* STY */
1192        case 0x24: /* STG */
1193        case 0x72: /* STCY */
1194        case 0x70: /* STHY */
1195        case 0x8e: /* STPQ */
1196        case 0x3f: /* STRVH */
1197        case 0x3e: /* STRV */
1198        case 0x2f: /* STRVG */
1199            is_write = 1;
1200        }
1201        break;
1202    }
1203    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1204                             is_write, &uc->uc_sigmask, puc);
1205}
1206
1207#elif defined(__mips__)
1208
1209int cpu_signal_handler(int host_signum, void *pinfo,
1210                       void *puc)
1211{
1212    siginfo_t *info = pinfo;
1213    struct ucontext *uc = puc;
1214    greg_t pc = uc->uc_mcontext.pc;
1215    int is_write;
1216
1217    /* XXX: compute is_write */
1218    is_write = 0;
1219    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1220                             is_write, &uc->uc_sigmask, puc);
1221}
1222
1223#elif defined(__hppa__)
1224
1225int cpu_signal_handler(int host_signum, void *pinfo,
1226                       void *puc)
1227{
1228    struct siginfo *info = pinfo;
1229    struct ucontext *uc = puc;
1230    unsigned long pc = uc->uc_mcontext.sc_iaoq[0];
1231    uint32_t insn = *(uint32_t *)pc;
1232    int is_write = 0;
1233
1234    /* XXX: need kernel patch to get write flag faster.  */
1235    switch (insn >> 26) {
1236    case 0x1a: /* STW */
1237    case 0x19: /* STH */
1238    case 0x18: /* STB */
1239    case 0x1b: /* STWM */
1240        is_write = 1;
1241        break;
1242
1243    case 0x09: /* CSTWX, FSTWX, FSTWS */
1244    case 0x0b: /* CSTDX, FSTDX, FSTDS */
1245        /* Distinguish from coprocessor load ... */
1246        is_write = (insn >> 9) & 1;
1247        break;
1248
1249    case 0x03:
1250        switch ((insn >> 6) & 15) {
1251        case 0xa: /* STWS */
1252        case 0x9: /* STHS */
1253        case 0x8: /* STBS */
1254        case 0xe: /* STWAS */
1255        case 0xc: /* STBYS */
1256            is_write = 1;
1257        }
1258        break;
1259    }
1260
1261    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1262                             is_write, &uc->uc_sigmask, puc);
1263}
1264
1265#else
1266
1267#error host CPU specific signal handler needed
1268
1269#endif
1270
1271#endif /* !defined(CONFIG_SOFTMMU) */
1272