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