qemu

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

sys_helper.c (10368B)


      1 /*
      2  * OpenRISC system instructions helper routines
      3  *
      4  * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
      5  *                         Zhizhou Zhang <etouzh@gmail.com>
      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 "cpu.h"
     23 #include "exec/exec-all.h"
     24 #include "exec/helper-proto.h"
     25 #include "exception.h"
     26 #ifndef CONFIG_USER_ONLY
     27 #include "hw/boards.h"
     28 #endif
     29 
     30 #define TO_SPR(group, number) (((group) << 11) + (number))
     31 
     32 void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb)
     33 {
     34 #ifndef CONFIG_USER_ONLY
     35     OpenRISCCPU *cpu = env_archcpu(env);
     36     CPUState *cs = env_cpu(env);
     37     target_ulong mr;
     38     int idx;
     39 #endif
     40 
     41     switch (spr) {
     42 #ifndef CONFIG_USER_ONLY
     43     case TO_SPR(0, 11): /* EVBAR */
     44         env->evbar = rb;
     45         break;
     46 
     47     case TO_SPR(0, 16): /* NPC */
     48         cpu_restore_state(cs, GETPC());
     49         /* ??? Mirror or1ksim in not trashing delayed branch state
     50            when "jumping" to the current instruction.  */
     51         if (env->pc != rb) {
     52             env->pc = rb;
     53             env->dflag = 0;
     54         }
     55         cpu_loop_exit(cs);
     56         break;
     57 
     58     case TO_SPR(0, 17): /* SR */
     59         cpu_set_sr(env, rb);
     60         break;
     61 
     62     case TO_SPR(0, 32): /* EPCR */
     63         env->epcr = rb;
     64         break;
     65 
     66     case TO_SPR(0, 48): /* EEAR */
     67         env->eear = rb;
     68         break;
     69 
     70     case TO_SPR(0, 64): /* ESR */
     71         env->esr = rb;
     72         break;
     73 
     74     case TO_SPR(0, 1024) ... TO_SPR(0, 1024 + (16 * 32)): /* Shadow GPRs */
     75         idx = (spr - 1024);
     76         env->shadow_gpr[idx / 32][idx % 32] = rb;
     77         break;
     78 
     79     case TO_SPR(1, 512) ... TO_SPR(1, 512 + TLB_SIZE - 1): /* DTLBW0MR 0-127 */
     80         idx = spr - TO_SPR(1, 512);
     81         mr = env->tlb.dtlb[idx].mr;
     82         if (mr & 1) {
     83             tlb_flush_page(cs, mr & TARGET_PAGE_MASK);
     84         }
     85         if (rb & 1) {
     86             tlb_flush_page(cs, rb & TARGET_PAGE_MASK);
     87         }
     88         env->tlb.dtlb[idx].mr = rb;
     89         break;
     90     case TO_SPR(1, 640) ... TO_SPR(1, 640 + TLB_SIZE - 1): /* DTLBW0TR 0-127 */
     91         idx = spr - TO_SPR(1, 640);
     92         env->tlb.dtlb[idx].tr = rb;
     93         break;
     94     case TO_SPR(1, 768) ... TO_SPR(1, 895):   /* DTLBW1MR 0-127 */
     95     case TO_SPR(1, 896) ... TO_SPR(1, 1023):  /* DTLBW1TR 0-127 */
     96     case TO_SPR(1, 1024) ... TO_SPR(1, 1151): /* DTLBW2MR 0-127 */
     97     case TO_SPR(1, 1152) ... TO_SPR(1, 1279): /* DTLBW2TR 0-127 */
     98     case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */
     99     case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
    100         break;
    101 
    102     case TO_SPR(2, 512) ... TO_SPR(2, 512 + TLB_SIZE - 1): /* ITLBW0MR 0-127 */
    103         idx = spr - TO_SPR(2, 512);
    104         mr = env->tlb.itlb[idx].mr;
    105         if (mr & 1) {
    106             tlb_flush_page(cs, mr & TARGET_PAGE_MASK);
    107         }
    108         if (rb & 1) {
    109             tlb_flush_page(cs, rb & TARGET_PAGE_MASK);
    110         }
    111         env->tlb.itlb[idx].mr = rb;
    112         break;
    113     case TO_SPR(2, 640) ... TO_SPR(2, 640 + TLB_SIZE - 1): /* ITLBW0TR 0-127 */
    114         idx = spr - TO_SPR(2, 640);
    115         env->tlb.itlb[idx].tr = rb;
    116         break;
    117     case TO_SPR(2, 768) ... TO_SPR(2, 895):   /* ITLBW1MR 0-127 */
    118     case TO_SPR(2, 896) ... TO_SPR(2, 1023):  /* ITLBW1TR 0-127 */
    119     case TO_SPR(2, 1024) ... TO_SPR(2, 1151): /* ITLBW2MR 0-127 */
    120     case TO_SPR(2, 1152) ... TO_SPR(2, 1279): /* ITLBW2TR 0-127 */
    121     case TO_SPR(2, 1280) ... TO_SPR(2, 1407): /* ITLBW3MR 0-127 */
    122     case TO_SPR(2, 1408) ... TO_SPR(2, 1535): /* ITLBW3TR 0-127 */
    123         break;
    124 
    125     case TO_SPR(5, 1):  /* MACLO */
    126         env->mac = deposit64(env->mac, 0, 32, rb);
    127         break;
    128     case TO_SPR(5, 2):  /* MACHI */
    129         env->mac = deposit64(env->mac, 32, 32, rb);
    130         break;
    131     case TO_SPR(8, 0):  /* PMR */
    132         env->pmr = rb;
    133         if (env->pmr & PMR_DME || env->pmr & PMR_SME) {
    134             cpu_restore_state(cs, GETPC());
    135             env->pc += 4;
    136             cs->halted = 1;
    137             raise_exception(cpu, EXCP_HALTED);
    138         }
    139         break;
    140     case TO_SPR(9, 0):  /* PICMR */
    141         env->picmr = rb;
    142         qemu_mutex_lock_iothread();
    143         if (env->picsr & env->picmr) {
    144             cpu_interrupt(cs, CPU_INTERRUPT_HARD);
    145         } else {
    146             cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
    147         }
    148         qemu_mutex_unlock_iothread();
    149         break;
    150     case TO_SPR(9, 2):  /* PICSR */
    151         env->picsr &= ~rb;
    152         break;
    153     case TO_SPR(10, 0): /* TTMR */
    154         {
    155             qemu_mutex_lock_iothread();
    156             if ((env->ttmr & TTMR_M) ^ (rb & TTMR_M)) {
    157                 switch (rb & TTMR_M) {
    158                 case TIMER_NONE:
    159                     cpu_openrisc_count_stop(cpu);
    160                     break;
    161                 case TIMER_INTR:
    162                 case TIMER_SHOT:
    163                 case TIMER_CONT:
    164                     cpu_openrisc_count_start(cpu);
    165                     break;
    166                 default:
    167                     break;
    168                 }
    169             }
    170 
    171             int ip = env->ttmr & TTMR_IP;
    172 
    173             if (rb & TTMR_IP) {    /* Keep IP bit.  */
    174                 env->ttmr = (rb & ~TTMR_IP) | ip;
    175             } else {    /* Clear IP bit.  */
    176                 env->ttmr = rb & ~TTMR_IP;
    177                 cs->interrupt_request &= ~CPU_INTERRUPT_TIMER;
    178             }
    179             cpu_openrisc_timer_update(cpu);
    180             qemu_mutex_unlock_iothread();
    181         }
    182         break;
    183 
    184     case TO_SPR(10, 1): /* TTCR */
    185         qemu_mutex_lock_iothread();
    186         cpu_openrisc_count_set(cpu, rb);
    187         cpu_openrisc_timer_update(cpu);
    188         qemu_mutex_unlock_iothread();
    189         break;
    190 #endif
    191 
    192     case TO_SPR(0, 20): /* FPCSR */
    193         cpu_set_fpcsr(env, rb);
    194         break;
    195     }
    196 }
    197 
    198 target_ulong HELPER(mfspr)(CPUOpenRISCState *env, target_ulong rd,
    199                            target_ulong spr)
    200 {
    201 #ifndef CONFIG_USER_ONLY
    202     uint64_t data[TARGET_INSN_START_WORDS];
    203     MachineState *ms = MACHINE(qdev_get_machine());
    204     OpenRISCCPU *cpu = env_archcpu(env);
    205     CPUState *cs = env_cpu(env);
    206     int idx;
    207 #endif
    208 
    209     switch (spr) {
    210 #ifndef CONFIG_USER_ONLY
    211     case TO_SPR(0, 0): /* VR */
    212         return env->vr;
    213 
    214     case TO_SPR(0, 1): /* UPR */
    215         return env->upr;
    216 
    217     case TO_SPR(0, 2): /* CPUCFGR */
    218         return env->cpucfgr;
    219 
    220     case TO_SPR(0, 3): /* DMMUCFGR */
    221         return env->dmmucfgr;
    222 
    223     case TO_SPR(0, 4): /* IMMUCFGR */
    224         return env->immucfgr;
    225 
    226     case TO_SPR(0, 9): /* VR2 */
    227         return env->vr2;
    228 
    229     case TO_SPR(0, 10): /* AVR */
    230         return env->avr;
    231 
    232     case TO_SPR(0, 11): /* EVBAR */
    233         return env->evbar;
    234 
    235     case TO_SPR(0, 16): /* NPC (equals PC) */
    236         if (cpu_unwind_state_data(cs, GETPC(), data)) {
    237             return data[0];
    238         }
    239         return env->pc;
    240 
    241     case TO_SPR(0, 17): /* SR */
    242         return cpu_get_sr(env);
    243 
    244     case TO_SPR(0, 18): /* PPC */
    245         if (cpu_unwind_state_data(cs, GETPC(), data)) {
    246             if (data[1] & 2) {
    247                 return data[0] - 4;
    248             }
    249         }
    250         return env->ppc;
    251 
    252     case TO_SPR(0, 32): /* EPCR */
    253         return env->epcr;
    254 
    255     case TO_SPR(0, 48): /* EEAR */
    256         return env->eear;
    257 
    258     case TO_SPR(0, 64): /* ESR */
    259         return env->esr;
    260 
    261     case TO_SPR(0, 128): /* COREID */
    262         return cpu->parent_obj.cpu_index;
    263 
    264     case TO_SPR(0, 129): /* NUMCORES */
    265         return ms->smp.max_cpus;
    266 
    267     case TO_SPR(0, 1024) ... TO_SPR(0, 1024 + (16 * 32)): /* Shadow GPRs */
    268         idx = (spr - 1024);
    269         return env->shadow_gpr[idx / 32][idx % 32];
    270 
    271     case TO_SPR(1, 512) ... TO_SPR(1, 512 + TLB_SIZE - 1): /* DTLBW0MR 0-127 */
    272         idx = spr - TO_SPR(1, 512);
    273         return env->tlb.dtlb[idx].mr;
    274 
    275     case TO_SPR(1, 640) ... TO_SPR(1, 640 + TLB_SIZE - 1): /* DTLBW0TR 0-127 */
    276         idx = spr - TO_SPR(1, 640);
    277         return env->tlb.dtlb[idx].tr;
    278 
    279     case TO_SPR(1, 768) ... TO_SPR(1, 895):   /* DTLBW1MR 0-127 */
    280     case TO_SPR(1, 896) ... TO_SPR(1, 1023):  /* DTLBW1TR 0-127 */
    281     case TO_SPR(1, 1024) ... TO_SPR(1, 1151): /* DTLBW2MR 0-127 */
    282     case TO_SPR(1, 1152) ... TO_SPR(1, 1279): /* DTLBW2TR 0-127 */
    283     case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */
    284     case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
    285         break;
    286 
    287     case TO_SPR(2, 512) ... TO_SPR(2, 512 + TLB_SIZE - 1): /* ITLBW0MR 0-127 */
    288         idx = spr - TO_SPR(2, 512);
    289         return env->tlb.itlb[idx].mr;
    290 
    291     case TO_SPR(2, 640) ... TO_SPR(2, 640 + TLB_SIZE - 1): /* ITLBW0TR 0-127 */
    292         idx = spr - TO_SPR(2, 640);
    293         return env->tlb.itlb[idx].tr;
    294 
    295     case TO_SPR(2, 768) ... TO_SPR(2, 895):   /* ITLBW1MR 0-127 */
    296     case TO_SPR(2, 896) ... TO_SPR(2, 1023):  /* ITLBW1TR 0-127 */
    297     case TO_SPR(2, 1024) ... TO_SPR(2, 1151): /* ITLBW2MR 0-127 */
    298     case TO_SPR(2, 1152) ... TO_SPR(2, 1279): /* ITLBW2TR 0-127 */
    299     case TO_SPR(2, 1280) ... TO_SPR(2, 1407): /* ITLBW3MR 0-127 */
    300     case TO_SPR(2, 1408) ... TO_SPR(2, 1535): /* ITLBW3TR 0-127 */
    301         break;
    302 
    303     case TO_SPR(5, 1):  /* MACLO */
    304         return (uint32_t)env->mac;
    305         break;
    306     case TO_SPR(5, 2):  /* MACHI */
    307         return env->mac >> 32;
    308         break;
    309 
    310     case TO_SPR(8, 0):  /* PMR */
    311         return env->pmr;
    312 
    313     case TO_SPR(9, 0):  /* PICMR */
    314         return env->picmr;
    315 
    316     case TO_SPR(9, 2):  /* PICSR */
    317         return env->picsr;
    318 
    319     case TO_SPR(10, 0): /* TTMR */
    320         return env->ttmr;
    321 
    322     case TO_SPR(10, 1): /* TTCR */
    323         qemu_mutex_lock_iothread();
    324         cpu_openrisc_count_update(cpu);
    325         qemu_mutex_unlock_iothread();
    326         return cpu_openrisc_count_get(cpu);
    327 #endif
    328 
    329     case TO_SPR(0, 20): /* FPCSR */
    330         return env->fpcsr;
    331     }
    332 
    333     /* for rd is passed in, if rd unchanged, just keep it back.  */
    334     return rd;
    335 }