qemu

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

cpu_loop.c (8185B)


      1 /*
      2  *  qemu user cpu loop
      3  *
      4  *  Copyright (c) 2003-2008 Fabrice Bellard
      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 #include "qemu/osdep.h"
     21 #include "qemu.h"
     22 #include "user-internals.h"
     23 #include "cpu_loop-common.h"
     24 #include "signal-common.h"
     25 
     26 static void xtensa_rfw(CPUXtensaState *env)
     27 {
     28     xtensa_restore_owb(env);
     29     env->pc = env->sregs[EPC1];
     30 }
     31 
     32 static void xtensa_rfwu(CPUXtensaState *env)
     33 {
     34     env->sregs[WINDOW_START] |= (1 << env->sregs[WINDOW_BASE]);
     35     xtensa_rfw(env);
     36 }
     37 
     38 static void xtensa_rfwo(CPUXtensaState *env)
     39 {
     40     env->sregs[WINDOW_START] &= ~(1 << env->sregs[WINDOW_BASE]);
     41     xtensa_rfw(env);
     42 }
     43 
     44 static void xtensa_overflow4(CPUXtensaState *env)
     45 {
     46     put_user_ual(env->regs[0], env->regs[5] - 16);
     47     put_user_ual(env->regs[1], env->regs[5] - 12);
     48     put_user_ual(env->regs[2], env->regs[5] -  8);
     49     put_user_ual(env->regs[3], env->regs[5] -  4);
     50     xtensa_rfwo(env);
     51 }
     52 
     53 static void xtensa_underflow4(CPUXtensaState *env)
     54 {
     55     get_user_ual(env->regs[0], env->regs[5] - 16);
     56     get_user_ual(env->regs[1], env->regs[5] - 12);
     57     get_user_ual(env->regs[2], env->regs[5] -  8);
     58     get_user_ual(env->regs[3], env->regs[5] -  4);
     59     xtensa_rfwu(env);
     60 }
     61 
     62 static void xtensa_overflow8(CPUXtensaState *env)
     63 {
     64     put_user_ual(env->regs[0], env->regs[9] - 16);
     65     get_user_ual(env->regs[0], env->regs[1] - 12);
     66     put_user_ual(env->regs[1], env->regs[9] - 12);
     67     put_user_ual(env->regs[2], env->regs[9] -  8);
     68     put_user_ual(env->regs[3], env->regs[9] -  4);
     69     put_user_ual(env->regs[4], env->regs[0] - 32);
     70     put_user_ual(env->regs[5], env->regs[0] - 28);
     71     put_user_ual(env->regs[6], env->regs[0] - 24);
     72     put_user_ual(env->regs[7], env->regs[0] - 20);
     73     xtensa_rfwo(env);
     74 }
     75 
     76 static void xtensa_underflow8(CPUXtensaState *env)
     77 {
     78     get_user_ual(env->regs[0], env->regs[9] - 16);
     79     get_user_ual(env->regs[1], env->regs[9] - 12);
     80     get_user_ual(env->regs[2], env->regs[9] -  8);
     81     get_user_ual(env->regs[7], env->regs[1] - 12);
     82     get_user_ual(env->regs[3], env->regs[9] -  4);
     83     get_user_ual(env->regs[4], env->regs[7] - 32);
     84     get_user_ual(env->regs[5], env->regs[7] - 28);
     85     get_user_ual(env->regs[6], env->regs[7] - 24);
     86     get_user_ual(env->regs[7], env->regs[7] - 20);
     87     xtensa_rfwu(env);
     88 }
     89 
     90 static void xtensa_overflow12(CPUXtensaState *env)
     91 {
     92     put_user_ual(env->regs[0],  env->regs[13] - 16);
     93     get_user_ual(env->regs[0],  env->regs[1]  - 12);
     94     put_user_ual(env->regs[1],  env->regs[13] - 12);
     95     put_user_ual(env->regs[2],  env->regs[13] -  8);
     96     put_user_ual(env->regs[3],  env->regs[13] -  4);
     97     put_user_ual(env->regs[4],  env->regs[0]  - 48);
     98     put_user_ual(env->regs[5],  env->regs[0]  - 44);
     99     put_user_ual(env->regs[6],  env->regs[0]  - 40);
    100     put_user_ual(env->regs[7],  env->regs[0]  - 36);
    101     put_user_ual(env->regs[8],  env->regs[0]  - 32);
    102     put_user_ual(env->regs[9],  env->regs[0]  - 28);
    103     put_user_ual(env->regs[10], env->regs[0]  - 24);
    104     put_user_ual(env->regs[11], env->regs[0]  - 20);
    105     xtensa_rfwo(env);
    106 }
    107 
    108 static void xtensa_underflow12(CPUXtensaState *env)
    109 {
    110     get_user_ual(env->regs[0],  env->regs[13] - 16);
    111     get_user_ual(env->regs[1],  env->regs[13] - 12);
    112     get_user_ual(env->regs[2],  env->regs[13] -  8);
    113     get_user_ual(env->regs[11], env->regs[1]  - 12);
    114     get_user_ual(env->regs[3],  env->regs[13] -  4);
    115     get_user_ual(env->regs[4],  env->regs[11] - 48);
    116     get_user_ual(env->regs[5],  env->regs[11] - 44);
    117     get_user_ual(env->regs[6],  env->regs[11] - 40);
    118     get_user_ual(env->regs[7],  env->regs[11] - 36);
    119     get_user_ual(env->regs[8],  env->regs[11] - 32);
    120     get_user_ual(env->regs[9],  env->regs[11] - 28);
    121     get_user_ual(env->regs[10], env->regs[11] - 24);
    122     get_user_ual(env->regs[11], env->regs[11] - 20);
    123     xtensa_rfwu(env);
    124 }
    125 
    126 void cpu_loop(CPUXtensaState *env)
    127 {
    128     CPUState *cs = env_cpu(env);
    129     abi_ulong ret;
    130     int trapnr;
    131 
    132     while (1) {
    133         cpu_exec_start(cs);
    134         trapnr = cpu_exec(cs);
    135         cpu_exec_end(cs);
    136         process_queued_cpu_work(cs);
    137 
    138         env->sregs[PS] &= ~PS_EXCM;
    139         switch (trapnr) {
    140         case EXCP_INTERRUPT:
    141             break;
    142 
    143         case EXC_WINDOW_OVERFLOW4:
    144             xtensa_overflow4(env);
    145             break;
    146         case EXC_WINDOW_UNDERFLOW4:
    147             xtensa_underflow4(env);
    148             break;
    149         case EXC_WINDOW_OVERFLOW8:
    150             xtensa_overflow8(env);
    151             break;
    152         case EXC_WINDOW_UNDERFLOW8:
    153             xtensa_underflow8(env);
    154             break;
    155         case EXC_WINDOW_OVERFLOW12:
    156             xtensa_overflow12(env);
    157             break;
    158         case EXC_WINDOW_UNDERFLOW12:
    159             xtensa_underflow12(env);
    160             break;
    161 
    162         case EXC_USER:
    163             switch (env->sregs[EXCCAUSE]) {
    164             case ILLEGAL_INSTRUCTION_CAUSE:
    165                 force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC,
    166                                 env->sregs[EPC1]);
    167                 break;
    168             case PRIVILEGED_CAUSE:
    169                 force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC,
    170                                 env->sregs[EPC1]);
    171                 break;
    172 
    173             case SYSCALL_CAUSE:
    174                 env->pc += 3;
    175                 ret = do_syscall(env, env->regs[2],
    176                                  env->regs[6], env->regs[3],
    177                                  env->regs[4], env->regs[5],
    178                                  env->regs[8], env->regs[9], 0, 0);
    179                 switch (ret) {
    180                 default:
    181                     env->regs[2] = ret;
    182                     break;
    183 
    184                 case -QEMU_ERESTARTSYS:
    185                     env->pc -= 3;
    186                     break;
    187 
    188                 case -QEMU_ESIGRETURN:
    189                     break;
    190                 }
    191                 break;
    192 
    193             case ALLOCA_CAUSE:
    194                 env->sregs[PS] = deposit32(env->sregs[PS],
    195                                            PS_OWB_SHIFT,
    196                                            PS_OWB_LEN,
    197                                            env->sregs[WINDOW_BASE]);
    198 
    199                 switch (env->regs[0] & 0xc0000000) {
    200                 case 0x00000000:
    201                 case 0x40000000:
    202                     xtensa_rotate_window(env, -1);
    203                     xtensa_underflow4(env);
    204                     break;
    205 
    206                 case 0x80000000:
    207                     xtensa_rotate_window(env, -2);
    208                     xtensa_underflow8(env);
    209                     break;
    210 
    211                 case 0xc0000000:
    212                     xtensa_rotate_window(env, -3);
    213                     xtensa_underflow12(env);
    214                     break;
    215                 }
    216                 break;
    217 
    218             case INTEGER_DIVIDE_BY_ZERO_CAUSE:
    219                 force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTDIV,
    220                                 env->sregs[EPC1]);
    221                 break;
    222 
    223             default:
    224                 fprintf(stderr, "exccause = %d\n", env->sregs[EXCCAUSE]);
    225                 g_assert_not_reached();
    226             }
    227             break;
    228         case EXCP_DEBUG:
    229             force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT,
    230                             env->sregs[EPC1]);
    231             break;
    232         case EXC_DEBUG:
    233         default:
    234             fprintf(stderr, "trapnr = %d\n", trapnr);
    235             g_assert_not_reached();
    236         }
    237         process_pending_signals(env);
    238     }
    239 }
    240 
    241 void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
    242 {
    243     int i;
    244     for (i = 0; i < 16; ++i) {
    245         env->regs[i] = regs->areg[i];
    246     }
    247     env->sregs[WINDOW_START] = regs->windowstart;
    248     env->pc = regs->pc;
    249 }