1 /*
2 * RISC-V CPU init and loop
3 *
4 * Copyright (c) 2019 Mark Corbin
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #ifndef TARGET_ARCH_CPU_H
21 #define TARGET_ARCH_CPU_H
22
23 #include "target_arch.h"
24 #include "signal-common.h"
25
26 #define TARGET_DEFAULT_CPU_MODEL "max"
27
target_cpu_init(CPURISCVState * env,struct target_pt_regs * regs)28 static inline void target_cpu_init(CPURISCVState *env,
29 struct target_pt_regs *regs)
30 {
31 int i;
32
33 for (i = 1; i < 32; i++) {
34 env->gpr[i] = regs->regs[i];
35 }
36
37 env->pc = regs->sepc;
38 }
39
target_cpu_loop(CPURISCVState * env)40 static inline void target_cpu_loop(CPURISCVState *env)
41 {
42 CPUState *cs = env_cpu(env);
43 int trapnr;
44 abi_long ret;
45 unsigned int syscall_num;
46 int32_t signo, code;
47
48 for (;;) {
49 cpu_exec_start(cs);
50 trapnr = cpu_exec(cs);
51 cpu_exec_end(cs);
52 process_queued_cpu_work(cs);
53
54 signo = 0;
55
56 switch (trapnr) {
57 case EXCP_INTERRUPT:
58 /* just indicate that signals should be handled asap */
59 break;
60 case EXCP_ATOMIC:
61 cpu_exec_step_atomic(cs);
62 break;
63 case RISCV_EXCP_U_ECALL:
64 syscall_num = env->gpr[xT0];
65 env->pc += TARGET_INSN_SIZE;
66 /* Compare to cpu_fetch_syscall_args() in riscv/riscv/trap.c */
67 if (TARGET_FREEBSD_NR___syscall == syscall_num ||
68 TARGET_FREEBSD_NR_syscall == syscall_num) {
69 ret = do_freebsd_syscall(env,
70 env->gpr[xA0],
71 env->gpr[xA1],
72 env->gpr[xA2],
73 env->gpr[xA3],
74 env->gpr[xA4],
75 env->gpr[xA5],
76 env->gpr[xA6],
77 env->gpr[xA7],
78 0);
79 } else {
80 ret = do_freebsd_syscall(env,
81 syscall_num,
82 env->gpr[xA0],
83 env->gpr[xA1],
84 env->gpr[xA2],
85 env->gpr[xA3],
86 env->gpr[xA4],
87 env->gpr[xA5],
88 env->gpr[xA6],
89 env->gpr[xA7]
90 );
91 }
92
93 /*
94 * Compare to cpu_set_syscall_retval() in
95 * riscv/riscv/vm_machdep.c
96 */
97 if (ret >= 0) {
98 env->gpr[xA0] = ret;
99 env->gpr[xT0] = 0;
100 } else if (ret == -TARGET_ERESTART) {
101 env->pc -= TARGET_INSN_SIZE;
102 } else if (ret != -TARGET_EJUSTRETURN) {
103 env->gpr[xA0] = -ret;
104 env->gpr[xT0] = 1;
105 }
106 break;
107 case RISCV_EXCP_ILLEGAL_INST:
108 signo = TARGET_SIGILL;
109 code = TARGET_ILL_ILLOPC;
110 break;
111 case RISCV_EXCP_BREAKPOINT:
112 signo = TARGET_SIGTRAP;
113 code = TARGET_TRAP_BRKPT;
114 break;
115 case EXCP_DEBUG:
116 signo = TARGET_SIGTRAP;
117 code = TARGET_TRAP_BRKPT;
118 break;
119 default:
120 fprintf(stderr, "qemu: unhandled CPU exception "
121 "0x%x - aborting\n", trapnr);
122 cpu_dump_state(cs, stderr, 0);
123 abort();
124 }
125
126 if (signo) {
127 force_sig_fault(signo, code, env->pc);
128 }
129
130 process_pending_signals(env);
131 }
132 }
133
target_cpu_clone_regs(CPURISCVState * env,target_ulong newsp)134 static inline void target_cpu_clone_regs(CPURISCVState *env, target_ulong newsp)
135 {
136 if (newsp) {
137 env->gpr[xSP] = newsp;
138 }
139
140 env->gpr[xA0] = 0;
141 env->gpr[xT0] = 0;
142 }
143
target_cpu_reset(CPUArchState * env)144 static inline void target_cpu_reset(CPUArchState *env)
145 {
146 }
147
148 #endif /* TARGET_ARCH_CPU_H */
149