Annotation of tme/ic/sparc/sparc-insns.c, revision 1.1

1.1     ! root        1: /* $Id: sparc-insns.c,v 1.5 2007/03/29 01:07:46 fredette Exp $ */
        !             2: 
        !             3: /* ic/sparc/sparc-insns.c - SPARC instruction functions: */
        !             4: 
        !             5: /*
        !             6:  * Copyright (c) 2005 Matt Fredette
        !             7:  * All rights reserved.
        !             8:  *
        !             9:  * Redistribution and use in source and binary forms, with or without
        !            10:  * modification, are permitted provided that the following conditions
        !            11:  * are met:
        !            12:  * 1. Redistributions of source code must retain the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer.
        !            14:  * 2. Redistributions in binary form must reproduce the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer in the
        !            16:  *    documentation and/or other materials provided with the distribution.
        !            17:  * 3. All advertising materials mentioning features or use of this software
        !            18:  *    must display the following acknowledgement:
        !            19:  *      This product includes software developed by Matt Fredette.
        !            20:  * 4. The name of the author may not be used to endorse or promote products
        !            21:  *    derived from this software without specific prior written permission.
        !            22:  *
        !            23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
        !            25:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
        !            26:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
        !            27:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
        !            28:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
        !            29:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
        !            31:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
        !            32:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            33:  * POSSIBILITY OF SUCH DAMAGE.
        !            34:  */
        !            35: 
        !            36: /* includes: */
        !            37: #include "sparc-impl.h"
        !            38: 
        !            39: _TME_RCSID("$Id: sparc-insns.c,v 1.5 2007/03/29 01:07:46 fredette Exp $");
        !            40: 
        !            41: #include "sparc-bus-auto.c"
        !            42: 
        !            43: TME_SPARC_FORMAT3(tme_sparc32_illegal, tme_uint32_t)
        !            44: {
        !            45:   TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_illegal_instruction);
        !            46: }
        !            47: 
        !            48: /* the coprocessor instructions are all illegal for now: */
        !            49: TME_SPARC_FORMAT3(tme_sparc32_cpop1, tme_uint32_t)
        !            50: {
        !            51:   TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_illegal_instruction);
        !            52: }
        !            53: TME_SPARC_FORMAT3(tme_sparc32_cpop2, tme_uint32_t)
        !            54: {
        !            55:   TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_illegal_instruction);
        !            56: }
        !            57: TME_SPARC_FORMAT3(tme_sparc32_ldc, tme_uint32_t)
        !            58: {
        !            59:   TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_illegal_instruction);
        !            60: }
        !            61: TME_SPARC_FORMAT3(tme_sparc32_ldcsr, tme_uint32_t)
        !            62: {
        !            63:   TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_illegal_instruction);
        !            64: }
        !            65: TME_SPARC_FORMAT3(tme_sparc32_lddc, tme_uint32_t)
        !            66: {
        !            67:   TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_illegal_instruction);
        !            68: }
        !            69: TME_SPARC_FORMAT3(tme_sparc32_stc, tme_uint32_t)
        !            70: {
        !            71:   TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_illegal_instruction);
        !            72: }
        !            73: TME_SPARC_FORMAT3(tme_sparc32_stcsr, tme_uint32_t)
        !            74: {
        !            75:   TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_illegal_instruction);
        !            76: }
        !            77: TME_SPARC_FORMAT3(tme_sparc32_stdc, tme_uint32_t)
        !            78: {
        !            79:   TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_illegal_instruction);
        !            80: }
        !            81: TME_SPARC_FORMAT3(tme_sparc32_stdcq, tme_uint32_t)
        !            82: {
        !            83:   TME_SPARC_INSN_PRIV;
        !            84:   TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_illegal_instruction);
        !            85: }
        !            86: 
        !            87: TME_SPARC_FORMAT3(tme_sparc32_rdasr, tme_uint32_t)
        !            88: {
        !            89:   unsigned int reg_rs1;
        !            90:   unsigned int reg_rd;
        !            91:   tme_uint32_t value;
        !            92: 
        !            93:   reg_rs1 = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, (0x1f << 14));
        !            94:   reg_rd = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD);
        !            95: 
        !            96:   /* rdy: */
        !            97:   if (reg_rs1 == 0) {
        !            98:     value = ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_Y);
        !            99:   }
        !           100: 
        !           101:   /* stbar: */
        !           102:   else if (reg_rs1 == 15 && reg_rd == 0) {
        !           103:     TME_SPARC_INSN_OK;
        !           104:   }
        !           105: 
        !           106:   else {
        !           107: 
        !           108:     /* all other rdasr instructions are privileged: */
        !           109:     TME_SPARC_INSN_PRIV;
        !           110: 
        !           111:     value = 0;
        !           112:     abort();
        !           113:   }
        !           114: 
        !           115:   TME_SPARC_FORMAT3_RD = value;
        !           116:   TME_SPARC_INSN_OK;
        !           117: }
        !           118: 
        !           119: TME_SPARC_FORMAT3(tme_sparc32_rdpsr, tme_uint32_t)
        !           120: {
        !           121:   TME_SPARC_INSN_PRIV;
        !           122:   TME_SPARC_FORMAT3_RD = ic->tme_sparc32_ireg_psr;
        !           123: 
        !           124:   /* the sunos32-type-0 idle type is detected when a "rd %psr, %l0"
        !           125:      instruction is followed three instructions later (in disassembly
        !           126:      order, not execution order) by a "mov %g1, %psr" that sets PIL
        !           127:      to 0xa, and the next write to %psr is a "mov %g1, %psr" that sets
        !           128:      PIL to 0x0 and is followed by a branch (to the idle loop): */
        !           129:   if (__tme_predict_false((TME_SPARC_INSN
        !           130:                           & ~((31 << 14)               /* rs1 (reserved) */
        !           131:                               | (1 << 13)              /* i (reserved) */
        !           132:                               | 0x1fff))               /* imm13 (reserved) */
        !           133:                          == ((tme_uint32_t)
        !           134:                              (2 << 30)                 /* format */
        !           135:                              | (0x10 << 25)            /* rd (%l0) */
        !           136:                              | (0x29 << 19)))) {       /* op3 (rdpsr) */
        !           137:     /* if we haven't detected the idle loop yet, remember the address
        !           138:        of this "rd %psr, %l0" instruction and enter state one: */
        !           139:     if (__tme_predict_false(TME_SPARC_IDLE_TYPE_PC_STATE(ic->tme_sparc_idle_type_pc32) != 0)) {
        !           140:       if (TME_SPARC_IDLE_TYPE_IS(ic, TME_SPARC_IDLE_TYPE_SUNOS32_TYPE_0)) {
        !           141:        ic->tme_sparc_idle_type_pc32
        !           142:          = (ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC)
        !           143:             + TME_SPARC_IDLE_TYPE_PC_STATE(1));
        !           144:       }
        !           145:     }
        !           146:   }
        !           147: 
        !           148:   TME_SPARC_INSN_OK;
        !           149: }
        !           150: 
        !           151: TME_SPARC_FORMAT3(tme_sparc32_rdwim, tme_uint32_t)
        !           152: {
        !           153:   TME_SPARC_INSN_PRIV;
        !           154:   TME_SPARC_FORMAT3_RD = ic->tme_sparc32_ireg_wim;
        !           155:   TME_SPARC_INSN_OK;
        !           156: }
        !           157: 
        !           158: TME_SPARC_FORMAT3(tme_sparc32_rdtbr, tme_uint32_t)
        !           159: {
        !           160:   TME_SPARC_INSN_PRIV;
        !           161:   TME_SPARC_FORMAT3_RD = ic->tme_sparc32_ireg_tbr;
        !           162:   TME_SPARC_INSN_OK;
        !           163: }
        !           164: 
        !           165: TME_SPARC_FORMAT3(tme_sparc32_wrasr, tme_uint32_t)
        !           166: {
        !           167:   unsigned int reg_rd;
        !           168:   tme_uint32_t value_xor;
        !           169:   
        !           170:   reg_rd = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD);
        !           171:   value_xor = TME_SPARC_FORMAT3_RS1 ^ TME_SPARC_FORMAT3_RS2;
        !           172: 
        !           173:   /* "WRY ... writes r[rs1] xor r[rs2] if the i field is zero, or
        !           174:      r[rs1] xor sign_ext(simm13) if the i field is one, to the
        !           175:      writable fields of the specified IU state register. (Note the
        !           176:      exclusive-or operation.)  Note that WRY is distinguished from
        !           177:      WRASR only by the rd field. The rd field must be zero and op3 =
        !           178:      0x30 to write the Y register." */
        !           179:   if (reg_rd == 0) {
        !           180:     ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_Y) = value_xor;
        !           181:   }
        !           182: 
        !           183:   else {
        !           184: 
        !           185:     /* all other wrasr instructions are privileged: */
        !           186:     TME_SPARC_INSN_PRIV;
        !           187: 
        !           188:     abort();
        !           189:   }
        !           190: 
        !           191:   TME_SPARC_INSN_OK;
        !           192: }
        !           193: 
        !           194: TME_SPARC_FORMAT3(tme_sparc32_wrpsr, tme_uint32_t)
        !           195: {
        !           196:   tme_uint32_t value;
        !           197:   tme_uint32_t mask_writable;
        !           198:   tme_uint32_t insn;
        !           199:   unsigned int cwp;
        !           200: 
        !           201:   TME_SPARC_INSN_PRIV;
        !           202: 
        !           203:   /* "WRPSR ... writes r[rs1] xor r[rs2] if the i field is zero, or
        !           204:      r[rs1] xor sign_ext(simm13) if the i field is one, to the
        !           205:      writable fields of the specified IU state register. (Note the
        !           206:      exclusive-or operation.)" */
        !           207:   value = TME_SPARC_FORMAT3_RS1 ^ TME_SPARC_FORMAT3_RS2;
        !           208: 
        !           209:   /* "If the result of a WRPSR instruction would cause the CWP field
        !           210:      of the PSR to point to an unimplemented window, it causes an
        !           211:      illegal_instruction trap and does not write the PSR." */
        !           212:   cwp = TME_FIELD_MASK_EXTRACTU(value, TME_SPARC32_PSR_CWP);
        !           213:   if (__tme_predict_false(cwp >= ic->tme_sparc_nwindows)) {
        !           214:     TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_illegal_instruction);
        !           215:   }
        !           216: 
        !           217:   /* set the new CWP offset: */
        !           218:   ic->tme_sparc_cwp_offset = TME_SPARC_CWP_OFFSET(cwp);
        !           219: 
        !           220:   /* set the new PSR value: */
        !           221:   mask_writable = (TME_SPARC32_PSR_ICC
        !           222:                   | TME_SPARC32_PSR_EC
        !           223:                   | TME_SPARC32_PSR_EF
        !           224:                   | TME_SPARC32_PSR_PIL
        !           225:                   | TME_SPARC32_PSR_S
        !           226:                   | TME_SPARC32_PSR_PS
        !           227:                   | TME_SPARC32_PSR_ET
        !           228:                   | TME_SPARC32_PSR_CWP);
        !           229:   value = (value & mask_writable) | (ic->tme_sparc32_ireg_psr & ~mask_writable);
        !           230:   ic->tme_sparc32_ireg_psr = value;
        !           231: 
        !           232:   /* the netbsd32-type-0 idle type is detected when an annulled "wr
        !           233:      %g1, PSR_PIL, %psr" or "wr %l1, (IPL_SCHED << 8), %psr"
        !           234:      instruction is found four instructions after (in disassembly
        !           235:      order, not execution order) a "wr %g1, 0, %psr" or "wr %l1, 0,
        !           236:      %psr" instruction that sets PIL to 0x0: */
        !           237:   if (__tme_predict_false((TME_SPARC_INSN
        !           238:                           & ~((31 << 25)       /* rd (reserved) */
        !           239:                               | (0x10 << 14))) /* rs1 (mask %ln to %gn) */
        !           240:                          == ((tme_uint32_t)
        !           241:                              (2 << 30)         /* format */
        !           242:                              | (0x31 << 19)    /* op3 (wrpsr) */
        !           243:                              | (0x01 << 14)    /* rs1 (%g1) */
        !           244:                              | (1 << 13)       /* i */
        !           245:                              | 0x0000))) {     /* imm13 (0) */
        !           246:     if (__tme_predict_false(TME_SPARC_IDLE_TYPE_PC_STATE(ic->tme_sparc_idle_type_pc32) != 0)) {
        !           247:       if (TME_SPARC_IDLE_TYPE_IS(ic, TME_SPARC_IDLE_TYPE_NETBSD32_TYPE_0)
        !           248:          && ((value & TME_SPARC32_PSR_PIL)
        !           249:              == (0x0 * _TME_FIELD_MASK_FACTOR(TME_SPARC32_PSR_PIL)))) {
        !           250:        ic->tme_sparc_idle_type_pc32
        !           251:          = (ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC)
        !           252:             + TME_SPARC_IDLE_TYPE_PC_STATE(1));
        !           253:       }
        !           254:     }
        !           255:   }
        !           256: 
        !           257:   /* the sunos32-type-0 idle type is detected when a "rd %psr, %l0"
        !           258:      instruction is followed three instructions later (in disassembly
        !           259:      order, not execution order) by a "mov %g1, %psr" that sets PIL
        !           260:      to 0xa, and the next write to %psr is a "mov %g1, %psr" that sets
        !           261:      PIL to 0x0 and is followed by a branch (to the idle loop): */
        !           262:   if (__tme_predict_false(TME_SPARC_IDLE_TYPE_IS(ic, TME_SPARC_IDLE_TYPE_SUNOS32_TYPE_0))) {
        !           263: 
        !           264:     /* if we haven't detected the idle loop yet: */
        !           265:     if (__tme_predict_false(TME_SPARC_IDLE_TYPE_PC_STATE(ic->tme_sparc_idle_type_pc32) != 0)) {
        !           266: 
        !           267:       /* if this is a "mov %g1, %psr" instruction: */
        !           268:       if (__tme_predict_false((TME_SPARC_INSN
        !           269:                               & ~((31 << 25)           /* rd (reserved) */
        !           270:                                   | 255 << 5))         /* unused (zero) */
        !           271:                              == ((tme_uint32_t)
        !           272:                                  (2 << 30)             /* format */
        !           273:                                  | (0x31 << 19)        /* op3 (wrpsr) */
        !           274:                                  | (0x01 << 14)        /* rs1 (%g1) */
        !           275:                                  | (0 << 13)           /* i */
        !           276:                                  | (0 << 0)))) {       /* rs2 (%g0) */
        !           277: 
        !           278:        /* if this "mov %g1, %psr" instruction is three instructions
        !           279:           in disassembly order after a "rd %psr, %l0" instruction and
        !           280:           sets PIL to 0xa: */
        !           281:        if ((ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC)
        !           282:             == (ic->tme_sparc_idle_type_pc32
        !           283:                 - TME_SPARC_IDLE_TYPE_PC_STATE(1)
        !           284:                 + (sizeof(tme_uint32_t) * 3)))
        !           285:            && ((value & TME_SPARC32_PSR_PIL)
        !           286:                == (0xa * _TME_FIELD_MASK_FACTOR(TME_SPARC32_PSR_PIL)))) {
        !           287: 
        !           288:          /* advance to the next state: */
        !           289:          ic->tme_sparc_idle_type_pc32 = TME_SPARC_IDLE_TYPE_PC_STATE(3);
        !           290:        }
        !           291: 
        !           292:        /* otherwise, if we detected a "mov %g1, %psr" instruction
        !           293:           three instructions in disassembly order after a "rd %psr,
        !           294:           %l0" instruction, and this "mov %g1, %psr" instruction sets
        !           295:           PIL to 0x0, and the next instruction is an unconditional
        !           296:           branch with an annulled delay slot: */
        !           297:        else if (ic->tme_sparc_idle_type_pc32 == TME_SPARC_IDLE_TYPE_PC_STATE(3)
        !           298:                 && ((value & TME_SPARC32_PSR_PIL)
        !           299:                     == (0x0 * _TME_FIELD_MASK_FACTOR(TME_SPARC32_PSR_PIL)))
        !           300:                 && (((insn = tme_sparc_fetch_nearby(ic, 1))
        !           301:                      & ~((0x3fffff << 0)))     /* disp22 */
        !           302:                     == ((0 << 30)              /* format */
        !           303:                         | (1 << 29)            /* a */
        !           304:                         | (8 << 25)            /* cond (Always) */
        !           305:                         | (2 << 22)))) {       /* op2 (bicc) */
        !           306:          
        !           307:          /* we have detected the address of the idle loop: */
        !           308:          ic->tme_sparc_idle_type_pc32
        !           309:            = (ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC)
        !           310:               + sizeof(tme_uint32_t)
        !           311:               + (TME_FIELD_MASK_EXTRACTS(insn, (tme_uint32_t) 0x003fffff) << 2));
        !           312:        }
        !           313: 
        !           314:        /* otherwise, this is some other "mov %g1, %psr" instruction,
        !           315:           or we couldn't fetch the next instruction or it isn't the
        !           316:           expected branch: */
        !           317:        else {
        !           318: 
        !           319:          /* poison the idle type state: */
        !           320:          ic->tme_sparc_idle_type_pc32 = TME_SPARC_IDLE_TYPE_PC_STATE(1);
        !           321:        }
        !           322:       }
        !           323: 
        !           324:       /* otherwise, this is some other wrpsr instruction: */
        !           325:       else {
        !           326: 
        !           327:        /* poison the idle type state: */
        !           328:        ic->tme_sparc_idle_type_pc32 = TME_SPARC_IDLE_TYPE_PC_STATE(1);
        !           329:       }
        !           330:     }
        !           331:   }
        !           332: 
        !           333:   /* redispatch, since the executor may have cached information
        !           334:      derived from the PSR (for example, default data ASI, ITLB, etc.)
        !           335:      that we need to invalidate: */
        !           336:   tme_sparc_redispatch(ic);
        !           337:   /* NOTREACHED */
        !           338: }
        !           339: 
        !           340: TME_SPARC_FORMAT3(tme_sparc32_wrwim, tme_uint32_t)
        !           341: {
        !           342:   tme_uint32_t value;
        !           343: 
        !           344:   TME_SPARC_INSN_PRIV;
        !           345: 
        !           346:   /* "WRWIM ... writes r[rs1] xor r[rs2] if the i field is zero, or
        !           347:      r[rs1] xor sign_ext(simm13) if the i field is one, to the
        !           348:      writable fields of the specified IU state register. (Note the
        !           349:      exclusive-or operation.)" */
        !           350:   value = TME_SPARC_FORMAT3_RS1 ^ TME_SPARC_FORMAT3_RS2;
        !           351: 
        !           352:   /* "A WRWIM with all bits set to 1, followed by a RDWIM, yields a
        !           353:      bit vector in which the imple- mented windows (and only the
        !           354:      implemented windows) are indicated by 1s." */
        !           355:   value &= (0xffffffff >> (32 - ic->tme_sparc_nwindows));
        !           356:   
        !           357:   ic->tme_sparc32_ireg_wim = value;
        !           358: 
        !           359:   TME_SPARC_INSN_OK;
        !           360: }
        !           361: 
        !           362: TME_SPARC_FORMAT3(tme_sparc32_wrtbr, tme_uint32_t)
        !           363: {
        !           364:   tme_uint32_t value;
        !           365: 
        !           366:   TME_SPARC_INSN_PRIV;
        !           367: 
        !           368:   /* "WRTBR ... writes r[rs1] xor r[rs2] if the i field is zero, or
        !           369:      r[rs1] xor sign_ext(simm13) if the i field is one, to the
        !           370:      writable fields of the specified IU state register. (Note the
        !           371:      exclusive-or operation.)" */
        !           372:   value = TME_SPARC_FORMAT3_RS1 ^ TME_SPARC_FORMAT3_RS2;
        !           373: 
        !           374:   /* "Bits 11 through 4 comprise the trap type (tt) field.  This 8-bit
        !           375:      field is written by the hardware when a trap occurs, and retains
        !           376:      its value until the next trap.  It provides an offset into the
        !           377:      trap table.  The WRTBR instruction does not affect the tt
        !           378:      field.  TBR_zero (0) Bits 3 through 0 are zeroes.  The WRTBR
        !           379:      instruction does not affect this field.  For future compatibility,
        !           380:      supervisor software should only issue a WRTBR instruction with a
        !           381:      zero value in this field." */
        !           382:   value = (value & 0xfffff000) | (ic->tme_sparc32_ireg_tbr & 0x00000ff0);
        !           383:   ic->tme_sparc32_ireg_tbr = value;
        !           384: 
        !           385:   TME_SPARC_INSN_OK;
        !           386: }
        !           387: 
        !           388: TME_SPARC_FORMAT3(tme_sparc32_flush, tme_uint32_t)
        !           389: {
        !           390:   /* nothing to do */
        !           391:   TME_SPARC_INSN_OK;
        !           392: }
        !           393: 
        !           394: TME_SPARC_FORMAT3(tme_sparc32_rett, tme_uint32_t)
        !           395: {
        !           396:   tme_uint32_t psr;
        !           397:   unsigned int cwp;
        !           398:   tme_uint32_t pc_next_next;
        !           399: 
        !           400:   /* "One of several traps may occur when an RETT is executed.  These
        !           401:      are described in priority order (highest priority first):
        !           402: 
        !           403:      If traps are enabled (ET=1) and the processor is in user mode
        !           404:      (S=0), a privileged_instruction trap occurs.
        !           405: 
        !           406:      If traps are enabled (ET=1) and the processor is in supervisor
        !           407:      mode (S=1), an illegal_instruction trap occurs.
        !           408: 
        !           409:      If traps are disabled (ET=0), and (a) the processor is in user
        !           410:      mode (S=0), or (b) a window_underflow condition is detected (WIM
        !           411:      and 2^new_CWP ) = 1, or (c) either of the low-order two bits of
        !           412:      the target address is nonzero, then the processor indicates a
        !           413:      trap condition of (a) privileged_instruction, (b)
        !           414:      window_underflow, or (c) mem_address_not_aligned (respectively)
        !           415:      in the tt field of the TBR register, and enters the error_mode
        !           416:      state." */
        !           417:   psr = ic->tme_sparc32_ireg_psr;
        !           418:   
        !           419:   if (__tme_predict_false((psr & TME_SPARC32_PSR_S) == 0)) {
        !           420:     TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_privileged_instruction);
        !           421:   }
        !           422: 
        !           423:   if (__tme_predict_false((psr & TME_SPARC32_PSR_ET) != 0)) {
        !           424:     TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_illegal_instruction);
        !           425:   }
        !           426:   
        !           427:   cwp = TME_FIELD_MASK_EXTRACTU(psr, TME_SPARC32_PSR_CWP);
        !           428:   cwp += 1;
        !           429:   cwp %= ic->tme_sparc_nwindows;
        !           430:   if (ic->tme_sparc32_ireg_wim & (((tme_uint32_t) 1) << cwp)) {
        !           431:     TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_window_underflow);
        !           432:   }
        !           433: 
        !           434:   pc_next_next = TME_SPARC_FORMAT3_RS1 + TME_SPARC_FORMAT3_RS2;
        !           435:   if (__tme_predict_false((pc_next_next % sizeof(tme_uint32_t)) != 0)) {
        !           436:     TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_mem_address_not_aligned);
        !           437:   }
        !           438: 
        !           439:   /* set the new PSR: */
        !           440:   TME_FIELD_MASK_DEPOSITU(psr, TME_SPARC32_PSR_CWP, cwp);
        !           441:   psr |= TME_SPARC32_PSR_ET;
        !           442:   psr &= ~TME_SPARC32_PSR_S;
        !           443:   psr |= ((psr & TME_SPARC32_PSR_PS) * (TME_SPARC32_PSR_S / TME_SPARC32_PSR_PS));
        !           444:   ic->tme_sparc32_ireg_psr = psr;
        !           445: 
        !           446:   /* set the new CWP offset: */
        !           447:   ic->tme_sparc_cwp_offset = TME_SPARC_CWP_OFFSET(cwp);
        !           448: 
        !           449:   /* set the delayed control transfer: */
        !           450:   ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT_NEXT) = pc_next_next;
        !           451: 
        !           452:   /* redispatch, since the executor may have cached information
        !           453:      derived from the PSR (for example, default data ASI, ITLB, etc.)
        !           454:      that we need to invalidate: */
        !           455:   tme_sparc_redispatch(ic);
        !           456: }
        !           457: 
        !           458: TME_SPARC_FORMAT3(tme_sparc32_save_restore, tme_uint32_t)
        !           459: {
        !           460:   int direction;
        !           461:   tme_uint32_t psr;
        !           462:   unsigned int cwp;
        !           463:   unsigned int cwp_offset;
        !           464:   unsigned int reg_rd;
        !           465: 
        !           466:   /* calculate the window direction: */
        !           467:   direction = -1 + (((TME_SPARC_INSN & TME_BIT(19)) != 0) * 2);
        !           468: 
        !           469:   /* calculate the new CWP: */
        !           470:   psr = ic->tme_sparc32_ireg_psr;
        !           471:   cwp = TME_FIELD_MASK_EXTRACTU(psr, TME_SPARC32_PSR_CWP);
        !           472:   cwp += direction;
        !           473:   cwp %= ic->tme_sparc_nwindows;
        !           474: 
        !           475:   /* if the new window is invalid: */
        !           476:   if (__tme_predict_false((ic->tme_sparc32_ireg_wim & (((tme_uint32_t) 1) << cwp)) != 0)) {
        !           477:     TME_SPARC_INSN_TRAP((direction < 0)
        !           478:                        ? TME_SPARC_TRAP_window_overflow
        !           479:                        : TME_SPARC_TRAP_window_underflow);
        !           480:   }
        !           481: 
        !           482:   /* write the new PSR: */
        !           483:   TME_FIELD_MASK_DEPOSITU(psr, TME_SPARC32_PSR_CWP, cwp);
        !           484:   ic->tme_sparc32_ireg_psr = psr;
        !           485: 
        !           486:   /* set the new CWP offset: */
        !           487:   cwp_offset = TME_SPARC_CWP_OFFSET(cwp);
        !           488:   ic->tme_sparc_cwp_offset = cwp_offset;
        !           489: 
        !           490:   /* decode rd: */
        !           491:   reg_rd = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD);
        !           492:   TME_SPARC_REG_INDEX(ic, reg_rd);
        !           493: 
        !           494:   /* do the add: */
        !           495:   ic->tme_sparc_ireg_uint32(reg_rd) = TME_SPARC_FORMAT3_RS1 + TME_SPARC_FORMAT3_RS2;
        !           496: 
        !           497:   TME_SPARC_INSN_OK;
        !           498: }
        !           499: 
        !           500: TME_SPARC_FORMAT3(tme_sparc32_ticc, tme_uint32_t)
        !           501: {
        !           502:   tme_uint8_t conds_mask_icc;
        !           503:   tme_uint16_t conds_mask;
        !           504:   unsigned int cond;
        !           505: 
        !           506:   conds_mask_icc = _tme_sparc_conds_icc[TME_FIELD_MASK_EXTRACTU(ic->tme_sparc32_ireg_psr, TME_SPARC32_PSR_ICC)];
        !           507: 
        !           508:   /* add the not-conditions to the conditions mask: */
        !           509:   conds_mask = conds_mask_icc ^ 0xff;
        !           510:   conds_mask = (conds_mask << 8) | conds_mask_icc;
        !           511: 
        !           512:   /* get the condition field: */
        !           513:   cond = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, (0xf << 25));
        !           514: 
        !           515:   /* if this condition is true: */
        !           516:   if (conds_mask & TME_BIT(cond)) {
        !           517:     TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_trap_instruction((TME_SPARC_FORMAT3_RS1 + TME_SPARC_FORMAT3_RS2) & 0x7f));
        !           518:   }
        !           519: 
        !           520:   TME_SPARC_INSN_OK;
        !           521: }
        !           522: 
        !           523: TME_SPARC_FORMAT3(tme_sparc32_fpop1, tme_uint32_t)
        !           524: {
        !           525:   tme_sparc_fpu_fpop1(ic);
        !           526:   TME_SPARC_INSN_OK;
        !           527: }
        !           528: TME_SPARC_FORMAT3(tme_sparc32_fpop2, tme_uint32_t)
        !           529: {
        !           530:   tme_sparc_fpu_fpop2(ic);
        !           531:   TME_SPARC_INSN_OK;
        !           532: }
        !           533: 
        !           534: #include "sparc-insns-auto.c"

unix.superglobalmegacorp.com

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