|  | /* | 
|  | *  RISC-V CPU init and loop | 
|  | * | 
|  | *  Copyright (c) 2019 Mark Corbin | 
|  | * | 
|  | *  This program is free software; you can redistribute it and/or modify | 
|  | *  it under the terms of the GNU General Public License as published by | 
|  | *  the Free Software Foundation; either version 2 of the License, or | 
|  | *  (at your option) any later version. | 
|  | * | 
|  | *  This program is distributed in the hope that it will be useful, | 
|  | *  but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | *  GNU General Public License for more details. | 
|  | * | 
|  | *  You should have received a copy of the GNU General Public License | 
|  | *  along with this program; if not, see <http://www.gnu.org/licenses/>. | 
|  | */ | 
|  |  | 
|  | #ifndef TARGET_ARCH_CPU_H | 
|  | #define TARGET_ARCH_CPU_H | 
|  |  | 
|  | #include "target_arch.h" | 
|  | #include "signal-common.h" | 
|  |  | 
|  | #define TARGET_DEFAULT_CPU_MODEL "max" | 
|  |  | 
|  | static inline void target_cpu_init(CPURISCVState *env, | 
|  | struct target_pt_regs *regs) | 
|  | { | 
|  | int i; | 
|  |  | 
|  | for (i = 1; i < 32; i++) { | 
|  | env->gpr[i] = regs->regs[i]; | 
|  | } | 
|  |  | 
|  | env->pc = regs->sepc; | 
|  | } | 
|  |  | 
|  | static inline G_NORETURN void target_cpu_loop(CPURISCVState *env) | 
|  | { | 
|  | CPUState *cs = env_cpu(env); | 
|  | int trapnr; | 
|  | abi_long ret; | 
|  | unsigned int syscall_num; | 
|  | int32_t signo, code; | 
|  |  | 
|  | for (;;) { | 
|  | cpu_exec_start(cs); | 
|  | trapnr = cpu_exec(cs); | 
|  | cpu_exec_end(cs); | 
|  | process_queued_cpu_work(cs); | 
|  |  | 
|  | signo = 0; | 
|  |  | 
|  | switch (trapnr) { | 
|  | case EXCP_INTERRUPT: | 
|  | /* just indicate that signals should be handled asap */ | 
|  | break; | 
|  | case EXCP_ATOMIC: | 
|  | cpu_exec_step_atomic(cs); | 
|  | break; | 
|  | case RISCV_EXCP_U_ECALL: | 
|  | syscall_num = env->gpr[xT0]; | 
|  | env->pc += TARGET_INSN_SIZE; | 
|  | /* Compare to cpu_fetch_syscall_args() in riscv/riscv/trap.c */ | 
|  | if (TARGET_FREEBSD_NR___syscall == syscall_num || | 
|  | TARGET_FREEBSD_NR_syscall == syscall_num) { | 
|  | ret = do_freebsd_syscall(env, | 
|  | env->gpr[xA0], | 
|  | env->gpr[xA1], | 
|  | env->gpr[xA2], | 
|  | env->gpr[xA3], | 
|  | env->gpr[xA4], | 
|  | env->gpr[xA5], | 
|  | env->gpr[xA6], | 
|  | env->gpr[xA7], | 
|  | 0); | 
|  | } else { | 
|  | ret = do_freebsd_syscall(env, | 
|  | syscall_num, | 
|  | env->gpr[xA0], | 
|  | env->gpr[xA1], | 
|  | env->gpr[xA2], | 
|  | env->gpr[xA3], | 
|  | env->gpr[xA4], | 
|  | env->gpr[xA5], | 
|  | env->gpr[xA6], | 
|  | env->gpr[xA7] | 
|  | ); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Compare to cpu_set_syscall_retval() in | 
|  | * riscv/riscv/vm_machdep.c | 
|  | */ | 
|  | if (ret >= 0) { | 
|  | env->gpr[xA0] = ret; | 
|  | env->gpr[xT0] = 0; | 
|  | } else if (ret == -TARGET_ERESTART) { | 
|  | env->pc -= TARGET_INSN_SIZE; | 
|  | } else if (ret != -TARGET_EJUSTRETURN) { | 
|  | env->gpr[xA0] = -ret; | 
|  | env->gpr[xT0] = 1; | 
|  | } | 
|  | break; | 
|  | case RISCV_EXCP_ILLEGAL_INST: | 
|  | signo = TARGET_SIGILL; | 
|  | code = TARGET_ILL_ILLOPC; | 
|  | break; | 
|  | case RISCV_EXCP_BREAKPOINT: | 
|  | signo = TARGET_SIGTRAP; | 
|  | code = TARGET_TRAP_BRKPT; | 
|  | break; | 
|  | case EXCP_DEBUG: | 
|  | signo = TARGET_SIGTRAP; | 
|  | code = TARGET_TRAP_BRKPT; | 
|  | break; | 
|  | default: | 
|  | fprintf(stderr, "qemu: unhandled CPU exception " | 
|  | "0x%x - aborting\n", trapnr); | 
|  | cpu_dump_state(cs, stderr, 0); | 
|  | abort(); | 
|  | } | 
|  |  | 
|  | if (signo) { | 
|  | force_sig_fault(signo, code, env->pc); | 
|  | } | 
|  |  | 
|  | process_pending_signals(env); | 
|  | } | 
|  | } | 
|  |  | 
|  | static inline void target_cpu_clone_regs(CPURISCVState *env, target_ulong newsp) | 
|  | { | 
|  | if (newsp) { | 
|  | env->gpr[xSP] = newsp; | 
|  | } | 
|  |  | 
|  | env->gpr[xA0] = 0; | 
|  | env->gpr[xT0] = 0; | 
|  | } | 
|  |  | 
|  | static inline void target_cpu_reset(CPUArchState *env) | 
|  | { | 
|  | } | 
|  |  | 
|  | #endif /* TARGET_ARCH_CPU_H */ |