Annotation of kernel/machdep/ppc/alignment.c, revision 1.1.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.