|
|
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.