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 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 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 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 144 static inline void target_cpu_reset(CPUArchState *env) 145 { 146 } 147 148 #endif /* TARGET_ARCH_CPU_H */ 149