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 } 250