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"
22cdf06ce5SPhilippe Mathieu-Daudé #include "qemu/timer.h"
233b249d26SPeter Maydell #include "user-internals.h"
24cd71c089SLaurent Vivier #include "cpu_loop-common.h"
252113aed6SPeter Maydell #include "signal-common.h"
26cd71c089SLaurent Vivier
cpu_ppc_get_tb(CPUPPCState * env)2711400516SLaurent Vivier static inline uint64_t cpu_ppc_get_tb(CPUPPCState *env)
2811400516SLaurent Vivier {
2911400516SLaurent Vivier return cpu_get_host_ticks();
3011400516SLaurent Vivier }
3111400516SLaurent Vivier
cpu_ppc_load_tbl(CPUPPCState * env)3211400516SLaurent Vivier uint64_t cpu_ppc_load_tbl(CPUPPCState *env)
3311400516SLaurent Vivier {
3411400516SLaurent Vivier return cpu_ppc_get_tb(env);
3511400516SLaurent Vivier }
3611400516SLaurent Vivier
cpu_ppc_load_tbu(CPUPPCState * env)3711400516SLaurent Vivier uint32_t cpu_ppc_load_tbu(CPUPPCState *env)
3811400516SLaurent Vivier {
3911400516SLaurent Vivier return cpu_ppc_get_tb(env) >> 32;
4011400516SLaurent Vivier }
4111400516SLaurent Vivier
cpu_ppc_load_atbl(CPUPPCState * env)4211400516SLaurent Vivier uint64_t cpu_ppc_load_atbl(CPUPPCState *env)
4311400516SLaurent Vivier {
4411400516SLaurent Vivier return cpu_ppc_get_tb(env);
4511400516SLaurent Vivier }
4611400516SLaurent Vivier
cpu_ppc_load_atbu(CPUPPCState * env)4711400516SLaurent Vivier uint32_t cpu_ppc_load_atbu(CPUPPCState *env)
4811400516SLaurent Vivier {
4911400516SLaurent Vivier return cpu_ppc_get_tb(env) >> 32;
5011400516SLaurent Vivier }
5111400516SLaurent Vivier
cpu_ppc_load_vtb(CPUPPCState * env)525d62725bSSuraj Jitindar Singh uint64_t cpu_ppc_load_vtb(CPUPPCState *env)
535d62725bSSuraj Jitindar Singh {
545d62725bSSuraj Jitindar Singh return cpu_ppc_get_tb(env);
555d62725bSSuraj Jitindar Singh }
565d62725bSSuraj Jitindar Singh
5711400516SLaurent Vivier /* XXX: to be fixed */
ppc_dcr_read(ppc_dcr_t * dcr_env,int dcrn,uint32_t * valp)5811400516SLaurent Vivier int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp)
5911400516SLaurent Vivier {
6011400516SLaurent Vivier return -1;
6111400516SLaurent Vivier }
6211400516SLaurent Vivier
ppc_dcr_write(ppc_dcr_t * dcr_env,int dcrn,uint32_t val)6311400516SLaurent Vivier int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
6411400516SLaurent Vivier {
6511400516SLaurent Vivier return -1;
6611400516SLaurent Vivier }
6711400516SLaurent Vivier
cpu_loop(CPUPPCState * env)6811400516SLaurent Vivier void cpu_loop(CPUPPCState *env)
6911400516SLaurent Vivier {
70db70b311SRichard Henderson CPUState *cs = env_cpu(env);
71d30e60e7SRichard Henderson int trapnr, si_signo, si_code;
7211400516SLaurent Vivier target_ulong ret;
7311400516SLaurent Vivier
7411400516SLaurent Vivier for(;;) {
7514db1899SRichard Henderson bool arch_interrupt;
7614db1899SRichard Henderson
7711400516SLaurent Vivier cpu_exec_start(cs);
7811400516SLaurent Vivier trapnr = cpu_exec(cs);
7911400516SLaurent Vivier cpu_exec_end(cs);
8011400516SLaurent Vivier process_queued_cpu_work(cs);
8111400516SLaurent Vivier
8214db1899SRichard Henderson arch_interrupt = true;
8311400516SLaurent Vivier switch (trapnr) {
8411400516SLaurent Vivier case POWERPC_EXCP_NONE:
8511400516SLaurent Vivier /* Just go on */
8611400516SLaurent Vivier break;
8711400516SLaurent Vivier case POWERPC_EXCP_CRITICAL: /* Critical input */
8811400516SLaurent Vivier cpu_abort(cs, "Critical interrupt while in user mode. "
8911400516SLaurent Vivier "Aborting\n");
9011400516SLaurent Vivier break;
9111400516SLaurent Vivier case POWERPC_EXCP_MCHECK: /* Machine check exception */
9211400516SLaurent Vivier cpu_abort(cs, "Machine check exception while in user mode. "
9311400516SLaurent Vivier "Aborting\n");
9411400516SLaurent Vivier break;
9511400516SLaurent Vivier case POWERPC_EXCP_DSI: /* Data storage exception */
9611400516SLaurent Vivier case POWERPC_EXCP_ISI: /* Instruction storage exception */
97d30e60e7SRichard Henderson /* FIXME: handle maperr in ppc_cpu_record_sigsegv. */
98d30e60e7SRichard Henderson force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR,
99d30e60e7SRichard Henderson env->spr[SPR_DAR]);
10011400516SLaurent Vivier break;
10111400516SLaurent Vivier case POWERPC_EXCP_EXTERNAL: /* External input */
10211400516SLaurent Vivier cpu_abort(cs, "External interrupt while in user mode. "
10311400516SLaurent Vivier "Aborting\n");
10411400516SLaurent Vivier break;
10511400516SLaurent Vivier case POWERPC_EXCP_PROGRAM: /* Program exception */
10611400516SLaurent Vivier case POWERPC_EXCP_HV_EMU: /* HV emulation */
10711400516SLaurent Vivier /* XXX: check this */
10811400516SLaurent Vivier switch (env->error_code & ~0xF) {
10911400516SLaurent Vivier case POWERPC_EXCP_FP:
110d30e60e7SRichard Henderson si_signo = TARGET_SIGFPE;
11111400516SLaurent Vivier switch (env->error_code & 0xF) {
11211400516SLaurent Vivier case POWERPC_EXCP_FP_OX:
113d30e60e7SRichard Henderson si_code = TARGET_FPE_FLTOVF;
11411400516SLaurent Vivier break;
11511400516SLaurent Vivier case POWERPC_EXCP_FP_UX:
116d30e60e7SRichard Henderson si_code = TARGET_FPE_FLTUND;
11711400516SLaurent Vivier break;
11811400516SLaurent Vivier case POWERPC_EXCP_FP_ZX:
11911400516SLaurent Vivier case POWERPC_EXCP_FP_VXZDZ:
120d30e60e7SRichard Henderson si_code = TARGET_FPE_FLTDIV;
12111400516SLaurent Vivier break;
12211400516SLaurent Vivier case POWERPC_EXCP_FP_XX:
123d30e60e7SRichard Henderson si_code = TARGET_FPE_FLTRES;
12411400516SLaurent Vivier break;
12511400516SLaurent Vivier case POWERPC_EXCP_FP_VXSOFT:
126d30e60e7SRichard Henderson si_code = TARGET_FPE_FLTINV;
12711400516SLaurent Vivier break;
12811400516SLaurent Vivier case POWERPC_EXCP_FP_VXSNAN:
12911400516SLaurent Vivier case POWERPC_EXCP_FP_VXISI:
13011400516SLaurent Vivier case POWERPC_EXCP_FP_VXIDI:
13111400516SLaurent Vivier case POWERPC_EXCP_FP_VXIMZ:
13211400516SLaurent Vivier case POWERPC_EXCP_FP_VXVC:
13311400516SLaurent Vivier case POWERPC_EXCP_FP_VXSQRT:
13411400516SLaurent Vivier case POWERPC_EXCP_FP_VXCVI:
135d30e60e7SRichard Henderson si_code = TARGET_FPE_FLTSUB;
13611400516SLaurent Vivier break;
13711400516SLaurent Vivier default:
13811400516SLaurent Vivier EXCP_DUMP(env, "Unknown floating point exception (%02x)\n",
13911400516SLaurent Vivier env->error_code);
140d30e60e7SRichard Henderson si_code = 0;
14111400516SLaurent Vivier break;
14211400516SLaurent Vivier }
14311400516SLaurent Vivier break;
14411400516SLaurent Vivier case POWERPC_EXCP_INVAL:
145d30e60e7SRichard Henderson si_signo = TARGET_SIGILL;
14611400516SLaurent Vivier switch (env->error_code & 0xF) {
14711400516SLaurent Vivier case POWERPC_EXCP_INVAL_INVAL:
148d30e60e7SRichard Henderson si_code = TARGET_ILL_ILLOPC;
14911400516SLaurent Vivier break;
15011400516SLaurent Vivier case POWERPC_EXCP_INVAL_LSWX:
151d30e60e7SRichard Henderson si_code = TARGET_ILL_ILLOPN;
15211400516SLaurent Vivier break;
15311400516SLaurent Vivier case POWERPC_EXCP_INVAL_SPR:
154d30e60e7SRichard Henderson si_code = TARGET_ILL_PRVREG;
15511400516SLaurent Vivier break;
15611400516SLaurent Vivier case POWERPC_EXCP_INVAL_FP:
157d30e60e7SRichard Henderson si_code = TARGET_ILL_COPROC;
15811400516SLaurent Vivier break;
15911400516SLaurent Vivier default:
16011400516SLaurent Vivier EXCP_DUMP(env, "Unknown invalid operation (%02x)\n",
16111400516SLaurent Vivier env->error_code & 0xF);
162d30e60e7SRichard Henderson si_code = TARGET_ILL_ILLADR;
16311400516SLaurent Vivier break;
16411400516SLaurent Vivier }
16511400516SLaurent Vivier break;
16611400516SLaurent Vivier case POWERPC_EXCP_PRIV:
167d30e60e7SRichard Henderson si_signo = TARGET_SIGILL;
16811400516SLaurent Vivier switch (env->error_code & 0xF) {
16911400516SLaurent Vivier case POWERPC_EXCP_PRIV_OPC:
170d30e60e7SRichard Henderson si_code = TARGET_ILL_PRVOPC;
17111400516SLaurent Vivier break;
17211400516SLaurent Vivier case POWERPC_EXCP_PRIV_REG:
173d30e60e7SRichard Henderson si_code = TARGET_ILL_PRVREG;
17411400516SLaurent Vivier break;
17511400516SLaurent Vivier default:
17611400516SLaurent Vivier EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",
17711400516SLaurent Vivier env->error_code & 0xF);
178d30e60e7SRichard Henderson si_code = TARGET_ILL_PRVOPC;
17911400516SLaurent Vivier break;
18011400516SLaurent Vivier }
18111400516SLaurent Vivier break;
18211400516SLaurent Vivier case POWERPC_EXCP_TRAP:
183*083fe9a1SMatheus Ferst si_signo = TARGET_SIGTRAP;
184*083fe9a1SMatheus Ferst si_code = TARGET_TRAP_BRKPT;
18511400516SLaurent Vivier break;
18611400516SLaurent Vivier default:
18711400516SLaurent Vivier /* Should not happen ! */
18811400516SLaurent Vivier cpu_abort(cs, "Unknown program exception (%02x)\n",
18911400516SLaurent Vivier env->error_code);
19011400516SLaurent Vivier break;
19111400516SLaurent Vivier }
192d30e60e7SRichard Henderson force_sig_fault(si_signo, si_code, env->nip);
19311400516SLaurent Vivier break;
19411400516SLaurent Vivier case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
195d30e60e7SRichard Henderson case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
196d30e60e7SRichard Henderson case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */
197d30e60e7SRichard Henderson case POWERPC_EXCP_VPU: /* Vector unavailable exception */
198d30e60e7SRichard Henderson force_sig_fault(TARGET_SIGILL, TARGET_ILL_COPROC, env->nip);
19911400516SLaurent Vivier break;
20011400516SLaurent Vivier case POWERPC_EXCP_SYSCALL: /* System call exception */
2013c89b8d6SNicholas Piggin case POWERPC_EXCP_SYSCALL_VECTORED:
20211400516SLaurent Vivier cpu_abort(cs, "Syscall exception while in user mode. "
20311400516SLaurent Vivier "Aborting\n");
20411400516SLaurent Vivier break;
20511400516SLaurent Vivier case POWERPC_EXCP_DECR: /* Decrementer exception */
20611400516SLaurent Vivier cpu_abort(cs, "Decrementer interrupt while in user mode. "
20711400516SLaurent Vivier "Aborting\n");
20811400516SLaurent Vivier break;
20911400516SLaurent Vivier case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
21011400516SLaurent Vivier cpu_abort(cs, "Fix interval timer interrupt while in user mode. "
21111400516SLaurent Vivier "Aborting\n");
21211400516SLaurent Vivier break;
21311400516SLaurent Vivier case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
21411400516SLaurent Vivier cpu_abort(cs, "Watchdog timer interrupt while in user mode. "
21511400516SLaurent Vivier "Aborting\n");
21611400516SLaurent Vivier break;
21711400516SLaurent Vivier case POWERPC_EXCP_DTLB: /* Data TLB error */
21811400516SLaurent Vivier cpu_abort(cs, "Data TLB exception while in user mode. "
21911400516SLaurent Vivier "Aborting\n");
22011400516SLaurent Vivier break;
22111400516SLaurent Vivier case POWERPC_EXCP_ITLB: /* Instruction TLB error */
22211400516SLaurent Vivier cpu_abort(cs, "Instruction TLB exception while in user mode. "
22311400516SLaurent Vivier "Aborting\n");
22411400516SLaurent Vivier break;
22511400516SLaurent Vivier case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */
22611400516SLaurent Vivier cpu_abort(cs, "Embedded floating-point data IRQ not handled\n");
22711400516SLaurent Vivier break;
22811400516SLaurent Vivier case POWERPC_EXCP_EFPRI: /* Embedded floating-point round IRQ */
22911400516SLaurent Vivier cpu_abort(cs, "Embedded floating-point round IRQ not handled\n");
23011400516SLaurent Vivier break;
23111400516SLaurent Vivier case POWERPC_EXCP_EPERFM: /* Embedded performance monitor IRQ */
23211400516SLaurent Vivier cpu_abort(cs, "Performance monitor exception not handled\n");
23311400516SLaurent Vivier break;
23411400516SLaurent Vivier case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
23511400516SLaurent Vivier cpu_abort(cs, "Doorbell interrupt while in user mode. "
23611400516SLaurent Vivier "Aborting\n");
23711400516SLaurent Vivier break;
23811400516SLaurent Vivier case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
23911400516SLaurent Vivier cpu_abort(cs, "Doorbell critical interrupt while in user mode. "
24011400516SLaurent Vivier "Aborting\n");
24111400516SLaurent Vivier break;
24211400516SLaurent Vivier case POWERPC_EXCP_RESET: /* System reset exception */
24311400516SLaurent Vivier cpu_abort(cs, "Reset interrupt while in user mode. "
24411400516SLaurent Vivier "Aborting\n");
24511400516SLaurent Vivier break;
24611400516SLaurent Vivier case POWERPC_EXCP_DSEG: /* Data segment exception */
24711400516SLaurent Vivier cpu_abort(cs, "Data segment exception while in user mode. "
24811400516SLaurent Vivier "Aborting\n");
24911400516SLaurent Vivier break;
25011400516SLaurent Vivier case POWERPC_EXCP_ISEG: /* Instruction segment exception */
25111400516SLaurent Vivier cpu_abort(cs, "Instruction segment exception "
25211400516SLaurent Vivier "while in user mode. Aborting\n");
25311400516SLaurent Vivier break;
25411400516SLaurent Vivier /* PowerPC 64 with hypervisor mode support */
25511400516SLaurent Vivier case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
25611400516SLaurent Vivier cpu_abort(cs, "Hypervisor decrementer interrupt "
25711400516SLaurent Vivier "while in user mode. Aborting\n");
25811400516SLaurent Vivier break;
25911400516SLaurent Vivier case POWERPC_EXCP_TRACE: /* Trace exception */
26011400516SLaurent Vivier /* Nothing to do:
26111400516SLaurent Vivier * we use this exception to emulate step-by-step execution mode.
26211400516SLaurent Vivier */
26311400516SLaurent Vivier break;
26411400516SLaurent Vivier /* PowerPC 64 with hypervisor mode support */
26511400516SLaurent Vivier case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
26611400516SLaurent Vivier cpu_abort(cs, "Hypervisor data storage exception "
26711400516SLaurent Vivier "while in user mode. Aborting\n");
26811400516SLaurent Vivier break;
26911400516SLaurent Vivier case POWERPC_EXCP_HISI: /* Hypervisor instruction storage excp */
27011400516SLaurent Vivier cpu_abort(cs, "Hypervisor instruction storage exception "
27111400516SLaurent Vivier "while in user mode. Aborting\n");
27211400516SLaurent Vivier break;
27311400516SLaurent Vivier case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
27411400516SLaurent Vivier cpu_abort(cs, "Hypervisor data segment exception "
27511400516SLaurent Vivier "while in user mode. Aborting\n");
27611400516SLaurent Vivier break;
27711400516SLaurent Vivier case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment excp */
27811400516SLaurent Vivier cpu_abort(cs, "Hypervisor instruction segment exception "
27911400516SLaurent Vivier "while in user mode. Aborting\n");
28011400516SLaurent Vivier break;
28111400516SLaurent Vivier case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */
28211400516SLaurent Vivier cpu_abort(cs, "Programmable interval timer interrupt "
28311400516SLaurent Vivier "while in user mode. Aborting\n");
28411400516SLaurent Vivier break;
28511400516SLaurent Vivier case POWERPC_EXCP_EMUL: /* Emulation trap exception */
28611400516SLaurent Vivier cpu_abort(cs, "Emulation trap exception not handled\n");
28711400516SLaurent Vivier break;
28811400516SLaurent Vivier case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
28911400516SLaurent Vivier cpu_abort(cs, "Instruction fetch TLB exception "
29011400516SLaurent Vivier "while in user-mode. Aborting");
29111400516SLaurent Vivier break;
29211400516SLaurent Vivier case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
29311400516SLaurent Vivier cpu_abort(cs, "Data load TLB exception while in user-mode. "
29411400516SLaurent Vivier "Aborting");
29511400516SLaurent Vivier break;
29611400516SLaurent Vivier case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
29711400516SLaurent Vivier cpu_abort(cs, "Data store TLB exception while in user-mode. "
29811400516SLaurent Vivier "Aborting");
29911400516SLaurent Vivier break;
30011400516SLaurent Vivier case POWERPC_EXCP_FPA: /* Floating-point assist exception */
30111400516SLaurent Vivier cpu_abort(cs, "Floating-point assist exception not handled\n");
30211400516SLaurent Vivier break;
30311400516SLaurent Vivier case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
30411400516SLaurent Vivier cpu_abort(cs, "Instruction address breakpoint exception "
30511400516SLaurent Vivier "not handled\n");
30611400516SLaurent Vivier break;
30711400516SLaurent Vivier case POWERPC_EXCP_SMI: /* System management interrupt */
30811400516SLaurent Vivier cpu_abort(cs, "System management interrupt while in user mode. "
30911400516SLaurent Vivier "Aborting\n");
31011400516SLaurent Vivier break;
31111400516SLaurent Vivier case POWERPC_EXCP_THERM: /* Thermal interrupt */
31211400516SLaurent Vivier cpu_abort(cs, "Thermal interrupt interrupt while in user mode. "
31311400516SLaurent Vivier "Aborting\n");
31411400516SLaurent Vivier break;
31511400516SLaurent Vivier case POWERPC_EXCP_PERFM: /* Embedded performance monitor IRQ */
31611400516SLaurent Vivier cpu_abort(cs, "Performance monitor exception not handled\n");
31711400516SLaurent Vivier break;
31811400516SLaurent Vivier case POWERPC_EXCP_VPUA: /* Vector assist exception */
31911400516SLaurent Vivier cpu_abort(cs, "Vector assist exception not handled\n");
32011400516SLaurent Vivier break;
32111400516SLaurent Vivier case POWERPC_EXCP_SOFTP: /* Soft patch exception */
32211400516SLaurent Vivier cpu_abort(cs, "Soft patch exception not handled\n");
32311400516SLaurent Vivier break;
32411400516SLaurent Vivier case POWERPC_EXCP_MAINT: /* Maintenance exception */
32511400516SLaurent Vivier cpu_abort(cs, "Maintenance exception while in user mode. "
32611400516SLaurent Vivier "Aborting\n");
32711400516SLaurent Vivier break;
32811400516SLaurent Vivier case POWERPC_EXCP_SYSCALL_USER:
32911400516SLaurent Vivier /* system call in user-mode emulation */
33011400516SLaurent Vivier /* WARNING:
33111400516SLaurent Vivier * PPC ABI uses overflow flag in cr0 to signal an error
33211400516SLaurent Vivier * in syscalls.
33311400516SLaurent Vivier */
33411400516SLaurent Vivier env->crf[0] &= ~0x1;
33511400516SLaurent Vivier env->nip += 4;
33611400516SLaurent Vivier ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
33711400516SLaurent Vivier env->gpr[5], env->gpr[6], env->gpr[7],
33811400516SLaurent Vivier env->gpr[8], 0, 0);
339af254a27SRichard Henderson if (ret == -QEMU_ERESTARTSYS) {
34011400516SLaurent Vivier env->nip -= 4;
34111400516SLaurent Vivier break;
34211400516SLaurent Vivier }
34357a0c938SRichard Henderson if (ret == (target_ulong)(-QEMU_ESIGRETURN)) {
34411400516SLaurent Vivier /* Returning from a successful sigreturn syscall.
34511400516SLaurent Vivier Avoid corrupting register state. */
34611400516SLaurent Vivier break;
34711400516SLaurent Vivier }
34811400516SLaurent Vivier if (ret > (target_ulong)(-515)) {
34911400516SLaurent Vivier env->crf[0] |= 0x1;
35011400516SLaurent Vivier ret = -ret;
35111400516SLaurent Vivier }
35211400516SLaurent Vivier env->gpr[3] = ret;
35311400516SLaurent Vivier break;
35411400516SLaurent Vivier case EXCP_DEBUG:
355d30e60e7SRichard Henderson force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->nip);
35611400516SLaurent Vivier break;
35711400516SLaurent Vivier case EXCP_INTERRUPT:
35811400516SLaurent Vivier /* just indicate that signals should be handled asap */
35911400516SLaurent Vivier break;
36011400516SLaurent Vivier case EXCP_ATOMIC:
36111400516SLaurent Vivier cpu_exec_step_atomic(cs);
36214db1899SRichard Henderson arch_interrupt = false;
36311400516SLaurent Vivier break;
36411400516SLaurent Vivier default:
36511400516SLaurent Vivier cpu_abort(cs, "Unknown exception 0x%x. Aborting\n", trapnr);
36611400516SLaurent Vivier break;
36711400516SLaurent Vivier }
36811400516SLaurent Vivier process_pending_signals(env);
36914db1899SRichard Henderson
37014db1899SRichard Henderson /* Most of the traps imply a transition through kernel mode,
37114db1899SRichard Henderson * which implies an REI instruction has been executed. Which
37214db1899SRichard Henderson * means that RX and LOCK_ADDR should be cleared. But there
37314db1899SRichard Henderson * are a few exceptions for traps internal to QEMU.
37414db1899SRichard Henderson */
37514db1899SRichard Henderson if (arch_interrupt) {
37614db1899SRichard Henderson env->reserve_addr = -1;
37714db1899SRichard Henderson }
37811400516SLaurent Vivier }
37911400516SLaurent Vivier }
38011400516SLaurent Vivier
target_cpu_copy_regs(CPUArchState * env,struct target_pt_regs * regs)381cd71c089SLaurent Vivier void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
382cd71c089SLaurent Vivier {
38311400516SLaurent Vivier int i;
38411400516SLaurent Vivier
38511400516SLaurent Vivier #if defined(TARGET_PPC64)
38611400516SLaurent Vivier int flag = (env->insns_flags2 & PPC2_BOOKE206) ? MSR_CM : MSR_SF;
38711400516SLaurent Vivier #if defined(TARGET_ABI32)
38875da4997SRichard Henderson ppc_store_msr(env, env->msr & ~((target_ulong)1 << flag));
38911400516SLaurent Vivier #else
39075da4997SRichard Henderson ppc_store_msr(env, env->msr | (target_ulong)1 << flag);
39111400516SLaurent Vivier #endif
39211400516SLaurent Vivier #endif
39375da4997SRichard Henderson
39411400516SLaurent Vivier env->nip = regs->nip;
39511400516SLaurent Vivier for(i = 0; i < 32; i++) {
39611400516SLaurent Vivier env->gpr[i] = regs->gpr[i];
39711400516SLaurent Vivier }
398cd71c089SLaurent Vivier }
399