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
, 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 */
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 */
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 table
= &align_tables
[DSISR_BITS_15_16(dsisr
)];
384 if (table
== (void *) 0
385 || table
->size
< DSISR_BITS_17_21(dsisr
)) {
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
));
396 entry
= &table
->table
[DSISR_BITS_17_21(dsisr
)];
398 if (entry
->a_instruct
== (void *) 0) {
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
));
408 * Check to see if the instruction is a
409 * floating point operation. Save off
410 * the FPU register set ...
413 if (entry
->a_is_float
)
417 * Pull in any bytes which are going to be
421 if (entry
->a_readbytes
) {
422 if (USER_MODE(ssp
->srr1
)) {
423 if (copyin((char *) dar
,
424 (char *) align_buffer
,
425 entry
->a_readbytes
)) {
430 (char *) align_buffer
,
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
);
443 act
= current_act(); /* Get the current activation */
445 success
= entry
->a_instruct(dsisr
,
447 find_user_fpu(act
), /* Find this user's FPU state. NULL if none */
448 /* NULL should never happen */
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 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 */
471 if (USER_MODE(ssp
->srr1
)) {
472 if (copyout((char *) align_buffer
,
474 entry
->a_writebytes
)) {
478 bcopy((char *) align_buffer
,
480 entry
->a_writebytes
);
484 ssp
->srr0
+= 4; /* Skip the instruction .. */
491 printf("ALIGNMENT EXCEPTION: (dsisr 0x%x) table %d 0x%x\n",
492 dsisr
, DSISR_BITS_15_16(dsisr
), DSISR_BITS_17_21(dsisr
));
500 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), align_buffer
, unsigned long);
507 GET_REG(ssp
, DSISR_BITS_REG(dsisr
), align_buffer
, unsigned long);
514 unsigned long value
= *((unsigned short *) align_buffer
);
516 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), &value
, unsigned long);
523 long value
= *((short *) align_buffer
);
525 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), &value
, unsigned long);
532 GET_REG(ssp
, DSISR_BITS_REG(dsisr
), align_buffer
, unsigned short);
541 for (i
= 0; i
< (32-DSISR_BITS_REG(dsisr
)); i
++)
543 SET_REG(ssp
, DSISR_BITS_REG(dsisr
)+i
, &align_buffer
[i
], unsigned long);
549 unsigned long s
:1; /* Sign bit */
550 unsigned long exp
:8; /* exponent + bias */
551 unsigned long fraction
:23; /* fraction */
553 typedef struct fpsp fpsp_t
, *fpspPtr
;
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 */
561 typedef struct fpdp fpdp_t
, *fpdpPtr
;
566 unsigned long lalign_buf
[2];
569 lfs (align_buffer
, lalign_buf
);
570 SET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), lalign_buf
);
576 SET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), align_buffer
);
582 unsigned long lalign_buf
[2];
585 GET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), lalign_buf
);
586 stfs(lalign_buf
, align_buffer
);
592 GET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), align_buffer
);
598 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), align_buffer
, unsigned long)
599 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
605 GET_REG(ssp
, DSISR_BITS_REG(dsisr
), align_buffer
, unsigned long)
606 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
613 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), align_buffer
, unsigned short)
614 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
620 unsigned long value
= *((short *) align_buffer
);
622 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), &value
, unsigned long);
623 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
630 GET_REG(ssp
, DSISR_BITS_REG(dsisr
), align_buffer
, unsigned short)
631 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
637 int i
, rS
= DSISR_BITS_REG(dsisr
);
638 int numRegs
= 32 - rS
;
639 int numBytes
= numRegs
* 4;
643 for (i
= 0; i
< numRegs
; i
++)
646 printf(" align_buffer[%d] == 0x%x\n",i
,align_buffer
[i
]);
648 GET_REG(ssp
, rS
+i
, &align_buffer
[i
], unsigned long);
650 printf(" now align_buffer[%d] == 0x%x\n",i
,align_buffer
[i
]);
653 if (USER_MODE(ssp
->srr1
)) {
654 if ((retval
=copyout((char *)align_buffer
,(char *)dar
,numBytes
)) != 0) {
658 printf(" copyout(%X, %X, %X) succeeded\n",align_buffer
,dar
,numBytes
);
662 bcopy((char *) align_buffer
, (char *) dar
, numBytes
);
669 unsigned long lalign_buf
[2];
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);
680 SET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), align_buffer
);
681 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
688 unsigned long lalign_buf
[2];
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);
700 GET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), align_buffer
);
701 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
708 int i
, nb
, nr
, inst
, zero
= 0;
711 /* check for invalid form of instruction */
712 if (DSISR_BITS_RA(dsisr
) >= DSISR_BITS_REG(dsisr
) )
715 if (USER_MODE(ssp
->srr1
)) {
716 if (copyin((char *) ssp
->srr0
, (char *) &inst
, 4 )) {
720 bcopy((char *) ssp
->srr0
, (char *) &inst
, 4 );
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 */
726 if ((nr
+ DSISR_BITS_REG(dsisr
)) > 31)
727 return FALSE
; /* not supported yet */
729 for (i
= 0; i
< nr
; i
++)
731 SET_REG(ssp
, DSISR_BITS_REG(dsisr
)+i
, &zero
, unsigned long);
733 /* copy the string into the save state */
734 bcopy((char *) align_buffer
, (char *) ssp
->r0
+DSISR_BITS_REG(dsisr
), nb
);
740 int i
, nb
, nr
, inst
, zero
= 0;
743 /* check for invalid form of instruction */
744 if (DSISR_BITS_RA(dsisr
) >= DSISR_BITS_REG(dsisr
) )
747 if (USER_MODE(ssp
->srr1
)) {
748 if (copyin((char *) ssp
->srr0
, (char *) &inst
, 4 )) {
752 bcopy((char *) ssp
->srr0
, (char *) &inst
, 4 );
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 */
758 if ((nr
+ DSISR_BITS_REG(dsisr
)) > 31)
759 return FALSE
; /* not supported yet */
761 for (i
= 0; i
< nr
; i
++)
763 SET_REG(ssp
, DSISR_BITS_REG(dsisr
)+i
, &zero
, unsigned long);
765 /* copy the string into the save state */
766 bcopy((char *) align_buffer
, (char *) ssp
->r0
+DSISR_BITS_REG(dsisr
), nb
);
798 unsigned long new_value
;
800 __asm__
volatile("lwbrx %0,0,%1" : : "b" (new_value
),
801 "b" (&align_buffer
[0]));
803 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), &new_value
, unsigned long);
812 GET_REG(ssp
, DSISR_BITS_REG(dsisr
), &value
, unsigned long);
813 __asm__
volatile("stwbrx %0,0,%1" : : "b" (value
), "b" (&align_buffer
[0]));
820 unsigned short value
;
822 __asm__
volatile("lhbrx %0,0,%1" : : "b" (value
), "b" (&align_buffer
[0]));
824 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), &value
, unsigned short);
831 unsigned short value
;
833 GET_REG(ssp
, DSISR_BITS_REG(dsisr
), &value
, unsigned short);
834 __asm__
volatile("sthbrx %0,0,%1" : : "b" (value
), "b" (&align_buffer
[0]));
851 long *alignedDAR
= (long *)((long)dar
& ~(CACHE_LINE_SIZE
-1));
854 if (USER_MODE(ssp
->srr1
)) {
865 if (copyout((char *)align_buffer
,(char *)alignedDAR
,CACHE_LINE_SIZE
) != 0)
868 /* Cannot use bcopy here just in case it caused the exception */
889 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), &align_buffer
[0], unsigned long);
896 GET_REG(ssp
, DSISR_BITS_REG(dsisr
), &align_buffer
[0], unsigned long);
903 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), &align_buffer
[0], unsigned short);
910 unsigned long value
= *((short *) &align_buffer
[0]);
912 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), &value
, unsigned long);
919 GET_REG(ssp
, DSISR_BITS_REG(dsisr
), &align_buffer
[0], unsigned short);
929 lfs (align_buffer
, lalign_buf
);
930 SET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), lalign_buf
);
936 SET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), align_buffer
);
946 GET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), lalign_buf
);
947 stfs(lalign_buf
, align_buffer
);
953 GET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), align_buffer
);
960 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), &align_buffer
[0], unsigned long);
961 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
968 GET_REG(ssp
, DSISR_BITS_REG(dsisr
), &align_buffer
[0], unsigned long);
969 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
976 unsigned long value
= *((unsigned short *)&align_buffer
[0]);
978 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), &value
, unsigned long);
979 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
986 long value
= *((short *) &align_buffer
[0]);
988 SET_REG(ssp
, DSISR_BITS_REG(dsisr
), &value
, unsigned long);
989 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
996 GET_REG(ssp
, DSISR_BITS_REG(dsisr
), &align_buffer
[0], unsigned short);
997 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
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);
1015 SET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), &align_buffer
[0]);
1016 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);
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);
1035 GET_FPU_REG(fsp
, DSISR_BITS_REG(dsisr
), &align_buffer
[0]);
1036 SET_REG(ssp
, DSISR_BITS_RA(dsisr
), &dar
, unsigned long);