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