1cd71c089SLaurent Vivier /* 2cd71c089SLaurent Vivier * qemu user cpu loop 3cd71c089SLaurent Vivier * 4cd71c089SLaurent Vivier * Copyright (c) 2003-2008 Fabrice Bellard 5cd71c089SLaurent Vivier * 6cd71c089SLaurent Vivier * This program is free software; you can redistribute it and/or modify 7cd71c089SLaurent Vivier * it under the terms of the GNU General Public License as published by 8cd71c089SLaurent Vivier * the Free Software Foundation; either version 2 of the License, or 9cd71c089SLaurent Vivier * (at your option) any later version. 10cd71c089SLaurent Vivier * 11cd71c089SLaurent Vivier * This program is distributed in the hope that it will be useful, 12cd71c089SLaurent Vivier * but WITHOUT ANY WARRANTY; without even the implied warranty of 13cd71c089SLaurent Vivier * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14cd71c089SLaurent Vivier * GNU General Public License for more details. 15cd71c089SLaurent Vivier * 16cd71c089SLaurent Vivier * You should have received a copy of the GNU General Public License 17cd71c089SLaurent Vivier * along with this program; if not, see <http://www.gnu.org/licenses/>. 18cd71c089SLaurent Vivier */ 19cd71c089SLaurent Vivier 20cd71c089SLaurent Vivier #include "qemu/osdep.h" 21cd71c089SLaurent Vivier #include "qemu.h" 223b249d26SPeter Maydell #include "user-internals.h" 23*b74c8981SPhilippe Mathieu-Daudé #include "user/cpu_loop.h" 242113aed6SPeter Maydell #include "signal-common.h" 25cd71c089SLaurent Vivier 26d0a28415SLaurent Vivier #define SPARC64_STACK_BIAS 2047 27d0a28415SLaurent Vivier 28d0a28415SLaurent Vivier //#define DEBUG_WIN 29d0a28415SLaurent Vivier 30d0a28415SLaurent Vivier /* WARNING: dealing with register windows _is_ complicated. More info 31d0a28415SLaurent Vivier can be found at http://www.sics.se/~psm/sparcstack.html */ 32d0a28415SLaurent Vivier static inline int get_reg_index(CPUSPARCState *env, int cwp, int index) 33d0a28415SLaurent Vivier { 34d0a28415SLaurent Vivier index = (index + cwp * 16) % (16 * env->nwindows); 35d0a28415SLaurent Vivier /* wrap handling : if cwp is on the last window, then we use the 36d0a28415SLaurent Vivier registers 'after' the end */ 37d0a28415SLaurent Vivier if (index < 8 && env->cwp == env->nwindows - 1) 38d0a28415SLaurent Vivier index += 16 * env->nwindows; 39d0a28415SLaurent Vivier return index; 40d0a28415SLaurent Vivier } 41d0a28415SLaurent Vivier 42d0a28415SLaurent Vivier /* save the register window 'cwp1' */ 43d0a28415SLaurent Vivier static inline void save_window_offset(CPUSPARCState *env, int cwp1) 44d0a28415SLaurent Vivier { 45d0a28415SLaurent Vivier unsigned int i; 46d0a28415SLaurent Vivier abi_ulong sp_ptr; 47d0a28415SLaurent Vivier 48d0a28415SLaurent Vivier sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)]; 49d0a28415SLaurent Vivier #ifdef TARGET_SPARC64 50d0a28415SLaurent Vivier if (sp_ptr & 3) 51d0a28415SLaurent Vivier sp_ptr += SPARC64_STACK_BIAS; 52d0a28415SLaurent Vivier #endif 53d0a28415SLaurent Vivier #if defined(DEBUG_WIN) 54d0a28415SLaurent Vivier printf("win_overflow: sp_ptr=0x" TARGET_ABI_FMT_lx " save_cwp=%d\n", 55d0a28415SLaurent Vivier sp_ptr, cwp1); 56d0a28415SLaurent Vivier #endif 57d0a28415SLaurent Vivier for(i = 0; i < 16; i++) { 58d0a28415SLaurent Vivier /* FIXME - what to do if put_user() fails? */ 59d0a28415SLaurent Vivier put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr); 60d0a28415SLaurent Vivier sp_ptr += sizeof(abi_ulong); 61d0a28415SLaurent Vivier } 62d0a28415SLaurent Vivier } 63d0a28415SLaurent Vivier 64d0a28415SLaurent Vivier static void save_window(CPUSPARCState *env) 65d0a28415SLaurent Vivier { 66d0a28415SLaurent Vivier #ifndef TARGET_SPARC64 67d0a28415SLaurent Vivier unsigned int new_wim; 68d0a28415SLaurent Vivier new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) & 69d0a28415SLaurent Vivier ((1LL << env->nwindows) - 1); 70d0a28415SLaurent Vivier save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2)); 71d0a28415SLaurent Vivier env->wim = new_wim; 72d0a28415SLaurent Vivier #else 73d43624c4SGiuseppe Musacchio /* 74d43624c4SGiuseppe Musacchio * cansave is zero if the spill trap handler is triggered by `save` and 75d43624c4SGiuseppe Musacchio * nonzero if triggered by a `flushw` 76d43624c4SGiuseppe Musacchio */ 77d43624c4SGiuseppe Musacchio save_window_offset(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2)); 78d0a28415SLaurent Vivier env->cansave++; 79d0a28415SLaurent Vivier env->canrestore--; 80d0a28415SLaurent Vivier #endif 81d0a28415SLaurent Vivier } 82d0a28415SLaurent Vivier 83d0a28415SLaurent Vivier static void restore_window(CPUSPARCState *env) 84d0a28415SLaurent Vivier { 85d0a28415SLaurent Vivier #ifndef TARGET_SPARC64 86d0a28415SLaurent Vivier unsigned int new_wim; 87d0a28415SLaurent Vivier #endif 88d0a28415SLaurent Vivier unsigned int i, cwp1; 89d0a28415SLaurent Vivier abi_ulong sp_ptr; 90d0a28415SLaurent Vivier 91d0a28415SLaurent Vivier #ifndef TARGET_SPARC64 92d0a28415SLaurent Vivier new_wim = ((env->wim << 1) | (env->wim >> (env->nwindows - 1))) & 93d0a28415SLaurent Vivier ((1LL << env->nwindows) - 1); 94d0a28415SLaurent Vivier #endif 95d0a28415SLaurent Vivier 96d0a28415SLaurent Vivier /* restore the invalid window */ 97d0a28415SLaurent Vivier cwp1 = cpu_cwp_inc(env, env->cwp + 1); 98d0a28415SLaurent Vivier sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)]; 99d0a28415SLaurent Vivier #ifdef TARGET_SPARC64 100d0a28415SLaurent Vivier if (sp_ptr & 3) 101d0a28415SLaurent Vivier sp_ptr += SPARC64_STACK_BIAS; 102d0a28415SLaurent Vivier #endif 103d0a28415SLaurent Vivier #if defined(DEBUG_WIN) 104d0a28415SLaurent Vivier printf("win_underflow: sp_ptr=0x" TARGET_ABI_FMT_lx " load_cwp=%d\n", 105d0a28415SLaurent Vivier sp_ptr, cwp1); 106d0a28415SLaurent Vivier #endif 107d0a28415SLaurent Vivier for(i = 0; i < 16; i++) { 108d0a28415SLaurent Vivier /* FIXME - what to do if get_user() fails? */ 109d0a28415SLaurent Vivier get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr); 110d0a28415SLaurent Vivier sp_ptr += sizeof(abi_ulong); 111d0a28415SLaurent Vivier } 112d0a28415SLaurent Vivier #ifdef TARGET_SPARC64 113d0a28415SLaurent Vivier env->canrestore++; 114d0a28415SLaurent Vivier if (env->cleanwin < env->nwindows - 1) 115d0a28415SLaurent Vivier env->cleanwin++; 116d0a28415SLaurent Vivier env->cansave--; 117d0a28415SLaurent Vivier #else 118d0a28415SLaurent Vivier env->wim = new_wim; 119d0a28415SLaurent Vivier #endif 120d0a28415SLaurent Vivier } 121d0a28415SLaurent Vivier 122d0a28415SLaurent Vivier static void flush_windows(CPUSPARCState *env) 123d0a28415SLaurent Vivier { 124d0a28415SLaurent Vivier int offset, cwp1; 125d0a28415SLaurent Vivier 126d0a28415SLaurent Vivier offset = 1; 127d0a28415SLaurent Vivier for(;;) { 128d0a28415SLaurent Vivier /* if restore would invoke restore_window(), then we can stop */ 129d0a28415SLaurent Vivier cwp1 = cpu_cwp_inc(env, env->cwp + offset); 130d0a28415SLaurent Vivier #ifndef TARGET_SPARC64 131d0a28415SLaurent Vivier if (env->wim & (1 << cwp1)) 132d0a28415SLaurent Vivier break; 133d0a28415SLaurent Vivier #else 134d0a28415SLaurent Vivier if (env->canrestore == 0) 135d0a28415SLaurent Vivier break; 136d0a28415SLaurent Vivier env->cansave++; 137d0a28415SLaurent Vivier env->canrestore--; 138d0a28415SLaurent Vivier #endif 139d0a28415SLaurent Vivier save_window_offset(env, cwp1); 140d0a28415SLaurent Vivier offset++; 141d0a28415SLaurent Vivier } 142d0a28415SLaurent Vivier cwp1 = cpu_cwp_inc(env, env->cwp + 1); 143d0a28415SLaurent Vivier #ifndef TARGET_SPARC64 144d0a28415SLaurent Vivier /* set wim so that restore will reload the registers */ 145d0a28415SLaurent Vivier env->wim = 1 << cwp1; 146d0a28415SLaurent Vivier #endif 147d0a28415SLaurent Vivier #if defined(DEBUG_WIN) 148d0a28415SLaurent Vivier printf("flush_windows: nb=%d\n", offset - 1); 149d0a28415SLaurent Vivier #endif 150d0a28415SLaurent Vivier } 151d0a28415SLaurent Vivier 1526abc58ebSRichard Henderson static void next_instruction(CPUSPARCState *env) 1536abc58ebSRichard Henderson { 1546abc58ebSRichard Henderson env->pc = env->npc; 1556abc58ebSRichard Henderson env->npc = env->npc + 4; 1566abc58ebSRichard Henderson } 1576abc58ebSRichard Henderson 1586abc58ebSRichard Henderson static uint32_t do_getcc(CPUSPARCState *env) 1596abc58ebSRichard Henderson { 1606abc58ebSRichard Henderson #ifdef TARGET_SPARC64 1616abc58ebSRichard Henderson return cpu_get_ccr(env) & 0xf; 1626abc58ebSRichard Henderson #else 1636abc58ebSRichard Henderson return extract32(cpu_get_psr(env), 20, 4); 1646abc58ebSRichard Henderson #endif 1656abc58ebSRichard Henderson } 1666abc58ebSRichard Henderson 1676abc58ebSRichard Henderson static void do_setcc(CPUSPARCState *env, uint32_t icc) 1686abc58ebSRichard Henderson { 1696abc58ebSRichard Henderson #ifdef TARGET_SPARC64 1706abc58ebSRichard Henderson cpu_put_ccr(env, (cpu_get_ccr(env) & 0xf0) | (icc & 0xf)); 1716abc58ebSRichard Henderson #else 1726abc58ebSRichard Henderson cpu_put_psr(env, deposit32(cpu_get_psr(env), 20, 4, icc)); 1736abc58ebSRichard Henderson #endif 1746abc58ebSRichard Henderson } 1756abc58ebSRichard Henderson 1766abc58ebSRichard Henderson static uint32_t do_getpsr(CPUSPARCState *env) 1776abc58ebSRichard Henderson { 1786abc58ebSRichard Henderson #ifdef TARGET_SPARC64 1796abc58ebSRichard Henderson const uint64_t TSTATE_CWP = 0x1f; 1806abc58ebSRichard Henderson const uint64_t TSTATE_ICC = 0xfull << 32; 1816abc58ebSRichard Henderson const uint64_t TSTATE_XCC = 0xfull << 36; 1826abc58ebSRichard Henderson const uint32_t PSR_S = 0x00000080u; 1836abc58ebSRichard Henderson const uint32_t PSR_V8PLUS = 0xff000000u; 1846abc58ebSRichard Henderson uint64_t tstate = sparc64_tstate(env); 1856abc58ebSRichard Henderson 1866abc58ebSRichard Henderson /* See <asm/psrcompat.h>, tstate_to_psr. */ 1876abc58ebSRichard Henderson return ((tstate & TSTATE_CWP) | 1886abc58ebSRichard Henderson PSR_S | 1896abc58ebSRichard Henderson ((tstate & TSTATE_ICC) >> 12) | 1906abc58ebSRichard Henderson ((tstate & TSTATE_XCC) >> 20) | 1916abc58ebSRichard Henderson PSR_V8PLUS); 1926abc58ebSRichard Henderson #else 1936abc58ebSRichard Henderson return (cpu_get_psr(env) & (PSR_ICC | PSR_CWP)) | PSR_S; 1946abc58ebSRichard Henderson #endif 1956abc58ebSRichard Henderson } 1966abc58ebSRichard Henderson 1979cee640aSRichard Henderson /* Avoid ifdefs below for the abi32 and abi64 paths. */ 1983116f020SRichard Henderson #ifdef TARGET_ABI32 1993116f020SRichard Henderson #define TARGET_TT_SYSCALL (TT_TRAP + 0x10) /* t_linux */ 2003116f020SRichard Henderson #else 2013116f020SRichard Henderson #define TARGET_TT_SYSCALL (TT_TRAP + 0x6d) /* tl0_linux64 */ 2023116f020SRichard Henderson #endif 2033116f020SRichard Henderson 2046f772241SRichard Henderson /* Avoid ifdefs below for the v9 and pre-v9 hw traps. */ 2056f772241SRichard Henderson #ifdef TARGET_SPARC64 2066f772241SRichard Henderson #define TARGET_TT_SPILL TT_SPILL 2076f772241SRichard Henderson #define TARGET_TT_FILL TT_FILL 2086f772241SRichard Henderson #else 2096f772241SRichard Henderson #define TARGET_TT_SPILL TT_WIN_OVF 2106f772241SRichard Henderson #define TARGET_TT_FILL TT_WIN_UNF 2116f772241SRichard Henderson #endif 2126f772241SRichard Henderson 213d0a28415SLaurent Vivier void cpu_loop (CPUSPARCState *env) 214d0a28415SLaurent Vivier { 2155a59fbceSRichard Henderson CPUState *cs = env_cpu(env); 216d0a28415SLaurent Vivier int trapnr; 217d0a28415SLaurent Vivier abi_long ret; 218d0a28415SLaurent Vivier 219d0a28415SLaurent Vivier while (1) { 220d0a28415SLaurent Vivier cpu_exec_start(cs); 221d0a28415SLaurent Vivier trapnr = cpu_exec(cs); 222d0a28415SLaurent Vivier cpu_exec_end(cs); 223d0a28415SLaurent Vivier process_queued_cpu_work(cs); 224d0a28415SLaurent Vivier 225d0a28415SLaurent Vivier switch (trapnr) { 2263116f020SRichard Henderson case TARGET_TT_SYSCALL: 227d0a28415SLaurent Vivier ret = do_syscall (env, env->gregs[1], 228d0a28415SLaurent Vivier env->regwptr[0], env->regwptr[1], 229d0a28415SLaurent Vivier env->regwptr[2], env->regwptr[3], 230d0a28415SLaurent Vivier env->regwptr[4], env->regwptr[5], 231d0a28415SLaurent Vivier 0, 0); 23257a0c938SRichard Henderson if (ret == -QEMU_ERESTARTSYS || ret == -QEMU_ESIGRETURN) { 233d0a28415SLaurent Vivier break; 234d0a28415SLaurent Vivier } 235d0a28415SLaurent Vivier if ((abi_ulong)ret >= (abi_ulong)(-515)) { 2362a1905c7SRichard Henderson set_syscall_C(env, 1); 237d0a28415SLaurent Vivier ret = -ret; 238d0a28415SLaurent Vivier } else { 2392a1905c7SRichard Henderson set_syscall_C(env, 0); 240d0a28415SLaurent Vivier } 241d0a28415SLaurent Vivier env->regwptr[0] = ret; 242d0a28415SLaurent Vivier /* next instruction */ 243d0a28415SLaurent Vivier env->pc = env->npc; 244d0a28415SLaurent Vivier env->npc = env->npc + 4; 245d0a28415SLaurent Vivier break; 24688cdb603SRichard Henderson 24752d104a5SRichard Henderson case TT_TRAP + 0x01: /* breakpoint */ 24852d104a5SRichard Henderson case EXCP_DEBUG: 24952d104a5SRichard Henderson force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); 25052d104a5SRichard Henderson break; 25152d104a5SRichard Henderson 2520908007fSRichard Henderson case TT_TRAP + 0x02: /* div0 */ 2530908007fSRichard Henderson case TT_DIV_ZERO: 2540908007fSRichard Henderson force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTDIV, env->pc); 2550908007fSRichard Henderson break; 2560908007fSRichard Henderson 25788cdb603SRichard Henderson case TT_TRAP + 0x03: /* flush windows */ 258d0a28415SLaurent Vivier flush_windows(env); 2596abc58ebSRichard Henderson next_instruction(env); 2606abc58ebSRichard Henderson break; 2616abc58ebSRichard Henderson 2626abc58ebSRichard Henderson case TT_TRAP + 0x20: /* getcc */ 2636abc58ebSRichard Henderson env->gregs[1] = do_getcc(env); 2646abc58ebSRichard Henderson next_instruction(env); 2656abc58ebSRichard Henderson break; 2666abc58ebSRichard Henderson case TT_TRAP + 0x21: /* setcc */ 2676abc58ebSRichard Henderson do_setcc(env, env->gregs[1]); 2686abc58ebSRichard Henderson next_instruction(env); 2696abc58ebSRichard Henderson break; 2706abc58ebSRichard Henderson case TT_TRAP + 0x22: /* getpsr */ 2716abc58ebSRichard Henderson env->gregs[1] = do_getpsr(env); 2726abc58ebSRichard Henderson next_instruction(env); 273d0a28415SLaurent Vivier break; 27488cdb603SRichard Henderson 275d6b03637SRichard Henderson #ifdef TARGET_SPARC64 276d6b03637SRichard Henderson case TT_TRAP + 0x6e: 277d6b03637SRichard Henderson flush_windows(env); 278d6b03637SRichard Henderson sparc64_get_context(env); 279d6b03637SRichard Henderson break; 280d6b03637SRichard Henderson case TT_TRAP + 0x6f: 281d6b03637SRichard Henderson flush_windows(env); 282d6b03637SRichard Henderson sparc64_set_context(env); 283d6b03637SRichard Henderson break; 284d6b03637SRichard Henderson #endif 285d6b03637SRichard Henderson 2866f772241SRichard Henderson case TARGET_TT_SPILL: /* window overflow */ 287d0a28415SLaurent Vivier save_window(env); 288d0a28415SLaurent Vivier break; 2896f772241SRichard Henderson case TARGET_TT_FILL: /* window underflow */ 290d0a28415SLaurent Vivier restore_window(env); 291d0a28415SLaurent Vivier break; 2926f772241SRichard Henderson 2934ea3af39SRichard Henderson case TT_FP_EXCP: 2944ea3af39SRichard Henderson { 2954ea3af39SRichard Henderson int code = TARGET_FPE_FLTUNK; 2961ccd6e13SRichard Henderson target_ulong fsr = cpu_get_fsr(env); 2974ea3af39SRichard Henderson 2984ea3af39SRichard Henderson if ((fsr & FSR_FTT_MASK) == FSR_FTT_IEEE_EXCP) { 2994ea3af39SRichard Henderson if (fsr & FSR_NVC) { 3004ea3af39SRichard Henderson code = TARGET_FPE_FLTINV; 3014ea3af39SRichard Henderson } else if (fsr & FSR_OFC) { 3024ea3af39SRichard Henderson code = TARGET_FPE_FLTOVF; 3034ea3af39SRichard Henderson } else if (fsr & FSR_UFC) { 3044ea3af39SRichard Henderson code = TARGET_FPE_FLTUND; 3054ea3af39SRichard Henderson } else if (fsr & FSR_DZC) { 3064ea3af39SRichard Henderson code = TARGET_FPE_FLTDIV; 3074ea3af39SRichard Henderson } else if (fsr & FSR_NXC) { 3084ea3af39SRichard Henderson code = TARGET_FPE_FLTRES; 3094ea3af39SRichard Henderson } 3104ea3af39SRichard Henderson } 3114ea3af39SRichard Henderson force_sig_fault(TARGET_SIGFPE, code, env->pc); 3124ea3af39SRichard Henderson } 3134ea3af39SRichard Henderson break; 3144ea3af39SRichard Henderson 315d0a28415SLaurent Vivier case EXCP_INTERRUPT: 316d0a28415SLaurent Vivier /* just indicate that signals should be handled asap */ 317d0a28415SLaurent Vivier break; 318d0a28415SLaurent Vivier case TT_ILL_INSN: 319ac80d8b1SRichard Henderson force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc); 320d0a28415SLaurent Vivier break; 32197ff1478SRichard Henderson case TT_PRIV_INSN: 32297ff1478SRichard Henderson force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->pc); 32397ff1478SRichard Henderson break; 324e64c6d42SRichard Henderson case TT_TOVF: 325e64c6d42SRichard Henderson force_sig_fault(TARGET_SIGEMT, TARGET_EMT_TAGOVF, env->pc); 326e64c6d42SRichard Henderson break; 327235f33b8SRichard Henderson #ifdef TARGET_SPARC64 328235f33b8SRichard Henderson case TT_PRIV_ACT: 329235f33b8SRichard Henderson /* Note do_privact defers to do_privop. */ 330235f33b8SRichard Henderson force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->pc); 331235f33b8SRichard Henderson break; 332c47d7c87SRichard Henderson #else 333c47d7c87SRichard Henderson case TT_NCP_INSN: 334c47d7c87SRichard Henderson force_sig_fault(TARGET_SIGILL, TARGET_ILL_COPROC, env->pc); 335c47d7c87SRichard Henderson break; 33681f04cd3SRichard Henderson case TT_UNIMP_FLUSH: 33781f04cd3SRichard Henderson next_instruction(env); 33881f04cd3SRichard Henderson break; 339235f33b8SRichard Henderson #endif 340d0a28415SLaurent Vivier case EXCP_ATOMIC: 341d0a28415SLaurent Vivier cpu_exec_step_atomic(cs); 342d0a28415SLaurent Vivier break; 343d0a28415SLaurent Vivier default: 34421a474c4SRichard Henderson /* 34521a474c4SRichard Henderson * Most software trap numbers vector to BAD_TRAP. 34621a474c4SRichard Henderson * Handle anything not explicitly matched above. 34721a474c4SRichard Henderson */ 34821a474c4SRichard Henderson if (trapnr >= TT_TRAP && trapnr <= TT_TRAP + 0x7f) { 34921a474c4SRichard Henderson force_sig_fault(TARGET_SIGILL, ILL_ILLTRP, env->pc); 35021a474c4SRichard Henderson break; 35121a474c4SRichard Henderson } 35284ca4fa9SPhilippe Mathieu-Daudé fprintf(stderr, "Unhandled trap: 0x%x\n", trapnr); 35390c84c56SMarkus Armbruster cpu_dump_state(cs, stderr, 0); 354d0a28415SLaurent Vivier exit(EXIT_FAILURE); 355d0a28415SLaurent Vivier } 356d0a28415SLaurent Vivier process_pending_signals (env); 357d0a28415SLaurent Vivier } 358d0a28415SLaurent Vivier } 359d0a28415SLaurent Vivier 360fb5c28e1SPhilippe Mathieu-Daudé void target_cpu_copy_regs(CPUArchState *env, target_pt_regs *regs) 361cd71c089SLaurent Vivier { 362d0a28415SLaurent Vivier int i; 363d0a28415SLaurent Vivier env->pc = regs->pc; 364d0a28415SLaurent Vivier env->npc = regs->npc; 365d0a28415SLaurent Vivier env->y = regs->y; 366d0a28415SLaurent Vivier for(i = 0; i < 8; i++) 367d0a28415SLaurent Vivier env->gregs[i] = regs->u_regs[i]; 368d0a28415SLaurent Vivier for(i = 0; i < 8; i++) 369d0a28415SLaurent Vivier env->regwptr[i] = regs->u_regs[i + 8]; 370cd71c089SLaurent Vivier } 371