qemu/linux-user/xtensa/cpu_loop.c
<<
>>
Prefs
   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
  26static void xtensa_rfw(CPUXtensaState *env)
  27{
  28    xtensa_restore_owb(env);
  29    env->pc = env->sregs[EPC1];
  30}
  31
  32static void xtensa_rfwu(CPUXtensaState *env)
  33{
  34    env->sregs[WINDOW_START] |= (1 << env->sregs[WINDOW_BASE]);
  35    xtensa_rfw(env);
  36}
  37
  38static void xtensa_rfwo(CPUXtensaState *env)
  39{
  40    env->sregs[WINDOW_START] &= ~(1 << env->sregs[WINDOW_BASE]);
  41    xtensa_rfw(env);
  42}
  43
  44static 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
  53static 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
  62static 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
  76static 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
  90static 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
 108static 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
 126void 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
 241void 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}
 250