|
|
1.1 ! root 1: /* ! 2: * Helpers for CWP and PSTATE handling ! 3: * ! 4: * Copyright (c) 2003-2005 Fabrice Bellard ! 5: * ! 6: * This library is free software; you can redistribute it and/or ! 7: * modify it under the terms of the GNU Lesser General Public ! 8: * License as published by the Free Software Foundation; either ! 9: * version 2 of the License, or (at your option) any later version. ! 10: * ! 11: * This library 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 GNU ! 14: * Lesser General Public License for more details. ! 15: * ! 16: * You should have received a copy of the GNU Lesser General Public ! 17: * License along with this library; if not, see <http://www.gnu.org/licenses/>. ! 18: */ ! 19: ! 20: #include "cpu.h" ! 21: #include "helper.h" ! 22: #include "trace.h" ! 23: ! 24: static inline void memcpy32(target_ulong *dst, const target_ulong *src) ! 25: { ! 26: dst[0] = src[0]; ! 27: dst[1] = src[1]; ! 28: dst[2] = src[2]; ! 29: dst[3] = src[3]; ! 30: dst[4] = src[4]; ! 31: dst[5] = src[5]; ! 32: dst[6] = src[6]; ! 33: dst[7] = src[7]; ! 34: } ! 35: ! 36: void cpu_set_cwp(CPUState *env, int new_cwp) ! 37: { ! 38: /* put the modified wrap registers at their proper location */ ! 39: if (env->cwp == env->nwindows - 1) { ! 40: memcpy32(env->regbase, env->regbase + env->nwindows * 16); ! 41: } ! 42: env->cwp = new_cwp; ! 43: ! 44: /* put the wrap registers at their temporary location */ ! 45: if (new_cwp == env->nwindows - 1) { ! 46: memcpy32(env->regbase + env->nwindows * 16, env->regbase); ! 47: } ! 48: env->regwptr = env->regbase + (new_cwp * 16); ! 49: } ! 50: ! 51: target_ulong cpu_get_psr(CPUState *env) ! 52: { ! 53: helper_compute_psr(env); ! 54: ! 55: #if !defined(TARGET_SPARC64) ! 56: return env->version | (env->psr & PSR_ICC) | ! 57: (env->psref ? PSR_EF : 0) | ! 58: (env->psrpil << 8) | ! 59: (env->psrs ? PSR_S : 0) | ! 60: (env->psrps ? PSR_PS : 0) | ! 61: (env->psret ? PSR_ET : 0) | env->cwp; ! 62: #else ! 63: return env->psr & PSR_ICC; ! 64: #endif ! 65: } ! 66: ! 67: void cpu_put_psr(CPUState *env, target_ulong val) ! 68: { ! 69: env->psr = val & PSR_ICC; ! 70: #if !defined(TARGET_SPARC64) ! 71: env->psref = (val & PSR_EF) ? 1 : 0; ! 72: env->psrpil = (val & PSR_PIL) >> 8; ! 73: #endif ! 74: #if ((!defined(TARGET_SPARC64)) && !defined(CONFIG_USER_ONLY)) ! 75: cpu_check_irqs(env); ! 76: #endif ! 77: #if !defined(TARGET_SPARC64) ! 78: env->psrs = (val & PSR_S) ? 1 : 0; ! 79: env->psrps = (val & PSR_PS) ? 1 : 0; ! 80: env->psret = (val & PSR_ET) ? 1 : 0; ! 81: cpu_set_cwp(env, val & PSR_CWP); ! 82: #endif ! 83: env->cc_op = CC_OP_FLAGS; ! 84: } ! 85: ! 86: int cpu_cwp_inc(CPUState *env, int cwp) ! 87: { ! 88: if (unlikely(cwp >= env->nwindows)) { ! 89: cwp -= env->nwindows; ! 90: } ! 91: return cwp; ! 92: } ! 93: ! 94: int cpu_cwp_dec(CPUState *env, int cwp) ! 95: { ! 96: if (unlikely(cwp < 0)) { ! 97: cwp += env->nwindows; ! 98: } ! 99: return cwp; ! 100: } ! 101: ! 102: #ifndef TARGET_SPARC64 ! 103: void helper_rett(CPUState *env) ! 104: { ! 105: unsigned int cwp; ! 106: ! 107: if (env->psret == 1) { ! 108: helper_raise_exception(env, TT_ILL_INSN); ! 109: } ! 110: ! 111: env->psret = 1; ! 112: cwp = cpu_cwp_inc(env, env->cwp + 1) ; ! 113: if (env->wim & (1 << cwp)) { ! 114: helper_raise_exception(env, TT_WIN_UNF); ! 115: } ! 116: cpu_set_cwp(env, cwp); ! 117: env->psrs = env->psrps; ! 118: } ! 119: ! 120: /* XXX: use another pointer for %iN registers to avoid slow wrapping ! 121: handling ? */ ! 122: void helper_save(CPUState *env) ! 123: { ! 124: uint32_t cwp; ! 125: ! 126: cwp = cpu_cwp_dec(env, env->cwp - 1); ! 127: if (env->wim & (1 << cwp)) { ! 128: helper_raise_exception(env, TT_WIN_OVF); ! 129: } ! 130: cpu_set_cwp(env, cwp); ! 131: } ! 132: ! 133: void helper_restore(CPUState *env) ! 134: { ! 135: uint32_t cwp; ! 136: ! 137: cwp = cpu_cwp_inc(env, env->cwp + 1); ! 138: if (env->wim & (1 << cwp)) { ! 139: helper_raise_exception(env, TT_WIN_UNF); ! 140: } ! 141: cpu_set_cwp(env, cwp); ! 142: } ! 143: ! 144: void helper_wrpsr(CPUState *env, target_ulong new_psr) ! 145: { ! 146: if ((new_psr & PSR_CWP) >= env->nwindows) { ! 147: helper_raise_exception(env, TT_ILL_INSN); ! 148: } else { ! 149: cpu_put_psr(env, new_psr); ! 150: } ! 151: } ! 152: ! 153: target_ulong helper_rdpsr(CPUState *env) ! 154: { ! 155: return cpu_get_psr(env); ! 156: } ! 157: ! 158: #else ! 159: /* XXX: use another pointer for %iN registers to avoid slow wrapping ! 160: handling ? */ ! 161: void helper_save(CPUState *env) ! 162: { ! 163: uint32_t cwp; ! 164: ! 165: cwp = cpu_cwp_dec(env, env->cwp - 1); ! 166: if (env->cansave == 0) { ! 167: helper_raise_exception(env, TT_SPILL | (env->otherwin != 0 ? ! 168: (TT_WOTHER | ! 169: ((env->wstate & 0x38) >> 1)) : ! 170: ((env->wstate & 0x7) << 2))); ! 171: } else { ! 172: if (env->cleanwin - env->canrestore == 0) { ! 173: /* XXX Clean windows without trap */ ! 174: helper_raise_exception(env, TT_CLRWIN); ! 175: } else { ! 176: env->cansave--; ! 177: env->canrestore++; ! 178: cpu_set_cwp(env, cwp); ! 179: } ! 180: } ! 181: } ! 182: ! 183: void helper_restore(CPUState *env) ! 184: { ! 185: uint32_t cwp; ! 186: ! 187: cwp = cpu_cwp_inc(env, env->cwp + 1); ! 188: if (env->canrestore == 0) { ! 189: helper_raise_exception(env, TT_FILL | (env->otherwin != 0 ? ! 190: (TT_WOTHER | ! 191: ((env->wstate & 0x38) >> 1)) : ! 192: ((env->wstate & 0x7) << 2))); ! 193: } else { ! 194: env->cansave++; ! 195: env->canrestore--; ! 196: cpu_set_cwp(env, cwp); ! 197: } ! 198: } ! 199: ! 200: void helper_flushw(CPUState *env) ! 201: { ! 202: if (env->cansave != env->nwindows - 2) { ! 203: helper_raise_exception(env, TT_SPILL | (env->otherwin != 0 ? ! 204: (TT_WOTHER | ! 205: ((env->wstate & 0x38) >> 1)) : ! 206: ((env->wstate & 0x7) << 2))); ! 207: } ! 208: } ! 209: ! 210: void helper_saved(CPUState *env) ! 211: { ! 212: env->cansave++; ! 213: if (env->otherwin == 0) { ! 214: env->canrestore--; ! 215: } else { ! 216: env->otherwin--; ! 217: } ! 218: } ! 219: ! 220: void helper_restored(CPUState *env) ! 221: { ! 222: env->canrestore++; ! 223: if (env->cleanwin < env->nwindows - 1) { ! 224: env->cleanwin++; ! 225: } ! 226: if (env->otherwin == 0) { ! 227: env->cansave--; ! 228: } else { ! 229: env->otherwin--; ! 230: } ! 231: } ! 232: ! 233: target_ulong cpu_get_ccr(CPUState *env) ! 234: { ! 235: target_ulong psr; ! 236: ! 237: psr = cpu_get_psr(env); ! 238: ! 239: return ((env->xcc >> 20) << 4) | ((psr & PSR_ICC) >> 20); ! 240: } ! 241: ! 242: void cpu_put_ccr(CPUState *env, target_ulong val) ! 243: { ! 244: env->xcc = (val >> 4) << 20; ! 245: env->psr = (val & 0xf) << 20; ! 246: CC_OP = CC_OP_FLAGS; ! 247: } ! 248: ! 249: target_ulong cpu_get_cwp64(CPUState *env) ! 250: { ! 251: return env->nwindows - 1 - env->cwp; ! 252: } ! 253: ! 254: void cpu_put_cwp64(CPUState *env, int cwp) ! 255: { ! 256: if (unlikely(cwp >= env->nwindows || cwp < 0)) { ! 257: cwp %= env->nwindows; ! 258: } ! 259: cpu_set_cwp(env, env->nwindows - 1 - cwp); ! 260: } ! 261: ! 262: target_ulong helper_rdccr(CPUState *env) ! 263: { ! 264: return cpu_get_ccr(env); ! 265: } ! 266: ! 267: void helper_wrccr(CPUState *env, target_ulong new_ccr) ! 268: { ! 269: cpu_put_ccr(env, new_ccr); ! 270: } ! 271: ! 272: /* CWP handling is reversed in V9, but we still use the V8 register ! 273: order. */ ! 274: target_ulong helper_rdcwp(CPUState *env) ! 275: { ! 276: return cpu_get_cwp64(env); ! 277: } ! 278: ! 279: void helper_wrcwp(CPUState *env, target_ulong new_cwp) ! 280: { ! 281: cpu_put_cwp64(env, new_cwp); ! 282: } ! 283: ! 284: static inline uint64_t *get_gregset(CPUState *env, uint32_t pstate) ! 285: { ! 286: switch (pstate) { ! 287: default: ! 288: trace_win_helper_gregset_error(pstate); ! 289: /* pass through to normal set of global registers */ ! 290: case 0: ! 291: return env->bgregs; ! 292: case PS_AG: ! 293: return env->agregs; ! 294: case PS_MG: ! 295: return env->mgregs; ! 296: case PS_IG: ! 297: return env->igregs; ! 298: } ! 299: } ! 300: ! 301: void cpu_change_pstate(CPUState *env, uint32_t new_pstate) ! 302: { ! 303: uint32_t pstate_regs, new_pstate_regs; ! 304: uint64_t *src, *dst; ! 305: ! 306: if (env->def->features & CPU_FEATURE_GL) { ! 307: /* PS_AG is not implemented in this case */ ! 308: new_pstate &= ~PS_AG; ! 309: } ! 310: ! 311: pstate_regs = env->pstate & 0xc01; ! 312: new_pstate_regs = new_pstate & 0xc01; ! 313: ! 314: if (new_pstate_regs != pstate_regs) { ! 315: trace_win_helper_switch_pstate(pstate_regs, new_pstate_regs); ! 316: ! 317: /* Switch global register bank */ ! 318: src = get_gregset(env, new_pstate_regs); ! 319: dst = get_gregset(env, pstate_regs); ! 320: memcpy32(dst, env->gregs); ! 321: memcpy32(env->gregs, src); ! 322: } else { ! 323: trace_win_helper_no_switch_pstate(new_pstate_regs); ! 324: } ! 325: env->pstate = new_pstate; ! 326: } ! 327: ! 328: void helper_wrpstate(CPUState *env, target_ulong new_state) ! 329: { ! 330: cpu_change_pstate(env, new_state & 0xf3f); ! 331: ! 332: #if !defined(CONFIG_USER_ONLY) ! 333: if (cpu_interrupts_enabled(env)) { ! 334: cpu_check_irqs(env); ! 335: } ! 336: #endif ! 337: } ! 338: ! 339: void helper_wrpil(CPUState *env, target_ulong new_pil) ! 340: { ! 341: #if !defined(CONFIG_USER_ONLY) ! 342: trace_win_helper_wrpil(env->psrpil, (uint32_t)new_pil); ! 343: ! 344: env->psrpil = new_pil; ! 345: ! 346: if (cpu_interrupts_enabled(env)) { ! 347: cpu_check_irqs(env); ! 348: } ! 349: #endif ! 350: } ! 351: ! 352: void helper_done(CPUState *env) ! 353: { ! 354: trap_state *tsptr = cpu_tsptr(env); ! 355: ! 356: env->pc = tsptr->tnpc; ! 357: env->npc = tsptr->tnpc + 4; ! 358: cpu_put_ccr(env, tsptr->tstate >> 32); ! 359: env->asi = (tsptr->tstate >> 24) & 0xff; ! 360: cpu_change_pstate(env, (tsptr->tstate >> 8) & 0xf3f); ! 361: cpu_put_cwp64(env, tsptr->tstate & 0xff); ! 362: env->tl--; ! 363: ! 364: trace_win_helper_done(env->tl); ! 365: ! 366: #if !defined(CONFIG_USER_ONLY) ! 367: if (cpu_interrupts_enabled(env)) { ! 368: cpu_check_irqs(env); ! 369: } ! 370: #endif ! 371: } ! 372: ! 373: void helper_retry(CPUState *env) ! 374: { ! 375: trap_state *tsptr = cpu_tsptr(env); ! 376: ! 377: env->pc = tsptr->tpc; ! 378: env->npc = tsptr->tnpc; ! 379: cpu_put_ccr(env, tsptr->tstate >> 32); ! 380: env->asi = (tsptr->tstate >> 24) & 0xff; ! 381: cpu_change_pstate(env, (tsptr->tstate >> 8) & 0xf3f); ! 382: cpu_put_cwp64(env, tsptr->tstate & 0xff); ! 383: env->tl--; ! 384: ! 385: trace_win_helper_retry(env->tl); ! 386: ! 387: #if !defined(CONFIG_USER_ONLY) ! 388: if (cpu_interrupts_enabled(env)) { ! 389: cpu_check_irqs(env); ! 390: } ! 391: #endif ! 392: } ! 393: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.