qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

op_helper.c (3607B)


      1 /*
      2  * Altera Nios II helper routines.
      3  *
      4  * Copyright (C) 2012 Chris Wulff <crwulff@gmail.com>
      5  *
      6  * This library is free software; you can redistribute it and/or
      7  * modify it under the terms of the GNU Lesser General Public
      8  * License as published by the Free Software Foundation; either
      9  * version 2.1 of the License, or (at your option) any later version.
     10  *
     11  * This library 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 GNU
     14  * Lesser General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU Lesser General Public
     17  * License along with this library; if not, see
     18  * <http://www.gnu.org/licenses/lgpl-2.1.html>
     19  */
     20 
     21 #include "qemu/osdep.h"
     22 #include "cpu.h"
     23 #include "exec/helper-proto.h"
     24 #include "exec/exec-all.h"
     25 #include "qemu/main-loop.h"
     26 
     27 void helper_raise_exception(CPUNios2State *env, uint32_t index)
     28 {
     29     CPUState *cs = env_cpu(env);
     30     cs->exception_index = index;
     31     cpu_loop_exit(cs);
     32 }
     33 
     34 void nios2_cpu_loop_exit_advance(CPUNios2State *env, uintptr_t retaddr)
     35 {
     36     CPUState *cs = env_cpu(env);
     37 
     38     /*
     39      * Note that PC is advanced for all hardware exceptions.
     40      * Do this here, rather than in restore_state_to_opc(),
     41      * lest we affect QEMU internal exceptions, like EXCP_DEBUG.
     42      */
     43     cpu_restore_state(cs, retaddr);
     44     env->pc += 4;
     45     cpu_loop_exit(cs);
     46 }
     47 
     48 static void maybe_raise_div(CPUNios2State *env, uintptr_t ra)
     49 {
     50     Nios2CPU *cpu = env_archcpu(env);
     51     CPUState *cs = env_cpu(env);
     52 
     53     if (cpu->diverr_present) {
     54         cs->exception_index = EXCP_DIV;
     55         nios2_cpu_loop_exit_advance(env, ra);
     56     }
     57 }
     58 
     59 int32_t helper_divs(CPUNios2State *env, int32_t num, int32_t den)
     60 {
     61     if (unlikely(den == 0) || unlikely(den == -1 && num == INT32_MIN)) {
     62         maybe_raise_div(env, GETPC());
     63         return num; /* undefined */
     64     }
     65     return num / den;
     66 }
     67 
     68 uint32_t helper_divu(CPUNios2State *env, uint32_t num, uint32_t den)
     69 {
     70     if (unlikely(den == 0)) {
     71         maybe_raise_div(env, GETPC());
     72         return num; /* undefined */
     73     }
     74     return num / den;
     75 }
     76 
     77 #ifndef CONFIG_USER_ONLY
     78 void helper_eret(CPUNios2State *env, uint32_t new_status, uint32_t new_pc)
     79 {
     80     Nios2CPU *cpu = env_archcpu(env);
     81     CPUState *cs = env_cpu(env);
     82 
     83     if (unlikely(new_pc & 3)) {
     84         env->ctrl[CR_BADADDR] = new_pc;
     85         cs->exception_index = EXCP_UNALIGND;
     86         nios2_cpu_loop_exit_advance(env, GETPC());
     87     }
     88 
     89     /*
     90      * None of estatus, bstatus, or sstatus have constraints on write;
     91      * do not allow reserved fields in status to be set.
     92      * When shadow registers are enabled, eret *does* restore CRS.
     93      * Rather than testing eic_present to decide, mask CRS out of
     94      * the set of readonly fields.
     95      */
     96     new_status &= cpu->cr_state[CR_STATUS].writable |
     97                   (cpu->cr_state[CR_STATUS].readonly & R_CR_STATUS_CRS_MASK);
     98 
     99     env->ctrl[CR_STATUS] = new_status;
    100     env->pc = new_pc;
    101     nios2_update_crs(env);
    102     cpu_loop_exit(cs);
    103 }
    104 
    105 /*
    106  * RDPRS and WRPRS are implemented out of line so that if PRS == CRS,
    107  * all of the tcg global temporaries are synced back to ENV.
    108  */
    109 uint32_t helper_rdprs(CPUNios2State *env, uint32_t regno)
    110 {
    111     unsigned prs = FIELD_EX32(env->ctrl[CR_STATUS], CR_STATUS, PRS);
    112     return env->shadow_regs[prs][regno];
    113 }
    114 
    115 void helper_wrprs(CPUNios2State *env, uint32_t regno, uint32_t val)
    116 {
    117     unsigned prs = FIELD_EX32(env->ctrl[CR_STATUS], CR_STATUS, PRS);
    118     env->shadow_regs[prs][regno] = val;
    119 }
    120 #endif /* !CONFIG_USER_ONLY */