18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  i386 emulator main execution loop
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  Copyright (c) 2003-2005 Fabrice Bellard
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This library is free software; you can redistribute it and/or
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * modify it under the terms of the GNU Lesser General Public
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * License as published by the Free Software Foundation; either
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * version 2 of the License, or (at your option) any later version.
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This library is distributed in the hope that it will be useful,
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Lesser General Public License for more details.
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * You should have received a copy of the GNU Lesser General Public
17a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner * License along with this library; if not, see <http://www.gnu.org/licenses/>.
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "config.h"
20a889d35e76c8ea18caf70c738fd585c64b857369David 'Digit' Turner#include "cpu.h"
21cc33b2d8035092608c7cba4154e9c44452727e1bDavid 'Digit' Turner#include "disas/disas.h"
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "tcg.h"
2334c48ff1e3ad5cd2084ca40188754d45f423750bDavid 'Digit' Turner#include "sysemu/kvm.h"
24e1e03df288d5a44bfbffbd86588395c7cbbc27dfDavid 'Digit' Turner#include "exec/hax.h"
25e1e03df288d5a44bfbffbd86588395c7cbbc27dfDavid 'Digit' Turner#include "qemu/atomic.h"
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_SOFTMMU)
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef EAX
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef ECX
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef EDX
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef EBX
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef ESP
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef EBP
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef ESI
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef EDI
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef EIP
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <signal.h>
385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __linux__
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/ucontext.h>
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint tb_invalidated_flag;
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
45a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner//#define CONFIG_DEBUG_EXEC
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project//#define DEBUG_SIGNAL
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
48bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turnerbool qemu_cpu_has_work(CPUState *cpu)
495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
50bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turner    return cpu_has_work(cpu);
515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
53a681001f110feadb11ebed7c46832262784f6720David 'Digit' Turnervoid cpu_loop_exit(CPUArchState* env)
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
55a681001f110feadb11ebed7c46832262784f6720David 'Digit' Turner    env->current_tb = NULL;
56a681001f110feadb11ebed7c46832262784f6720David 'Digit' Turner    longjmp(env->jmp_env, 1);
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* exit the current TB from a signal handler. The host registers are
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   restored in a state compatible with the CPU emulator
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
62a681001f110feadb11ebed7c46832262784f6720David 'Digit' Turnervoid cpu_resume_from_signal(CPUArchState *env, void *puc)
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_SOFTMMU)
655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __linux__
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(__OpenBSD__)
685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct sigcontext *uc = puc;
695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: restore cpu registers saved in host registers */
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_SOFTMMU)
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (puc) {
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* XXX: use siglongjmp ? */
775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __linux__
7824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#ifdef __ia64
7924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        sigprocmask(SIG_SETMASK, (sigset_t *)&uc->uc_sigmask, NULL);
8024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#else
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
8224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#endif
835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(__OpenBSD__)
845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        sigprocmask(SIG_SETMASK, &uc->sc_mask, NULL);
855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    env->exception_index = -1;
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    longjmp(env->jmp_env, 1);
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Execute the code without caching the generated code. An interpreter
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   could be used if available. */
94a681001f110feadb11ebed7c46832262784f6720David 'Digit' Turnerstatic void cpu_exec_nocache(CPUArchState *env, int max_cycles, TranslationBlock *orig_tb)
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9653a08edf171bdbc7e3a2d89b78b96a33361a2760David 'Digit' Turner    tcg_target_ulong next_tb;
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TranslationBlock *tb;
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Should never happen.
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       We only end up here when an existing TB is too long.  */
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (max_cycles > CF_COUNT_MASK)
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        max_cycles = CF_COUNT_MASK;
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     max_cycles);
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->current_tb = tb;
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* execute the generated code */
108a681001f110feadb11ebed7c46832262784f6720David 'Digit' Turner    next_tb = tcg_qemu_tb_exec(env, tb->tc_ptr);
10924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    env->current_tb = NULL;
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((next_tb & 3) == 2) {
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Restore PC.  This may happen if async event occurs before
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           the TB starts executing.  */
1145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        cpu_pc_from_tb(env, tb);
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tb_phys_invalidate(tb, -1);
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tb_free(tb);
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
120a681001f110feadb11ebed7c46832262784f6720David 'Digit' Turnerstatic TranslationBlock *tb_find_slow(CPUArchState *env,
121a681001f110feadb11ebed7c46832262784f6720David 'Digit' Turner                                      target_ulong pc,
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                      target_ulong cs_base,
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                      uint64_t flags)
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TranslationBlock *tb, **ptb1;
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned int h;
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tb_invalidated_flag = 0;
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* find translated block using physical mappings */
1321348777d4229cf65ef12d0a4ee531d4502847277David 'Digit' Turner    phys_pc = get_page_addr_code(env, pc);
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    phys_page1 = phys_pc & TARGET_PAGE_MASK;
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    phys_page2 = -1;
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    h = tb_phys_hash_func(phys_pc);
1361348777d4229cf65ef12d0a4ee531d4502847277David 'Digit' Turner    ptb1 = &tcg_ctx.tb_ctx.tb_phys_hash[h];
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(;;) {
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tb = *ptb1;
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!tb)
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto not_found;
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (tb->pc == pc &&
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tb->page_addr[0] == phys_page1 &&
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tb->cs_base == cs_base &&
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tb->flags == flags) {
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* check next page if needed */
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (tb->page_addr[1] != -1) {
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                virt_page2 = (pc & TARGET_PAGE_MASK) +
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    TARGET_PAGE_SIZE;
1491348777d4229cf65ef12d0a4ee531d4502847277David 'Digit' Turner                phys_page2 = get_page_addr_code(env, virt_page2);
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (tb->page_addr[1] == phys_page2)
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto found;
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto found;
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ptb1 = &tb->phys_hash_next;
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project not_found:
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* if no translated code available, then translate it now */
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tb = tb_gen_code(env, pc, cs_base, flags, 0);
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project found:
1635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* Move the last found TB to the head of the list */
1645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (likely(*ptb1)) {
1655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        *ptb1 = tb->phys_hash_next;
1661348777d4229cf65ef12d0a4ee531d4502847277David 'Digit' Turner        tb->phys_hash_next = tcg_ctx.tb_ctx.tb_phys_hash[h];
1671348777d4229cf65ef12d0a4ee531d4502847277David 'Digit' Turner        tcg_ctx.tb_ctx.tb_phys_hash[h] = tb;
1685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* we add the TB in the virtual pc hash table */
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tb;
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
174a681001f110feadb11ebed7c46832262784f6720David 'Digit' Turnerstatic inline TranslationBlock *tb_find_fast(CPUArchState *env)
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TranslationBlock *tb;
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    target_ulong cs_base, pc;
1785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int flags;
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* we record a subset of the CPU state. It will
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       always be the same before a given translated block
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       is executed. */
1835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 tb->flags != flags)) {
187a681001f110feadb11ebed7c46832262784f6720David 'Digit' Turner        tb = tb_find_slow(env, pc, cs_base, flags);
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tb;
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic CPUDebugExcpHandler *debug_excp_handler;
1935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1941348777d4229cf65ef12d0a4ee531d4502847277David 'Digit' Turnervoid cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
1955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    debug_excp_handler = handler;
1975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
199e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic void cpu_handle_debug_exception(CPUOldState *env)
2005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
2015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CPUWatchpoint *wp;
2025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
203427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner    if (!env->watchpoint_hit) {
204427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner        QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
2055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            wp->flags &= ~BP_WATCHPOINT_HIT;
206427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner        }
207427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner    }
208427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner    if (debug_excp_handler) {
2095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        debug_excp_handler(env);
210427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner    }
2115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* main execution loop */
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turnervolatile sig_atomic_t exit_request;
21624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
217a381ef07088ce479610129e37bfef42538f397daJun Nakajima/*
218a381ef07088ce479610129e37bfef42538f397daJun Nakajima * Qemu emulation can happen because of MMIO or emulation mode,
219a381ef07088ce479610129e37bfef42538f397daJun Nakajima * i.e. non-PG mode.  For MMIO cases, the pending interrupt should not
220a381ef07088ce479610129e37bfef42538f397daJun Nakajima * be emulated in qemu because MMIO is emulated for only one
221a381ef07088ce479610129e37bfef42538f397daJun Nakajima * instruction now and then back to the HAX kernel module.
222a381ef07088ce479610129e37bfef42538f397daJun Nakajima */
223e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerint need_handle_intr_request(CPUOldState *env)
224a381ef07088ce479610129e37bfef42538f397daJun Nakajima{
2256657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    CPUState *cpu = ENV_GET_CPU(env);
226a381ef07088ce479610129e37bfef42538f397daJun Nakajima#ifdef CONFIG_HAX
2277f38c7f905384c064b88fbdfa2eb054a92be63f3David 'Digit' Turner    if (!hax_enabled() || hax_vcpu_emulation_mode(cpu))
2286657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner        return cpu->interrupt_request;
229a381ef07088ce479610129e37bfef42538f397daJun Nakajima    return 0;
230a381ef07088ce479610129e37bfef42538f397daJun Nakajima#else
2316657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    return cpu->interrupt_request;
232a381ef07088ce479610129e37bfef42538f397daJun Nakajima#endif
233a381ef07088ce479610129e37bfef42538f397daJun Nakajima}
234a381ef07088ce479610129e37bfef42538f397daJun Nakajima
235a681001f110feadb11ebed7c46832262784f6720David 'Digit' Turnerint cpu_exec(CPUOldState *env)
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret, interrupt_request;
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TranslationBlock *tb;
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t *tc_ptr;
24053a08edf171bdbc7e3a2d89b78b96a33361a2760David 'Digit' Turner    tcg_target_ulong next_tb;
2416657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    CPUState *cpu = ENV_GET_CPU(env);
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2436657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    if (cpu->halted) {
2446657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner        if (!cpu_has_work(cpu)) {
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return EXCP_HALTED;
2465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
2475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
2486657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner        cpu->halted = 0;
2495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2516657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    current_cpu = cpu;
2526657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    //cpu_single_env = env;
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    if (unlikely(exit_request)) {
2556657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner        cpu->exit_request = 1;
25624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    }
25724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_I386)
25924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    if (!kvm_enabled()) {
26024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        /* put eflags in CPU temporary format */
26124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
26224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        DF = 1 - (2 * ((env->eflags >> 10) & 1));
26324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        CC_OP = CC_OP_EFLAGS;
26424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
26524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    }
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_SPARC)
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_M68K)
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->cc_op = CC_OP_FLAGS;
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->cc_dest = env->sr & 0xf;
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->cc_x = (env->sr >> 4) & 1;
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_ALPHA)
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_ARM)
273427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner#elif defined(TARGET_UNICORE32)
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_PPC)
275427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner#elif defined(TARGET_LM32)
2765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(TARGET_MICROBLAZE)
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_MIPS)
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_SH4)
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_CRIS)
280a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner#elif defined(TARGET_S390X)
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXXXX */
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#error unsupported target CPU
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->exception_index = -1;
2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* prepare setjmp context for exception handling */
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(;;) {
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (setjmp(env->jmp_env) == 0) {
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* if an exception is pending, we execute it here */
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (env->exception_index >= 0) {
2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (env->exception_index >= EXCP_INTERRUPT) {
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* exit request from the cpu execution loop */
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    ret = env->exception_index;
295427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                    if (ret == EXCP_DEBUG) {
2965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        cpu_handle_debug_exception(env);
297427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                    }
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
2995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                } else {
3005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if defined(CONFIG_USER_ONLY)
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* if user mode only, we simulate a fake exception
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       which will be handled outside the cpu execution
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       loop */
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_I386)
305bf2340f1eae08ddada9ed09490aa83e0a1bd7586David 'Digit' Turner                    do_interrupt(env);
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    ret = env->exception_index;
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
3095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    do_interrupt(env);
311a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                    env->exception_index = -1;
3125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
316a381ef07088ce479610129e37bfef42538f397daJun Nakajima#ifdef CONFIG_HAX
3177f38c7f905384c064b88fbdfa2eb054a92be63f3David 'Digit' Turner            if (hax_enabled() && !hax_vcpu_exec(cpu))
318a381ef07088ce479610129e37bfef42538f397daJun Nakajima                longjmp(env->jmp_env, 1);
319a381ef07088ce479610129e37bfef42538f397daJun Nakajima#endif
320a381ef07088ce479610129e37bfef42538f397daJun Nakajima
3215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (kvm_enabled()) {
3227f38c7f905384c064b88fbdfa2eb054a92be63f3David 'Digit' Turner                kvm_cpu_exec(cpu);
3235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                longjmp(env->jmp_env, 1);
3245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
3255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            next_tb = 0; /* force lookup of first TB */
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for(;;) {
3286657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner                interrupt_request = cpu->interrupt_request;
329a381ef07088ce479610129e37bfef42538f397daJun Nakajima                if (unlikely(need_handle_intr_request(env))) {
330fed223d2bab55eda155e3463b9cb6966e69dd73cDavid 'Digit' Turner                    if (unlikely(cpu->singlestep_enabled & SSTEP_NOIRQ)) {
3315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        /* Mask out external interrupts for this step. */
3325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
3335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    }
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_DEBUG) {
3356657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner                        cpu->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->exception_index = EXCP_DEBUG;
33785c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turner                        cpu_loop_exit(env);
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
3405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
341427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner    defined(TARGET_MICROBLAZE) || defined(TARGET_LM32) || defined(TARGET_UNICORE32)
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_HALT) {
3436657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner                        cpu->interrupt_request &= ~CPU_INTERRUPT_HALT;
3446657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner                        cpu->halted = 1;
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->exception_index = EXCP_HLT;
34685c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turner                        cpu_loop_exit(env);
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_I386)
350a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                    if (interrupt_request & CPU_INTERRUPT_INIT) {
351bf2340f1eae08ddada9ed09490aa83e0a1bd7586David 'Digit' Turner                            svm_check_intercept(env, SVM_EXIT_INIT);
352a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                            do_cpu_init(env);
353a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                            env->exception_index = EXCP_HALTED;
35485c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turner                            cpu_loop_exit(env);
355a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                    } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
356a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                            do_cpu_sipi(env);
357a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                    } else if (env->hflags2 & HF2_GIF_MASK) {
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if ((interrupt_request & CPU_INTERRUPT_SMI) &&
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            !(env->hflags & HF_SMM_MASK)) {
360bf2340f1eae08ddada9ed09490aa83e0a1bd7586David 'Digit' Turner                            svm_check_intercept(env, SVM_EXIT_SMI);
3616657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner                            cpu->interrupt_request &= ~CPU_INTERRUPT_SMI;
362bf2340f1eae08ddada9ed09490aa83e0a1bd7586David 'Digit' Turner                            do_smm_enter(env);
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            next_tb = 0;
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                   !(env->hflags2 & HF2_NMI_MASK)) {
3666657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner                            cpu->interrupt_request &= ~CPU_INTERRUPT_NMI;
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            env->hflags2 |= HF2_NMI_MASK;
368bf2340f1eae08ddada9ed09490aa83e0a1bd7586David 'Digit' Turner                            do_interrupt_x86_hardirq(env, EXCP02_NMI, 1);
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            next_tb = 0;
370a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner			} else if (interrupt_request & CPU_INTERRUPT_MCE) {
3716657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner                            cpu->interrupt_request &= ~CPU_INTERRUPT_MCE;
372bf2340f1eae08ddada9ed09490aa83e0a1bd7586David 'Digit' Turner                            do_interrupt_x86_hardirq(env, EXCP12_MCHK, 0);
373a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                            next_tb = 0;
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
375f645f7d6fd841e39524e5df8c1a7fd8347f92ac1David 'Digit' Turner                                   (((env->hflags2 & HF2_VINTR_MASK) &&
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                     (env->hflags2 & HF2_HIF_MASK)) ||
377f645f7d6fd841e39524e5df8c1a7fd8347f92ac1David 'Digit' Turner                                    (!(env->hflags2 & HF2_VINTR_MASK) &&
378f645f7d6fd841e39524e5df8c1a7fd8347f92ac1David 'Digit' Turner                                     (env->eflags & IF_MASK &&
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                      !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            int intno;
381bf2340f1eae08ddada9ed09490aa83e0a1bd7586David 'Digit' Turner                            svm_check_intercept(env, SVM_EXIT_INTR);
3826657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner                            cpu->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            intno = cpu_get_pic_interrupt(env);
3845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
385bf2340f1eae08ddada9ed09490aa83e0a1bd7586David 'Digit' Turner                            do_interrupt_x86_hardirq(env, intno, 1);
3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* ensure that no TB jump will be modified as
3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               the program flow was changed */
3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            next_tb = 0;
3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_USER_ONLY)
3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
391f645f7d6fd841e39524e5df8c1a7fd8347f92ac1David 'Digit' Turner                                   (env->eflags & IF_MASK) &&
3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                   !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            int intno;
3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* FIXME: this should respect TPR */
395bf2340f1eae08ddada9ed09490aa83e0a1bd7586David 'Digit' Turner                            svm_check_intercept(env, SVM_EXIT_VINTR);
3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
3975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
398bf2340f1eae08ddada9ed09490aa83e0a1bd7586David 'Digit' Turner                            do_interrupt_x86_hardirq(env, intno, 1);
3996657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner                            cpu->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            next_tb = 0;
4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_PPC)
4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((interrupt_request & CPU_INTERRUPT_RESET)) {
407a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                        cpu_reset(env);
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_HARD) {
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        ppc_hw_interrupt(env);
4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (env->pending_interrupts == 0)
4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
416427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner#elif defined(TARGET_LM32)
417427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                    if ((interrupt_request & CPU_INTERRUPT_HARD)
418427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                        && (env->ie & IE_IE)) {
419427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                        env->exception_index = EXCP_IRQ;
420427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                        do_interrupt(env);
421427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                        next_tb = 0;
422427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                    }
4235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(TARGET_MICROBLAZE)
4245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    if ((interrupt_request & CPU_INTERRUPT_HARD)
4255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        && (env->sregs[SR_MSR] & MSR_IE)
4265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
4275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        && !(env->iflags & (D_FLAG | IMM_FLAG))) {
4285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        env->exception_index = EXCP_IRQ;
4295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        do_interrupt(env);
4305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        next_tb = 0;
4315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    }
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_MIPS)
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
434427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                        cpu_mips_hw_interrupts_pending(env)) {
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Raise it */
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->exception_index = EXCP_EXT_INTERRUPT;
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->error_code = 0;
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        do_interrupt(env);
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_SPARC)
44224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                    if (interrupt_request & CPU_INTERRUPT_HARD) {
44324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                        if (cpu_interrupts_enabled(env) &&
44424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                            env->interrupt_index > 0) {
44524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                            int pil = env->interrupt_index & 0xf;
44624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                            int type = env->interrupt_index & 0xf0;
44724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
44824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                            if (((type == TT_EXTINT) &&
44924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                                  cpu_pil_allowed(env, pil)) ||
45024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                                  type != TT_EXTINT) {
45124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                                env->exception_index = env->interrupt_index;
45224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                                do_interrupt(env);
45324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                                next_tb = 0;
45424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                            }
45524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                        }
4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    }
4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_ARM)
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_FIQ
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        && !(env->uncached_cpsr & CPSR_F)) {
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->exception_index = EXCP_FIQ;
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        do_interrupt(env);
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* ARMv7-M interrupt return works by loading a magic value
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       into the PC.  On real hardware the load causes the
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       return to occur.  The qemu implementation performs the
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       jump normally, then does the exception return when the
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       CPU tries to execute code at the magic address.
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       This will cause the magic PC value to be pushed to
4705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                       the stack if an interrupt occurred at the wrong time.
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       We avoid this by disabling interrupts when
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       pc contains a magic address.  */
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_HARD
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        && ((IS_M(env) && env->regs[15] < 0xfffffff0)
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            || !(env->uncached_cpsr & CPSR_I))) {
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->exception_index = EXCP_IRQ;
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        do_interrupt(env);
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
480427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner#elif defined(TARGET_UNICORE32)
481427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                    if (interrupt_request & CPU_INTERRUPT_HARD
482427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                        && !(env->uncached_asr & ASR_I)) {
483427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                        do_interrupt(env);
484427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                        next_tb = 0;
485427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                    }
4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_SH4)
4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_HARD) {
4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        do_interrupt(env);
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_ALPHA)
4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_HARD) {
4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        do_interrupt(env);
4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_CRIS)
4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_HARD
49824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                        && (env->pregs[PR_CCS] & I_FLAG)
49924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                        && !env->locked_irq) {
5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->exception_index = EXCP_IRQ;
5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        do_interrupt(env);
5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_NMI
5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        && (env->pregs[PR_CCS] & M_FLAG)) {
5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->exception_index = EXCP_NMI;
5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        do_interrupt(env);
5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_M68K)
5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_HARD
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        && ((env->sr & SR_I) >> SR_I_SHIFT)
5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            < env->pending_level) {
5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Real hardware gets the interrupt vector via an
5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           IACK cycle at this point.  Current emulated
5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           hardware doesn't rely on this, so we
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           provide/save the vector when the interrupt is
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           first signalled.  */
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->exception_index = env->pending_vector;
520bf2340f1eae08ddada9ed09490aa83e0a1bd7586David 'Digit' Turner                        do_interrupt_m68k_hardirq(env, 1);
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
523427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner#elif defined(TARGET_S390X) && !defined(CONFIG_USER_ONLY)
524427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
525427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                        (env->psw.mask & PSW_MASK_EXT)) {
526427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                        do_interrupt(env);
527427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                        next_tb = 0;
528427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner                    }
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
5305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                   /* Don't use the cached interrupt_request value,
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                      do_interrupt may have updated the EXITTB flag. */
5326657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner                    if (cpu->interrupt_request & CPU_INTERRUPT_EXITTB) {
5336657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner                        cpu->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* ensure that no TB jump will be modified as
5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           the program flow was changed */
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
5385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
5396657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner                if (unlikely(cpu->exit_request)) {
5406657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner                    cpu->exit_request = 0;
5415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    env->exception_index = EXCP_INTERRUPT;
54285c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turner                    cpu_loop_exit(env);
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
54424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#if defined(DEBUG_DISAS) || defined(CONFIG_DEBUG_EXEC)
5455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* restore flags in standard format */
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_I386)
548bf2340f1eae08ddada9ed09490aa83e0a1bd7586David 'Digit' Turner                    env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
549bf2340f1eae08ddada9ed09490aa83e0a1bd7586David 'Digit' Turner                        | (DF & DF_MASK);
550bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turner                    log_cpu_state(cpu, X86_DUMP_CCOP);
5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_M68K)
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    cpu_m68k_flush_flags(env, env->cc_op);
5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    env->cc_op = CC_OP_FLAGS;
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    env->sr = (env->sr & 0xffe0)
5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              | env->cc_dest | (env->cc_x << 4);
557bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turner                    log_cpu_state(cpu, 0);
5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
559bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turner                    log_cpu_state(cpu, 0);
5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
56224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#endif /* DEBUG_DISAS || CONFIG_DEBUG_EXEC */
5631348777d4229cf65ef12d0a4ee531d4502847277David 'Digit' Turner                spin_lock(&tcg_ctx.tb_ctx.tb_lock);
564a681001f110feadb11ebed7c46832262784f6720David 'Digit' Turner                tb = tb_find_fast(env);
5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Note: we do it here to avoid a gcc bug on Mac OS X when
5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   doing it in tb_find_slow */
5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (tb_invalidated_flag) {
5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* as some TB could have been invalidated because
5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       of memory exceptions while generating the code, we
5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       must recompute the hash index here */
5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    next_tb = 0;
5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tb_invalidated_flag = 0;
5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
57424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#ifdef CONFIG_DEBUG_EXEC
5755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                qemu_log_mask(CPU_LOG_EXEC, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
5765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                             (long)tb->tc_ptr, tb->pc,
5775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                             lookup_symbol(tb->pc));
5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* see if we can patch the calling TB. When the TB
5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   spans two pages, we cannot safely do a direct
5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   jump. */
58224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                if (next_tb != 0 && tb->page_addr[1] == -1) {
5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
5851348777d4229cf65ef12d0a4ee531d4502847277David 'Digit' Turner                spin_unlock(&tcg_ctx.tb_ctx.tb_lock);
5865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                /* cpu_interrupt might be called while translating the
5885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   TB, but before it is linked into a potentially
5895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   infinite loop and becomes env->current_tb. Avoid
5905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   starting execution if there is a pending interrupt. */
59124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                env->current_tb = tb;
59224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                barrier();
5936657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner                if (likely(!cpu->exit_request)) {
5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tc_ptr = tb->tc_ptr;
5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* execute the generated code */
596a681001f110feadb11ebed7c46832262784f6720David 'Digit' Turner                    next_tb = tcg_qemu_tb_exec(env, tc_ptr);
5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((next_tb & 3) == 2) {
5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Instruction counter expired.  */
5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        int insns_left;
6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tb = (TranslationBlock *)(long)(next_tb & ~3);
6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Restore PC.  */
6025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        cpu_pc_from_tb(env, tb);
6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        insns_left = env->icount_decr.u32;
6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (env->icount_extra && insns_left >= 0) {
6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* Refill decrementer and continue execution.  */
6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            env->icount_extra += insns_left;
6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (env->icount_extra > 0xffff) {
6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                insns_left = 0xffff;
6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else {
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                insns_left = env->icount_extra;
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            env->icount_extra -= insns_left;
6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            env->icount_decr.u16.low = insns_left;
6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (insns_left > 0) {
6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                /* Execute remaining instructions.  */
617a681001f110feadb11ebed7c46832262784f6720David 'Digit' Turner                                cpu_exec_nocache(env, insns_left, tb);
6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            env->exception_index = EXCP_INTERRUPT;
6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            next_tb = 0;
62185c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turner                            cpu_loop_exit(env);
6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
62524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                env->current_tb = NULL;
626a381ef07088ce479610129e37bfef42538f397daJun Nakajima#ifdef CONFIG_HAX
6277f38c7f905384c064b88fbdfa2eb054a92be63f3David 'Digit' Turner                if (hax_enabled() && hax_stop_emulation(cpu))
62885c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turner                    cpu_loop_exit(env);
629a381ef07088ce479610129e37bfef42538f397daJun Nakajima#endif
6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* reset soft MMU for next block (it can currently
6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   only be set by a memory fault) */
6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } /* for(;;) */
633730dce73a94ca51ad8f49861996058771dcd98b2David 'Digit' Turner        } else {
634730dce73a94ca51ad8f49861996058771dcd98b2David 'Digit' Turner            /* Reload env after longjmp - the compiler may have smashed all
635730dce73a94ca51ad8f49861996058771dcd98b2David 'Digit' Turner             * local variables as longjmp is marked 'noreturn'. */
636730dce73a94ca51ad8f49861996058771dcd98b2David 'Digit' Turner            env = cpu_single_env;
6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
6388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } /* for(;;) */
6398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_I386)
6428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* restore flags in standard format */
643bf2340f1eae08ddada9ed09490aa83e0a1bd7586David 'Digit' Turner    env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
644bf2340f1eae08ddada9ed09490aa83e0a1bd7586David 'Digit' Turner        | (DF & DF_MASK);
6458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_ARM)
6468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: Save/restore host fpu exception state?.  */
647427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner#elif defined(TARGET_UNICORE32)
6488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_SPARC)
6498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_PPC)
650427603850ef4ad967c7d6bb23584a0a8de0d930dDavid 'Digit' Turner#elif defined(TARGET_LM32)
6518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_M68K)
6528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_m68k_flush_flags(env, env->cc_op);
6538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->cc_op = CC_OP_FLAGS;
6548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->sr = (env->sr & 0xffe0)
6558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              | env->cc_dest | (env->cc_x << 4);
6565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(TARGET_MICROBLAZE)
6578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_MIPS)
6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_SH4)
6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_ALPHA)
6608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_CRIS)
66124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#elif defined(TARGET_S390X)
6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXXXX */
6638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#error unsupported target CPU
6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* fail safe : never use cpu_single_env outside cpu_exec() */
6686657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    current_cpu = NULL;
6698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
6708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CPUX86State *saved_env;
6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    saved_env = env;
6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env = s;
6808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
6818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        selector &= 0xffff;
6828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cpu_x86_load_seg_cache(env, seg_reg, selector,
6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               (selector << 4), 0xffff, 0);
6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
6858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        helper_load_seg(seg_reg, selector);
6868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env = saved_env;
6888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CPUX86State *saved_env;
6938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    saved_env = env;
6958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env = s;
6968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    helper_fsave(ptr, data32);
6988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env = saved_env;
7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
7038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CPUX86State *saved_env;
7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    saved_env = env;
7078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env = s;
7088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    helper_frstor(ptr, data32);
7108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env = saved_env;
7128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* TARGET_I386 */
7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_SOFTMMU)
7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_I386)
71924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#define EXCEPTION_ACTION raise_exception_err(env->exception_index, env->error_code)
72024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#else
72185c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turner#define EXCEPTION_ACTION cpu_loop_exit(env)
72224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#endif
7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 'pc' is the host PC at which the exception was raised. 'address' is
7258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   the effective address of the memory exception. 'is_write' is 1 if a
7268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   write caused the exception and otherwise 0'. 'old_set' is the
7278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   signal set which should be restored */
7288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline int handle_cpu_signal(unsigned long pc, unsigned long address,
7298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                    int is_write, sigset_t *old_set,
7308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                    void *puc)
7318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TranslationBlock *tb;
7338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret;
7348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cpu_single_env)
7368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env = cpu_single_env; /* XXX: find a correct solution for multithread */
7378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(DEBUG_SIGNAL)
7388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
7398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                pc, address, is_write, *(unsigned long *)old_set);
7408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
7418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: locking issue */
7428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (is_write && page_unprotect(h2g(address), pc, puc)) {
7438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
7448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* see if it is an MMU fault */
74724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
7488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0)
7498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0; /* not an MMU fault */
7508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret == 0)
7518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1; /* the MMU fault was handled without causing real CPU fault */
7528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* now we have a real cpu fault */
7538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tb = tb_find_pc(pc);
7548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (tb) {
7558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* the PC is inside the translated code. It means that we have
7568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           a virtual CPU fault */
7573e0677df2819b1366819fe4112dc8464425b6edaDavid 'Digit' Turner        cpu_restore_state(env, pc);
7588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* we restore the process signal mask as the sigreturn should
7618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       do it (XXX: use sigsetjmp) */
7628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sigprocmask(SIG_SETMASK, old_set, NULL);
76324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    EXCEPTION_ACTION;
7648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* never comes here */
7668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 1;
7678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(__i386__)
7708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(__APPLE__)
7728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# include <sys/ucontext.h>
7738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
7758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
7768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
7775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner# define MASK_sig(context)    ((context)->uc_sigmask)
77824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#elif defined (__NetBSD__)
77924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# include <ucontext.h>
78024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
78124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define EIP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_EIP])
78224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define TRAP_sig(context)    ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
78324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define ERROR_sig(context)   ((context)->uc_mcontext.__gregs[_REG_ERR])
78424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define MASK_sig(context)    ((context)->uc_sigmask)
78524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#elif defined (__FreeBSD__) || defined(__DragonFly__)
78624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# include <ucontext.h>
78724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
78824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_eip))
78924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define TRAP_sig(context)    ((context)->uc_mcontext.mc_trapno)
79024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define ERROR_sig(context)   ((context)->uc_mcontext.mc_err)
79124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define MASK_sig(context)    ((context)->uc_sigmask)
7925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(__OpenBSD__)
7935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner# define EIP_sig(context)     ((context)->sc_eip)
7945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner# define TRAP_sig(context)    ((context)->sc_trapno)
7955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner# define ERROR_sig(context)   ((context)->sc_err)
7965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner# define MASK_sig(context)    ((context)->sc_mask)
7978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
7988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
7998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
8008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
8015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner# define MASK_sig(context)    ((context)->uc_sigmask)
8028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
8038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
8058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       void *puc)
8068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
80824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
80924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    ucontext_t *uc = puc;
81024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#elif defined(__OpenBSD__)
8115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct sigcontext *uc = puc;
8125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
8138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
8145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
8158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pc;
8168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int trapno;
8178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef REG_EIP
8198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* for glibc 2.1 */
8208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define REG_EIP    EIP
8218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define REG_ERR    ERR
8228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define REG_TRAPNO TRAPNO
8238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
8248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pc = EIP_sig(uc);
8258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    trapno = TRAP_sig(uc);
8268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
8278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             trapno == 0xe ?
8288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             (ERROR_sig(uc) >> 1) & 1 : 0,
8295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                             &MASK_sig(uc), puc);
8308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__x86_64__)
8338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __NetBSD__
8355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define PC_sig(context)       _UC_MACHINE_PC(context)
8365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define TRAP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
8375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define ERROR_sig(context)    ((context)->uc_mcontext.__gregs[_REG_ERR])
8385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define MASK_sig(context)     ((context)->uc_sigmask)
8395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(__OpenBSD__)
8405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define PC_sig(context)       ((context)->sc_rip)
8415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define TRAP_sig(context)     ((context)->sc_trapno)
8425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define ERROR_sig(context)    ((context)->sc_err)
8435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define MASK_sig(context)     ((context)->sc_mask)
84424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#elif defined (__FreeBSD__) || defined(__DragonFly__)
84524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#include <ucontext.h>
84624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
84724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#define PC_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_rip))
84824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#define TRAP_sig(context)     ((context)->uc_mcontext.mc_trapno)
84924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#define ERROR_sig(context)    ((context)->uc_mcontext.mc_err)
85024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#define MASK_sig(context)     ((context)->uc_sigmask)
8515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
8525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define PC_sig(context)       ((context)->uc_mcontext.gregs[REG_RIP])
8535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define TRAP_sig(context)     ((context)->uc_mcontext.gregs[REG_TRAPNO])
8545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define ERROR_sig(context)    ((context)->uc_mcontext.gregs[REG_ERR])
8555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define MASK_sig(context)     ((context)->uc_sigmask)
8565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
8575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
8598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       void *puc)
8608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
8628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pc;
86324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
8645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ucontext_t *uc = puc;
8655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(__OpenBSD__)
8665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct sigcontext *uc = puc;
8675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
8685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct ucontext *uc = puc;
8695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
8708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    pc = PC_sig(uc);
8728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
8735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                             TRAP_sig(uc) == 0xe ?
8745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                             (ERROR_sig(uc) >> 1) & 1 : 0,
8755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                             &MASK_sig(uc), puc);
8768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(_ARCH_PPC)
8798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/***********************************************************************
8818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * signal context platform-specific definitions
8828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * From Wine
8838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
8848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef linux
8858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* All Registers access - only for local access */
8868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define REG_sig(reg_name, context)		((context)->uc_mcontext.regs->reg_name)
8878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Gpr Registers access  */
8888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define GPR_sig(reg_num, context)		REG_sig(gpr[reg_num], context)
8898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define IAR_sig(context)			REG_sig(nip, context)	/* Program counter */
8908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define MSR_sig(context)			REG_sig(msr, context)   /* Machine State Register (Supervisor) */
8918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define CTR_sig(context)			REG_sig(ctr, context)   /* Count register */
8928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define XER_sig(context)			REG_sig(xer, context) /* User's integer exception register */
8938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define LR_sig(context)			REG_sig(link, context) /* Link register */
8948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define CR_sig(context)			REG_sig(ccr, context) /* Condition register */
8958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Float Registers access  */
8968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define FLOAT_sig(reg_num, context)		(((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
8978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define FPSCR_sig(context)			(*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
8988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Exception Registers access */
8998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define DAR_sig(context)			REG_sig(dar, context)
9008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define DSISR_sig(context)			REG_sig(dsisr, context)
9018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define TRAP_sig(context)			REG_sig(trap, context)
9028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* linux */
9038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
90424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
90524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#include <ucontext.h>
90624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define IAR_sig(context)		((context)->uc_mcontext.mc_srr0)
90724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define MSR_sig(context)		((context)->uc_mcontext.mc_srr1)
90824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define CTR_sig(context)		((context)->uc_mcontext.mc_ctr)
90924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define XER_sig(context)		((context)->uc_mcontext.mc_xer)
91024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define LR_sig(context)		((context)->uc_mcontext.mc_lr)
91124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define CR_sig(context)		((context)->uc_mcontext.mc_cr)
91224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner/* Exception Registers access */
91324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define DAR_sig(context)		((context)->uc_mcontext.mc_dar)
91424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define DSISR_sig(context)		((context)->uc_mcontext.mc_dsisr)
91524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define TRAP_sig(context)		((context)->uc_mcontext.mc_exc)
91624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#endif /* __FreeBSD__|| __FreeBSD_kernel__ */
91724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
9188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef __APPLE__
9198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# include <sys/ucontext.h>
9208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct ucontext SIGCONTEXT;
9218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* All Registers access - only for local access */
9228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define REG_sig(reg_name, context)		((context)->uc_mcontext->ss.reg_name)
9238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define FLOATREG_sig(reg_name, context)	((context)->uc_mcontext->fs.reg_name)
9248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define EXCEPREG_sig(reg_name, context)	((context)->uc_mcontext->es.reg_name)
9258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define VECREG_sig(reg_name, context)		((context)->uc_mcontext->vs.reg_name)
9268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Gpr Registers access */
9278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define GPR_sig(reg_num, context)		REG_sig(r##reg_num, context)
9288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define IAR_sig(context)			REG_sig(srr0, context)	/* Program counter */
9298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define MSR_sig(context)			REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
9308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define CTR_sig(context)			REG_sig(ctr, context)
9318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define XER_sig(context)			REG_sig(xer, context) /* Link register */
9328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define LR_sig(context)			REG_sig(lr, context)  /* User's integer exception register */
9338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define CR_sig(context)			REG_sig(cr, context)  /* Condition register */
9348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Float Registers access */
9358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define FLOAT_sig(reg_num, context)		FLOATREG_sig(fpregs[reg_num], context)
9368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define FPSCR_sig(context)			((double)FLOATREG_sig(fpscr, context))
9378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Exception Registers access */
9388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define DAR_sig(context)			EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
9398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define DSISR_sig(context)			EXCEPREG_sig(dsisr, context)
9408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define TRAP_sig(context)			EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
9418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* __APPLE__ */
9428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
9448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       void *puc)
9458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
94724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
94824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    ucontext_t *uc = puc;
94924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#else
9508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
95124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#endif
9528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pc;
9538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int is_write;
9548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pc = IAR_sig(uc);
9568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    is_write = 0;
9578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
9588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* ppc 4xx case */
9598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (DSISR_sig(uc) & 0x00800000)
9608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        is_write = 1;
9618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
9628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
9638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        is_write = 1;
9648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
9658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
9668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             is_write, &uc->uc_sigmask, puc);
9678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__alpha__)
9708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
9728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           void *puc)
9738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
9758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
9768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t *pc = uc->uc_mcontext.sc_pc;
9778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t insn = *pc;
9788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int is_write = 0;
9798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: need kernel patch to get write flag faster */
9818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (insn >> 26) {
9828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x0d: // stw
9838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x0e: // stb
9848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x0f: // stq_u
9858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x24: // stf
9868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x25: // stg
9878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x26: // sts
9888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x27: // stt
9898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x2c: // stl
9908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x2d: // stq
9918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x2e: // stl_c
9928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x2f: // stq_c
9938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	is_write = 1;
9948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
9978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             is_write, &uc->uc_sigmask, puc);
9988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__sparc__)
10008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
10028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       void *puc)
10038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
10058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int is_write;
10068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t insn;
10072c538c86c15d597cc875dc926e4e39285c5625dfDavid 'Digit' Turner#if !defined(__arch64__) || defined(CONFIG_SOLARIS)
10088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t *regs = (uint32_t *)(info + 1);
10098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    void *sigmask = (regs + 20);
10108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: is there a standard glibc define ? */
10118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pc = regs[1];
10128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
10135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __linux__
10148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct sigcontext *sc = puc;
10158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pc = sc->sigc_regs.tpc;
10168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    void *sigmask = (void *)sc->sigc_mask;
10175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(__OpenBSD__)
10185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct sigcontext *uc = puc;
10195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    unsigned long pc = uc->sc_pc;
10205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    void *sigmask = (void *)(long)uc->sc_mask;
10215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
10228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
10238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: need kernel patch to get write flag faster */
10258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    is_write = 0;
10268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    insn = *(uint32_t *)pc;
10278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((insn >> 30) == 3) {
10288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      switch((insn >> 19) & 0x3f) {
10298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case 0x05: // stb
10305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x15: // stba
10318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case 0x06: // sth
10325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x16: // stha
10338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case 0x04: // st
10345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x14: // sta
10358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case 0x07: // std
10365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x17: // stda
10375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x0e: // stx
10385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x1e: // stxa
10398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case 0x24: // stf
10405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x34: // stfa
10418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case 0x27: // stdf
10425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x37: // stdfa
10435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x26: // stqf
10445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x36: // stqfa
10458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case 0x25: // stfsr
10465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x3c: // casa
10475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x3e: // casxa
10488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	is_write = 1;
10498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	break;
10508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
10518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
10538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             is_write, sigmask, NULL);
10548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__arm__)
10578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
10598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       void *puc)
10608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
10628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
10638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pc;
10648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int is_write;
10658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
10678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pc = uc->uc_mcontext.gregs[R15];
10688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
10698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pc = uc->uc_mcontext.arm_pc;
10708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
10718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: compute is_write */
10728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    is_write = 0;
10738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
10748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             is_write,
10758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             &uc->uc_sigmask, puc);
10768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__mc68000)
10798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
10818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       void *puc)
10828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
10848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
10858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pc;
10868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int is_write;
10878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pc = uc->uc_mcontext.gregs[16];
10898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: compute is_write */
10908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    is_write = 0;
10918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
10928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             is_write,
10938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             &uc->uc_sigmask, puc);
10948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__ia64)
10978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef __ISR_VALID
10998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  /* This ought to be in <bits/siginfo.h>... */
11008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define __ISR_VALID	1
11018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
11028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo, void *puc)
11048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
11068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
11078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long ip;
11088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int is_write = 0;
11098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ip = uc->uc_mcontext.sc_ip;
11118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (host_signum) {
11128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case SIGILL:
11138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case SIGFPE:
11148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case SIGSEGV:
11158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case SIGBUS:
11168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case SIGTRAP:
11178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  if (info->si_code && (info->si_segvflags & __ISR_VALID))
11188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	      /* ISR.W (write-access) is bit 33:  */
11198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	      is_write = (info->si_isr >> 33) & 1;
11208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  break;
11218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      default:
11238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  break;
11248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
11268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             is_write,
112724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                             (sigset_t *)&uc->uc_sigmask, puc);
11288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__s390__)
11318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
11338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       void *puc)
11348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
11368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
11378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pc;
113824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    uint16_t *pinsn;
113924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    int is_write = 0;
11408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pc = uc->uc_mcontext.psw.addr;
114224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
114324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    /* ??? On linux, the non-rt signal handler has 4 (!) arguments instead
114424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner       of the normal 2 arguments.  The 3rd argument contains the "int_code"
114524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner       from the hardware which does in fact contain the is_write value.
114624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner       The rt signal handler, as far as I can tell, does not give this value
114724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner       at all.  Not that we could get to it from here even if it were.  */
114824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    /* ??? This is not even close to complete, since it ignores all
114924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner       of the read-modify-write instructions.  */
115024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    pinsn = (uint16_t *)pc;
115124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    switch (pinsn[0] >> 8) {
115224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x50: /* ST */
115324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x42: /* STC */
115424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x40: /* STH */
115524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        is_write = 1;
115624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        break;
115724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0xc4: /* RIL format insns */
115824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        switch (pinsn[0] & 0xf) {
115924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0xf: /* STRL */
116024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0xb: /* STGRL */
116124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x7: /* STHRL */
116224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner            is_write = 1;
116324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        }
116424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        break;
116524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0xe3: /* RXY format insns */
116624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        switch (pinsn[2] & 0xff) {
116724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x50: /* STY */
116824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x24: /* STG */
116924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x72: /* STCY */
117024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x70: /* STHY */
117124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x8e: /* STPQ */
117224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x3f: /* STRVH */
117324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x3e: /* STRV */
117424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x2f: /* STRVG */
117524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner            is_write = 1;
117624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        }
117724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        break;
117824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    }
11798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
11808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             is_write, &uc->uc_sigmask, puc);
11818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__mips__)
11848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
11868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       void *puc)
11878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
11898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
11908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    greg_t pc = uc->uc_mcontext.pc;
11918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int is_write;
11928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: compute is_write */
11948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    is_write = 0;
11958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
11968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             is_write, &uc->uc_sigmask, puc);
11978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__hppa__)
12008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
12028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       void *puc)
12038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct siginfo *info = pinfo;
12058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
120624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    unsigned long pc = uc->uc_mcontext.sc_iaoq[0];
120724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    uint32_t insn = *(uint32_t *)pc;
120824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    int is_write = 0;
120924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
121024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    /* XXX: need kernel patch to get write flag faster.  */
121124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    switch (insn >> 26) {
121224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x1a: /* STW */
121324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x19: /* STH */
121424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x18: /* STB */
121524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x1b: /* STWM */
121624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        is_write = 1;
121724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        break;
121824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
121924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x09: /* CSTWX, FSTWX, FSTWS */
122024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x0b: /* CSTDX, FSTDX, FSTDS */
122124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        /* Distinguish from coprocessor load ... */
122224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        is_write = (insn >> 9) & 1;
122324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        break;
122424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
122524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x03:
122624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        switch ((insn >> 6) & 15) {
122724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0xa: /* STWS */
122824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x9: /* STHS */
122924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x8: /* STBS */
123024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0xe: /* STWAS */
123124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0xc: /* STBYS */
123224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner            is_write = 1;
123324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        }
123424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        break;
123524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    }
12368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1237f645f7d6fd841e39524e5df8c1a7fd8347f92ac1David 'Digit' Turner    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
123824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                             is_write, &uc->uc_sigmask, puc);
12398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
12428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#error host CPU specific signal handler needed
12448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
12468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* !defined(CONFIG_SOFTMMU) */
1248