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