qemu

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

helper.c (8519B)


      1 /*
      2  *  CRIS helper routines.
      3  *
      4  *  Copyright (c) 2007 AXIS Communications AB
      5  *  Written by Edgar E. Iglesias.
      6  *
      7  * This library is free software; you can redistribute it and/or
      8  * modify it under the terms of the GNU Lesser General Public
      9  * License as published by the Free Software Foundation; either
     10  * version 2.1 of the License, or (at your option) any later version.
     11  *
     12  * This library is distributed in the hope that it will be useful,
     13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15  * Lesser General Public License for more details.
     16  *
     17  * You should have received a copy of the GNU Lesser General Public
     18  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
     19  */
     20 
     21 #include "qemu/osdep.h"
     22 #include "qemu/log.h"
     23 #include "cpu.h"
     24 #include "hw/core/tcg-cpu-ops.h"
     25 #include "mmu.h"
     26 #include "qemu/host-utils.h"
     27 #include "exec/exec-all.h"
     28 #include "exec/cpu_ldst.h"
     29 #include "exec/helper-proto.h"
     30 
     31 
     32 //#define CRIS_HELPER_DEBUG
     33 
     34 
     35 #ifdef CRIS_HELPER_DEBUG
     36 #define D(x) x
     37 #define D_LOG(...) qemu_log(__VA_ARGS__)
     38 #else
     39 #define D(x)
     40 #define D_LOG(...) do { } while (0)
     41 #endif
     42 
     43 static void cris_shift_ccs(CPUCRISState *env)
     44 {
     45     uint32_t ccs;
     46     /* Apply the ccs shift.  */
     47     ccs = env->pregs[PR_CCS];
     48     ccs = ((ccs & 0xc0000000) | ((ccs << 12) >> 2)) & ~0x3ff;
     49     env->pregs[PR_CCS] = ccs;
     50 }
     51 
     52 bool cris_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
     53                        MMUAccessType access_type, int mmu_idx,
     54                        bool probe, uintptr_t retaddr)
     55 {
     56     CRISCPU *cpu = CRIS_CPU(cs);
     57     CPUCRISState *env = &cpu->env;
     58     struct cris_mmu_result res;
     59     int prot, miss;
     60     target_ulong phy;
     61 
     62     miss = cris_mmu_translate(&res, env, address & TARGET_PAGE_MASK,
     63                               access_type, mmu_idx, 0);
     64     if (likely(!miss)) {
     65         /*
     66          * Mask off the cache selection bit. The ETRAX busses do not
     67          * see the top bit.
     68          */
     69         phy = res.phy & ~0x80000000;
     70         prot = res.prot;
     71         tlb_set_page(cs, address & TARGET_PAGE_MASK, phy,
     72                      prot, mmu_idx, TARGET_PAGE_SIZE);
     73         return true;
     74     }
     75 
     76     if (probe) {
     77         return false;
     78     }
     79 
     80     if (cs->exception_index == EXCP_BUSFAULT) {
     81         cpu_abort(cs, "CRIS: Illegal recursive bus fault."
     82                       "addr=%" VADDR_PRIx " access_type=%d\n",
     83                       address, access_type);
     84     }
     85 
     86     env->pregs[PR_EDA] = address;
     87     cs->exception_index = EXCP_BUSFAULT;
     88     env->fault_vector = res.bf_vec;
     89     if (retaddr) {
     90         if (cpu_restore_state(cs, retaddr)) {
     91             /* Evaluate flags after retranslation. */
     92             helper_top_evaluate_flags(env);
     93         }
     94     }
     95     cpu_loop_exit(cs);
     96 }
     97 
     98 void crisv10_cpu_do_interrupt(CPUState *cs)
     99 {
    100     CRISCPU *cpu = CRIS_CPU(cs);
    101     CPUCRISState *env = &cpu->env;
    102     int ex_vec = -1;
    103 
    104     D_LOG("exception index=%d interrupt_req=%d\n",
    105           cs->exception_index,
    106           cs->interrupt_request);
    107 
    108     if (env->dslot) {
    109         /* CRISv10 never takes interrupts while in a delay-slot.  */
    110         cpu_abort(cs, "CRIS: Interrupt on delay-slot\n");
    111     }
    112 
    113     assert(!(env->pregs[PR_CCS] & PFIX_FLAG));
    114     switch (cs->exception_index) {
    115     case EXCP_BREAK:
    116         /* These exceptions are genereated by the core itself.
    117            ERP should point to the insn following the brk.  */
    118         ex_vec = env->trap_vector;
    119         env->pregs[PRV10_BRP] = env->pc;
    120         break;
    121 
    122     case EXCP_NMI:
    123         /* NMI is hardwired to vector zero.  */
    124         ex_vec = 0;
    125         env->pregs[PR_CCS] &= ~M_FLAG_V10;
    126         env->pregs[PRV10_BRP] = env->pc;
    127         break;
    128 
    129     case EXCP_BUSFAULT:
    130         cpu_abort(cs, "Unhandled busfault");
    131         break;
    132 
    133     default:
    134         /* The interrupt controller gives us the vector.  */
    135         ex_vec = env->interrupt_vector;
    136         /* Normal interrupts are taken between
    137            TB's.  env->pc is valid here.  */
    138         env->pregs[PR_ERP] = env->pc;
    139         break;
    140     }
    141 
    142     if (env->pregs[PR_CCS] & U_FLAG) {
    143         /* Swap stack pointers.  */
    144         env->pregs[PR_USP] = env->regs[R_SP];
    145         env->regs[R_SP] = env->ksp;
    146     }
    147 
    148     /* Now that we are in kernel mode, load the handlers address.  */
    149     env->pc = cpu_ldl_code(env, env->pregs[PR_EBP] + ex_vec * 4);
    150     env->locked_irq = 1;
    151     env->pregs[PR_CCS] |= F_FLAG_V10; /* set F.  */
    152 
    153     qemu_log_mask(CPU_LOG_INT, "%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n",
    154                   __func__, env->pc, ex_vec,
    155                   env->pregs[PR_CCS],
    156                   env->pregs[PR_PID],
    157                   env->pregs[PR_ERP]);
    158 }
    159 
    160 void cris_cpu_do_interrupt(CPUState *cs)
    161 {
    162     CRISCPU *cpu = CRIS_CPU(cs);
    163     CPUCRISState *env = &cpu->env;
    164     int ex_vec = -1;
    165 
    166     D_LOG("exception index=%d interrupt_req=%d\n",
    167           cs->exception_index,
    168           cs->interrupt_request);
    169 
    170     switch (cs->exception_index) {
    171     case EXCP_BREAK:
    172         /* These exceptions are genereated by the core itself.
    173            ERP should point to the insn following the brk.  */
    174         ex_vec = env->trap_vector;
    175         env->pregs[PR_ERP] = env->pc;
    176         break;
    177 
    178     case EXCP_NMI:
    179         /* NMI is hardwired to vector zero.  */
    180         ex_vec = 0;
    181         env->pregs[PR_CCS] &= ~M_FLAG_V32;
    182         env->pregs[PR_NRP] = env->pc;
    183         break;
    184 
    185     case EXCP_BUSFAULT:
    186         ex_vec = env->fault_vector;
    187         env->pregs[PR_ERP] = env->pc;
    188         break;
    189 
    190     default:
    191         /* The interrupt controller gives us the vector.  */
    192         ex_vec = env->interrupt_vector;
    193         /* Normal interrupts are taken between
    194            TB's.  env->pc is valid here.  */
    195         env->pregs[PR_ERP] = env->pc;
    196         break;
    197     }
    198 
    199     /* Fill in the IDX field.  */
    200     env->pregs[PR_EXS] = (ex_vec & 0xff) << 8;
    201 
    202     if (env->dslot) {
    203         D_LOG("excp isr=%x PC=%x ds=%d SP=%x"
    204               " ERP=%x pid=%x ccs=%x cc=%d %x\n",
    205               ex_vec, env->pc, env->dslot,
    206               env->regs[R_SP],
    207               env->pregs[PR_ERP], env->pregs[PR_PID],
    208               env->pregs[PR_CCS],
    209               env->cc_op, env->cc_mask);
    210         /* We loose the btarget, btaken state here so rexec the
    211            branch.  */
    212         env->pregs[PR_ERP] -= env->dslot;
    213         /* Exception starts with dslot cleared.  */
    214         env->dslot = 0;
    215     }
    216 
    217     if (env->pregs[PR_CCS] & U_FLAG) {
    218         /* Swap stack pointers.  */
    219         env->pregs[PR_USP] = env->regs[R_SP];
    220         env->regs[R_SP] = env->ksp;
    221     }
    222 
    223     /* Apply the CRIS CCS shift. Clears U if set.  */
    224     cris_shift_ccs(env);
    225 
    226     /* Now that we are in kernel mode, load the handlers address.
    227        This load may not fault, real hw leaves that behaviour as
    228        undefined.  */
    229     env->pc = cpu_ldl_code(env, env->pregs[PR_EBP] + ex_vec * 4);
    230 
    231     /* Clear the excption_index to avoid spurios hw_aborts for recursive
    232        bus faults.  */
    233     cs->exception_index = -1;
    234 
    235     D_LOG("%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n",
    236           __func__, env->pc, ex_vec,
    237           env->pregs[PR_CCS],
    238           env->pregs[PR_PID],
    239           env->pregs[PR_ERP]);
    240 }
    241 
    242 hwaddr cris_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
    243 {
    244     CRISCPU *cpu = CRIS_CPU(cs);
    245     uint32_t phy = addr;
    246     struct cris_mmu_result res;
    247     int miss;
    248 
    249     miss = cris_mmu_translate(&res, &cpu->env, addr, MMU_DATA_LOAD, 0, 1);
    250     /* If D TLB misses, try I TLB.  */
    251     if (miss) {
    252         miss = cris_mmu_translate(&res, &cpu->env, addr, MMU_INST_FETCH, 0, 1);
    253     }
    254 
    255     if (!miss) {
    256         phy = res.phy;
    257     }
    258     D(fprintf(stderr, "%s %x -> %x\n", __func__, addr, phy));
    259     return phy;
    260 }
    261 
    262 bool cris_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
    263 {
    264     CPUClass *cc = CPU_GET_CLASS(cs);
    265     CRISCPU *cpu = CRIS_CPU(cs);
    266     CPUCRISState *env = &cpu->env;
    267     bool ret = false;
    268 
    269     if (interrupt_request & CPU_INTERRUPT_HARD
    270         && (env->pregs[PR_CCS] & I_FLAG)
    271         && !env->locked_irq) {
    272         cs->exception_index = EXCP_IRQ;
    273         cc->tcg_ops->do_interrupt(cs);
    274         ret = true;
    275     }
    276     if (interrupt_request & CPU_INTERRUPT_NMI) {
    277         unsigned int m_flag_archval;
    278         if (env->pregs[PR_VR] < 32) {
    279             m_flag_archval = M_FLAG_V10;
    280         } else {
    281             m_flag_archval = M_FLAG_V32;
    282         }
    283         if ((env->pregs[PR_CCS] & m_flag_archval)) {
    284             cs->exception_index = EXCP_NMI;
    285             cc->tcg_ops->do_interrupt(cs);
    286             ret = true;
    287         }
    288     }
    289 
    290     return ret;
    291 }