Annotation of XNU/osfmk/ppc/alignment.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*
        !            23:  * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991  
        !            24:  *              All Rights Reserved 
        !            25:  *  
        !            26:  * Permission to use, copy, modify, and distribute this software and 
        !            27:  * its documentation for any purpose and without fee is hereby granted, 
        !            28:  * provided that the above copyright notice appears in all copies and 
        !            29:  * that both the copyright notice and this permission notice appear in 
        !            30:  * supporting documentation. 
        !            31:  *  
        !            32:  * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 
        !            33:  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
        !            34:  * FOR A PARTICULAR PURPOSE. 
        !            35:  *  
        !            36:  * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR 
        !            37:  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 
        !            38:  * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, 
        !            39:  * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 
        !            40:  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 
        !            41:  * 
        !            42:  */
        !            43: /*
        !            44:  * Copyright 1996 1995 by Apple Computer, Inc. 1997 1996 1995 1994 1993 1992 1991  
        !            45:  *              All Rights Reserved 
        !            46:  *  
        !            47:  * Permission to use, copy, modify, and distribute this software and 
        !            48:  * its documentation for any purpose and without fee is hereby granted, 
        !            49:  * provided that the above copyright notice appears in all copies and 
        !            50:  * that both the copyright notice and this permission notice appear in 
        !            51:  * supporting documentation. 
        !            52:  *  
        !            53:  * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 
        !            54:  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
        !            55:  * FOR A PARTICULAR PURPOSE. 
        !            56:  *  
        !            57:  * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR 
        !            58:  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 
        !            59:  * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, 
        !            60:  * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 
        !            61:  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 
        !            62:  */
        !            63: 
        !            64: #include <debug.h>
        !            65: #include <kern/thread_act.h>
        !            66: #include <mach/thread_status.h>
        !            67: #include <mach/boolean.h>
        !            68: #include <kern/misc_protos.h>
        !            69: #include <kern/simple_lock.h>
        !            70: #include <ppc/proc_reg.h>
        !            71: #include <ppc/fpu_protos.h>
        !            72: #include <ppc/misc_protos.h>
        !            73: #include <ppc/exception.h>
        !            74: 
        !            75: #if DEBUG
        !            76: /* These variable may be used to keep track of alignment exceptions */
        !            77: int alignment_exception_count_user;
        !            78: int alignment_exception_count_kernel;
        !            79: #endif
        !            80: 
        !            81: #define        _AINST(x)       boolean_t  align_##x##(unsigned long dsisr,\
        !            82:                                               struct ppc_saved_state *ssp, \
        !            83:                                               struct ppc_float_state *fsp, \
        !            84:                                               unsigned long *align_buffer, \
        !            85:                                               unsigned long dar)
        !            86: 
        !            87: 
        !            88: #define        _AFENTRY(name, r, b)    { #name, align_##name##, r, b, TRUE }
        !            89: #define        _AENTRY(name, r, b)     { #name, align_##name##, r, b, FALSE }
        !            90: #define        _ANIL                   { (void *) 0, (void *) 0, 0, 0 }
        !            91: 
        !            92: _AINST(lwz);
        !            93: _AINST(stw);
        !            94: _AINST(lhz);
        !            95: _AINST(lha);
        !            96: _AINST(sth);
        !            97: _AINST(lmw);
        !            98: _AINST(lfs);
        !            99: _AINST(lfd);
        !           100: _AINST(stfs);
        !           101: _AINST(stfd);
        !           102: _AINST(lwzu);
        !           103: _AINST(stwu);
        !           104: _AINST(lhzu);
        !           105: _AINST(lhau);
        !           106: _AINST(sthu);
        !           107: _AINST(lfsu);
        !           108: _AINST(lfdu);
        !           109: _AINST(stfsu);
        !           110: _AINST(stfdu);
        !           111: _AINST(lswx);
        !           112: _AINST(lswi);
        !           113: _AINST(lwbrx);
        !           114: _AINST(stwbrx);
        !           115: _AINST(lhbrx);
        !           116: _AINST(sthbrx);
        !           117: _AINST(dcbz);
        !           118: _AINST(lwzx);
        !           119: _AINST(stwx);
        !           120: _AINST(lhzx);
        !           121: _AINST(lhax);
        !           122: _AINST(sthx);
        !           123: _AINST(lfsx);
        !           124: _AINST(lfdx);
        !           125: _AINST(stfsx);
        !           126: _AINST(stfdx);
        !           127: _AINST(lwzux);
        !           128: _AINST(stwux);
        !           129: _AINST(lhzux);
        !           130: _AINST(lhaux);
        !           131: _AINST(sthux);
        !           132: _AINST(stmw);
        !           133: _AINST(lfsux);
        !           134: _AINST(lfdux);
        !           135: _AINST(stfsux);
        !           136: _AINST(stfdux);
        !           137: 
        !           138: /*
        !           139:  * Routines to set and get FPU registers.
        !           140:  */
        !           141: 
        !           142: void GET_FPU_REG(struct ppc_float_state *fsp,
        !           143:                 unsigned long reg,
        !           144:                 unsigned long *value);
        !           145: void SET_FPU_REG(struct ppc_float_state *fsp,
        !           146:                 unsigned long reg,
        !           147:                 unsigned long *value);
        !           148: 
        !           149: __inline__ void GET_FPU_REG(struct ppc_float_state *fsp,
        !           150:                            unsigned long reg,
        !           151:                            unsigned long *value)
        !           152: {
        !           153:        value[0] = ((unsigned long *) &fsp->fpregs[reg])[0];
        !           154:        value[1] = ((unsigned long *) &fsp->fpregs[reg])[1];
        !           155: }
        !           156: 
        !           157: __inline__ void SET_FPU_REG(struct ppc_float_state *fsp,
        !           158:                            unsigned long reg, unsigned long *value)
        !           159: {
        !           160:        ((unsigned long *) &fsp->fpregs[reg])[0] = value[0]; 
        !           161:        ((unsigned long *) &fsp->fpregs[reg])[1] = value[1];
        !           162: }
        !           163: 
        !           164: 
        !           165: /*
        !           166:  * Macros to load and set registers according to 
        !           167:  * a given cast type.
        !           168:  */
        !           169: 
        !           170: #define        GET_REG(p, reg, value, cast) \
        !           171:        { *((cast *) value) = *((cast *) (&p->r0+reg)); }
        !           172: #define        SET_REG(p, reg, value, cast) \
        !           173:        { *((cast *) (&p->r0+reg)) = *((cast *) value); }
        !           174: 
        !           175: /*
        !           176:  * Macros to help decode the DSISR.
        !           177:  */
        !           178: 
        !           179: #define        DSISR_BITS_15_16(bits)  ((bits>>15) & 0x3)
        !           180: #define        DSISR_BITS_17_21(bits)  ((bits>>10) & 0x1f)     
        !           181: #define        DSISR_BITS_REG(bits)    ((bits>>5) & 0x1f)
        !           182: #define        DSISR_BITS_RA(bits)     (bits & 0x1f)
        !           183: 
        !           184: 
        !           185: struct ppc_align_instruction {
        !           186:        char            *name;
        !           187:        boolean_t       (*a_instruct)(unsigned long,
        !           188:                                      struct ppc_saved_state *,
        !           189:                                      struct ppc_float_state *,
        !           190:                                      unsigned long *,
        !           191:                                      unsigned long );
        !           192:        int             a_readbytes;
        !           193:        int             a_writebytes;
        !           194:        boolean_t       a_is_float;
        !           195: } align_table00[] = {
        !           196: _AENTRY(lwz, 4, 0),    /* 00 0 0000 */
        !           197: _ANIL,                 /* 00 0 0001 */
        !           198: _AENTRY(stw, 0, 4),    /* 00 0 0010 */
        !           199: _ANIL,                 /* 00 0 0011 */
        !           200: _AENTRY(lhz, 2, 0),    /* 00 0 0100 */
        !           201: _AENTRY(lha, 2, 0),    /* 00 0 0101 */
        !           202: _AENTRY(sth, 0, 2),    /* 00 0 0110 */
        !           203: _AENTRY(lmw, 32*4,0),  /* 00 0 0111 */
        !           204: _AFENTRY(lfs, 4, 0),   /* 00 0 1000 */
        !           205: _AFENTRY(lfd, 8, 0),   /* 00 0 1001 */
        !           206: _AFENTRY(stfs, 0, 4),  /* 00 0 1010 */
        !           207: _AFENTRY(stfd, 0, 8),  /* 00 0 1011 */
        !           208: _ANIL,                 /* 00 0 1100 ?*/
        !           209: _ANIL,                 /* 00 0 1101 - lwa */
        !           210: _ANIL,                 /* 00 0 1110 ?*/
        !           211: _ANIL,                 /* 00 0 1111 - std */
        !           212: _AENTRY(lwzu, 4, 0),   /* 00 1 0000 */
        !           213: _ANIL,                 /* 00 1 0001 ?*/
        !           214: _AENTRY(stwu, 0, 4),   /* 00 1 0010 */
        !           215: _ANIL,                 /* 00 1 0011 */
        !           216: _AENTRY(lhzu, 2, 0),   /* 00 1 0100 */
        !           217: _AENTRY(lhau, 2, 0),   /* 00 1 0101 */
        !           218: _AENTRY(sthu, 0, 2),   /* 00 1 0110 */
        !           219: _AENTRY(stmw, 0, 0),   /* 00 1 0111 */
        !           220: _AFENTRY(lfsu, 4, 0),  /* 00 1 1000 */
        !           221: _AFENTRY(lfdu, 8, 0),  /* 00 1 1001 - lfdu */
        !           222: _AFENTRY(stfsu, 0, 4), /* 00 1 1010 */
        !           223: _AFENTRY(stfdu, 0, 8), /* 00 1 1011 - stfdu */
        !           224: };
        !           225: 
        !           226: struct ppc_align_instruction align_table01[] = {
        !           227: _ANIL,                 /* 01 0 0000 - ldx */
        !           228: _ANIL,                 /* 01 0 0001 ?*/
        !           229: _ANIL,                 /* 01 0 0010 - stdx */
        !           230: _ANIL,                 /* 01 0 0011 ?*/
        !           231: _ANIL,                 /* 01 0 0100 ?*/
        !           232: _ANIL,                 /* 01 0 0101 - lwax */
        !           233: _ANIL,                 /* 01 0 0110 ?*/
        !           234: _ANIL,                 /* 01 0 0111 ?*/
        !           235: _AENTRY(lswx,32, 0),   /* 01 0 1000 - lswx */
        !           236: _AENTRY(lswi,32, 0),   /* 01 0 1001 - lswi */
        !           237: _ANIL,                 /* 01 0 1010 - stswx */
        !           238: _ANIL,                 /* 01 0 1011 - stswi */
        !           239: _ANIL,                 /* 01 0 1100 ?*/
        !           240: _ANIL,                 /* 01 0 1101 ?*/
        !           241: _ANIL,                 /* 01 0 1110 ?*/
        !           242: _ANIL,                 /* 01 0 1111 ?*/
        !           243: _ANIL,                 /* 01 1 0000 - ldux */
        !           244: _ANIL,                 /* 01 1 0001 ?*/
        !           245: _ANIL,                 /* 01 1 0010 - stdux */
        !           246: _ANIL,                 /* 01 1 0011 ?*/
        !           247: _ANIL,                 /* 01 1 0100 ?*/
        !           248: _ANIL,                 /* 01 1 0101 - lwaux */
        !           249: };
        !           250: 
        !           251: struct ppc_align_instruction align_table10[] = {
        !           252: _ANIL,                 /* 10 0 0000 ?*/
        !           253: _ANIL,                 /* 10 0 0001 ?*/
        !           254: _ANIL,                 /* 10 0 0010 - stwcx. */
        !           255: _ANIL,                 /* 10 0 0011 - stdcx.*/
        !           256: _ANIL,                 /* 10 0 0100 ?*/
        !           257: _ANIL,                 /* 10 0 0101 ?*/
        !           258: _ANIL,                 /* 10 0 0110 ?*/
        !           259: _ANIL,                 /* 10 0 0111 ?*/
        !           260: _AENTRY(lwbrx, 2, 0),  /* 10 0 1000 */
        !           261: _ANIL,                 /* 10 0 1001 ?*/
        !           262: _AENTRY(stwbrx, 0, 4), /* 10 0 1010 */
        !           263: _ANIL,                 /* 10 0 1011 */
        !           264: _AENTRY(lhbrx, 2, 0),  /* 10 0 1110 */
        !           265: _ANIL,                 /* 10 0 1101 ?*/
        !           266: _AENTRY(sthbrx, 0, 2), /* 10 0 1110 */
        !           267: _ANIL,                 /* 10 0 1111 ?*/
        !           268: _ANIL,                 /* 10 1 0000 ?*/
        !           269: _ANIL,                 /* 10 1 0001 ?*/
        !           270: _ANIL,                 /* 10 1 0010 ?*/
        !           271: _ANIL,                 /* 10 1 0011 ?*/
        !           272: _ANIL,                 /* 10 1 0100 - eciwx */
        !           273: _ANIL,                 /* 10 1 0101 ?*/
        !           274: _ANIL,                 /* 10 1 0110 - ecowx */
        !           275: _ANIL,                 /* 10 1 0111 ?*/
        !           276: _ANIL,                 /* 10 1 1000 ?*/
        !           277: _ANIL,                 /* 10 1 1001 ?*/
        !           278: _ANIL,                 /* 10 1 1010 ?*/
        !           279: _ANIL,                 /* 10 1 1011 ?*/
        !           280: _ANIL,                 /* 10 1 1100 ?*/
        !           281: _ANIL,                 /* 10 1 1101 ?*/
        !           282: _ANIL,                 /* 10 1 1110 ?*/
        !           283: _AENTRY(dcbz, 0, 0),   /* 10 1 1111 */
        !           284: };
        !           285: 
        !           286: struct ppc_align_instruction align_table11[] = {
        !           287: _AENTRY(lwzx, 4, 0),   /* 11 0 0000 */
        !           288: _ANIL,                 /* 11 0 0001 ?*/
        !           289: _AENTRY(stwx, 0, 4),   /* 11 0 0010 */
        !           290: _ANIL,                 /* 11 0 0011 */
        !           291: _AENTRY(lhzx, 2, 0),   /* 11 0 0100 */
        !           292: _AENTRY(lhax, 2, 0),   /* 11 0 0101 */
        !           293: _AENTRY(sthx, 0, 2),   /* 11 0 0110 */
        !           294: _ANIL,                 /* 11 0 0111?*/
        !           295: _AFENTRY(lfsx, 4, 0),  /* 11 0 1000 */
        !           296: _AFENTRY(lfdx, 8, 0),  /* 11 0 1001 */
        !           297: _AFENTRY(stfsx, 0, 4), /* 11 0 1010 */
        !           298: _AFENTRY(stfdx, 0, 8), /* 11 0 1011 */
        !           299: _ANIL,                 /* 11 0 1100 ?*/
        !           300: _ANIL,                 /* 11 0 1101 ?*/
        !           301: _ANIL,                 /* 11 0 1110 ?*/
        !           302: _ANIL,                 /* 11 0 1111 - stfiwx */
        !           303: _AENTRY(lwzux, 4, 0),  /* 11 1 0000 */
        !           304: _ANIL,                 /* 11 1 0001 ?*/
        !           305: _AENTRY(stwux, 0, 4),  /* 11 1 0010 */
        !           306: _ANIL,                 /* 11 1 0011 */
        !           307: _AENTRY(lhzux, 4, 0),  /* 11 1 0100 */
        !           308: _AENTRY(lhaux, 4, 0),  /* 11 1 0101 */
        !           309: _AENTRY(sthux, 0, 4),  /* 11 1 0110 */
        !           310: _ANIL,                 /* 11 1 0111 ?*/
        !           311: _AFENTRY(lfsux, 4, 0), /* 11 1 1000 */
        !           312: _AFENTRY(lfdux, 0, 8), /* 11 1 1001 */
        !           313: _AFENTRY(stfsux, 0, 4),        /* 11 1 1010 */
        !           314: _AFENTRY(stfdux, 0, 8),        /* 11 1 1011 */
        !           315: };
        !           316: 
        !           317: 
        !           318: struct ppc_align_instruction_table {
        !           319:        struct ppc_align_instruction    *table;
        !           320:        int                             size;
        !           321: } align_tables[4] = {
        !           322:        align_table00,  sizeof(align_table00)/
        !           323:                        sizeof(struct ppc_align_instruction),
        !           324: 
        !           325:        align_table01,  sizeof(align_table01)/
        !           326:                        sizeof(struct ppc_align_instruction),
        !           327: 
        !           328:        align_table10,  sizeof(align_table10)/
        !           329:                        sizeof(struct ppc_align_instruction),
        !           330: 
        !           331:        align_table11,  sizeof(align_table11)/
        !           332:                        sizeof(struct ppc_align_instruction)
        !           333: };
        !           334: 
        !           335: extern int             real_ncpus;                                             /* Number of actual CPUs */
        !           336: 
        !           337: /*
        !           338:  * Alignment Exception Handler
        !           339:  *
        !           340:  *
        !           341:  * This handler is called when the chip attempts
        !           342:  * to execute an instruction which causes page
        !           343:  * boundaries to be crossed. Typically, this will
        !           344:  * happen on stfd* and lfd* instructions.
        !           345:  * (A request has been made for GNU C compiler
        !           346:  * NOT to make use of these instructions to 
        !           347:  * load and store 8 bytes at a time.)
        !           348:  *
        !           349:  * This is a *SLOW* handler. There is room for vast
        !           350:  * improvement. However, it is expected that alignment
        !           351:  * exceptions will be very infrequent.
        !           352:  *
        !           353:  * Not all of the 64 instructions (as listed in 
        !           354:  * PowerPC Microprocessor Family book under the Alignment
        !           355:  * Exception section) are handled yet.
        !           356:  * Only the most common ones which are expected to
        !           357:  * happen.
        !           358:  * 
        !           359:  * -- Michael Burg, Apple Computer, Inc. 1996
        !           360:  *
        !           361:  * TODO NMGS finish handler
        !           362:  */
        !           363: 
        !           364: boolean_t
        !           365: alignment(unsigned long dsisr, unsigned long dar,
        !           366:               struct ppc_saved_state *ssp)
        !           367: {
        !           368:        struct ppc_align_instruction_table      *table;
        !           369:        struct ppc_align_instruction            *entry;
        !           370:        struct ppc_float_state                          *fpc;
        !           371:        unsigned long           align_buffer[32];
        !           372:        boolean_t               success = FALSE;
        !           373:        thread_act_t act;
        !           374:        spl_t                   s;
        !           375:        int i;
        !           376: 
        !           377: #if    DEBUG
        !           378:        if (USER_MODE(ssp->srr1))       (void)hw_atomic_add(&alignment_exception_count_user, 1);
        !           379:        else                                            (void)hw_atomic_add(&alignment_exception_count_kernel, 1);
        !           380: #endif
        !           381: 
        !           382:        table = &align_tables[DSISR_BITS_15_16(dsisr)];
        !           383: 
        !           384:        if (table == (void *) 0
        !           385:        || table->size < DSISR_BITS_17_21(dsisr)) {
        !           386: #if    DEBUG
        !           387:                printf("EXCEPTION NOT HANDLED: Out of range.\n");
        !           388:                printf("dsisr=%X, dar=%X\n",dsisr, dar);
        !           389:                printf("table=%X\n",DSISR_BITS_15_16(dsisr));
        !           390:                printf("table->size=%X\n", table->size);
        !           391:                printf("entry=%X\n",DSISR_BITS_17_21(dsisr));
        !           392: #endif
        !           393:                goto out;
        !           394:        }
        !           395: 
        !           396:        entry = &table->table[DSISR_BITS_17_21(dsisr)];
        !           397: 
        !           398:        if (entry->a_instruct == (void *) 0) {
        !           399: #if    DEBUG
        !           400:                printf("EXCEPTION NOT HANDLED: Inst out of table range.\n");
        !           401:                printf("table=%X\n",DSISR_BITS_15_16(dsisr));
        !           402:                printf("entry=%X\n",DSISR_BITS_17_21(dsisr));
        !           403: #endif
        !           404:                goto out;
        !           405:        }
        !           406: 
        !           407:        /*
        !           408:         * Check to see if the instruction is a 
        !           409:         * floating point operation. Save off
        !           410:         * the FPU register set ...
        !           411:         */
        !           412: 
        !           413:        if (entry->a_is_float)
        !           414:                fpu_save();
        !           415: 
        !           416:        /*
        !           417:         * Pull in any bytes which are going to be
        !           418:         * read.
        !           419:         */
        !           420: 
        !           421:        if (entry->a_readbytes) {
        !           422:                if (USER_MODE(ssp->srr1)) {
        !           423:                        if (copyin((char *) dar,
        !           424:                                   (char *) align_buffer,
        !           425:                                   entry->a_readbytes)) {
        !           426:                                return  TRUE;
        !           427:                        }
        !           428:                } else {
        !           429:                        bcopy((char *) dar,
        !           430:                              (char *) align_buffer,
        !           431:                              entry->a_readbytes);
        !           432:                }
        !           433:        }
        !           434: 
        !           435: #if    0 && DEBUG
        !           436:        printf("Alignment exception: %s %d,0x%x (r%d/w%d) (tmp %x/%x)\n",
        !           437:               entry->name, DSISR_BITS_REG(dsisr),
        !           438:               dar, entry->a_readbytes, entry->a_writebytes, 
        !           439:               align_buffer[0], align_buffer[1]);
        !           440:        printf("    pc=(0x%08X), msr=(0x%X)",ssp->srr0, ssp->srr1);
        !           441: #endif
        !           442: 
        !           443:        act = current_act();                                            /* Get the current activation */
        !           444:        
        !           445:        success = entry->a_instruct(dsisr,
        !           446:                                    ssp,
        !           447:                                        find_user_fpu(act),                     /* Find this user's FPU state. NULL if none */
        !           448:                                                                                                /* NULL should never happen */
        !           449:                                    align_buffer,
        !           450:                                    dar);
        !           451: 
        !           452:        if (success) {
        !           453:                if (entry->a_writebytes) {
        !           454:                        if (USER_MODE(ssp->srr1)) {
        !           455:                                if (copyout((char *) align_buffer,
        !           456:                                            (char *) dar,
        !           457:                                            entry->a_writebytes)) {
        !           458:                                        return  TRUE;
        !           459:                                }
        !           460:                        } else {
        !           461:                                bcopy((char *) align_buffer,
        !           462:                                      (char *) dar,
        !           463:                                      entry->a_writebytes);
        !           464:                        }
        !           465:                }
        !           466:                else {
        !           467:                        for(i=0; i < real_ncpus; i++) {                                                 /* Cycle through processors */
        !           468:                                (void)hw_compare_and_store((unsigned int)act, 0, &per_proc_info[i].FPU_thread); /* Clear if ours */
        !           469:                        }
        !           470: 
        !           471:                        if (USER_MODE(ssp->srr1)) {
        !           472:                                if (copyout((char *) align_buffer,
        !           473:                                            (char *) dar,
        !           474:                                            entry->a_writebytes)) {
        !           475:                                        return  TRUE;
        !           476:                                }
        !           477:                        } else {
        !           478:                                bcopy((char *) align_buffer,
        !           479:                                      (char *) dar,
        !           480:                                      entry->a_writebytes);
        !           481:                        }
        !           482:                }
        !           483: 
        !           484:                ssp->srr0 += 4; /* Skip the instruction .. */
        !           485:        }
        !           486: 
        !           487:        return  !success;
        !           488: 
        !           489: out:
        !           490: #if    0 && DEBUG
        !           491:        printf("ALIGNMENT EXCEPTION: (dsisr 0x%x) table %d 0x%x\n",
        !           492:                dsisr, DSISR_BITS_15_16(dsisr), DSISR_BITS_17_21(dsisr));
        !           493: #endif
        !           494: 
        !           495:        return  TRUE;
        !           496: }
        !           497: 
        !           498: _AINST(lwz)
        !           499: {
        !           500:        SET_REG(ssp, DSISR_BITS_REG(dsisr), align_buffer, unsigned long);
        !           501: 
        !           502:        return  TRUE;
        !           503: }
        !           504: 
        !           505: _AINST(stw)
        !           506: {
        !           507:        GET_REG(ssp, DSISR_BITS_REG(dsisr), align_buffer, unsigned long);
        !           508: 
        !           509:        return  TRUE;
        !           510: }
        !           511: 
        !           512: _AINST(lhz)
        !           513: {
        !           514:        unsigned long value = *((unsigned short *) align_buffer);
        !           515: 
        !           516:        SET_REG(ssp, DSISR_BITS_REG(dsisr), &value, unsigned long);
        !           517: 
        !           518:        return  TRUE;
        !           519: }
        !           520: 
        !           521: _AINST(lha)
        !           522: {
        !           523:        long value = *((short *) align_buffer);
        !           524: 
        !           525:        SET_REG(ssp, DSISR_BITS_REG(dsisr), &value, unsigned long);
        !           526: 
        !           527:        return  TRUE;
        !           528: }
        !           529: 
        !           530: _AINST(sth)
        !           531: {
        !           532:        GET_REG(ssp, DSISR_BITS_REG(dsisr), align_buffer, unsigned short);
        !           533: 
        !           534:        return  TRUE;
        !           535: }
        !           536: 
        !           537: _AINST(lmw)
        !           538: {
        !           539:     int        i;
        !           540: 
        !           541:     for (i = 0; i < (32-DSISR_BITS_REG(dsisr)); i++)
        !           542:     {
        !           543:        SET_REG(ssp, DSISR_BITS_REG(dsisr)+i, &align_buffer[i], unsigned long);
        !           544:     }
        !           545:     return TRUE;
        !           546: }
        !           547: 
        !           548: struct fpsp {
        !           549:        unsigned long   s       :1;     /* Sign bit */
        !           550:        unsigned long   exp     :8;     /* exponent + bias */
        !           551:        unsigned long   fraction:23;    /* fraction */
        !           552: };
        !           553: typedef struct fpsp fpsp_t, *fpspPtr;
        !           554: 
        !           555: struct fpdp {
        !           556:        unsigned long   s       :1;     /* Sign bit */
        !           557:        unsigned long   exp     :11;    /* exponent + bias */
        !           558:        unsigned long   fraction:20;    /* fraction */
        !           559:        unsigned long   fraction1;      /* fraction */
        !           560: };
        !           561: typedef struct fpdp fpdp_t, *fpdpPtr;
        !           562: 
        !           563: 
        !           564: _AINST(lfs)
        !           565: {
        !           566:        unsigned long   lalign_buf[2];
        !           567: 
        !           568: 
        !           569:        lfs (align_buffer, lalign_buf);
        !           570:        SET_FPU_REG(fsp, DSISR_BITS_REG(dsisr), lalign_buf);
        !           571:        return  TRUE;
        !           572: }
        !           573: 
        !           574: _AINST(lfd)
        !           575: {
        !           576:        SET_FPU_REG(fsp, DSISR_BITS_REG(dsisr), align_buffer);
        !           577:        return  TRUE;
        !           578: }
        !           579: 
        !           580: _AINST(stfs)
        !           581: {
        !           582:        unsigned long   lalign_buf[2];
        !           583: 
        !           584: 
        !           585:        GET_FPU_REG(fsp, DSISR_BITS_REG(dsisr), lalign_buf);
        !           586:        stfs(lalign_buf, align_buffer);
        !           587:        return TRUE;
        !           588: }
        !           589: 
        !           590: _AINST(stfd)
        !           591: {
        !           592:        GET_FPU_REG(fsp, DSISR_BITS_REG(dsisr), align_buffer);
        !           593:        return TRUE;
        !           594: }
        !           595: 
        !           596: _AINST(lwzu)
        !           597: {
        !           598:        SET_REG(ssp, DSISR_BITS_REG(dsisr), align_buffer, unsigned long)
        !           599:        SET_REG(ssp, DSISR_BITS_RA(dsisr), &dar, unsigned long);
        !           600:        return TRUE;
        !           601: }
        !           602: 
        !           603: _AINST(stwu)
        !           604: {
        !           605:        GET_REG(ssp, DSISR_BITS_REG(dsisr), align_buffer, unsigned long)
        !           606:        SET_REG(ssp, DSISR_BITS_RA(dsisr), &dar, unsigned long);
        !           607:        return TRUE;
        !           608: }
        !           609: 
        !           610: 
        !           611: _AINST(lhzu)
        !           612: {
        !           613:        SET_REG(ssp, DSISR_BITS_REG(dsisr), align_buffer, unsigned short)
        !           614:        SET_REG(ssp, DSISR_BITS_RA(dsisr), &dar, unsigned long);
        !           615:        return TRUE;
        !           616: }
        !           617: 
        !           618: _AINST(lhau)
        !           619: {
        !           620:        unsigned long   value = *((short *) align_buffer);
        !           621: 
        !           622:        SET_REG(ssp, DSISR_BITS_REG(dsisr), &value, unsigned long);
        !           623:        SET_REG(ssp, DSISR_BITS_RA(dsisr), &dar, unsigned long);
        !           624: 
        !           625:        return  TRUE;
        !           626: }
        !           627: 
        !           628: _AINST(sthu)
        !           629: {
        !           630:        GET_REG(ssp, DSISR_BITS_REG(dsisr), align_buffer, unsigned short)
        !           631:        SET_REG(ssp, DSISR_BITS_RA(dsisr), &dar, unsigned long);
        !           632:        return  TRUE;
        !           633: }
        !           634: 
        !           635: _AINST(stmw)
        !           636: {
        !           637:     int        i, rS = DSISR_BITS_REG(dsisr);
        !           638:     int numRegs = 32 - rS;
        !           639:     int numBytes = numRegs * 4;
        !           640:     int retval;
        !           641: 
        !           642: 
        !           643:     for (i = 0; i < numRegs; i++)
        !           644:     {
        !           645: #if 0
        !           646:        printf("    align_buffer[%d] == 0x%x\n",i,align_buffer[i]);
        !           647: #endif
        !           648:        GET_REG(ssp, rS+i, &align_buffer[i], unsigned long);
        !           649: #if 0
        !           650:        printf("    now align_buffer[%d] == 0x%x\n",i,align_buffer[i]);
        !           651: #endif
        !           652:     }
        !           653:     if (USER_MODE(ssp->srr1)) {
        !           654:        if ((retval=copyout((char *)align_buffer,(char *)dar,numBytes)) != 0) {
        !           655:            return FALSE;
        !           656:        }
        !           657: #if 0
        !           658:        printf("    copyout(%X, %X, %X) succeeded\n",align_buffer,dar,numBytes);
        !           659: #endif
        !           660:     }
        !           661:     else {
        !           662:        bcopy((char *) align_buffer, (char *) dar, numBytes);
        !           663:     }
        !           664:     return TRUE;
        !           665: }
        !           666: 
        !           667: _AINST(lfsu)
        !           668: {
        !           669:        unsigned long   lalign_buf[2];
        !           670: 
        !           671: 
        !           672:        lfs (align_buffer, lalign_buf);
        !           673:        SET_FPU_REG(fsp, DSISR_BITS_REG(dsisr), lalign_buf);
        !           674:        SET_REG(ssp, DSISR_BITS_RA(dsisr), &dar, unsigned long);
        !           675:        return  TRUE;
        !           676: }
        !           677: 
        !           678: _AINST(lfdu)
        !           679: {
        !           680:        SET_FPU_REG(fsp, DSISR_BITS_REG(dsisr), align_buffer);
        !           681:        SET_REG(ssp, DSISR_BITS_RA(dsisr), &dar, unsigned long);
        !           682: 
        !           683:        return  TRUE;
        !           684: }
        !           685: 
        !           686: _AINST(stfsu)
        !           687: {
        !           688:        unsigned long   lalign_buf[2];
        !           689: 
        !           690: 
        !           691:        GET_FPU_REG(fsp, DSISR_BITS_REG(dsisr), lalign_buf);
        !           692:        stfs(lalign_buf, align_buffer);
        !           693:        SET_REG(ssp, DSISR_BITS_RA(dsisr), &dar, unsigned long);
        !           694:        return  TRUE;
        !           695: }
        !           696: 
        !           697: 
        !           698: _AINST(stfdu)
        !           699: {
        !           700:        GET_FPU_REG(fsp, DSISR_BITS_REG(dsisr), align_buffer);
        !           701:        SET_REG(ssp, DSISR_BITS_RA(dsisr), &dar, unsigned long);
        !           702: 
        !           703:        return  TRUE;
        !           704: }
        !           705: 
        !           706: _AINST(lswx)
        !           707: {
        !           708:     int        i, nb, nr, inst, zero = 0;
        !           709: 
        !           710: 
        !           711:     /* check for invalid form of instruction */
        !           712:     if (DSISR_BITS_RA(dsisr) >= DSISR_BITS_REG(dsisr) )
        !           713:        return FALSE;
        !           714: 
        !           715:     if (USER_MODE(ssp->srr1)) {
        !           716:        if (copyin((char *) ssp->srr0, (char *) &inst, 4 )) {
        !           717:        return  FALSE;
        !           718:        }
        !           719:     } else {
        !           720:        bcopy((char *) ssp->srr0, (char *) &inst, 4 );
        !           721:     }
        !           722:        
        !           723:     nb = (inst >> 11) & 0x1F;  /* get the number of bytes in the instr */
        !           724:     nr = (nb + sizeof(long)-1) / sizeof(long);/* get the number of regs to copy */
        !           725: 
        !           726:     if ((nr + DSISR_BITS_REG(dsisr)) > 31)
        !           727:        return FALSE;           /* not supported yet */
        !           728: 
        !           729:     for (i = 0; i < nr; i++)
        !           730:     {
        !           731:        SET_REG(ssp, DSISR_BITS_REG(dsisr)+i, &zero, unsigned long);
        !           732:     }
        !           733:     /* copy the string into the save state */
        !           734:     bcopy((char *) align_buffer, (char *) ssp->r0+DSISR_BITS_REG(dsisr), nb );
        !           735:     return TRUE;
        !           736: }
        !           737: 
        !           738: _AINST(lswi)
        !           739: {
        !           740:     int        i, nb, nr, inst, zero = 0;
        !           741: 
        !           742: 
        !           743:     /* check for invalid form of instruction */
        !           744:     if (DSISR_BITS_RA(dsisr) >= DSISR_BITS_REG(dsisr) )
        !           745:        return FALSE;
        !           746: 
        !           747:     if (USER_MODE(ssp->srr1)) {
        !           748:        if (copyin((char *) ssp->srr0, (char *) &inst, 4 )) {
        !           749:        return  FALSE;
        !           750:        }
        !           751:     } else {
        !           752:        bcopy((char *) ssp->srr0, (char *) &inst, 4 );
        !           753:     }
        !           754:        
        !           755:     nb = (inst >> 11) & 0x1F;  /* get the number of bytes in the instr */
        !           756:     nr = (nb + sizeof(long)-1) / sizeof(long);/* get the number of regs to copy */
        !           757: 
        !           758:     if ((nr + DSISR_BITS_REG(dsisr)) > 31)
        !           759:        return FALSE;           /* not supported yet */
        !           760: 
        !           761:     for (i = 0; i < nr; i++)
        !           762:     {
        !           763:        SET_REG(ssp, DSISR_BITS_REG(dsisr)+i, &zero, unsigned long);
        !           764:     }
        !           765:     /* copy the string into the save state */
        !           766:     bcopy((char *) align_buffer, (char *) ssp->r0+DSISR_BITS_REG(dsisr), nb );
        !           767:     return TRUE;
        !           768: }
        !           769: 
        !           770: _AINST(stswx)
        !           771: {
        !           772:        return  FALSE;
        !           773: }
        !           774: 
        !           775: _AINST(stswi)
        !           776: {
        !           777:        return  FALSE;
        !           778: }
        !           779: 
        !           780: 
        !           781: 
        !           782: 
        !           783: 
        !           784: 
        !           785: 
        !           786: _AINST(stwcx)
        !           787: {
        !           788:        return  FALSE;
        !           789: }
        !           790: 
        !           791: _AINST(stdcx)
        !           792: {
        !           793:        return  FALSE;
        !           794: }
        !           795: 
        !           796: _AINST(lwbrx)
        !           797: {
        !           798:        unsigned long   new_value;
        !           799: 
        !           800:        __asm__ volatile("lwbrx %0,0,%1" : : "b" (new_value),
        !           801:                        "b" (&align_buffer[0]));
        !           802: 
        !           803:        SET_REG(ssp, DSISR_BITS_REG(dsisr), &new_value, unsigned long);
        !           804: 
        !           805:        return  TRUE;
        !           806: }
        !           807: 
        !           808: _AINST(stwbrx)
        !           809: {
        !           810:        unsigned long   value;
        !           811: 
        !           812:        GET_REG(ssp, DSISR_BITS_REG(dsisr), &value, unsigned long);
        !           813:        __asm__ volatile("stwbrx        %0,0,%1" : : "b" (value), "b" (&align_buffer[0]));
        !           814: 
        !           815:        return  TRUE;
        !           816: }
        !           817: 
        !           818: _AINST(lhbrx)
        !           819: {
        !           820:        unsigned short  value;
        !           821: 
        !           822:        __asm__ volatile("lhbrx %0,0,%1" : : "b" (value), "b" (&align_buffer[0]));
        !           823: 
        !           824:        SET_REG(ssp, DSISR_BITS_REG(dsisr), &value, unsigned short);
        !           825: 
        !           826:        return  TRUE;
        !           827: }
        !           828: 
        !           829: _AINST(sthbrx)
        !           830: {
        !           831:        unsigned short value;
        !           832: 
        !           833:        GET_REG(ssp, DSISR_BITS_REG(dsisr), &value, unsigned short);
        !           834:        __asm__ volatile("sthbrx %0,0,%1" : : "b" (value), "b" (&align_buffer[0]));
        !           835: 
        !           836:        return  TRUE;
        !           837: }
        !           838: 
        !           839: _AINST(eciwx)
        !           840: {
        !           841:        return  FALSE;
        !           842: }
        !           843: 
        !           844: _AINST(ecowx)
        !           845: {
        !           846:        return  FALSE;
        !           847: }
        !           848: 
        !           849: _AINST(dcbz)
        !           850: {
        !           851:     long *alignedDAR = (long *)((long)dar & ~(CACHE_LINE_SIZE-1));
        !           852: 
        !           853: 
        !           854:     if (USER_MODE(ssp->srr1)) {
        !           855: 
        !           856:            align_buffer[0] = 0;
        !           857:            align_buffer[1] = 0;
        !           858:            align_buffer[2] = 0;
        !           859:            align_buffer[3] = 0;
        !           860:            align_buffer[4] = 0;
        !           861:            align_buffer[5] = 0;
        !           862:            align_buffer[6] = 0;
        !           863:            align_buffer[7] = 0;
        !           864: 
        !           865:        if (copyout((char *)align_buffer,(char *)alignedDAR,CACHE_LINE_SIZE) != 0)
        !           866:            return FALSE;
        !           867:     } else {
        !           868:            /* Cannot use bcopy here just in case it caused the exception */
        !           869:            alignedDAR[0] = 0;
        !           870:            alignedDAR[1] = 0;
        !           871:            alignedDAR[2] = 0;
        !           872:            alignedDAR[3] = 0;
        !           873:            alignedDAR[4] = 0;
        !           874:            alignedDAR[5] = 0;
        !           875:            alignedDAR[6] = 0;
        !           876:            alignedDAR[7] = 0;
        !           877:     }
        !           878:     return     TRUE;
        !           879: }
        !           880: 
        !           881: 
        !           882: 
        !           883: 
        !           884: 
        !           885: 
        !           886: 
        !           887: _AINST(lwzx)
        !           888: {
        !           889:        SET_REG(ssp, DSISR_BITS_REG(dsisr), &align_buffer[0], unsigned long);
        !           890: 
        !           891:        return  TRUE;
        !           892: }
        !           893: 
        !           894: _AINST(stwx)
        !           895: {
        !           896:        GET_REG(ssp, DSISR_BITS_REG(dsisr), &align_buffer[0], unsigned long);
        !           897: 
        !           898:        return  TRUE;
        !           899: }
        !           900: 
        !           901: _AINST(lhzx)
        !           902: {
        !           903:        SET_REG(ssp, DSISR_BITS_REG(dsisr), &align_buffer[0], unsigned short);
        !           904: 
        !           905:        return  TRUE;
        !           906: }
        !           907: 
        !           908: _AINST(lhax)
        !           909: {
        !           910:        unsigned long   value   = *((short *) &align_buffer[0]);
        !           911: 
        !           912:        SET_REG(ssp, DSISR_BITS_REG(dsisr), &value, unsigned long);
        !           913: 
        !           914:        return  TRUE;
        !           915: }
        !           916: 
        !           917: _AINST(sthx)
        !           918: {
        !           919:        GET_REG(ssp, DSISR_BITS_REG(dsisr), &align_buffer[0], unsigned short);
        !           920: 
        !           921:        return  TRUE;
        !           922: }
        !           923: 
        !           924: _AINST(lfsx)
        !           925: {
        !           926:        long    lalign_buf[2];
        !           927: 
        !           928: 
        !           929:        lfs (align_buffer, lalign_buf);
        !           930:        SET_FPU_REG(fsp, DSISR_BITS_REG(dsisr), lalign_buf);
        !           931:        return  TRUE;
        !           932: }
        !           933: 
        !           934: _AINST(lfdx)
        !           935: {
        !           936:        SET_FPU_REG(fsp, DSISR_BITS_REG(dsisr), align_buffer);
        !           937: 
        !           938:        return  TRUE;
        !           939: }
        !           940: 
        !           941: _AINST(stfsx)
        !           942: {
        !           943:        long    lalign_buf[2];
        !           944: 
        !           945: 
        !           946:        GET_FPU_REG(fsp, DSISR_BITS_REG(dsisr), lalign_buf);
        !           947:        stfs(lalign_buf, align_buffer);
        !           948:        return  TRUE;
        !           949: }
        !           950: 
        !           951: _AINST(stfdx)
        !           952: {
        !           953:        GET_FPU_REG(fsp, DSISR_BITS_REG(dsisr), align_buffer);
        !           954: 
        !           955:        return  TRUE;
        !           956: }
        !           957: 
        !           958: _AINST(lwzux)
        !           959: {
        !           960:        SET_REG(ssp, DSISR_BITS_REG(dsisr), &align_buffer[0], unsigned long);
        !           961:        SET_REG(ssp, DSISR_BITS_RA(dsisr), &dar, unsigned long);
        !           962: 
        !           963:        return  TRUE;
        !           964: }
        !           965: 
        !           966: _AINST(stwux)
        !           967: {
        !           968:        GET_REG(ssp, DSISR_BITS_REG(dsisr), &align_buffer[0], unsigned long);
        !           969:        SET_REG(ssp, DSISR_BITS_RA(dsisr), &dar, unsigned long);
        !           970: 
        !           971:        return  TRUE;
        !           972: }
        !           973: 
        !           974: _AINST(lhzux)
        !           975: {
        !           976:        unsigned long value = *((unsigned short *)&align_buffer[0]);
        !           977: 
        !           978:        SET_REG(ssp, DSISR_BITS_REG(dsisr), &value, unsigned long);
        !           979:        SET_REG(ssp, DSISR_BITS_RA(dsisr), &dar, unsigned long);
        !           980: 
        !           981:        return  TRUE;
        !           982: }
        !           983: 
        !           984: _AINST(lhaux)
        !           985: {
        !           986:        long value = *((short *) &align_buffer[0]);
        !           987: 
        !           988:        SET_REG(ssp, DSISR_BITS_REG(dsisr), &value, unsigned long);
        !           989:        SET_REG(ssp, DSISR_BITS_RA(dsisr), &dar, unsigned long);
        !           990: 
        !           991:        return  TRUE;
        !           992: }
        !           993: 
        !           994: _AINST(sthux)
        !           995: {
        !           996:        GET_REG(ssp, DSISR_BITS_REG(dsisr), &align_buffer[0], unsigned short);
        !           997:        SET_REG(ssp, DSISR_BITS_RA(dsisr), &dar, unsigned long);
        !           998: 
        !           999:        return  TRUE;
        !          1000: }
        !          1001: 
        !          1002: _AINST(lfsux)
        !          1003: {
        !          1004:        long    lalign_buf[2];
        !          1005: 
        !          1006: 
        !          1007:        lfs (align_buffer, lalign_buf);
        !          1008:        SET_FPU_REG(fsp, DSISR_BITS_REG(dsisr), lalign_buf);
        !          1009:        SET_REG(ssp, DSISR_BITS_RA(dsisr), &dar, unsigned long);
        !          1010:        return  TRUE;
        !          1011: }
        !          1012: 
        !          1013: _AINST(lfdux)
        !          1014: {
        !          1015:        SET_FPU_REG(fsp, DSISR_BITS_REG(dsisr), &align_buffer[0]);
        !          1016:        SET_REG(ssp, DSISR_BITS_RA(dsisr), &dar, unsigned long);
        !          1017: 
        !          1018:        return  TRUE;
        !          1019: }
        !          1020: 
        !          1021: 
        !          1022: _AINST(stfsux)
        !          1023: {
        !          1024:        long    lalign_buf[2];
        !          1025: 
        !          1026: 
        !          1027:        GET_FPU_REG(fsp, DSISR_BITS_REG(dsisr), lalign_buf);
        !          1028:        stfs(lalign_buf, align_buffer);
        !          1029:        SET_REG(ssp, DSISR_BITS_RA(dsisr), &dar, unsigned long);
        !          1030:        return  TRUE;
        !          1031: }
        !          1032: 
        !          1033: _AINST(stfdux)
        !          1034: {
        !          1035:        GET_FPU_REG(fsp, DSISR_BITS_REG(dsisr), &align_buffer[0]);
        !          1036:        SET_REG(ssp, DSISR_BITS_RA(dsisr), &dar, unsigned long);
        !          1037: 
        !          1038:        return  TRUE;
        !          1039: }

unix.superglobalmegacorp.com

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