|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.