Annotation of qemu/target-sparc/win_helper.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.