1cd71c089SLaurent Vivier /* 2cd71c089SLaurent Vivier * qemu user cpu loop 3cd71c089SLaurent Vivier * 4cd71c089SLaurent Vivier * Copyright (c) 2003-2008 Fabrice Bellard 5cd71c089SLaurent Vivier * 6cd71c089SLaurent Vivier * This program is free software; you can redistribute it and/or modify 7cd71c089SLaurent Vivier * it under the terms of the GNU General Public License as published by 8cd71c089SLaurent Vivier * the Free Software Foundation; either version 2 of the License, or 9cd71c089SLaurent Vivier * (at your option) any later version. 10cd71c089SLaurent Vivier * 11cd71c089SLaurent Vivier * This program is distributed in the hope that it will be useful, 12cd71c089SLaurent Vivier * but WITHOUT ANY WARRANTY; without even the implied warranty of 13cd71c089SLaurent Vivier * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14cd71c089SLaurent Vivier * GNU General Public License for more details. 15cd71c089SLaurent Vivier * 16cd71c089SLaurent Vivier * You should have received a copy of the GNU General Public License 17cd71c089SLaurent Vivier * along with this program; if not, see <http://www.gnu.org/licenses/>. 18cd71c089SLaurent Vivier */ 19cd71c089SLaurent Vivier 20cd71c089SLaurent Vivier #include "qemu/osdep.h" 21cd71c089SLaurent Vivier #include "qemu.h" 22cd71c089SLaurent Vivier #include "cpu_loop-common.h" 23cd71c089SLaurent Vivier 24*c37dcb4fSLaurent Vivier void cpu_loop(CPUSH4State *env) 25*c37dcb4fSLaurent Vivier { 26*c37dcb4fSLaurent Vivier CPUState *cs = CPU(sh_env_get_cpu(env)); 27*c37dcb4fSLaurent Vivier int trapnr, ret; 28*c37dcb4fSLaurent Vivier target_siginfo_t info; 29*c37dcb4fSLaurent Vivier 30*c37dcb4fSLaurent Vivier while (1) { 31*c37dcb4fSLaurent Vivier bool arch_interrupt = true; 32*c37dcb4fSLaurent Vivier 33*c37dcb4fSLaurent Vivier cpu_exec_start(cs); 34*c37dcb4fSLaurent Vivier trapnr = cpu_exec(cs); 35*c37dcb4fSLaurent Vivier cpu_exec_end(cs); 36*c37dcb4fSLaurent Vivier process_queued_cpu_work(cs); 37*c37dcb4fSLaurent Vivier 38*c37dcb4fSLaurent Vivier switch (trapnr) { 39*c37dcb4fSLaurent Vivier case 0x160: 40*c37dcb4fSLaurent Vivier env->pc += 2; 41*c37dcb4fSLaurent Vivier ret = do_syscall(env, 42*c37dcb4fSLaurent Vivier env->gregs[3], 43*c37dcb4fSLaurent Vivier env->gregs[4], 44*c37dcb4fSLaurent Vivier env->gregs[5], 45*c37dcb4fSLaurent Vivier env->gregs[6], 46*c37dcb4fSLaurent Vivier env->gregs[7], 47*c37dcb4fSLaurent Vivier env->gregs[0], 48*c37dcb4fSLaurent Vivier env->gregs[1], 49*c37dcb4fSLaurent Vivier 0, 0); 50*c37dcb4fSLaurent Vivier if (ret == -TARGET_ERESTARTSYS) { 51*c37dcb4fSLaurent Vivier env->pc -= 2; 52*c37dcb4fSLaurent Vivier } else if (ret != -TARGET_QEMU_ESIGRETURN) { 53*c37dcb4fSLaurent Vivier env->gregs[0] = ret; 54*c37dcb4fSLaurent Vivier } 55*c37dcb4fSLaurent Vivier break; 56*c37dcb4fSLaurent Vivier case EXCP_INTERRUPT: 57*c37dcb4fSLaurent Vivier /* just indicate that signals should be handled asap */ 58*c37dcb4fSLaurent Vivier break; 59*c37dcb4fSLaurent Vivier case EXCP_DEBUG: 60*c37dcb4fSLaurent Vivier { 61*c37dcb4fSLaurent Vivier int sig; 62*c37dcb4fSLaurent Vivier 63*c37dcb4fSLaurent Vivier sig = gdb_handlesig(cs, TARGET_SIGTRAP); 64*c37dcb4fSLaurent Vivier if (sig) { 65*c37dcb4fSLaurent Vivier info.si_signo = sig; 66*c37dcb4fSLaurent Vivier info.si_errno = 0; 67*c37dcb4fSLaurent Vivier info.si_code = TARGET_TRAP_BRKPT; 68*c37dcb4fSLaurent Vivier queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 69*c37dcb4fSLaurent Vivier } else { 70*c37dcb4fSLaurent Vivier arch_interrupt = false; 71*c37dcb4fSLaurent Vivier } 72*c37dcb4fSLaurent Vivier } 73*c37dcb4fSLaurent Vivier break; 74*c37dcb4fSLaurent Vivier case 0xa0: 75*c37dcb4fSLaurent Vivier case 0xc0: 76*c37dcb4fSLaurent Vivier info.si_signo = TARGET_SIGSEGV; 77*c37dcb4fSLaurent Vivier info.si_errno = 0; 78*c37dcb4fSLaurent Vivier info.si_code = TARGET_SEGV_MAPERR; 79*c37dcb4fSLaurent Vivier info._sifields._sigfault._addr = env->tea; 80*c37dcb4fSLaurent Vivier queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 81*c37dcb4fSLaurent Vivier break; 82*c37dcb4fSLaurent Vivier case EXCP_ATOMIC: 83*c37dcb4fSLaurent Vivier cpu_exec_step_atomic(cs); 84*c37dcb4fSLaurent Vivier arch_interrupt = false; 85*c37dcb4fSLaurent Vivier break; 86*c37dcb4fSLaurent Vivier default: 87*c37dcb4fSLaurent Vivier printf ("Unhandled trap: 0x%x\n", trapnr); 88*c37dcb4fSLaurent Vivier cpu_dump_state(cs, stderr, fprintf, 0); 89*c37dcb4fSLaurent Vivier exit(EXIT_FAILURE); 90*c37dcb4fSLaurent Vivier } 91*c37dcb4fSLaurent Vivier process_pending_signals (env); 92*c37dcb4fSLaurent Vivier 93*c37dcb4fSLaurent Vivier /* Most of the traps imply an exception or interrupt, which 94*c37dcb4fSLaurent Vivier implies an REI instruction has been executed. Which means 95*c37dcb4fSLaurent Vivier that LDST (aka LOK_ADDR) should be cleared. But there are 96*c37dcb4fSLaurent Vivier a few exceptions for traps internal to QEMU. */ 97*c37dcb4fSLaurent Vivier if (arch_interrupt) { 98*c37dcb4fSLaurent Vivier env->lock_addr = -1; 99*c37dcb4fSLaurent Vivier } 100*c37dcb4fSLaurent Vivier } 101*c37dcb4fSLaurent Vivier } 102*c37dcb4fSLaurent Vivier 103cd71c089SLaurent Vivier void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) 104cd71c089SLaurent Vivier { 105*c37dcb4fSLaurent Vivier int i; 106*c37dcb4fSLaurent Vivier 107*c37dcb4fSLaurent Vivier for(i = 0; i < 16; i++) { 108*c37dcb4fSLaurent Vivier env->gregs[i] = regs->regs[i]; 109*c37dcb4fSLaurent Vivier } 110*c37dcb4fSLaurent Vivier env->pc = regs->pc; 111cd71c089SLaurent Vivier } 112