xref: /qemu/linux-user/loongarch64/cpu_loop.c (revision da8c70ea82de0d5387d04b33de2bcf5cbe7afe86)
1*da8c70eaSSong Gao /* SPDX-License-Identifier: GPL-2.0-or-later */
2*da8c70eaSSong Gao /*
3*da8c70eaSSong Gao  * QEMU LoongArch user cpu_loop.
4*da8c70eaSSong Gao  *
5*da8c70eaSSong Gao  * Copyright (c) 2021 Loongson Technology Corporation Limited
6*da8c70eaSSong Gao  */
7*da8c70eaSSong Gao 
8*da8c70eaSSong Gao #include "qemu/osdep.h"
9*da8c70eaSSong Gao #include "qemu.h"
10*da8c70eaSSong Gao #include "user-internals.h"
11*da8c70eaSSong Gao #include "cpu_loop-common.h"
12*da8c70eaSSong Gao #include "signal-common.h"
13*da8c70eaSSong Gao 
14*da8c70eaSSong Gao void cpu_loop(CPULoongArchState *env)
15*da8c70eaSSong Gao {
16*da8c70eaSSong Gao     CPUState *cs = env_cpu(env);
17*da8c70eaSSong Gao     int trapnr, si_code;
18*da8c70eaSSong Gao     abi_long ret;
19*da8c70eaSSong Gao 
20*da8c70eaSSong Gao     for (;;) {
21*da8c70eaSSong Gao         cpu_exec_start(cs);
22*da8c70eaSSong Gao         trapnr = cpu_exec(cs);
23*da8c70eaSSong Gao         cpu_exec_end(cs);
24*da8c70eaSSong Gao         process_queued_cpu_work(cs);
25*da8c70eaSSong Gao 
26*da8c70eaSSong Gao         switch (trapnr) {
27*da8c70eaSSong Gao         case EXCP_INTERRUPT:
28*da8c70eaSSong Gao             /* just indicate that signals should be handled asap */
29*da8c70eaSSong Gao             break;
30*da8c70eaSSong Gao         case EXCCODE_SYS:
31*da8c70eaSSong Gao             env->pc += 4;
32*da8c70eaSSong Gao             ret = do_syscall(env, env->gpr[11],
33*da8c70eaSSong Gao                              env->gpr[4], env->gpr[5],
34*da8c70eaSSong Gao                              env->gpr[6], env->gpr[7],
35*da8c70eaSSong Gao                              env->gpr[8], env->gpr[9],
36*da8c70eaSSong Gao                              -1, -1);
37*da8c70eaSSong Gao             if (ret == -QEMU_ERESTARTSYS) {
38*da8c70eaSSong Gao                 env->pc -= 4;
39*da8c70eaSSong Gao                 break;
40*da8c70eaSSong Gao             }
41*da8c70eaSSong Gao             if (ret == -QEMU_ESIGRETURN) {
42*da8c70eaSSong Gao                 /*
43*da8c70eaSSong Gao                  * Returning from a successful sigreturn syscall.
44*da8c70eaSSong Gao                  * Avoid clobbering register state.
45*da8c70eaSSong Gao                  */
46*da8c70eaSSong Gao                 break;
47*da8c70eaSSong Gao             }
48*da8c70eaSSong Gao             env->gpr[4] = ret;
49*da8c70eaSSong Gao             break;
50*da8c70eaSSong Gao         case EXCCODE_INE:
51*da8c70eaSSong Gao             force_sig_fault(TARGET_SIGILL, 0, env->pc);
52*da8c70eaSSong Gao             break;
53*da8c70eaSSong Gao         case EXCCODE_FPE:
54*da8c70eaSSong Gao             si_code = TARGET_FPE_FLTUNK;
55*da8c70eaSSong Gao             if (GET_FP_CAUSE(env->fcsr0) & FP_INVALID) {
56*da8c70eaSSong Gao                 si_code = TARGET_FPE_FLTINV;
57*da8c70eaSSong Gao             } else if (GET_FP_CAUSE(env->fcsr0) & FP_DIV0) {
58*da8c70eaSSong Gao                 si_code = TARGET_FPE_FLTDIV;
59*da8c70eaSSong Gao             } else if (GET_FP_CAUSE(env->fcsr0) & FP_OVERFLOW) {
60*da8c70eaSSong Gao                 si_code = TARGET_FPE_FLTOVF;
61*da8c70eaSSong Gao             } else if (GET_FP_CAUSE(env->fcsr0) & FP_UNDERFLOW) {
62*da8c70eaSSong Gao                 si_code = TARGET_FPE_FLTUND;
63*da8c70eaSSong Gao             } else if (GET_FP_CAUSE(env->fcsr0) & FP_INEXACT) {
64*da8c70eaSSong Gao                 si_code = TARGET_FPE_FLTRES;
65*da8c70eaSSong Gao             }
66*da8c70eaSSong Gao             force_sig_fault(TARGET_SIGFPE, si_code, env->pc);
67*da8c70eaSSong Gao             break;
68*da8c70eaSSong Gao         case EXCP_DEBUG:
69*da8c70eaSSong Gao         case EXCCODE_BRK:
70*da8c70eaSSong Gao             force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
71*da8c70eaSSong Gao             break;
72*da8c70eaSSong Gao         case EXCCODE_BCE:
73*da8c70eaSSong Gao             force_sig_fault(TARGET_SIGSYS, TARGET_SI_KERNEL, env->pc);
74*da8c70eaSSong Gao             break;
75*da8c70eaSSong Gao         case EXCP_ATOMIC:
76*da8c70eaSSong Gao             cpu_exec_step_atomic(cs);
77*da8c70eaSSong Gao             break;
78*da8c70eaSSong Gao         default:
79*da8c70eaSSong Gao             EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n",
80*da8c70eaSSong Gao                       trapnr);
81*da8c70eaSSong Gao             exit(EXIT_FAILURE);
82*da8c70eaSSong Gao         }
83*da8c70eaSSong Gao         process_pending_signals(env);
84*da8c70eaSSong Gao     }
85*da8c70eaSSong Gao }
86*da8c70eaSSong Gao 
87*da8c70eaSSong Gao void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
88*da8c70eaSSong Gao {
89*da8c70eaSSong Gao     int i;
90*da8c70eaSSong Gao 
91*da8c70eaSSong Gao     for (i = 0; i < 32; i++) {
92*da8c70eaSSong Gao         env->gpr[i] = regs->regs[i];
93*da8c70eaSSong Gao     }
94*da8c70eaSSong Gao     env->pc = regs->csr.era;
95*da8c70eaSSong Gao 
96*da8c70eaSSong Gao }
97