Annotation of kernel/machdep/ppc/alignment.c, revision 1.1

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

unix.superglobalmegacorp.com

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