1*d62589d5Swdenk/* 2*d62589d5Swdenk * (C) Copyright 2000-2002 3*d62589d5Swdenk * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4*d62589d5Swdenk * 5*d62589d5Swdenk * See file CREDITS for list of people who contributed to this 6*d62589d5Swdenk * project. 7*d62589d5Swdenk * 8*d62589d5Swdenk * This program is free software; you can redistribute it and/or 9*d62589d5Swdenk * modify it under the terms of the GNU General Public License as 10*d62589d5Swdenk * published by the Free Software Foundation; either version 2 of 11*d62589d5Swdenk * the License, or (at your option) any later version. 12*d62589d5Swdenk * 13*d62589d5Swdenk * This program is distributed in the hope that it will be useful, 14*d62589d5Swdenk * but WITHOUT ANY WARRANTY; without even the implied warranty of 15*d62589d5Swdenk * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*d62589d5Swdenk * GNU General Public License for more details. 17*d62589d5Swdenk * 18*d62589d5Swdenk * You should have received a copy of the GNU General Public License 19*d62589d5Swdenk * along with this program; if not, write to the Free Software 20*d62589d5Swdenk * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21*d62589d5Swdenk * MA 02111-1307 USA 22*d62589d5Swdenk */ 23*d62589d5Swdenk 24*d62589d5Swdenk/* 25*d62589d5Swdenk * This file contains all the macros and symbols which define 26*d62589d5Swdenk * a PowerPC assembly language environment. 27*d62589d5Swdenk */ 28*d62589d5Swdenk#ifndef __PPC_ASM_TMPL__ 29*d62589d5Swdenk#define __PPC_ASM_TMPL__ 30*d62589d5Swdenk 31*d62589d5Swdenk/*************************************************************************** 32*d62589d5Swdenk * 33*d62589d5Swdenk * These definitions simplify the ugly declarations necessary for GOT 34*d62589d5Swdenk * definitions. 35*d62589d5Swdenk * 36*d62589d5Swdenk * Stolen from prepboot/bootldr.h, (C) 1998 Gabriel Paubert, paubert@iram.es 37*d62589d5Swdenk * 38*d62589d5Swdenk * Uses r14 to access the GOT 39*d62589d5Swdenk */ 40*d62589d5Swdenk 41*d62589d5Swdenk#define START_GOT \ 42*d62589d5Swdenk .section ".got2","aw"; \ 43*d62589d5Swdenk.LCTOC1 = .+32768 44*d62589d5Swdenk 45*d62589d5Swdenk#define END_GOT \ 46*d62589d5Swdenk .text 47*d62589d5Swdenk 48*d62589d5Swdenk#define GET_GOT \ 49*d62589d5Swdenk bl 1f ; \ 50*d62589d5Swdenk .text 2 ; \ 51*d62589d5Swdenk0: .long .LCTOC1-1f ; \ 52*d62589d5Swdenk .text ; \ 53*d62589d5Swdenk1: mflr r14 ; \ 54*d62589d5Swdenk lwz r0,0b-1b(r14) ; \ 55*d62589d5Swdenk add r14,r0,r14 ; 56*d62589d5Swdenk 57*d62589d5Swdenk#define GOT_ENTRY(NAME) .L_ ## NAME = . - .LCTOC1 ; .long NAME 58*d62589d5Swdenk 59*d62589d5Swdenk#define GOT(NAME) .L_ ## NAME (r14) 60*d62589d5Swdenk 61*d62589d5Swdenk 62*d62589d5Swdenk/*************************************************************************** 63*d62589d5Swdenk * Register names 64*d62589d5Swdenk */ 65*d62589d5Swdenk#define r0 0 66*d62589d5Swdenk#define r1 1 67*d62589d5Swdenk#define r2 2 68*d62589d5Swdenk#define r3 3 69*d62589d5Swdenk#define r4 4 70*d62589d5Swdenk#define r5 5 71*d62589d5Swdenk#define r6 6 72*d62589d5Swdenk#define r7 7 73*d62589d5Swdenk#define r8 8 74*d62589d5Swdenk#define r9 9 75*d62589d5Swdenk#define r10 10 76*d62589d5Swdenk#define r11 11 77*d62589d5Swdenk#define r12 12 78*d62589d5Swdenk#define r13 13 79*d62589d5Swdenk#define r14 14 80*d62589d5Swdenk#define r15 15 81*d62589d5Swdenk#define r16 16 82*d62589d5Swdenk#define r17 17 83*d62589d5Swdenk#define r18 18 84*d62589d5Swdenk#define r19 19 85*d62589d5Swdenk#define r20 20 86*d62589d5Swdenk#define r21 21 87*d62589d5Swdenk#define r22 22 88*d62589d5Swdenk#define r23 23 89*d62589d5Swdenk#define r24 24 90*d62589d5Swdenk#define r25 25 91*d62589d5Swdenk#define r26 26 92*d62589d5Swdenk#define r27 27 93*d62589d5Swdenk#define r28 28 94*d62589d5Swdenk#define r29 29 95*d62589d5Swdenk#define r30 30 96*d62589d5Swdenk#define r31 31 97*d62589d5Swdenk 98*d62589d5Swdenk 99*d62589d5Swdenk#if defined(CONFIG_8xx) || defined(CONFIG_MPC824X) 100*d62589d5Swdenk 101*d62589d5Swdenk/* Some special registers */ 102*d62589d5Swdenk 103*d62589d5Swdenk#define ICR 148 /* Interrupt Cause Register (37-44) */ 104*d62589d5Swdenk#define DER 149 105*d62589d5Swdenk#define COUNTA 150 /* Breakpoint Counter (37-44) */ 106*d62589d5Swdenk#define COUNTB 151 /* Breakpoint Counter (37-44) */ 107*d62589d5Swdenk#define LCTRL1 156 /* Load/Store Support (37-40) */ 108*d62589d5Swdenk#define LCTRL2 157 /* Load/Store Support (37-41) */ 109*d62589d5Swdenk#define ICTRL 158 110*d62589d5Swdenk 111*d62589d5Swdenk#endif /* CONFIG_8xx, CONFIG_MPC824X */ 112*d62589d5Swdenk 113*d62589d5Swdenk#if defined(CONFIG_8xx) 114*d62589d5Swdenk 115*d62589d5Swdenk/* Registers in the processor's internal memory map that we use. 116*d62589d5Swdenk*/ 117*d62589d5Swdenk#define SYPCR 0x00000004 118*d62589d5Swdenk#define BR0 0x00000100 119*d62589d5Swdenk#define OR0 0x00000104 120*d62589d5Swdenk#define BR1 0x00000108 121*d62589d5Swdenk#define OR1 0x0000010c 122*d62589d5Swdenk#define BR2 0x00000110 123*d62589d5Swdenk#define OR2 0x00000114 124*d62589d5Swdenk#define BR3 0x00000118 125*d62589d5Swdenk#define OR3 0x0000011c 126*d62589d5Swdenk#define BR4 0x00000120 127*d62589d5Swdenk#define OR4 0x00000124 128*d62589d5Swdenk 129*d62589d5Swdenk#define MAR 0x00000164 130*d62589d5Swdenk#define MCR 0x00000168 131*d62589d5Swdenk#define MAMR 0x00000170 132*d62589d5Swdenk#define MBMR 0x00000174 133*d62589d5Swdenk#define MSTAT 0x00000178 134*d62589d5Swdenk#define MPTPR 0x0000017a 135*d62589d5Swdenk#define MDR 0x0000017c 136*d62589d5Swdenk 137*d62589d5Swdenk#define TBSCR 0x00000200 138*d62589d5Swdenk#define TBREFF0 0x00000204 139*d62589d5Swdenk 140*d62589d5Swdenk#define PLPRCR 0x00000284 141*d62589d5Swdenk 142*d62589d5Swdenk#elif defined(CONFIG_8260) 143*d62589d5Swdenk 144*d62589d5Swdenk#define HID2 1011 145*d62589d5Swdenk 146*d62589d5Swdenk#define HID0_IFEM (1<<7) 147*d62589d5Swdenk 148*d62589d5Swdenk#define HID0_ICE_BITPOS 16 149*d62589d5Swdenk#define HID0_DCE_BITPOS 17 150*d62589d5Swdenk 151*d62589d5Swdenk#define IM_REGBASE 0x10000 152*d62589d5Swdenk#define IM_SYPCR (IM_REGBASE+0x0004) 153*d62589d5Swdenk#define IM_SWSR (IM_REGBASE+0x000e) 154*d62589d5Swdenk#define IM_BR0 (IM_REGBASE+0x0100) 155*d62589d5Swdenk#define IM_OR0 (IM_REGBASE+0x0104) 156*d62589d5Swdenk#define IM_BR1 (IM_REGBASE+0x0108) 157*d62589d5Swdenk#define IM_OR1 (IM_REGBASE+0x010c) 158*d62589d5Swdenk#define IM_BR2 (IM_REGBASE+0x0110) 159*d62589d5Swdenk#define IM_OR2 (IM_REGBASE+0x0114) 160*d62589d5Swdenk#define IM_MPTPR (IM_REGBASE+0x0184) 161*d62589d5Swdenk#define IM_PSDMR (IM_REGBASE+0x0190) 162*d62589d5Swdenk#define IM_PSRT (IM_REGBASE+0x019c) 163*d62589d5Swdenk#define IM_IMMR (IM_REGBASE+0x01a8) 164*d62589d5Swdenk#define IM_SCCR (IM_REGBASE+0x0c80) 165*d62589d5Swdenk 166*d62589d5Swdenk#endif 167*d62589d5Swdenk 168*d62589d5Swdenk#define curptr r2 169*d62589d5Swdenk 170*d62589d5Swdenk#define SYNC \ 171*d62589d5Swdenk sync; \ 172*d62589d5Swdenk isync 173*d62589d5Swdenk 174*d62589d5Swdenk/* 175*d62589d5Swdenk * Macros for storing registers into and loading registers from 176*d62589d5Swdenk * exception frames. 177*d62589d5Swdenk */ 178*d62589d5Swdenk#define SAVE_GPR(n, base) stw n,GPR0+4*(n)(base) 179*d62589d5Swdenk#define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base) 180*d62589d5Swdenk#define SAVE_4GPRS(n, base) SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base) 181*d62589d5Swdenk#define SAVE_8GPRS(n, base) SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base) 182*d62589d5Swdenk#define SAVE_10GPRS(n, base) SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base) 183*d62589d5Swdenk#define REST_GPR(n, base) lwz n,GPR0+4*(n)(base) 184*d62589d5Swdenk#define REST_2GPRS(n, base) REST_GPR(n, base); REST_GPR(n+1, base) 185*d62589d5Swdenk#define REST_4GPRS(n, base) REST_2GPRS(n, base); REST_2GPRS(n+2, base) 186*d62589d5Swdenk#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base) 187*d62589d5Swdenk#define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, base) 188*d62589d5Swdenk 189*d62589d5Swdenk/* 190*d62589d5Swdenk * GCC sometimes accesses words at negative offsets from the stack 191*d62589d5Swdenk * pointer, although the SysV ABI says it shouldn't. To cope with 192*d62589d5Swdenk * this, we leave this much untouched space on the stack on exception 193*d62589d5Swdenk * entry. 194*d62589d5Swdenk */ 195*d62589d5Swdenk#define STACK_UNDERHEAD 64 196*d62589d5Swdenk 197*d62589d5Swdenk/* 198*d62589d5Swdenk * Exception entry code. This code runs with address translation 199*d62589d5Swdenk * turned off, i.e. using physical addresses. 200*d62589d5Swdenk * We assume sprg3 has the physical address of the current 201*d62589d5Swdenk * task's thread_struct. 202*d62589d5Swdenk */ 203*d62589d5Swdenk#define EXCEPTION_PROLOG \ 204*d62589d5Swdenk mtspr SPRG0,r20; \ 205*d62589d5Swdenk mtspr SPRG1,r21; \ 206*d62589d5Swdenk mfcr r20; \ 207*d62589d5Swdenk subi r21,r1,INT_FRAME_SIZE+STACK_UNDERHEAD; /* alloc exc. frame */\ 208*d62589d5Swdenk stw r20,_CCR(r21); /* save registers */ \ 209*d62589d5Swdenk stw r22,GPR22(r21); \ 210*d62589d5Swdenk stw r23,GPR23(r21); \ 211*d62589d5Swdenk mfspr r20,SPRG0; \ 212*d62589d5Swdenk stw r20,GPR20(r21); \ 213*d62589d5Swdenk mfspr r22,SPRG1; \ 214*d62589d5Swdenk stw r22,GPR21(r21); \ 215*d62589d5Swdenk mflr r20; \ 216*d62589d5Swdenk stw r20,_LINK(r21); \ 217*d62589d5Swdenk mfctr r22; \ 218*d62589d5Swdenk stw r22,_CTR(r21); \ 219*d62589d5Swdenk mfspr r20,XER; \ 220*d62589d5Swdenk stw r20,_XER(r21); \ 221*d62589d5Swdenk mfspr r22,SRR0; \ 222*d62589d5Swdenk mfspr r23,SRR1; \ 223*d62589d5Swdenk stw r0,GPR0(r21); \ 224*d62589d5Swdenk stw r1,GPR1(r21); \ 225*d62589d5Swdenk stw r2,GPR2(r21); \ 226*d62589d5Swdenk stw r1,0(r21); \ 227*d62589d5Swdenk mr r1,r21; /* set new kernel sp */ \ 228*d62589d5Swdenk SAVE_4GPRS(3, r21); 229*d62589d5Swdenk/* 230*d62589d5Swdenk * Note: code which follows this uses cr0.eq (set if from kernel), 231*d62589d5Swdenk * r21, r22 (SRR0), and r23 (SRR1). 232*d62589d5Swdenk */ 233*d62589d5Swdenk 234*d62589d5Swdenk/* 235*d62589d5Swdenk * Critical exception entry code. This is just like the other exception 236*d62589d5Swdenk * code except that it uses SRR2 and SRR3 instead of SRR0 and SRR1. 237*d62589d5Swdenk */ 238*d62589d5Swdenk#define CRITICAL_EXCEPTION_PROLOG \ 239*d62589d5Swdenk mtspr SPRG0,r20; \ 240*d62589d5Swdenk mtspr SPRG1,r21; \ 241*d62589d5Swdenk mfcr r20; \ 242*d62589d5Swdenk subi r21,r1,INT_FRAME_SIZE+STACK_UNDERHEAD; /* alloc exc. frame */\ 243*d62589d5Swdenk stw r20,_CCR(r21); /* save registers */ \ 244*d62589d5Swdenk stw r22,GPR22(r21); \ 245*d62589d5Swdenk stw r23,GPR23(r21); \ 246*d62589d5Swdenk mfspr r20,SPRG0; \ 247*d62589d5Swdenk stw r20,GPR20(r21); \ 248*d62589d5Swdenk mfspr r22,SPRG1; \ 249*d62589d5Swdenk stw r22,GPR21(r21); \ 250*d62589d5Swdenk mflr r20; \ 251*d62589d5Swdenk stw r20,_LINK(r21); \ 252*d62589d5Swdenk mfctr r22; \ 253*d62589d5Swdenk stw r22,_CTR(r21); \ 254*d62589d5Swdenk mfspr r20,XER; \ 255*d62589d5Swdenk stw r20,_XER(r21); \ 256*d62589d5Swdenk mfspr r22,990; /* SRR2 */ \ 257*d62589d5Swdenk mfspr r23,991; /* SRR3 */ \ 258*d62589d5Swdenk stw r0,GPR0(r21); \ 259*d62589d5Swdenk stw r1,GPR1(r21); \ 260*d62589d5Swdenk stw r2,GPR2(r21); \ 261*d62589d5Swdenk stw r1,0(r21); \ 262*d62589d5Swdenk mr r1,r21; /* set new kernel sp */ \ 263*d62589d5Swdenk SAVE_4GPRS(3, r21); 264*d62589d5Swdenk/* 265*d62589d5Swdenk * Note: code which follows this uses cr0.eq (set if from kernel), 266*d62589d5Swdenk * r21, r22 (SRR2), and r23 (SRR3). 267*d62589d5Swdenk */ 268*d62589d5Swdenk 269*d62589d5Swdenk/* 270*d62589d5Swdenk * Exception vectors. 271*d62589d5Swdenk * 272*d62589d5Swdenk * The data words for `hdlr' and `int_return' are initialized with 273*d62589d5Swdenk * OFFSET values only; they must be relocated first before they can 274*d62589d5Swdenk * be used! 275*d62589d5Swdenk */ 276*d62589d5Swdenk#define STD_EXCEPTION(n, label, hdlr) \ 277*d62589d5Swdenk . = n; \ 278*d62589d5Swdenklabel: \ 279*d62589d5Swdenk EXCEPTION_PROLOG; \ 280*d62589d5Swdenk lwz r3,GOT(transfer_to_handler); \ 281*d62589d5Swdenk mtlr r3; \ 282*d62589d5Swdenk addi r3,r1,STACK_FRAME_OVERHEAD; \ 283*d62589d5Swdenk li r20,MSR_KERNEL; \ 284*d62589d5Swdenk rlwimi r20,r23,0,25,25; \ 285*d62589d5Swdenk blrl ; \ 286*d62589d5Swdenk.L_ ## label : \ 287*d62589d5Swdenk .long hdlr - _start + EXC_OFF_SYS_RESET; \ 288*d62589d5Swdenk .long int_return - _start + EXC_OFF_SYS_RESET 289*d62589d5Swdenk 290*d62589d5Swdenk 291*d62589d5Swdenk#define CRIT_EXCEPTION(n, label, hdlr) \ 292*d62589d5Swdenk . = n; \ 293*d62589d5Swdenklabel: \ 294*d62589d5Swdenk CRITICAL_EXCEPTION_PROLOG; \ 295*d62589d5Swdenk lwz r3,GOT(transfer_to_handler); \ 296*d62589d5Swdenk mtlr r3; \ 297*d62589d5Swdenk addi r3,r1,STACK_FRAME_OVERHEAD; \ 298*d62589d5Swdenk li r20,MSR_KERNEL; \ 299*d62589d5Swdenk rlwimi r20,r23,0,25,25; \ 300*d62589d5Swdenk blrl ; \ 301*d62589d5Swdenk.L_ ## label : \ 302*d62589d5Swdenk .long hdlr - _start + EXC_OFF_SYS_RESET; \ 303*d62589d5Swdenk .long crit_return - _start + EXC_OFF_SYS_RESET 304*d62589d5Swdenk 305*d62589d5Swdenk#endif /* __PPC_ASM_TMPL__ */ 306