2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991
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.
32 * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
33 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
34 * FOR A PARTICULAR PURPOSE.
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.
44 * Copyright 1996 1995 by Apple Computer, Inc. 1997 1996 1995 1994 1993 1992 1991
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.
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.
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.
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>
76 /* These variable may be used to keep track of alignment exceptions */
77 int alignment_exception_count_user
;
78 int alignment_exception_count_kernel
;
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, \
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 }
139 * Routines to set and get FPU registers.
142 void GET_FPU_REG(struct ppc_float_state
*fsp
,
144 unsigned long *value
);
145 void SET_FPU_REG(struct ppc_float_state
*fsp
,
147 unsigned long *value
);
149 __inline__
void GET_FPU_REG(struct ppc_float_state
*fsp
,
151 unsigned long *value
)
153 value
[0] = ((unsigned long *) &fsp
->fpregs
[reg
])[0];
154 value
[1] = ((unsigned long *) &fsp
->fpregs
[reg
])[1];
157 __inline__
void SET_FPU_REG(struct ppc_float_state
*fsp
,
158 unsigned long reg
, unsigned long *value
)
160 ((unsigned long *) &fsp
->fpregs
[reg
])[0] = value
[0];
161 ((unsigned long *) &fsp
->fpregs
[reg
])[1] = value
[1];
166 * Macros to load and set registers according to
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); }
176 * Macros to help decode the DSISR.
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)
185 struct ppc_align_instruction
{
187 boolean_t (*a_instruct
)(unsigned long,
188 struct ppc_saved_state
*,
189 struct ppc_float_state
*,
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 */
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 */
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
, 4, 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 */
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
, 8, 0), /* 11 1 1001 */
313 _AFENTRY(stfsux
, 0, 4), /* 11 1 1010 */
314 _AFENTRY(stfdux
, 0, 8), /* 11 1 1011 */
318 struct ppc_align_instruction_table
{
319 struct ppc_align_instruction
*table
;
321 } align_tables
[4] = {
322 align_table00
, sizeof(align_table00
)/
323 sizeof(struct ppc_align_instruction
),
325 align_table01
, sizeof(align_table01
)/
326 sizeof(struct ppc_align_instruction
),
328 align_table10
, sizeof(align_table10
)/
329 sizeof(struct ppc_align_instruction
),
331 align_table11
, sizeof(align_table11
)/
332 sizeof(struct ppc_align_instruction
)
335 extern int real_ncpus
; /* Number of actual CPUs */
338 * Alignment Exception Handler
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.)
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.
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
359 * -- Michael Burg, Apple Computer, Inc. 1996
361 * TODO NMGS finish handler
365 alignment(unsigned long dsisr
, unsigned long dar
,
366 struct ppc_saved_state
*ssp
)
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
;
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);
382 act
= current_act(); /* Get the current activation */
384 table
= &align_tables
[DSISR_BITS_15_16(dsisr
)];
386 if (table
== (void *) 0
387 || table
->size
< DSISR_BITS_17_21(dsisr
)) {
389 printf("EXCEPTION NOT HANDLED: Out of range.\n");
390 printf("dsisr=%X, dar=%X\n",dsisr
, dar
);
391 printf("table=%X\n",DSISR_BITS_15_16(dsisr
));
392 printf("table->size=%X\n", table
->size
);
393 printf("entry=%X\n",DSISR_BITS_17_21(dsisr
));
398 entry
= &table
->table
[DSISR_BITS_17_21(dsisr
)];
400 if (entry
->a_instruct
== (void *) 0) {
402 printf("EXCEPTION NOT HANDLED: Inst out of table range.\n");
403 printf("table=%X\n",DSISR_BITS_15_16(dsisr
));
404 printf("entry=%X\n",DSISR_BITS_17_21(dsisr
));
410 * Check to see if the instruction is a
411 * floating point operation. Save off
412 * the FPU register set ...
415 if (entry
->a_is_float
)
419 * Pull in any bytes which are going to be
423 if (entry
->a_readbytes
) {
424 if (USER_MODE(ssp
->srr1
)) {
425 if (copyin((char *) dar
,
426 (char *) align_buffer
,
427 entry
->a_readbytes
)) {
432 (char *) align_buffer
,
438 printf("Alignment exception: %s %d,0x%x (r%d/w%d) (tmp %x/%x)\n",
439 entry
->name
, DSISR_BITS_REG(dsisr
),
440 dar
, entry
->a_readbytes
, entry
->a_writebytes
,
441 align_buffer
[0], align_buffer
[1]);
442 printf(" pc=(0x%08X), msr=(0x%X)",ssp
->srr0
, ssp
->srr1
);
446 success
= entry
->a_instruct(dsisr
,
448 (entry
->a_is_float
? find_user_fpu(act
) : 0), /* Find this user's FPU state if FP op */
453 if (entry
->a_writebytes
) {
454 if (USER_MODE(ssp
->srr1
)) {
455 if (copyout((char *) align_buffer
,
457 entry
->a_writebytes
)) {
461 bcopy((char *) align_buffer
,
463 entry
->a_writebytes
);
467 if(entry
->a_is_float
) { /* If we are an FP op, blow away live context */
468 for(i
=0; i
< real_ncpus
; i
++) { /* Cycle through processors */
469 (void)hw_compare_and_store((unsigned int)act
, 0, &per_proc_info
[i
].FPU_thread
); /* Clear if ours */
473 if (USER_MODE(ssp
->srr1
)) {
474 if (copyout((char *) align_buffer
,
476 entry
->a_writebytes
)) {
480 bcopy((char *) align_buffer
,
482 entry
->a_writebytes
);
486 ssp
->srr0
+= 4; /* Skip the instruction .. */
493 printf("ALIGNMENT EXCEPTION: (dsisr 0x%x) table %d 0x%x\n",
494 dsisr
, DSISR_BITS_15_16(dsisr
), DSISR_BITS_17_21(dsisr
));
502 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), align_buffer
, unsigned long);
509 GET_REG(ssp
, DSISR_BITS_REG(dsisr
), align_buffer
, unsigned long);
516 unsigned long value
= *((unsigned short *) align_buffer
);
518 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), &value
, unsigned long);
525 long value
= *((short *) align_buffer
);
527 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), &value
, unsigned long);
534 GET_REG(ssp
, DSISR_BITS_REG(dsisr
), align_buffer
, unsigned short);
543 for (i
= 0; i
< (32-DSISR_BITS_REG(dsisr
)); i
++)
545 SET_REG(ssp
, DSISR_BITS_REG(dsisr
)+i
, &align_buffer
[i
], unsigned long);
551 unsigned long s
:1; /* Sign bit */
552 unsigned long exp
:8; /* exponent + bias */
553 unsigned long fraction
:23; /* fraction */
555 typedef struct fpsp fpsp_t
, *fpspPtr
;
558 unsigned long s
:1; /* Sign bit */
559 unsigned long exp
:11; /* exponent + bias */
560 unsigned long fraction
:20; /* fraction */
561 unsigned long fraction1
; /* fraction */
563 typedef struct fpdp fpdp_t
, *fpdpPtr
;
568 unsigned long lalign_buf
[2];
571 lfs (align_buffer
, lalign_buf
);
572 SET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), lalign_buf
);
578 SET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), align_buffer
);
584 unsigned long lalign_buf
[2];
587 GET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), lalign_buf
);
588 stfs(lalign_buf
, align_buffer
);
594 GET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), align_buffer
);
600 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), align_buffer
, unsigned long)
601 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
607 GET_REG(ssp
, DSISR_BITS_REG(dsisr
), align_buffer
, unsigned long)
608 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
615 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), align_buffer
, unsigned short)
616 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
622 unsigned long value
= *((short *) align_buffer
);
624 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), &value
, unsigned long);
625 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
632 GET_REG(ssp
, DSISR_BITS_REG(dsisr
), align_buffer
, unsigned short)
633 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
639 int i
, rS
= DSISR_BITS_REG(dsisr
);
640 int numRegs
= 32 - rS
;
641 int numBytes
= numRegs
* 4;
645 for (i
= 0; i
< numRegs
; i
++)
648 printf(" align_buffer[%d] == 0x%x\n",i
,align_buffer
[i
]);
650 GET_REG(ssp
, rS
+i
, &align_buffer
[i
], unsigned long);
652 printf(" now align_buffer[%d] == 0x%x\n",i
,align_buffer
[i
]);
655 if (USER_MODE(ssp
->srr1
)) {
656 if ((retval
=copyout((char *)align_buffer
,(char *)dar
,numBytes
)) != 0) {
660 printf(" copyout(%X, %X, %X) succeeded\n",align_buffer
,dar
,numBytes
);
664 bcopy((char *) align_buffer
, (char *) dar
, numBytes
);
671 unsigned long lalign_buf
[2];
674 lfs (align_buffer
, lalign_buf
);
675 SET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), lalign_buf
);
676 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
682 SET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), align_buffer
);
683 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
690 unsigned long lalign_buf
[2];
693 GET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), lalign_buf
);
694 stfs(lalign_buf
, align_buffer
);
695 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
702 GET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), align_buffer
);
703 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
710 int i
, nb
, nr
, inst
, zero
= 0;
713 /* check for invalid form of instruction */
714 if (DSISR_BITS_RA(dsisr
) >= DSISR_BITS_REG(dsisr
) )
717 if (USER_MODE(ssp
->srr1
)) {
718 if (copyin((char *) ssp
->srr0
, (char *) &inst
, 4 )) {
722 bcopy((char *) ssp
->srr0
, (char *) &inst
, 4 );
725 nb
= (inst
>> 11) & 0x1F; /* get the number of bytes in the instr */
726 nr
= (nb
+ sizeof(long)-1) / sizeof(long);/* get the number of regs to copy */
728 if ((nr
+ DSISR_BITS_REG(dsisr
)) > 31)
729 return FALSE
; /* not supported yet */
731 for (i
= 0; i
< nr
; i
++)
733 SET_REG(ssp
, DSISR_BITS_REG(dsisr
)+i
, &zero
, unsigned long);
735 /* copy the string into the save state */
736 bcopy((char *) align_buffer
, (char *) ssp
->r0
+DSISR_BITS_REG(dsisr
), nb
);
742 int i
, nb
, nr
, inst
, zero
= 0;
745 /* check for invalid form of instruction */
746 if (DSISR_BITS_RA(dsisr
) >= DSISR_BITS_REG(dsisr
) )
749 if (USER_MODE(ssp
->srr1
)) {
750 if (copyin((char *) ssp
->srr0
, (char *) &inst
, 4 )) {
754 bcopy((char *) ssp
->srr0
, (char *) &inst
, 4 );
757 nb
= (inst
>> 11) & 0x1F; /* get the number of bytes in the instr */
758 nr
= (nb
+ sizeof(long)-1) / sizeof(long);/* get the number of regs to copy */
760 if ((nr
+ DSISR_BITS_REG(dsisr
)) > 31)
761 return FALSE
; /* not supported yet */
763 for (i
= 0; i
< nr
; i
++)
765 SET_REG(ssp
, DSISR_BITS_REG(dsisr
)+i
, &zero
, unsigned long);
767 /* copy the string into the save state */
768 bcopy((char *) align_buffer
, (char *) ssp
->r0
+DSISR_BITS_REG(dsisr
), nb
);
800 unsigned long new_value
;
802 __asm__
volatile("lwbrx %0,0,%1" : : "b" (new_value
),
803 "b" (&align_buffer
[0]));
805 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), &new_value
, unsigned long);
814 GET_REG(ssp
, DSISR_BITS_REG(dsisr
), &value
, unsigned long);
815 __asm__
volatile("stwbrx %0,0,%1" : : "b" (value
), "b" (&align_buffer
[0]));
822 unsigned short value
;
824 __asm__
volatile("lhbrx %0,0,%1" : : "b" (value
), "b" (&align_buffer
[0]));
826 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), &value
, unsigned short);
833 unsigned short value
;
835 GET_REG(ssp
, DSISR_BITS_REG(dsisr
), &value
, unsigned short);
836 __asm__
volatile("sthbrx %0,0,%1" : : "b" (value
), "b" (&align_buffer
[0]));
853 long *alignedDAR
= (long *)((long)dar
& ~(CACHE_LINE_SIZE
-1));
856 if (USER_MODE(ssp
->srr1
)) {
867 if (copyout((char *)align_buffer
,(char *)alignedDAR
,CACHE_LINE_SIZE
) != 0)
870 /* Cannot use bcopy here just in case it caused the exception */
891 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), &align_buffer
[0], unsigned long);
898 GET_REG(ssp
, DSISR_BITS_REG(dsisr
), &align_buffer
[0], unsigned long);
905 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), &align_buffer
[0], unsigned short);
912 unsigned long value
= *((short *) &align_buffer
[0]);
914 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), &value
, unsigned long);
921 GET_REG(ssp
, DSISR_BITS_REG(dsisr
), &align_buffer
[0], unsigned short);
931 lfs (align_buffer
, lalign_buf
);
932 SET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), lalign_buf
);
938 SET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), align_buffer
);
948 GET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), lalign_buf
);
949 stfs(lalign_buf
, align_buffer
);
955 GET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), align_buffer
);
962 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), &align_buffer
[0], unsigned long);
963 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
970 GET_REG(ssp
, DSISR_BITS_REG(dsisr
), &align_buffer
[0], unsigned long);
971 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
978 unsigned long value
= *((unsigned short *)&align_buffer
[0]);
980 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), &value
, unsigned long);
981 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
988 long value
= *((short *) &align_buffer
[0]);
990 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), &value
, unsigned long);
991 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
998 GET_REG(ssp
, DSISR_BITS_REG(dsisr
), &align_buffer
[0], unsigned short);
999 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
1009 lfs (align_buffer
, lalign_buf
);
1010 SET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), lalign_buf
);
1011 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
1017 SET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), &align_buffer
[0]);
1018 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
1029 GET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), lalign_buf
);
1030 stfs(lalign_buf
, align_buffer
);
1031 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
1037 GET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), &align_buffer
[0]);
1038 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);