Bring back sam build into life.
[AROS.git] / arch / ppc-sam440 / kernel / intr.c
blob224ebc671f8a43fa2f375c58861dd85aa7294245
1 #include <aros/kernel.h>
2 #include <aros/libcall.h>
3 #include <asm/amcc440.h>
4 #include <stddef.h>
6 #include <proto/exec.h>
7 #include <proto/kernel.h>
9 #include "kernel_intern.h"
10 #include "syscall.h"
12 AROS_LH4(void *, KrnAddIRQHandler,
13 AROS_LHA(uint8_t, irq, D0),
14 AROS_LHA(void *, handler, A0),
15 AROS_LHA(void *, handlerData, A1),
16 AROS_LHA(void *, handlerData2, A2),
17 struct KernelBase *, KernelBase, 7, Kernel)
19 AROS_LIBFUNC_INIT
21 struct ExecBase *SysBase = getSysBase();
22 struct IntrNode *handle = NULL;
23 D(bug("[KRN] KrnAddIRQHandler(%02x, %012p, %012p, %012p):\n", irq, handler, handlerData, handlerData2));
25 if (irq < 63)
27 /* Go to supervisor mode */
28 goSuper();
30 handle = Allocate(KernelBase->kb_SupervisorMem, sizeof(struct IntrNode));
32 if (handle)
34 handle->in_Handler = handler;
35 handle->in_HandlerData = handlerData;
36 handle->in_HandlerData2 = handlerData2;
37 handle->in_type = it_interrupt;
38 handle->in_nr = irq;
40 Disable();
41 ADDHEAD(&KernelBase->kb_Interrupts[irq], &handle->in_Node);
43 if (irq < 32)
45 wrdcr(UIC0_ER, rddcr(UIC0_ER) | (0x80000000 >> irq));
47 else
49 wrdcr(UIC1_ER, rddcr(UIC1_ER) | (0x80000000 >> (irq - 32)));
50 wrdcr(UIC0_ER, rddcr(UIC0_ER) | 0x00000003);
53 Enable();
56 goUser();
59 D(bug("[KRN] handle=%012p\n", handle));
60 return handle;
62 AROS_LIBFUNC_EXIT
65 AROS_LH1(void, KrnRemIRQHandler,
66 AROS_LHA(void *, handle, A0),
67 struct KernelBase *, KernelBase, 8, Kernel)
69 AROS_LIBFUNC_INIT
71 struct ExecBase *SysBase = getSysBase();
72 struct IntrNode *h = handle;
73 uint8_t irq = h->in_nr;
75 if (h && (h->in_type == it_interrupt))
77 goSuper();
79 Disable();
80 REMOVE(h);
81 if (IsListEmpty(&KernelBase->kb_Interrupts[irq]))
83 if (irq < 30)
85 wrdcr(UIC0_ER, rddcr(UIC0_ER) & ~(0x80000000 >> irq));
87 else if (irq > 31)
89 wrdcr(UIC1_ER, rddcr(UIC0_ER) & ~(0x80000000 >> (irq - 32)));
92 Enable();
94 Deallocate(KernelBase->kb_SupervisorMem, h, sizeof(struct IntrNode));
96 goUser();
99 AROS_LIBFUNC_EXIT
102 AROS_LH4(void *, KrnAddExceptionHandler,
103 AROS_LHA(uint8_t, irq, D0),
104 AROS_LHA(void *, handler, A0),
105 AROS_LHA(void *, handlerData, A1),
106 AROS_LHA(void *, handlerData2, A2),
107 struct KernelBase *, KernelBase, 14, Kernel)
109 AROS_LIBFUNC_INIT
111 struct ExecBase *SysBase = getSysBase();
112 struct IntrNode *handle = NULL;
113 D(bug("[KRN] KrnAddExceptionHandler(%02x, %012p, %012p, %012p):\n", irq, handler, handlerData, handlerData2));
115 if (irq < 16)
117 /* Go to supervisor mode */
118 goSuper();
120 handle = Allocate(KernelBase->kb_SupervisorMem, sizeof(struct IntrNode));
121 D(bug("[KRN] handle=%012p\n", handle));
123 if (handle)
125 handle->in_Handler = handler;
126 handle->in_HandlerData = handlerData;
127 handle->in_HandlerData2 = handlerData2;
128 handle->in_type = it_exception;
129 handle->in_nr = irq;
131 Disable();
132 ADDHEAD(&KernelBase->kb_Exceptions[irq], &handle->in_Node);
133 Enable();
136 goUser();
139 return handle;
141 AROS_LIBFUNC_EXIT
144 AROS_LH1(void, KrnRemExceptionHandler,
145 AROS_LHA(void *, handle, A0),
146 struct KernelBase *, KernelBase, 15, Kernel)
148 AROS_LIBFUNC_INIT
150 struct ExecBase *SysBase = getSysBase();
151 struct IntrNode *h = handle;
153 if (h && (h->in_type == it_exception))
155 goSuper();
157 Disable();
158 REMOVE(h);
159 Enable();
161 Deallocate(KernelBase->kb_SupervisorMem, h, sizeof(struct IntrNode));
163 goUser();
166 AROS_LIBFUNC_EXIT
169 AROS_LH0I(void, KrnCli,
170 struct KernelBase *, KernelBase, 9, Kernel)
172 AROS_LIBFUNC_INIT
174 asm volatile("li %%r3,%0; sc"::"i"(SC_CLI):"memory","r3");
176 AROS_LIBFUNC_EXIT
179 AROS_LH0I(void, KrnSti,
180 struct KernelBase *, KernelBase, 10, Kernel)
182 AROS_LIBFUNC_INIT
184 asm volatile("li %%r3,%0; sc"::"i"(SC_STI):"memory","r3");
186 AROS_LIBFUNC_EXIT
189 AROS_LH0I(void, KrnIsSuper,
190 struct KernelBase *, KernelBase, 13, Kernel)
192 AROS_LIBFUNC_INIT
194 register int retval asm ("r3");
196 asm volatile("sc":"=r"(retval):"0"(SC_ISSUPERSTATE):"memory");
198 return retval;
200 AROS_LIBFUNC_EXIT
203 void *__EXCEPTION_0_Prolog();
204 void *__EXCEPTION_1_Prolog();
205 void *__EXCEPTION_2_Prolog();
206 void *__EXCEPTION_3_Prolog();
207 void *__EXCEPTION_4_Prolog();
208 void *__EXCEPTION_5_Prolog();
209 void *__EXCEPTION_6_Prolog();
210 void *__EXCEPTION_7_Prolog();
211 void *__EXCEPTION_8_Prolog();
212 void *__EXCEPTION_9_Prolog();
213 void *__EXCEPTION_10_Prolog();
214 void *__EXCEPTION_11_Prolog();
215 void *__EXCEPTION_12_Prolog();
216 void *__EXCEPTION_13_Prolog();
217 void *__EXCEPTION_14_Prolog();
218 void *__EXCEPTION_15_Prolog();
220 void intr_init()
222 D(bug("[KRN] Setting up exception handlers\n"));
223 wrspr(IVPR, ((uint32_t)&__EXCEPTION_0_Prolog) & 0xffff0000);
225 wrspr(IVOR0, ((uint32_t)&__EXCEPTION_0_Prolog) & 0x0000fff0);
226 wrspr(IVOR1, ((uint32_t)&__EXCEPTION_1_Prolog) & 0x0000fff0);
227 wrspr(IVOR2, ((uint32_t)&__EXCEPTION_2_Prolog) & 0x0000fff0);
228 wrspr(IVOR3, ((uint32_t)&__EXCEPTION_3_Prolog) & 0x0000fff0);
229 wrspr(IVOR4, ((uint32_t)&__EXCEPTION_4_Prolog) & 0x0000fff0);
230 wrspr(IVOR5, ((uint32_t)&__EXCEPTION_5_Prolog) & 0x0000fff0);
231 wrspr(IVOR6, ((uint32_t)&__EXCEPTION_6_Prolog) & 0x0000fff0);
232 wrspr(IVOR7, ((uint32_t)&__EXCEPTION_7_Prolog) & 0x0000fff0);
233 wrspr(IVOR8, ((uint32_t)&__EXCEPTION_8_Prolog) & 0x0000fff0);
234 wrspr(IVOR9, ((uint32_t)&__EXCEPTION_9_Prolog) & 0x0000fff0);
235 wrspr(IVOR10, ((uint32_t)&__EXCEPTION_10_Prolog) & 0x0000fff0);
236 wrspr(IVOR11, ((uint32_t)&__EXCEPTION_11_Prolog) & 0x0000fff0);
237 wrspr(IVOR12, ((uint32_t)&__EXCEPTION_12_Prolog) & 0x0000fff0);
238 wrspr(IVOR13, ((uint32_t)&__EXCEPTION_13_Prolog) & 0x0000fff0);
239 wrspr(IVOR14, ((uint32_t)&__EXCEPTION_14_Prolog) & 0x0000fff0);
240 wrspr(IVOR15, ((uint32_t)&__EXCEPTION_15_Prolog) & 0x0000fff0);
242 /* Disable external interrupts completely */
243 wrdcr(UIC0_ER, 0);
244 wrdcr(UIC1_ER, 0);
247 #define _STR(x) #x
248 #define STR(x) _STR(x)
249 #define PUT_INTR_TEMPLATE(num, handler) \
250 asm volatile(".section .text,\"ax\"\n\t.align 5\n\t.globl __EXCEPTION_" STR(num) "_Prolog\n\t.type __EXCEPTION_" STR(num) "_Prolog,@function\n" \
251 "__EXCEPTION_" STR(num) "_Prolog: \n\t" \
252 "mtsprg1 %%r3 \n\t" /* save %r3 */ \
253 "mfcr %%r3 \n\t" /* copy CR to %r3 */ \
254 "mtsprg2 %%r3 \n\t" /* save %r3 */ \
255 "mfsrr1 %%r3 \n\t" /* srr1 (previous MSR) reg into %r3 */ \
256 "andi. %%r3,%%r3,%0 \n\t" /* Was the PR bit set in MSR already? */ \
257 "beq- 1f \n\t" /* No, we were in supervisor mode */ \
259 "mfsprg0 %%r3 \n\t" /* user mode case: SSP into %r3 */ \
260 "b 2f \n" \
261 "1: mr %%r3,%%r1 \n\t" /* Supervisor case: use current stack */ \
262 "2: addi %%r3,%%r3,%1 " \
263 ::"i"(MSR_PR),"i"(-sizeof(context_t))); \
264 asm volatile("stw %%r0, %[gpr0](%%r3) \n\t" \
265 "stw %%r1, %[gpr1](%%r3) \n\t" \
266 "stw %%r2, %[gpr2](%%r3) \n\t" \
267 "mfsprg1 %%r0 \n\t" \
268 "stw %%r4, %[gpr4](%%r3) \n\t" \
269 "stw %%r0, %[gpr3](%%r3) \n\t" \
270 "stw %%r5, %[gpr5](%%r3) \n\t" \
271 "mfsprg2 %%r2 \n\t" \
272 "mfsrr0 %%r0 \n\t" \
273 "mfsrr1 %%r1 \n\t" \
274 "lis %%r5, " #handler "@ha\n\t" \
275 "la %%r5, " #handler "@l(%%r5)\n\t" \
276 "li %%r4, %[irq] \n\t" \
277 "stw %%r2,%[ccr](%%r3) \n\t" \
278 "stw %%r0,%[srr0](%%r3) \n\t" \
279 "stw %%r1,%[srr1](%%r3) \n\t" \
280 "mfctr %%r0 \n\t" \
281 "mflr %%r1 \n\t" \
282 "mfxer %%r2 \n\t" \
283 "stw %%r0,%[ctr](%%r3) \n\t" \
284 "stw %%r1,%[lr](%%r3) \n\t" \
285 "stw %%r2,%[xer](%%r3) \n\t" \
287 :: \
288 [gpr0]"i"(offsetof(regs_t, gpr[0])), \
289 [gpr1]"i"(offsetof(regs_t, gpr[1])), \
290 [gpr2]"i"(offsetof(regs_t, gpr[2])), \
291 [gpr3]"i"(offsetof(regs_t, gpr[3])), \
292 [gpr4]"i"(offsetof(regs_t, gpr[4])), \
293 [gpr5]"i"(offsetof(regs_t, gpr[5])), \
295 [ccr]"i"(offsetof(regs_t, ccr)), \
296 [srr0]"i"(offsetof(regs_t, srr0)), \
297 [srr1]"i"(offsetof(regs_t, srr1)), \
298 [ctr]"i"(offsetof(regs_t, ctr)), \
299 [lr]"i"(offsetof(regs_t, lr)), \
300 [xer]"i"(offsetof(regs_t, xer)), \
301 [irq]"i"(num) \
302 ); \
303 /* \
304 * Registers %r0 to %r5 are now saved together with CPU state. Go to the \
305 * trampoline code which will care about the rest. Adjust the stack frame pointer now, \
306 * or else it will be destroyed later by C code. \
307 */ \
308 asm volatile("addi %r1,%r3,-16"); \
310 /* \
311 * Go to the trampoline code. Use long call within whole 4GB addresspace in order to \
312 * avoid any trouble in future. \
313 */ \
314 asm volatile( "b __EXCEPTION_Trampoline\n\t");
316 uint64_t idle_time;
317 static uint64_t last_calc;
319 void __attribute__((noreturn)) decrementer_handler(regs_t *ctx, uint8_t exception, void *self)
321 struct KernelBase *KernelBase = getKernelBase();
322 struct ExecBase *SysBase = getSysBase();
324 /* Clear the DIS bit - we have received decrementer exception */
325 wrspr(TSR, TSR_DIS);
326 //D(bug("[KRN] Decrementer handler. Context @ %p. srr1=%08x\n", ctx, ctx->srr1));
328 if (!IsListEmpty(&KernelBase->kb_Exceptions[exception]))
330 struct IntrNode *in, *in2;
332 ForeachNodeSafe(&KernelBase->kb_Exceptions[exception], in, in2)
334 if (in->in_Handler)
335 in->in_Handler(in->in_HandlerData, in->in_HandlerData2);
339 if (SysBase && SysBase->Elapsed)
341 if (--SysBase->Elapsed == 0)
343 if (IsListEmpty(&SysBase->TaskReady))
345 SysBase->Elapsed = SysBase->Quantum;
347 else
349 bug("[KRN] Force reschedule (Task %08x '%s')\n", SysBase->ThisTask, SysBase->ThisTask ? SysBase->ThisTask->tc_Node.ln_Name : "???");
350 SysBase->SysFlags |= 0x2000;
351 SysBase->AttnResched |= 0x80;
352 SysBase->ThisTask->tc_Node.ln_Pri = -128;
357 /* Idle time calculator */
359 uint64_t current = mftbu();
360 if (current - last_calc > KernelBase->kb_OPBFreq)
362 uint32_t total_time = current - last_calc;
364 if (total_time < idle_time)
365 total_time = idle_time;
367 KernelBase->kb_CPUUsage = 1000 - ((uint32_t)idle_time) / (total_time / 1000);
369 if (KernelBase->kb_CPUUsage > 999)
371 D(bug("[KRN] CPU usage: %3d.%d (%s)\n", KernelBase->kb_CPUUsage / 10, KernelBase->kb_CPUUsage % 10,
372 SysBase->ThisTask->tc_Node.ln_Name));
374 else
375 D(bug("[KRN] CPU usage: %3d.%d\n", KernelBase->kb_CPUUsage / 10, KernelBase->kb_CPUUsage % 10));
377 idle_time = 0;
378 last_calc = current;
381 core_ExitInterrupt(ctx);
385 void __attribute__((noreturn)) generic_handler(regs_t *ctx, uint8_t exception, void *self)
387 struct KernelBase *KernelBase = getKernelBase();
388 struct ExecBase *SysBase = getSysBase();
390 if (!IsListEmpty(&KernelBase->kb_Exceptions[exception]))
392 struct IntrNode *in, *in2;
394 ForeachNodeSafe(&KernelBase->kb_Exceptions[exception], in, in2)
396 if (in->in_Handler)
397 in->in_Handler(in->in_HandlerData, in->in_HandlerData2);
401 D(bug("[KRN] Exception %d handler. Context @ %p, SysBase @ %p, KernelBase @ %p\n", exception, ctx, SysBase, KernelBase));
402 if (SysBase)
404 struct Task *t = FindTask(NULL);
405 uint32_t offset;
406 char *func, *mod;
408 offset = findNames(ctx->srr0, &mod, &func);
410 D(bug("[KRN] %s %p (%s)\n", t->tc_Node.ln_Type == NT_TASK ? "Task":"Process", t, t->tc_Node.ln_Name ? t->tc_Node.ln_Name : "--unknown--"));
412 if (func)
413 D(bug("[KRN] Crash at byte %d in func %s, module %s\n", offset, func, mod));
414 else if (mod)
415 D(bug("[KRN] Crash at byte %d in module %s\n", offset, mod));
417 D(bug("[KRN] SPLower=%08x SPUpper=%08x\n", t->tc_SPLower, t->tc_SPUpper));
418 D(bug("[KRN] Stack usage: %d bytes (%d %%)\n", t->tc_SPUpper - ctx->gpr[1],
419 100 * ((uintptr_t)t->tc_SPUpper - ctx->gpr[1]) / ((uintptr_t)t->tc_SPUpper - (uintptr_t)t->tc_SPLower)));
421 if (ctx->gpr[1] >= t->tc_SPLower && ctx->gpr[1] < t->tc_SPUpper)
422 D(bug("[KRN] Stack in bounds\n"));
423 else
424 D(bug("[KRN] Stack exceeded the allowed size!\n"));
426 D(bug("[KRN] SRR0=%08x, SRR1=%08x DEAR=%08x ESR=%08x\n",ctx->srr0, ctx->srr1, rdspr(DEAR), rdspr(ESR)));
427 D(bug("[KRN] CTR=%08x LR=%08x XER=%08x CCR=%08x\n", ctx->ctr, ctx->lr, ctx->xer, ctx->ccr));
428 D(bug("[KRN] DAR=%08x DSISR=%08x\n", ctx->dar, ctx->dsisr));
429 D(bug("[KRN] GPR00=%08x GPR01=%08x GPR02=%08x GPR03=%08x\n",
430 ctx->gpr[0],ctx->gpr[1],ctx->gpr[2],ctx->gpr[3]));
431 D(bug("[KRN] GPR04=%08x GPR05=%08x GPR06=%08x GPR07=%08x\n",
432 ctx->gpr[4],ctx->gpr[5],ctx->gpr[6],ctx->gpr[7]));
433 D(bug("[KRN] GPR08=%08x GPR09=%08x GPR10=%08x GPR11=%08x\n",
434 ctx->gpr[8],ctx->gpr[9],ctx->gpr[10],ctx->gpr[11]));
435 D(bug("[KRN] GPR12=%08x GPR13=%08x GPR14=%08x GPR15=%08x\n",
436 ctx->gpr[12],ctx->gpr[13],ctx->gpr[14],ctx->gpr[15]));
438 D(bug("[KRN] GPR16=%08x GPR17=%08x GPR18=%08x GPR19=%08x\n",
439 ctx->gpr[16],ctx->gpr[17],ctx->gpr[18],ctx->gpr[19]));
440 D(bug("[KRN] GPR20=%08x GPR21=%08x GPR22=%08x GPR23=%08x\n",
441 ctx->gpr[20],ctx->gpr[21],ctx->gpr[22],ctx->gpr[23]));
442 D(bug("[KRN] GPR24=%08x GPR25=%08x GPR26=%08x GPR27=%08x\n",
443 ctx->gpr[24],ctx->gpr[25],ctx->gpr[26],ctx->gpr[27]));
444 D(bug("[KRN] GPR28=%08x GPR29=%08x GPR30=%08x GPR31=%08x\n",
445 ctx->gpr[28],ctx->gpr[29],ctx->gpr[30],ctx->gpr[31]));
447 D(bug("[KRN] Instruction dump:\n"));
448 int i;
449 ULONG *p = (ULONG*)ctx->srr0;
450 for (i=0; i < 8; i++)
452 D(bug("[KRN] %08x: %08x\n", &p[i], p[i]));
456 char *mod, *func;
457 uint32_t offset;
459 offset = findNames(ctx->lr, &mod, &func);
461 D(bug("[KRN] LR=%08x", ctx->lr));
463 if (func)
464 D(bug(": byte %d in func %s, module %s\n", offset, func, mod));
465 else if (mod)
466 D(bug(": byte %d in module %s\n", offset, mod));
467 else
468 D(bug("\n"));
472 D(bug("[KRN] Backtrace:\n"));
473 uint32_t *sp = ctx->gpr[1];
474 while(*sp)
476 char *mod, *func;
477 sp = (uint32_t *)sp[0];
478 uint32_t offset;
480 offset = findNames(sp[1], &mod, &func);
482 if (func)
483 D(bug("[KRN] %08x: byte %d in func %s, module %s\n", sp[1], offset, func, mod));
484 else if (mod)
485 D(bug("[KRN] %08x: byte %d in module %s\n", sp[1], offset, mod));
486 else
487 D(bug("[KRN] %08x\n", sp[1]));
491 if (IsListEmpty(&KernelBase->kb_Exceptions[exception]))
493 D(bug("[KRN] **UNHANDLED EXCEPTION** stopping here...\n"));
495 while(1) {
496 wrmsr(rdmsr() | MSR_POW);
500 core_ExitInterrupt(ctx);
503 void __attribute__((noreturn)) mmu_handler(regs_t *ctx, uint8_t exception, void *self)
505 struct KernelBase *KernelBase = getKernelBase();
507 uint32_t insn = *(uint32_t *)ctx->srr0;
509 /* SysBase access at 4UL? Occurs only with lwz instruction and DEAR=4 */
510 if ((insn & 0xfc000000) == 0x80000000 && rdspr(DEAR) == 4)
512 int reg = (insn & 0x03e00000) >> 21;
514 // D(bug("[KRN] Pagefault exception. Someone tries to get SysBase (%08x) from 0x00000004 into r%d. EVIL EVIL EVIL!\n",
515 // getSysBase(), reg));
517 ctx->gpr[reg] = getSysBase();
518 ctx->srr0 += 4;
520 core_LeaveInterrupt(ctx);
522 else
523 generic_handler(ctx, exception, self);
526 double lfd(intptr_t addr)
528 union {
529 uint8_t u8[8];
530 uint16_t u16[4];
531 uint32_t u32[2];
532 uint64_t u64;
533 float f[2];
534 double d;
535 } conv;
537 switch ((intptr_t)addr & 3)
539 case 0:
540 conv.u32[0] = ((uint32_t *)addr)[0];
541 conv.u32[1] = ((uint32_t *)addr)[1];
542 break;
544 case 2:
545 conv.u16[0] = ((uint16_t *)addr)[0];
546 conv.u16[1] = ((uint16_t *)addr)[1];
547 conv.u16[2] = ((uint16_t *)addr)[2];
548 conv.u16[3] = ((uint16_t *)addr)[3];
549 break;
551 default:
552 conv.u8[0] = ((uint8_t *)addr)[0];
553 conv.u8[1] = ((uint8_t *)addr)[1];
554 conv.u8[2] = ((uint8_t *)addr)[2];
555 conv.u8[3] = ((uint8_t *)addr)[3];
556 conv.u8[4] = ((uint8_t *)addr)[4];
557 conv.u8[5] = ((uint8_t *)addr)[5];
558 conv.u8[6] = ((uint8_t *)addr)[6];
559 conv.u8[7] = ((uint8_t *)addr)[7];
560 break;
563 return conv.d;
566 float lfs(intptr_t addr)
568 union {
569 uint8_t u8[8];
570 uint16_t u16[4];
571 uint32_t u32[2];
572 uint64_t u64;
573 float f[2];
574 double d;
575 } conv;
577 switch ((intptr_t)addr & 3)
579 case 0:
580 conv.u32[0] = ((uint32_t *)addr)[0];
581 break;
583 case 2:
584 conv.u16[0] = ((uint16_t *)addr)[0];
585 conv.u16[1] = ((uint16_t *)addr)[1];
586 break;
588 default:
589 conv.u8[0] = ((uint8_t *)addr)[0];
590 conv.u8[1] = ((uint8_t *)addr)[1];
591 conv.u8[2] = ((uint8_t *)addr)[2];
592 conv.u8[3] = ((uint8_t *)addr)[3];
593 break;
596 return conv.f[0];
599 void stfd(double v, intptr_t addr)
601 union {
602 uint8_t u8[8];
603 uint16_t u16[4];
604 uint32_t u32[2];
605 uint64_t u64;
606 float f[2];
607 double d;
608 } conv;
610 conv.d = v;
612 switch ((intptr_t)addr & 3)
614 case 0:
615 ((uint32_t *)addr)[0] = conv.u32[0];
616 ((uint32_t *)addr)[1] = conv.u32[1];
617 break;
619 case 2:
620 ((uint16_t *)addr)[0] = conv.u16[0];
621 ((uint16_t *)addr)[1] = conv.u16[1];
622 ((uint16_t *)addr)[2] = conv.u16[2];
623 ((uint16_t *)addr)[3] = conv.u16[3];
624 break;
626 default:
627 ((uint8_t *)addr)[0] = conv.u8[0];
628 ((uint8_t *)addr)[1] = conv.u8[1];
629 ((uint8_t *)addr)[2] = conv.u8[2];
630 ((uint8_t *)addr)[3] = conv.u8[3];
631 ((uint8_t *)addr)[4] = conv.u8[4];
632 ((uint8_t *)addr)[5] = conv.u8[5];
633 ((uint8_t *)addr)[6] = conv.u8[6];
634 ((uint8_t *)addr)[7] = conv.u8[7];
635 break;
639 void stfs(float v, intptr_t addr)
641 union {
642 uint8_t u8[8];
643 uint16_t u16[4];
644 uint32_t u32[2];
645 uint64_t u64;
646 float f[2];
647 double d;
648 } conv;
650 conv.f[0] = v;
652 switch ((intptr_t)addr & 3)
654 case 0:
655 ((uint32_t *)addr)[0] = conv.u32[0];
656 break;
658 case 2:
659 ((uint16_t *)addr)[0] = conv.u16[0];
660 ((uint16_t *)addr)[1] = conv.u16[1];
661 break;
663 default:
664 ((uint8_t *)addr)[0] = conv.u8[0];
665 ((uint8_t *)addr)[1] = conv.u8[1];
666 ((uint8_t *)addr)[2] = conv.u8[2];
667 ((uint8_t *)addr)[3] = conv.u8[3];
668 break;
672 void __attribute__((noreturn)) alignment_handler(context_t *ctx, uint8_t exception, void *self)
674 struct KernelBase *KernelBase = getKernelBase();
675 int fixed = 1;
677 union {
678 uint8_t u8[8];
679 uint16_t u16[4];
680 uint32_t u32[2];
681 uint64_t u64;
682 float f[2];
683 double d;
684 } conv __attribute__((aligned(16)));
686 intptr_t dear = rdspr(DEAR);
687 uint32_t insn = *(uint32_t *)ctx->cpu.srr0;
689 uint8_t reg = (insn >> 21) & 0x1f; // source/dest register
690 uint8_t areg = (insn >> 16) & 0x1f; // register to be updated with dear value
693 switch (insn >> 26)
695 case 50: // lfd
696 ctx->fpu.fpr[reg] = lfd(dear);
697 break;
698 case 51: // lfdu
699 ctx->fpu.fpr[reg] = lfd(dear);
700 ctx->cpu.gpr[areg] = dear;
701 break;
702 case 48: // lfs
703 ctx->fpu.fpr[reg] = lfs(dear);
704 break;
705 case 49: // lfsu
706 ctx->fpu.fpr[reg] = lfs(dear);
707 ctx->cpu.gpr[areg] = dear;
708 break;
709 case 54: // stfd
710 stfd(ctx->fpu.fpr[reg], dear);
711 break;
712 case 55: // stfdu
713 stfd(ctx->fpu.fpr[reg], dear);
714 ctx->cpu.gpr[areg] = dear;
715 break;
716 case 52: // stfs
717 stfs(ctx->fpu.fpr[reg], dear);
718 break;
719 case 53: // stfsu
720 stfs(ctx->fpu.fpr[reg], dear);
721 ctx->cpu.gpr[areg] = dear;
722 break;
723 case 31: // lfdux, lfdx, lfsux, lfsx, stfdux, stfdx, stfsux, stfsx
724 switch ((insn & 0x00001ffe) >> 1)
726 case 631: // lfdux
727 ctx->fpu.fpr[reg] = lfd(dear);
728 ctx->cpu.gpr[areg] = dear;
729 break;
730 case 599: // lfdx
731 ctx->fpu.fpr[reg] = lfd(dear);
732 break;
733 case 567: // lfsux
734 ctx->fpu.fpr[reg] = lfs(dear);
735 ctx->cpu.gpr[areg] = dear;
736 break;
737 case 535: // lfsx
738 ctx->fpu.fpr[reg] = lfs(dear);
739 break;
740 case 759: // stfdux
741 stfd(ctx->fpu.fpr[reg], dear);
742 ctx->cpu.gpr[areg] = dear;
743 break;
744 case 727: // stfdx
745 stfd(ctx->fpu.fpr[reg], dear);
746 break;
747 case 695: // stfsux
748 stfs(ctx->fpu.fpr[reg], dear);
749 ctx->cpu.gpr[areg] = dear;
750 break;
751 case 663: // stfsx
752 stfs(ctx->fpu.fpr[reg], dear);
753 break;
754 default:
755 fixed = 0;
756 break;
758 break;
759 default:
760 fixed = 0;
761 break;
764 if (fixed)
766 ctx->cpu.srr0 += 4;
767 core_LeaveInterrupt(ctx);
769 else
771 D(bug("[KRN] Alignment exception handler failed to help... INSN=%08x, DEAR=%08x\n", insn, dear));
772 generic_handler(ctx, exception, self);
777 static void __attribute__((used)) __EXCEPTION_Prolog_template()
781 * Create partial context on the stack. It is impossible to save it fully since the
782 * exception handlers have limited size. This code will do as much as possible and then
783 * jump to general trampoline...
786 PUT_INTR_TEMPLATE(0, generic_handler); /* crit */
787 PUT_INTR_TEMPLATE(1, generic_handler);
788 PUT_INTR_TEMPLATE(2, generic_handler);
789 PUT_INTR_TEMPLATE(3, generic_handler);
790 PUT_INTR_TEMPLATE(4, uic_handler);
791 PUT_INTR_TEMPLATE(5, alignment_handler);
792 PUT_INTR_TEMPLATE(6, generic_handler);
793 PUT_INTR_TEMPLATE(7, generic_handler);
794 PUT_INTR_TEMPLATE(8, syscall_handler);
795 PUT_INTR_TEMPLATE(9, generic_handler);
796 PUT_INTR_TEMPLATE(10, decrementer_handler);
797 PUT_INTR_TEMPLATE(11, generic_handler);
798 PUT_INTR_TEMPLATE(12, generic_handler); /* crit */
799 PUT_INTR_TEMPLATE(13, mmu_handler);
800 PUT_INTR_TEMPLATE(14, mmu_handler);
801 PUT_INTR_TEMPLATE(15, generic_handler); /* crit */
804 static void __attribute__((used)) __EXCEPTION_Trampoline_template()
806 asm volatile(".section .text,\"ax\"\n\t.align 5\n\t.globl __EXCEPTION_Trampoline\n\t.type __EXCEPTION_Trampoline,@function\n"
807 "__EXCEPTION_Trampoline: \n\t"
808 "stw %%r6,%[gpr6](%%r3) \n\t"
809 "stw %%r7,%[gpr7](%%r3) \n\t"
810 "stw %%r8,%[gpr8](%%r3) \n\t"
811 "stw %%r9,%[gpr9](%%r3) \n\t"
812 "stw %%r10,%[gpr10](%%r3) \n\t"
813 "stw %%r11,%[gpr11](%%r3) \n\t"
814 "stw %%r12,%[gpr12](%%r3) \n\t"
815 "stw %%r13,%[gpr13](%%r3) \n\t"
816 "stw %%r14,%[gpr14](%%r3) \n\t"
817 "stw %%r15,%[gpr15](%%r3) \n\t"
818 "stw %%r16,%[gpr16](%%r3) \n\t"
819 "stw %%r17,%[gpr17](%%r3) \n\t"
820 "stw %%r18,%[gpr18](%%r3) \n\t"
821 "stw %%r19,%[gpr19](%%r3) \n\t"
822 "stw %%r20,%[gpr20](%%r3) \n\t"
823 "stw %%r21,%[gpr21](%%r3) \n\t"
824 "stw %%r22,%[gpr22](%%r3) \n\t"
825 "stw %%r23,%[gpr23](%%r3) \n\t"
826 "stw %%r24,%[gpr24](%%r3) \n\t"
827 "stw %%r25,%[gpr25](%%r3) \n\t"
828 "stw %%r26,%[gpr26](%%r3) \n\t"
829 "stw %%r27,%[gpr27](%%r3) \n\t"
830 "stw %%r28,%[gpr28](%%r3) \n\t"
831 "stw %%r29,%[gpr29](%%r3) \n\t"
832 "stw %%r30,%[gpr30](%%r3) \n\t"
833 "stw %%r31,%[gpr31](%%r3) \n\t"
835 [gpr6]"i"(offsetof(regs_t, gpr[6])),
836 [gpr7]"i"(offsetof(regs_t, gpr[7])),
837 [gpr8]"i"(offsetof(regs_t, gpr[8])),
838 [gpr9]"i"(offsetof(regs_t, gpr[9])),
839 [gpr10]"i"(offsetof(regs_t, gpr[10])),
840 [gpr11]"i"(offsetof(regs_t, gpr[11])),
841 [gpr12]"i"(offsetof(regs_t, gpr[12])),
842 [gpr13]"i"(offsetof(regs_t, gpr[13])),
843 [gpr14]"i"(offsetof(regs_t, gpr[14])),
844 [gpr15]"i"(offsetof(regs_t, gpr[15])),
845 [gpr16]"i"(offsetof(regs_t, gpr[16])),
846 [gpr17]"i"(offsetof(regs_t, gpr[17])),
847 [gpr18]"i"(offsetof(regs_t, gpr[18])),
848 [gpr19]"i"(offsetof(regs_t, gpr[19])),
849 [gpr20]"i"(offsetof(regs_t, gpr[20])),
850 [gpr21]"i"(offsetof(regs_t, gpr[21])),
851 [gpr22]"i"(offsetof(regs_t, gpr[22])),
852 [gpr23]"i"(offsetof(regs_t, gpr[23])),
853 [gpr24]"i"(offsetof(regs_t, gpr[24])),
854 [gpr25]"i"(offsetof(regs_t, gpr[25])),
855 [gpr26]"i"(offsetof(regs_t, gpr[26])),
856 [gpr27]"i"(offsetof(regs_t, gpr[27])),
857 [gpr28]"i"(offsetof(regs_t, gpr[28])),
858 [gpr29]"i"(offsetof(regs_t, gpr[29])),
859 [gpr30]"i"(offsetof(regs_t, gpr[30])),
860 [gpr31]"i"(offsetof(regs_t, gpr[31]))
863 asm volatile(
864 "mfmsr %%r0 \n\t"
865 "ori %%r0,%%r0, %[msrval]@l \n\t"
866 "mtmsr %%r0; isync \n\t"
867 "stfd %%f0,%[fr0](%%r3) \n\t"
868 "mffs %%f0 \n\t"
869 "stfd %%f0,%[fpscr](%%r3) \n\t"
870 "stfd %%f1,%[fr1](%%r3) \n\t"
871 "stfd %%f2,%[fr2](%%r3) \n\t"
872 "stfd %%f3,%[fr3](%%r3) \n\t"
873 "stfd %%f4,%[fr4](%%r3) \n\t"
874 "stfd %%f5,%[fr5](%%r3) \n\t"
875 "stfd %%f6,%[fr6](%%r3) \n\t"
876 "stfd %%f7,%[fr7](%%r3) \n\t"
877 "stfd %%f8,%[fr8](%%r3) \n\t"
878 "stfd %%f9,%[fr9](%%r3) \n\t"
879 "stfd %%f10,%[fr10](%%r3) \n\t"
880 "stfd %%f11,%[fr11](%%r3) \n\t"
881 "stfd %%f12,%[fr12](%%r3) \n\t"
882 "stfd %%f13,%[fr13](%%r3) \n\t"
883 "stfd %%f14,%[fr14](%%r3) \n\t"
884 "stfd %%f15,%[fr15](%%r3) \n\t"
886 [fpscr]"i"(offsetof(context_t, fpu.fpscr)),
887 [fr0]"i"(offsetof(context_t, fpu.fpr[0])),
888 [fr1]"i"(offsetof(context_t, fpu.fpr[1])),
889 [fr2]"i"(offsetof(context_t, fpu.fpr[2])),
890 [fr3]"i"(offsetof(context_t, fpu.fpr[3])),
891 [fr4]"i"(offsetof(context_t, fpu.fpr[4])),
892 [fr5]"i"(offsetof(context_t, fpu.fpr[5])),
893 [fr6]"i"(offsetof(context_t, fpu.fpr[6])),
894 [fr7]"i"(offsetof(context_t, fpu.fpr[7])),
895 [fr8]"i"(offsetof(context_t, fpu.fpr[8])),
896 [fr9]"i"(offsetof(context_t, fpu.fpr[9])),
897 [fr10]"i"(offsetof(context_t, fpu.fpr[10])),
898 [fr11]"i"(offsetof(context_t, fpu.fpr[11])),
899 [fr12]"i"(offsetof(context_t, fpu.fpr[12])),
900 [fr13]"i"(offsetof(context_t, fpu.fpr[13])),
901 [fr14]"i"(offsetof(context_t, fpu.fpr[14])),
902 [fr15]"i"(offsetof(context_t, fpu.fpr[15])),
903 [msrval]"i"(MSR_FP)
906 asm volatile(
907 "stfd %%f16,%[fr16](%%r3) \n\t"
908 "stfd %%f17,%[fr17](%%r3) \n\t"
909 "stfd %%f18,%[fr18](%%r3) \n\t"
910 "stfd %%f19,%[fr19](%%r3) \n\t"
911 "stfd %%f20,%[fr20](%%r3) \n\t"
912 "stfd %%f21,%[fr21](%%r3) \n\t"
913 "stfd %%f22,%[fr22](%%r3) \n\t"
914 "stfd %%f23,%[fr23](%%r3) \n\t"
915 "stfd %%f24,%[fr24](%%r3) \n\t"
916 "stfd %%f25,%[fr25](%%r3) \n\t"
917 "stfd %%f26,%[fr26](%%r3) \n\t"
918 "stfd %%f27,%[fr27](%%r3) \n\t"
919 "stfd %%f28,%[fr28](%%r3) \n\t"
920 "stfd %%f29,%[fr29](%%r3) \n\t"
921 "stfd %%f30,%[fr30](%%r3) \n\t"
922 "stfd %%f31,%[fr31](%%r3) \n\t"
923 "mr %%r28,%%r3 \n\t"
924 "mr %%r29,%%r4 \n\t"
925 "mr %%r30,%%r5 \n\t"
926 "mtsrr0 %%r5 \n\t"
927 "lis %%r9, %[msrval]@ha \n\t"
928 "ori %%r9,%%r9, %[msrval]@l \n\t"
929 "mtsrr1 %%r9 \n\t"
930 "sync; isync; rfi"
932 [fr16]"i"(offsetof(context_t, fpu.fpr[16])),
933 [fr17]"i"(offsetof(context_t, fpu.fpr[17])),
934 [fr18]"i"(offsetof(context_t, fpu.fpr[18])),
935 [fr19]"i"(offsetof(context_t, fpu.fpr[19])),
936 [fr20]"i"(offsetof(context_t, fpu.fpr[20])),
937 [fr21]"i"(offsetof(context_t, fpu.fpr[21])),
938 [fr22]"i"(offsetof(context_t, fpu.fpr[22])),
939 [fr23]"i"(offsetof(context_t, fpu.fpr[23])),
940 [fr24]"i"(offsetof(context_t, fpu.fpr[24])),
941 [fr25]"i"(offsetof(context_t, fpu.fpr[25])),
942 [fr26]"i"(offsetof(context_t, fpu.fpr[26])),
943 [fr27]"i"(offsetof(context_t, fpu.fpr[27])),
944 [fr28]"i"(offsetof(context_t, fpu.fpr[28])),
945 [fr29]"i"(offsetof(context_t, fpu.fpr[29])),
946 [fr30]"i"(offsetof(context_t, fpu.fpr[30])),
947 [fr31]"i"(offsetof(context_t, fpu.fpr[31])),
948 [msrval]"i"(MSR_ME|MSR_CE|MSR_FP)
953 static void __attribute__((used)) __core_LeaveInterrupt()
955 asm volatile(".section .text,\"ax\"\n\t.align 5\n\t.globl core_LeaveInterrupt\n\t.type core_LeaveInterrupt,@function\n"
956 "core_LeaveInterrupt: wrteei 0 \n\t"
957 "lwz %%r31,%[gpr31](%%r3) \n\t"
958 "lwz %%r30,%[gpr30](%%r3) \n\t"
959 "lwz %%r29,%[gpr29](%%r3) \n\t"
960 "lwz %%r28,%[gpr28](%%r3) \n\t"
961 "lwz %%r27,%[gpr27](%%r3) \n\t"
962 "lwz %%r26,%[gpr26](%%r3) \n\t"
963 "lwz %%r25,%[gpr25](%%r3) \n\t"
964 "lwz %%r24,%[gpr24](%%r3) \n\t"
965 "lwz %%r23,%[gpr23](%%r3) \n\t"
966 "lwz %%r22,%[gpr22](%%r3) \n\t"
967 "lwz %%r21,%[gpr21](%%r3) \n\t"
968 "lwz %%r20,%[gpr20](%%r3) \n\t"
969 "lwz %%r19,%[gpr19](%%r3) \n\t"
970 "lwz %%r18,%[gpr18](%%r3) \n\t"
971 "lwz %%r17,%[gpr17](%%r3) \n\t"
972 "lwz %%r16,%[gpr16](%%r3) \n\t"
973 "lwz %%r15,%[gpr15](%%r3) \n\t"
974 "lwz %%r14,%[gpr14](%%r3) \n\t"
975 "lwz %%r13,%[gpr13](%%r3) \n\t"
976 "lwz %%r12,%[gpr12](%%r3) \n\t"
978 [gpr12]"i"(offsetof(regs_t, gpr[12])),
979 [gpr13]"i"(offsetof(regs_t, gpr[13])),
980 [gpr14]"i"(offsetof(regs_t, gpr[14])),
981 [gpr15]"i"(offsetof(regs_t, gpr[15])),
982 [gpr16]"i"(offsetof(regs_t, gpr[16])),
983 [gpr17]"i"(offsetof(regs_t, gpr[17])),
984 [gpr18]"i"(offsetof(regs_t, gpr[18])),
985 [gpr19]"i"(offsetof(regs_t, gpr[19])),
986 [gpr20]"i"(offsetof(regs_t, gpr[20])),
987 [gpr21]"i"(offsetof(regs_t, gpr[21])),
988 [gpr22]"i"(offsetof(regs_t, gpr[22])),
989 [gpr23]"i"(offsetof(regs_t, gpr[23])),
990 [gpr24]"i"(offsetof(regs_t, gpr[24])),
991 [gpr25]"i"(offsetof(regs_t, gpr[25])),
992 [gpr26]"i"(offsetof(regs_t, gpr[26])),
993 [gpr27]"i"(offsetof(regs_t, gpr[27])),
994 [gpr28]"i"(offsetof(regs_t, gpr[28])),
995 [gpr29]"i"(offsetof(regs_t, gpr[29])),
996 [gpr30]"i"(offsetof(regs_t, gpr[30])),
997 [gpr31]"i"(offsetof(regs_t, gpr[31]))
1000 asm volatile(
1001 "lfd %%f0,%[fpscr](%%r3) \n\t"
1002 "mtfsf 255,%%f0 \n\t"
1003 "lfd %%f0,%[fr0](%%r3) \n\t"
1004 "lfd %%f1,%[fr1](%%r3) \n\t"
1005 "lfd %%f2,%[fr2](%%r3) \n\t"
1006 "lfd %%f3,%[fr3](%%r3) \n\t"
1007 "lfd %%f4,%[fr4](%%r3) \n\t"
1008 "lfd %%f5,%[fr5](%%r3) \n\t"
1009 "lfd %%f6,%[fr6](%%r3) \n\t"
1010 "lfd %%f7,%[fr7](%%r3) \n\t"
1011 "lfd %%f8,%[fr8](%%r3) \n\t"
1012 "lfd %%f9,%[fr9](%%r3) \n\t"
1013 "lfd %%f10,%[fr10](%%r3) \n\t"
1014 "lfd %%f11,%[fr11](%%r3) \n\t"
1015 "lfd %%f12,%[fr12](%%r3) \n\t"
1016 "lfd %%f13,%[fr13](%%r3) \n\t"
1017 "lfd %%f14,%[fr14](%%r3) \n\t"
1018 "lfd %%f15,%[fr15](%%r3) \n\t"
1020 [fpscr]"i"(offsetof(context_t, fpu.fpscr)),
1021 [fr0]"i"(offsetof(context_t, fpu.fpr[0])),
1022 [fr1]"i"(offsetof(context_t, fpu.fpr[1])),
1023 [fr2]"i"(offsetof(context_t, fpu.fpr[2])),
1024 [fr3]"i"(offsetof(context_t, fpu.fpr[3])),
1025 [fr4]"i"(offsetof(context_t, fpu.fpr[4])),
1026 [fr5]"i"(offsetof(context_t, fpu.fpr[5])),
1027 [fr6]"i"(offsetof(context_t, fpu.fpr[6])),
1028 [fr7]"i"(offsetof(context_t, fpu.fpr[7])),
1029 [fr8]"i"(offsetof(context_t, fpu.fpr[8])),
1030 [fr9]"i"(offsetof(context_t, fpu.fpr[9])),
1031 [fr10]"i"(offsetof(context_t, fpu.fpr[10])),
1032 [fr11]"i"(offsetof(context_t, fpu.fpr[11])),
1033 [fr12]"i"(offsetof(context_t, fpu.fpr[12])),
1034 [fr13]"i"(offsetof(context_t, fpu.fpr[13])),
1035 [fr14]"i"(offsetof(context_t, fpu.fpr[14])),
1036 [fr15]"i"(offsetof(context_t, fpu.fpr[15]))
1038 asm volatile(
1039 "lfd %%f16,%[fr16](%%r3) \n\t"
1040 "lfd %%f17,%[fr17](%%r3) \n\t"
1041 "lfd %%f18,%[fr18](%%r3) \n\t"
1042 "lfd %%f19,%[fr19](%%r3) \n\t"
1043 "lfd %%f20,%[fr20](%%r3) \n\t"
1044 "lfd %%f21,%[fr21](%%r3) \n\t"
1045 "lfd %%f22,%[fr22](%%r3) \n\t"
1046 "lfd %%f23,%[fr23](%%r3) \n\t"
1047 "lfd %%f24,%[fr24](%%r3) \n\t"
1048 "lfd %%f25,%[fr25](%%r3) \n\t"
1049 "lfd %%f26,%[fr26](%%r3) \n\t"
1050 "lfd %%f27,%[fr27](%%r3) \n\t"
1051 "lfd %%f28,%[fr28](%%r3) \n\t"
1052 "lfd %%f29,%[fr29](%%r3) \n\t"
1053 "lfd %%f30,%[fr30](%%r3) \n\t"
1054 "lfd %%f31,%[fr31](%%r3) \n\t"
1056 [fr16]"i"(offsetof(context_t, fpu.fpr[16])),
1057 [fr17]"i"(offsetof(context_t, fpu.fpr[17])),
1058 [fr18]"i"(offsetof(context_t, fpu.fpr[18])),
1059 [fr19]"i"(offsetof(context_t, fpu.fpr[19])),
1060 [fr20]"i"(offsetof(context_t, fpu.fpr[20])),
1061 [fr21]"i"(offsetof(context_t, fpu.fpr[21])),
1062 [fr22]"i"(offsetof(context_t, fpu.fpr[22])),
1063 [fr23]"i"(offsetof(context_t, fpu.fpr[23])),
1064 [fr24]"i"(offsetof(context_t, fpu.fpr[24])),
1065 [fr25]"i"(offsetof(context_t, fpu.fpr[25])),
1066 [fr26]"i"(offsetof(context_t, fpu.fpr[26])),
1067 [fr27]"i"(offsetof(context_t, fpu.fpr[27])),
1068 [fr28]"i"(offsetof(context_t, fpu.fpr[28])),
1069 [fr29]"i"(offsetof(context_t, fpu.fpr[29])),
1070 [fr30]"i"(offsetof(context_t, fpu.fpr[30])),
1071 [fr31]"i"(offsetof(context_t, fpu.fpr[31]))
1074 asm volatile(
1075 "lwz %%r11,%[gpr11](%%r3) \n\t"
1076 "lwz %%r0,%[srr0](%%r3) \n\t"
1077 "mtsrr0 %%r0 \n\t"
1078 "lwz %%r0,%[srr1](%%r3) \n\t"
1079 "rlwinm %%r0,%%r0,0,14,12 \n\t"
1080 "mtsrr1 %%r0 \n\t"
1081 "lwz %%r0,%[ctr](%%r3) \n\t"
1082 "mtctr %%r0 \n\t"
1083 "lwz %%r0,%[lr](%%r3) \n\t"
1084 "mtlr %%r0 \n\t"
1085 "lwz %%r0,%[xer](%%r3) \n\t"
1086 "mtxer %%r0 \n\t"
1087 "lwz %%r10,%[gpr10](%%r3) \n\t"
1088 "lwz %%r9,%[gpr9](%%r3) \n\t"
1089 "lwz %%r8,%[gpr8](%%r3) \n\t"
1090 "lwz %%r7,%[gpr7](%%r3) \n\t"
1091 "lwz %%r6,%[gpr6](%%r3) \n\t"
1092 "lwz %%r5,%[gpr5](%%r3) \n\t"
1093 "lwz %%r4,%[gpr4](%%r3) \n\t"
1094 "lwz %%r0,%[gpr3](%%r3) \n\t"
1095 "mtsprg1 %%r0 \n\t"
1096 "lwz %%r2,%[gpr2](%%r3) \n\t"
1097 "stwcx. %%r0,0,%%r1 \n\t"
1098 "lwz %%r0,%[ccr](%%r3) \n\t"
1099 "mtcr %%r0 \n\t"
1100 "lwz %%r1,%[gpr1](%%r3) \n\t"
1101 "lwz %%r0,%[gpr0](%%r3) \n\t"
1102 "mfsprg1 %%r3 \n\t"
1103 "sync; isync; rfi"
1105 [ccr]"i"(offsetof(regs_t, ccr)), /* */
1106 [srr0]"i"(offsetof(regs_t, srr0)), /* */
1107 [srr1]"i"(offsetof(regs_t, srr1)),/* */
1108 [ctr]"i"(offsetof(regs_t, ctr)),/**/
1109 [lr]"i"(offsetof(regs_t, lr)),/**/
1110 [xer]"i"(offsetof(regs_t, xer)),
1111 [gpr0]"i"(offsetof(regs_t, gpr[0])),
1112 [gpr1]"i"(offsetof(regs_t, gpr[1])),
1113 [gpr2]"i"(offsetof(regs_t, gpr[2])),
1114 [gpr3]"i"(offsetof(regs_t, gpr[3])),
1115 [gpr4]"i"(offsetof(regs_t, gpr[4])),
1116 [gpr5]"i"(offsetof(regs_t, gpr[5])),
1117 [gpr6]"i"(offsetof(regs_t, gpr[6])),
1118 [gpr7]"i"(offsetof(regs_t, gpr[7])),
1119 [gpr8]"i"(offsetof(regs_t, gpr[8])),
1120 [gpr9]"i"(offsetof(regs_t, gpr[9])),
1121 [gpr10]"i"(offsetof(regs_t, gpr[10])),
1122 [gpr11]"i"(offsetof(regs_t, gpr[11]))