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 target_siginfo_t info; 130 abi_ulong ret; 131 int trapnr; 132 133 while (1) { 134 cpu_exec_start(cs); 135 trapnr = cpu_exec(cs); 136 cpu_exec_end(cs); 137 process_queued_cpu_work(cs); 138 139 env->sregs[PS] &= ~PS_EXCM; 140 switch (trapnr) { 141 case EXCP_INTERRUPT: 142 break; 143 144 case EXC_WINDOW_OVERFLOW4: 145 xtensa_overflow4(env); 146 break; 147 case EXC_WINDOW_UNDERFLOW4: 148 xtensa_underflow4(env); 149 break; 150 case EXC_WINDOW_OVERFLOW8: 151 xtensa_overflow8(env); 152 break; 153 case EXC_WINDOW_UNDERFLOW8: 154 xtensa_underflow8(env); 155 break; 156 case EXC_WINDOW_OVERFLOW12: 157 xtensa_overflow12(env); 158 break; 159 case EXC_WINDOW_UNDERFLOW12: 160 xtensa_underflow12(env); 161 break; 162 163 case EXC_USER: 164 switch (env->sregs[EXCCAUSE]) { 165 case ILLEGAL_INSTRUCTION_CAUSE: 166 case PRIVILEGED_CAUSE: 167 info.si_signo = TARGET_SIGILL; 168 info.si_errno = 0; 169 info.si_code = 170 env->sregs[EXCCAUSE] == ILLEGAL_INSTRUCTION_CAUSE ? 171 TARGET_ILL_ILLOPC : TARGET_ILL_PRVOPC; 172 info._sifields._sigfault._addr = env->sregs[EPC1]; 173 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 174 break; 175 176 case SYSCALL_CAUSE: 177 env->pc += 3; 178 ret = do_syscall(env, env->regs[2], 179 env->regs[6], env->regs[3], 180 env->regs[4], env->regs[5], 181 env->regs[8], env->regs[9], 0, 0); 182 switch (ret) { 183 default: 184 env->regs[2] = ret; 185 break; 186 187 case -TARGET_ERESTARTSYS: 188 env->pc -= 3; 189 break; 190 191 case -TARGET_QEMU_ESIGRETURN: 192 break; 193 } 194 break; 195 196 case ALLOCA_CAUSE: 197 env->sregs[PS] = deposit32(env->sregs[PS], 198 PS_OWB_SHIFT, 199 PS_OWB_LEN, 200 env->sregs[WINDOW_BASE]); 201 202 switch (env->regs[0] & 0xc0000000) { 203 case 0x00000000: 204 case 0x40000000: 205 xtensa_rotate_window(env, -1); 206 xtensa_underflow4(env); 207 break; 208 209 case 0x80000000: 210 xtensa_rotate_window(env, -2); 211 xtensa_underflow8(env); 212 break; 213 214 case 0xc0000000: 215 xtensa_rotate_window(env, -3); 216 xtensa_underflow12(env); 217 break; 218 } 219 break; 220 221 case INTEGER_DIVIDE_BY_ZERO_CAUSE: 222 info.si_signo = TARGET_SIGFPE; 223 info.si_errno = 0; 224 info.si_code = TARGET_FPE_INTDIV; 225 info._sifields._sigfault._addr = env->sregs[EPC1]; 226 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 227 break; 228 229 case LOAD_PROHIBITED_CAUSE: 230 case STORE_PROHIBITED_CAUSE: 231 info.si_signo = TARGET_SIGSEGV; 232 info.si_errno = 0; 233 info.si_code = TARGET_SEGV_ACCERR; 234 info._sifields._sigfault._addr = env->sregs[EXCVADDR]; 235 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 236 break; 237 238 default: 239 fprintf(stderr, "exccause = %d\n", env->sregs[EXCCAUSE]); 240 g_assert_not_reached(); 241 } 242 break; 243 case EXCP_DEBUG: 244 info.si_signo = TARGET_SIGTRAP; 245 info.si_errno = 0; 246 info.si_code = TARGET_TRAP_BRKPT; 247 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 248 break; 249 case EXC_DEBUG: 250 default: 251 fprintf(stderr, "trapnr = %d\n", trapnr); 252 g_assert_not_reached(); 253 } 254 process_pending_signals(env); 255 } 256 } 257 258 void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) 259 { 260 int i; 261 for (i = 0; i < 16; ++i) { 262 env->regs[i] = regs->areg[i]; 263 } 264 env->sregs[WINDOW_START] = regs->windowstart; 265 env->pc = regs->pc; 266 } 267