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

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

unix.superglobalmegacorp.com

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