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