cpu-exec.c revision f645f7d6fd841e39524e5df8c1a7fd8347f92ac1
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"
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "exec.h"
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "disas.h"
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "tcg.h"
235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "kvm.h"
2424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#include "qemu-barrier.h"
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_SOFTMMU)
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef EAX
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef ECX
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef EDX
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef EBX
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef ESP
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef EBP
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef ESI
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef EDI
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef EIP
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <signal.h>
375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __linux__
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/ucontext.h>
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
422c538c86c15d597cc875dc926e4e39285c5625dfDavid 'Digit' Turner#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project// Work around ugly bugs in glibc that mangle global register contents
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef env
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define env cpu_single_env
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint tb_invalidated_flag;
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
50a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner//#define CONFIG_DEBUG_EXEC
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project//#define DEBUG_SIGNAL
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_cpu_has_work(CPUState *env)
545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return cpu_has_work(env);
565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid cpu_loop_exit(void)
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    env->current_tb = NULL;
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    longjmp(env->jmp_env, 1);
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* exit the current TB from a signal handler. The host registers are
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   restored in a state compatible with the CPU emulator
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid cpu_resume_from_signal(CPUState *env1, void *puc)
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_SOFTMMU)
705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __linux__
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(__OpenBSD__)
735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct sigcontext *uc = puc;
745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env = env1;
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: restore cpu registers saved in host registers */
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_SOFTMMU)
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (puc) {
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* XXX: use siglongjmp ? */
845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __linux__
8524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#ifdef __ia64
8624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        sigprocmask(SIG_SETMASK, (sigset_t *)&uc->uc_sigmask, NULL);
8724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#else
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
8924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#endif
905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(__OpenBSD__)
915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        sigprocmask(SIG_SETMASK, &uc->sc_mask, NULL);
925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    env->exception_index = -1;
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    longjmp(env->jmp_env, 1);
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Execute the code without caching the generated code. An interpreter
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   could be used if available. */
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long next_tb;
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TranslationBlock *tb;
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Should never happen.
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       We only end up here when an existing TB is too long.  */
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (max_cycles > CF_COUNT_MASK)
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        max_cycles = CF_COUNT_MASK;
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     max_cycles);
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->current_tb = tb;
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* execute the generated code */
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    next_tb = tcg_qemu_tb_exec(tb->tc_ptr);
11624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    env->current_tb = NULL;
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((next_tb & 3) == 2) {
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Restore PC.  This may happen if async event occurs before
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           the TB starts executing.  */
1215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        cpu_pc_from_tb(env, tb);
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tb_phys_invalidate(tb, -1);
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tb_free(tb);
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic TranslationBlock *tb_find_slow(target_ulong pc,
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                      target_ulong cs_base,
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                      uint64_t flags)
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TranslationBlock *tb, **ptb1;
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned int h;
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tb_invalidated_flag = 0;
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* find translated block using physical mappings */
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    phys_pc = get_phys_addr_code(env, pc);
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    phys_page1 = phys_pc & TARGET_PAGE_MASK;
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    phys_page2 = -1;
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    h = tb_phys_hash_func(phys_pc);
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ptb1 = &tb_phys_hash[h];
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(;;) {
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tb = *ptb1;
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!tb)
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto not_found;
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (tb->pc == pc &&
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tb->page_addr[0] == phys_page1 &&
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tb->cs_base == cs_base &&
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tb->flags == flags) {
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* check next page if needed */
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (tb->page_addr[1] != -1) {
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                virt_page2 = (pc & TARGET_PAGE_MASK) +
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    TARGET_PAGE_SIZE;
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                phys_page2 = get_phys_addr_code(env, virt_page2);
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (tb->page_addr[1] == phys_page2)
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto found;
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto found;
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ptb1 = &tb->phys_hash_next;
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project not_found:
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* if no translated code available, then translate it now */
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tb = tb_gen_code(env, pc, cs_base, flags, 0);
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project found:
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
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TranslationBlock *tb_find_fast(void)
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)) {
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tb = tb_find_slow(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
1945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerCPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
1955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CPUDebugExcpHandler *old_handler = debug_excp_handler;
1975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    debug_excp_handler = handler;
1995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return old_handler;
2005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void cpu_handle_debug_exception(CPUState *env)
2035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
2045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CPUWatchpoint *wp;
2055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!env->watchpoint_hit)
207a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner        QTAILQ_FOREACH(wp, &env->watchpoints, entry)
2085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            wp->flags &= ~BP_WATCHPOINT_HIT;
2095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (debug_excp_handler)
2115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        debug_excp_handler(env);
2125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* main execution loop */
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turnervolatile sig_atomic_t exit_request;
21724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_exec(CPUState *env1)
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
22024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    volatile host_reg_t saved_env_reg;
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret, interrupt_request;
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TranslationBlock *tb;
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t *tc_ptr;
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long next_tb;
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cpu_halted(env1) == EXCP_HALTED)
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return EXCP_HALTED;
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_single_env = env1;
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    /* the access to env below is actually saving the global register's
23224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner       value, so that files not including target-xyz/exec.h are free to
23324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner       use it.  */
23424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    QEMU_BUILD_BUG_ON (sizeof (saved_env_reg) != sizeof (env));
23524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    saved_env_reg = (host_reg_t) env;
23624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    barrier();
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env = env1;
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    if (unlikely(exit_request)) {
24024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        env->exit_request = 1;
24124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    }
24224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_I386)
24424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    if (!kvm_enabled()) {
24524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        /* put eflags in CPU temporary format */
24624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
24724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        DF = 1 - (2 * ((env->eflags >> 10) & 1));
24824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        CC_OP = CC_OP_EFLAGS;
24924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
25024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    }
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_SPARC)
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_M68K)
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->cc_op = CC_OP_FLAGS;
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->cc_dest = env->sr & 0xf;
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->cc_x = (env->sr >> 4) & 1;
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_ALPHA)
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_ARM)
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_PPC)
2595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(TARGET_MICROBLAZE)
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_MIPS)
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_SH4)
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_CRIS)
263a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner#elif defined(TARGET_S390X)
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXXXX */
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#error unsupported target CPU
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->exception_index = -1;
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* prepare setjmp context for exception handling */
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(;;) {
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (setjmp(env->jmp_env) == 0) {
2732c538c86c15d597cc875dc926e4e39285c5625dfDavid 'Digit' Turner#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
2745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#undef env
2755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    env = cpu_single_env;
2765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define env cpu_single_env
2775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* if an exception is pending, we execute it here */
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (env->exception_index >= 0) {
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (env->exception_index >= EXCP_INTERRUPT) {
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* exit request from the cpu execution loop */
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    ret = env->exception_index;
2835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    if (ret == EXCP_DEBUG)
2845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        cpu_handle_debug_exception(env);
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
2865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                } else {
2875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if defined(CONFIG_USER_ONLY)
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* if user mode only, we simulate a fake exception
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       which will be handled outside the cpu execution
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       loop */
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_I386)
2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    do_interrupt_user(env->exception_index,
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                      env->exception_is_int,
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                      env->error_code,
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                      env->exception_next_eip);
2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* successfully delivered */
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    env->old_exception = -1;
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    ret = env->exception_index;
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
3015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_I386)
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* simulate a real cpu exception. On i386, it can
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       trigger new exceptions, but we do not handle
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       double or triple faults yet. */
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    do_interrupt(env->exception_index,
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                 env->exception_is_int,
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                 env->error_code,
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                 env->exception_next_eip, 0);
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* successfully delivered */
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    env->old_exception = -1;
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_PPC)
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    do_interrupt(env);
3145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(TARGET_MICROBLAZE)
3155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    do_interrupt(env);
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_MIPS)
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    do_interrupt(env);
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_SPARC)
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    do_interrupt(env);
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_ARM)
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    do_interrupt(env);
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_SH4)
3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    do_interrupt(env);
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_ALPHA)
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    do_interrupt(env);
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_CRIS)
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    do_interrupt(env);
3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_M68K)
3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    do_interrupt(0);
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
331a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                    env->exception_index = -1;
3325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (kvm_enabled()) {
3375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                kvm_cpu_exec(env);
3385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                longjmp(env->jmp_env, 1);
3395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
3405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            next_tb = 0; /* force lookup of first TB */
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for(;;) {
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                interrupt_request = env->interrupt_request;
3445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (unlikely(interrupt_request)) {
3455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
3465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        /* Mask out external interrupts for this step. */
3475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        interrupt_request &= ~(CPU_INTERRUPT_HARD |
3485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                               CPU_INTERRUPT_FIQ |
3495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                               CPU_INTERRUPT_SMI |
3505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                               CPU_INTERRUPT_NMI);
3515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    }
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_DEBUG) {
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->exception_index = EXCP_DEBUG;
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        cpu_loop_exit();
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
3585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
3595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    defined(TARGET_MICROBLAZE)
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_HALT) {
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->halted = 1;
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->exception_index = EXCP_HLT;
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        cpu_loop_exit();
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_I386)
368a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                    if (interrupt_request & CPU_INTERRUPT_INIT) {
369a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                            svm_check_intercept(SVM_EXIT_INIT);
370a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                            do_cpu_init(env);
371a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                            env->exception_index = EXCP_HALTED;
372a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                            cpu_loop_exit();
373a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                    } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
374a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                            do_cpu_sipi(env);
375a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                    } else if (env->hflags2 & HF2_GIF_MASK) {
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if ((interrupt_request & CPU_INTERRUPT_SMI) &&
3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            !(env->hflags & HF_SMM_MASK)) {
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            svm_check_intercept(SVM_EXIT_SMI);
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            env->interrupt_request &= ~CPU_INTERRUPT_SMI;
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            do_smm_enter();
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            next_tb = 0;
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                   !(env->hflags2 & HF2_NMI_MASK)) {
3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            env->interrupt_request &= ~CPU_INTERRUPT_NMI;
3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            env->hflags2 |= HF2_NMI_MASK;
3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            next_tb = 0;
388a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner			} else if (interrupt_request & CPU_INTERRUPT_MCE) {
389a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                            env->interrupt_request &= ~CPU_INTERRUPT_MCE;
390a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                            do_interrupt(EXCP12_MCHK, 0, 0, 0, 0);
391a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                            next_tb = 0;
3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
393f645f7d6fd841e39524e5df8c1a7fd8347f92ac1David 'Digit' Turner                                   (((env->hflags2 & HF2_VINTR_MASK) &&
3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                     (env->hflags2 & HF2_HIF_MASK)) ||
395f645f7d6fd841e39524e5df8c1a7fd8347f92ac1David 'Digit' Turner                                    (!(env->hflags2 & HF2_VINTR_MASK) &&
396f645f7d6fd841e39524e5df8c1a7fd8347f92ac1David 'Digit' Turner                                     (env->eflags & IF_MASK &&
3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                      !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            int intno;
3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            svm_check_intercept(SVM_EXIT_INTR);
4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            intno = cpu_get_pic_interrupt(env);
4025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
4032c538c86c15d597cc875dc926e4e39285c5625dfDavid 'Digit' Turner#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
4045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#undef env
4055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    env = cpu_single_env;
4065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define env cpu_single_env
4075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            do_interrupt(intno, 0, 0, 0, 1);
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* ensure that no TB jump will be modified as
4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               the program flow was changed */
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            next_tb = 0;
4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_USER_ONLY)
4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
414f645f7d6fd841e39524e5df8c1a7fd8347f92ac1David 'Digit' Turner                                   (env->eflags & IF_MASK) &&
4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                   !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            int intno;
4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* FIXME: this should respect TPR */
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            svm_check_intercept(SVM_EXIT_VINTR);
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
4205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            do_interrupt(intno, 0, 0, 0, 1);
4225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            next_tb = 0;
4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_PPC)
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((interrupt_request & CPU_INTERRUPT_RESET)) {
430a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner                        cpu_reset(env);
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_HARD) {
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        ppc_hw_interrupt(env);
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (env->pending_interrupts == 0)
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
4395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(TARGET_MICROBLAZE)
4405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    if ((interrupt_request & CPU_INTERRUPT_HARD)
4415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        && (env->sregs[SR_MSR] & MSR_IE)
4425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
4435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        && !(env->iflags & (D_FLAG | IMM_FLAG))) {
4445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        env->exception_index = EXCP_IRQ;
4455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        do_interrupt(env);
4465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        next_tb = 0;
4475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    }
4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_MIPS)
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
45024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                        cpu_mips_hw_interrupts_pending(env) &&
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        (env->CP0_Status & (1 << CP0St_IE)) &&
4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        !(env->CP0_Status & (1 << CP0St_EXL)) &&
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        !(env->CP0_Status & (1 << CP0St_ERL)) &&
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        !(env->hflags & MIPS_HFLAG_DM)) {
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Raise it */
4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->exception_index = EXCP_EXT_INTERRUPT;
4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->error_code = 0;
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        do_interrupt(env);
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_SPARC)
46224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                    if (interrupt_request & CPU_INTERRUPT_HARD) {
46324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                        if (cpu_interrupts_enabled(env) &&
46424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                            env->interrupt_index > 0) {
46524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                            int pil = env->interrupt_index & 0xf;
46624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                            int type = env->interrupt_index & 0xf0;
46724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
46824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                            if (((type == TT_EXTINT) &&
46924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                                  cpu_pil_allowed(env, pil)) ||
47024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                                  type != TT_EXTINT) {
47124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                                env->exception_index = env->interrupt_index;
47224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                                do_interrupt(env);
47324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                                next_tb = 0;
47424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                            }
47524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                        }
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			//do_interrupt(0, 0, 0, 0, 0);
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    }
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_ARM)
4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_FIQ
4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        && !(env->uncached_cpsr & CPSR_F)) {
4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->exception_index = EXCP_FIQ;
4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        do_interrupt(env);
4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* ARMv7-M interrupt return works by loading a magic value
4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       into the PC.  On real hardware the load causes the
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       return to occur.  The qemu implementation performs the
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       jump normally, then does the exception return when the
4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       CPU tries to execute code at the magic address.
4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       This will cause the magic PC value to be pushed to
4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       the stack if an interrupt occured at the wrong time.
4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       We avoid this by disabling interrupts when
4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       pc contains a magic address.  */
4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_HARD
4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        && ((IS_M(env) && env->regs[15] < 0xfffffff0)
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            || !(env->uncached_cpsr & CPSR_I))) {
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->exception_index = EXCP_IRQ;
5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        do_interrupt(env);
5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_SH4)
5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_HARD) {
5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        do_interrupt(env);
5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_ALPHA)
5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_HARD) {
5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        do_interrupt(env);
5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_CRIS)
5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_HARD
51524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                        && (env->pregs[PR_CCS] & I_FLAG)
51624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                        && !env->locked_irq) {
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->exception_index = EXCP_IRQ;
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        do_interrupt(env);
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_NMI
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        && (env->pregs[PR_CCS] & M_FLAG)) {
5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->exception_index = EXCP_NMI;
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        do_interrupt(env);
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_M68K)
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (interrupt_request & CPU_INTERRUPT_HARD
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        && ((env->sr & SR_I) >> SR_I_SHIFT)
5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            < env->pending_level) {
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Real hardware gets the interrupt vector via an
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           IACK cycle at this point.  Current emulated
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           hardware doesn't rely on this, so we
5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           provide/save the vector when the interrupt is
5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           first signalled.  */
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->exception_index = env->pending_vector;
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        do_interrupt(1);
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   /* Don't use the cached interupt_request value,
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                      do_interrupt may have updated the EXITTB flag. */
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* ensure that no TB jump will be modified as
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           the program flow was changed */
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        next_tb = 0;
5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
5495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
5505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (unlikely(env->exit_request)) {
5515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    env->exit_request = 0;
5525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    env->exception_index = EXCP_INTERRUPT;
5535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    cpu_loop_exit();
5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
55524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#if defined(DEBUG_DISAS) || defined(CONFIG_DEBUG_EXEC)
5565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* restore flags in standard format */
5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_I386)
5595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
5605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    log_cpu_state(env, X86_DUMP_CCOP);
5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_M68K)
5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    cpu_m68k_flush_flags(env, env->cc_op);
5648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    env->cc_op = CC_OP_FLAGS;
5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    env->sr = (env->sr & 0xffe0)
5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              | env->cc_dest | (env->cc_x << 4);
5675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    log_cpu_state(env, 0);
5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
56924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                    log_cpu_state(env, 0);
5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
57224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#endif /* DEBUG_DISAS || CONFIG_DEBUG_EXEC */
5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                spin_lock(&tb_lock);
5748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tb = tb_find_fast();
5758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Note: we do it here to avoid a gcc bug on Mac OS X when
5768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   doing it in tb_find_slow */
5778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (tb_invalidated_flag) {
5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* as some TB could have been invalidated because
5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       of memory exceptions while generating the code, we
5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       must recompute the hash index here */
5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    next_tb = 0;
5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tb_invalidated_flag = 0;
5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
58424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#ifdef CONFIG_DEBUG_EXEC
5855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                qemu_log_mask(CPU_LOG_EXEC, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
5865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                             (long)tb->tc_ptr, tb->pc,
5875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                             lookup_symbol(tb->pc));
5888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
5898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* see if we can patch the calling TB. When the TB
5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   spans two pages, we cannot safely do a direct
5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   jump. */
59224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                if (next_tb != 0 && tb->page_addr[1] == -1) {
5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                spin_unlock(&tb_lock);
5965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                /* cpu_interrupt might be called while translating the
5985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   TB, but before it is linked into a potentially
5995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   infinite loop and becomes env->current_tb. Avoid
6005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   starting execution if there is a pending interrupt. */
60124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                env->current_tb = tb;
60224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                barrier();
60324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                if (likely(!env->exit_request)) {
6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tc_ptr = tb->tc_ptr;
6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* execute the generated code */
6062c538c86c15d597cc875dc926e4e39285c5625dfDavid 'Digit' Turner#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef env
6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    env = cpu_single_env;
6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define env cpu_single_env
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    next_tb = tcg_qemu_tb_exec(tc_ptr);
6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((next_tb & 3) == 2) {
6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Instruction counter expired.  */
6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        int insns_left;
6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tb = (TranslationBlock *)(long)(next_tb & ~3);
6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Restore PC.  */
6175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        cpu_pc_from_tb(env, tb);
6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        insns_left = env->icount_decr.u32;
6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (env->icount_extra && insns_left >= 0) {
6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* Refill decrementer and continue execution.  */
6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            env->icount_extra += insns_left;
6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (env->icount_extra > 0xffff) {
6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                insns_left = 0xffff;
6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else {
6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                insns_left = env->icount_extra;
6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            env->icount_extra -= insns_left;
6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            env->icount_decr.u16.low = insns_left;
6298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (insns_left > 0) {
6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                /* Execute remaining instructions.  */
6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                cpu_exec_nocache(insns_left, tb);
6338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
6348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            env->exception_index = EXCP_INTERRUPT;
6358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            next_tb = 0;
6368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            cpu_loop_exit();
6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
6388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
6398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
64024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                env->current_tb = NULL;
6418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* reset soft MMU for next block (it can currently
6428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   only be set by a memory fault) */
6438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } /* for(;;) */
6448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
6458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } /* for(;;) */
6468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_I386)
6498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* restore flags in standard format */
6505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
6518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_ARM)
6528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: Save/restore host fpu exception state?.  */
6538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_SPARC)
6548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_PPC)
6558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_M68K)
6568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_m68k_flush_flags(env, env->cc_op);
6578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->cc_op = CC_OP_FLAGS;
6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->sr = (env->sr & 0xffe0)
6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              | env->cc_dest | (env->cc_x << 4);
6605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(TARGET_MICROBLAZE)
6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_MIPS)
6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_SH4)
6638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_ALPHA)
6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(TARGET_CRIS)
66524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#elif defined(TARGET_S390X)
6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXXXX */
6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
6688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#error unsupported target CPU
6698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* restore global registers */
67224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    barrier();
67324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    env = (void *) saved_env_reg;
6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* fail safe : never use cpu_single_env outside cpu_exec() */
6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_single_env = NULL;
6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* must only be called from the generated code as an exception can be
6818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   generated */
6828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid tb_invalidate_page_range(target_ulong start, target_ulong end)
6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: cannot enable it yet because it yields to MMU exception
6858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       where NIP != read address on PowerPC */
6868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    target_ulong phys_addr;
6888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    phys_addr = get_phys_addr_code(env, start);
6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
6948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
6968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CPUX86State *saved_env;
6988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    saved_env = env;
7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env = s;
7018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        selector &= 0xffff;
7038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cpu_x86_load_seg_cache(env, seg_reg, selector,
7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               (selector << 4), 0xffff, 0);
7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
7068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        helper_load_seg(seg_reg, selector);
7078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env = saved_env;
7098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
7128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CPUX86State *saved_env;
7148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    saved_env = env;
7168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env = s;
7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    helper_fsave(ptr, data32);
7198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env = saved_env;
7218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
7248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CPUX86State *saved_env;
7268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    saved_env = env;
7288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env = s;
7298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    helper_frstor(ptr, data32);
7318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env = saved_env;
7338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* TARGET_I386 */
7368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_SOFTMMU)
7388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_I386)
74024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#define EXCEPTION_ACTION raise_exception_err(env->exception_index, env->error_code)
74124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#else
74224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#define EXCEPTION_ACTION cpu_loop_exit()
74324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#endif
7448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 'pc' is the host PC at which the exception was raised. 'address' is
7468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   the effective address of the memory exception. 'is_write' is 1 if a
7478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   write caused the exception and otherwise 0'. 'old_set' is the
7488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   signal set which should be restored */
7498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline int handle_cpu_signal(unsigned long pc, unsigned long address,
7508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                    int is_write, sigset_t *old_set,
7518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                    void *puc)
7528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TranslationBlock *tb;
7548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret;
7558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cpu_single_env)
7578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env = cpu_single_env; /* XXX: find a correct solution for multithread */
7588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(DEBUG_SIGNAL)
7598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
7608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                pc, address, is_write, *(unsigned long *)old_set);
7618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
7628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: locking issue */
7638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (is_write && page_unprotect(h2g(address), pc, puc)) {
7648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
7658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* see if it is an MMU fault */
76824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
7698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0)
7708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0; /* not an MMU fault */
7718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret == 0)
7728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1; /* the MMU fault was handled without causing real CPU fault */
7738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* now we have a real cpu fault */
7748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tb = tb_find_pc(pc);
7758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (tb) {
7768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* the PC is inside the translated code. It means that we have
7778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           a virtual CPU fault */
778f645f7d6fd841e39524e5df8c1a7fd8347f92ac1David 'Digit' Turner        cpu_restore_state(tb, env, pc);
7798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* we restore the process signal mask as the sigreturn should
7828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       do it (XXX: use sigsetjmp) */
7838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sigprocmask(SIG_SETMASK, old_set, NULL);
78424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    EXCEPTION_ACTION;
7858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* never comes here */
7878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 1;
7888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(__i386__)
7918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(__APPLE__)
7938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# include <sys/ucontext.h>
7948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
7968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
7978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
7985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner# define MASK_sig(context)    ((context)->uc_sigmask)
79924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#elif defined (__NetBSD__)
80024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# include <ucontext.h>
80124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
80224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define EIP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_EIP])
80324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define TRAP_sig(context)    ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
80424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define ERROR_sig(context)   ((context)->uc_mcontext.__gregs[_REG_ERR])
80524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define MASK_sig(context)    ((context)->uc_sigmask)
80624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#elif defined (__FreeBSD__) || defined(__DragonFly__)
80724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# include <ucontext.h>
80824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
80924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_eip))
81024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define TRAP_sig(context)    ((context)->uc_mcontext.mc_trapno)
81124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define ERROR_sig(context)   ((context)->uc_mcontext.mc_err)
81224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define MASK_sig(context)    ((context)->uc_sigmask)
8135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(__OpenBSD__)
8145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner# define EIP_sig(context)     ((context)->sc_eip)
8155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner# define TRAP_sig(context)    ((context)->sc_trapno)
8165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner# define ERROR_sig(context)   ((context)->sc_err)
8175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner# define MASK_sig(context)    ((context)->sc_mask)
8188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
8198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
8208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
8218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
8225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner# define MASK_sig(context)    ((context)->uc_sigmask)
8238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
8248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
8268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       void *puc)
8278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
82924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
83024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    ucontext_t *uc = puc;
83124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#elif defined(__OpenBSD__)
8325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct sigcontext *uc = puc;
8335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
8348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
8355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
8368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pc;
8378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int trapno;
8388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef REG_EIP
8408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* for glibc 2.1 */
8418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define REG_EIP    EIP
8428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define REG_ERR    ERR
8438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define REG_TRAPNO TRAPNO
8448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
8458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pc = EIP_sig(uc);
8468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    trapno = TRAP_sig(uc);
8478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
8488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             trapno == 0xe ?
8498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             (ERROR_sig(uc) >> 1) & 1 : 0,
8505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                             &MASK_sig(uc), puc);
8518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__x86_64__)
8548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __NetBSD__
8565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define PC_sig(context)       _UC_MACHINE_PC(context)
8575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define TRAP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
8585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define ERROR_sig(context)    ((context)->uc_mcontext.__gregs[_REG_ERR])
8595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define MASK_sig(context)     ((context)->uc_sigmask)
8605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(__OpenBSD__)
8615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define PC_sig(context)       ((context)->sc_rip)
8625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define TRAP_sig(context)     ((context)->sc_trapno)
8635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define ERROR_sig(context)    ((context)->sc_err)
8645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define MASK_sig(context)     ((context)->sc_mask)
86524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#elif defined (__FreeBSD__) || defined(__DragonFly__)
86624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#include <ucontext.h>
86724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
86824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#define PC_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_rip))
86924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#define TRAP_sig(context)     ((context)->uc_mcontext.mc_trapno)
87024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#define ERROR_sig(context)    ((context)->uc_mcontext.mc_err)
87124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#define MASK_sig(context)     ((context)->uc_sigmask)
8725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
8735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define PC_sig(context)       ((context)->uc_mcontext.gregs[REG_RIP])
8745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define TRAP_sig(context)     ((context)->uc_mcontext.gregs[REG_TRAPNO])
8755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define ERROR_sig(context)    ((context)->uc_mcontext.gregs[REG_ERR])
8765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define MASK_sig(context)     ((context)->uc_sigmask)
8775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
8785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
8808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       void *puc)
8818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
8838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pc;
88424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
8855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ucontext_t *uc = puc;
8865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(__OpenBSD__)
8875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct sigcontext *uc = puc;
8885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
8895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct ucontext *uc = puc;
8905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
8918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    pc = PC_sig(uc);
8938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
8945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                             TRAP_sig(uc) == 0xe ?
8955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                             (ERROR_sig(uc) >> 1) & 1 : 0,
8965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                             &MASK_sig(uc), puc);
8978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(_ARCH_PPC)
9008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/***********************************************************************
9028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * signal context platform-specific definitions
9038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * From Wine
9048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
9058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef linux
9068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* All Registers access - only for local access */
9078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define REG_sig(reg_name, context)		((context)->uc_mcontext.regs->reg_name)
9088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Gpr Registers access  */
9098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define GPR_sig(reg_num, context)		REG_sig(gpr[reg_num], context)
9108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define IAR_sig(context)			REG_sig(nip, context)	/* Program counter */
9118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define MSR_sig(context)			REG_sig(msr, context)   /* Machine State Register (Supervisor) */
9128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define CTR_sig(context)			REG_sig(ctr, context)   /* Count register */
9138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define XER_sig(context)			REG_sig(xer, context) /* User's integer exception register */
9148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define LR_sig(context)			REG_sig(link, context) /* Link register */
9158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define CR_sig(context)			REG_sig(ccr, context) /* Condition register */
9168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Float Registers access  */
9178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define FLOAT_sig(reg_num, context)		(((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
9188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define FPSCR_sig(context)			(*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
9198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Exception Registers access */
9208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define DAR_sig(context)			REG_sig(dar, context)
9218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define DSISR_sig(context)			REG_sig(dsisr, context)
9228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define TRAP_sig(context)			REG_sig(trap, context)
9238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* linux */
9248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
92524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
92624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#include <ucontext.h>
92724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define IAR_sig(context)		((context)->uc_mcontext.mc_srr0)
92824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define MSR_sig(context)		((context)->uc_mcontext.mc_srr1)
92924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define CTR_sig(context)		((context)->uc_mcontext.mc_ctr)
93024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define XER_sig(context)		((context)->uc_mcontext.mc_xer)
93124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define LR_sig(context)		((context)->uc_mcontext.mc_lr)
93224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define CR_sig(context)		((context)->uc_mcontext.mc_cr)
93324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner/* Exception Registers access */
93424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define DAR_sig(context)		((context)->uc_mcontext.mc_dar)
93524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define DSISR_sig(context)		((context)->uc_mcontext.mc_dsisr)
93624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner# define TRAP_sig(context)		((context)->uc_mcontext.mc_exc)
93724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#endif /* __FreeBSD__|| __FreeBSD_kernel__ */
93824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
9398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef __APPLE__
9408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# include <sys/ucontext.h>
9418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct ucontext SIGCONTEXT;
9428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* All Registers access - only for local access */
9438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define REG_sig(reg_name, context)		((context)->uc_mcontext->ss.reg_name)
9448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define FLOATREG_sig(reg_name, context)	((context)->uc_mcontext->fs.reg_name)
9458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define EXCEPREG_sig(reg_name, context)	((context)->uc_mcontext->es.reg_name)
9468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define VECREG_sig(reg_name, context)		((context)->uc_mcontext->vs.reg_name)
9478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Gpr Registers access */
9488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define GPR_sig(reg_num, context)		REG_sig(r##reg_num, context)
9498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define IAR_sig(context)			REG_sig(srr0, context)	/* Program counter */
9508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define MSR_sig(context)			REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
9518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define CTR_sig(context)			REG_sig(ctr, context)
9528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define XER_sig(context)			REG_sig(xer, context) /* Link register */
9538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define LR_sig(context)			REG_sig(lr, context)  /* User's integer exception register */
9548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define CR_sig(context)			REG_sig(cr, context)  /* Condition register */
9558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Float Registers access */
9568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define FLOAT_sig(reg_num, context)		FLOATREG_sig(fpregs[reg_num], context)
9578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define FPSCR_sig(context)			((double)FLOATREG_sig(fpscr, context))
9588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Exception Registers access */
9598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define DAR_sig(context)			EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
9608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define DSISR_sig(context)			EXCEPREG_sig(dsisr, context)
9618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define TRAP_sig(context)			EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
9628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* __APPLE__ */
9638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
9658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       void *puc)
9668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
96824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
96924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    ucontext_t *uc = puc;
97024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#else
9718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
97224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner#endif
9738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pc;
9748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int is_write;
9758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pc = IAR_sig(uc);
9778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    is_write = 0;
9788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
9798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* ppc 4xx case */
9808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (DSISR_sig(uc) & 0x00800000)
9818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        is_write = 1;
9828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
9838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
9848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        is_write = 1;
9858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
9868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
9878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             is_write, &uc->uc_sigmask, puc);
9888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__alpha__)
9918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
9938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           void *puc)
9948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
9968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
9978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t *pc = uc->uc_mcontext.sc_pc;
9988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t insn = *pc;
9998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int is_write = 0;
10008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: need kernel patch to get write flag faster */
10028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (insn >> 26) {
10038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x0d: // stw
10048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x0e: // stb
10058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x0f: // stq_u
10068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x24: // stf
10078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x25: // stg
10088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x26: // sts
10098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x27: // stt
10108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x2c: // stl
10118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x2d: // stq
10128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x2e: // stl_c
10138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x2f: // stq_c
10148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	is_write = 1;
10158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
10188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             is_write, &uc->uc_sigmask, puc);
10198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__sparc__)
10218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
10238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       void *puc)
10248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
10268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int is_write;
10278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t insn;
10282c538c86c15d597cc875dc926e4e39285c5625dfDavid 'Digit' Turner#if !defined(__arch64__) || defined(CONFIG_SOLARIS)
10298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t *regs = (uint32_t *)(info + 1);
10308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    void *sigmask = (regs + 20);
10318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: is there a standard glibc define ? */
10328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pc = regs[1];
10338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
10345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __linux__
10358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct sigcontext *sc = puc;
10368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pc = sc->sigc_regs.tpc;
10378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    void *sigmask = (void *)sc->sigc_mask;
10385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(__OpenBSD__)
10395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct sigcontext *uc = puc;
10405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    unsigned long pc = uc->sc_pc;
10415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    void *sigmask = (void *)(long)uc->sc_mask;
10425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
10438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
10448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: need kernel patch to get write flag faster */
10468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    is_write = 0;
10478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    insn = *(uint32_t *)pc;
10488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((insn >> 30) == 3) {
10498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      switch((insn >> 19) & 0x3f) {
10508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case 0x05: // stb
10515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x15: // stba
10528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case 0x06: // sth
10535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x16: // stha
10548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case 0x04: // st
10555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x14: // sta
10568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case 0x07: // std
10575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x17: // stda
10585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x0e: // stx
10595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x1e: // stxa
10608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case 0x24: // stf
10615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x34: // stfa
10628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case 0x27: // stdf
10635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x37: // stdfa
10645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x26: // stqf
10655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x36: // stqfa
10668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case 0x25: // stfsr
10675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x3c: // casa
10685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case 0x3e: // casxa
10698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	is_write = 1;
10708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	break;
10718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
10728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
10748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             is_write, sigmask, NULL);
10758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__arm__)
10788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
10808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       void *puc)
10818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
10838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
10848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pc;
10858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int is_write;
10868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
10888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pc = uc->uc_mcontext.gregs[R15];
10898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
10908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pc = uc->uc_mcontext.arm_pc;
10918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
10928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: compute is_write */
10938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    is_write = 0;
10948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
10958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             is_write,
10968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             &uc->uc_sigmask, puc);
10978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__mc68000)
11008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
11028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       void *puc)
11038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
11058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
11068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pc;
11078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int is_write;
11088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pc = uc->uc_mcontext.gregs[16];
11108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: compute is_write */
11118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    is_write = 0;
11128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
11138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             is_write,
11148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             &uc->uc_sigmask, puc);
11158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__ia64)
11188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef __ISR_VALID
11208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  /* This ought to be in <bits/siginfo.h>... */
11218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project# define __ISR_VALID	1
11228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
11238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo, void *puc)
11258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
11278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
11288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long ip;
11298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int is_write = 0;
11308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ip = uc->uc_mcontext.sc_ip;
11328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (host_signum) {
11338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case SIGILL:
11348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case SIGFPE:
11358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case SIGSEGV:
11368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case SIGBUS:
11378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case SIGTRAP:
11388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  if (info->si_code && (info->si_segvflags & __ISR_VALID))
11398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	      /* ISR.W (write-access) is bit 33:  */
11408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	      is_write = (info->si_isr >> 33) & 1;
11418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  break;
11428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      default:
11448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  break;
11458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
11478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             is_write,
114824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                             (sigset_t *)&uc->uc_sigmask, puc);
11498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__s390__)
11528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
11548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       void *puc)
11558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
11578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
11588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pc;
115924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    uint16_t *pinsn;
116024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    int is_write = 0;
11618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pc = uc->uc_mcontext.psw.addr;
116324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
116424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    /* ??? On linux, the non-rt signal handler has 4 (!) arguments instead
116524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner       of the normal 2 arguments.  The 3rd argument contains the "int_code"
116624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner       from the hardware which does in fact contain the is_write value.
116724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner       The rt signal handler, as far as I can tell, does not give this value
116824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner       at all.  Not that we could get to it from here even if it were.  */
116924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    /* ??? This is not even close to complete, since it ignores all
117024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner       of the read-modify-write instructions.  */
117124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    pinsn = (uint16_t *)pc;
117224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    switch (pinsn[0] >> 8) {
117324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x50: /* ST */
117424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x42: /* STC */
117524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x40: /* STH */
117624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        is_write = 1;
117724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        break;
117824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0xc4: /* RIL format insns */
117924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        switch (pinsn[0] & 0xf) {
118024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0xf: /* STRL */
118124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0xb: /* STGRL */
118224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x7: /* STHRL */
118324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner            is_write = 1;
118424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        }
118524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        break;
118624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0xe3: /* RXY format insns */
118724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        switch (pinsn[2] & 0xff) {
118824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x50: /* STY */
118924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x24: /* STG */
119024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x72: /* STCY */
119124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x70: /* STHY */
119224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x8e: /* STPQ */
119324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x3f: /* STRVH */
119424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x3e: /* STRV */
119524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x2f: /* STRVG */
119624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner            is_write = 1;
119724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        }
119824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        break;
119924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    }
12008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
12018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             is_write, &uc->uc_sigmask, puc);
12028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__mips__)
12058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
12078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       void *puc)
12088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    siginfo_t *info = pinfo;
12108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
12118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    greg_t pc = uc->uc_mcontext.pc;
12128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int is_write;
12138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: compute is_write */
12158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    is_write = 0;
12168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
12178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             is_write, &uc->uc_sigmask, puc);
12188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#elif defined(__hppa__)
12218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_signal_handler(int host_signum, void *pinfo,
12238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       void *puc)
12248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct siginfo *info = pinfo;
12268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ucontext *uc = puc;
122724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    unsigned long pc = uc->uc_mcontext.sc_iaoq[0];
122824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    uint32_t insn = *(uint32_t *)pc;
122924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    int is_write = 0;
123024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
123124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    /* XXX: need kernel patch to get write flag faster.  */
123224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    switch (insn >> 26) {
123324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x1a: /* STW */
123424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x19: /* STH */
123524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x18: /* STB */
123624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x1b: /* STWM */
123724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        is_write = 1;
123824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        break;
123924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
124024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x09: /* CSTWX, FSTWX, FSTWS */
124124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x0b: /* CSTDX, FSTDX, FSTDS */
124224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        /* Distinguish from coprocessor load ... */
124324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        is_write = (insn >> 9) & 1;
124424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        break;
124524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner
124624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    case 0x03:
124724cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        switch ((insn >> 6) & 15) {
124824cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0xa: /* STWS */
124924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x9: /* STHS */
125024cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0x8: /* STBS */
125124cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0xe: /* STWAS */
125224cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        case 0xc: /* STBYS */
125324cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner            is_write = 1;
125424cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        }
125524cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner        break;
125624cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner    }
12578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1258f645f7d6fd841e39524e5df8c1a7fd8347f92ac1David 'Digit' Turner    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
125924cd25ab654ab829ba8e9c0c634db50ed28f325aDavid Turner                             is_write, &uc->uc_sigmask, puc);
12608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
12638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#error host CPU specific signal handler needed
12658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
12678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* !defined(CONFIG_SOFTMMU) */
1269