1/* 2 * File: arch/blackfin/kernel/context.S 3 * Based on: 4 * Author: 5 * 6 * Created: 7 * Description: 8 * 9 * Modified: 10 * Copyright 2004-2007 Analog Devices Inc. 11 * 12 * Bugs: Enter bugs at http://blackfin.uclinux.org/ 13 * 14 * This program is free software; you can redistribute it and/or modify 15 * it under the terms of the GNU General Public License as published by 16 * the Free Software Foundation; either version 2 of the License, or 17 * (at your option) any later version. 18 * 19 * This program is distributed in the hope that it will be useful, 20 * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * GNU General Public License for more details. 23 * 24 * You should have received a copy of the GNU General Public License 25 * along with this program; if not, see the file COPYING, or write 26 * to the Free Software Foundation, Inc., 27 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 28 */ 29 30/* 31 * NOTE! The single-stepping code assumes that all interrupt handlers 32 * start by saving SYSCFG on the stack with their first instruction. 33 */ 34 35/* 36 * Code to save processor context. 37 * We even save the register which are preserved by a function call 38 * - r4, r5, r6, r7, p3, p4, p5 39 */ 40.macro save_context_with_interrupts 41 [--sp] = SYSCFG; 42 43 [--sp] = P0; /*orig_p0*/ 44 [--sp] = R0; /*orig_r0*/ 45 46 [--sp] = ( R7:0, P5:0 ); 47 [--sp] = fp; 48 [--sp] = usp; 49 50 [--sp] = i0; 51 [--sp] = i1; 52 [--sp] = i2; 53 [--sp] = i3; 54 55 [--sp] = m0; 56 [--sp] = m1; 57 [--sp] = m2; 58 [--sp] = m3; 59 60 [--sp] = l0; 61 [--sp] = l1; 62 [--sp] = l2; 63 [--sp] = l3; 64 65 [--sp] = b0; 66 [--sp] = b1; 67 [--sp] = b2; 68 [--sp] = b3; 69 [--sp] = a0.x; 70 [--sp] = a0.w; 71 [--sp] = a1.x; 72 [--sp] = a1.w; 73 74 [--sp] = LC0; 75 [--sp] = LC1; 76 [--sp] = LT0; 77 [--sp] = LT1; 78 [--sp] = LB0; 79 [--sp] = LB1; 80 81 [--sp] = ASTAT; 82 83 [--sp] = r0; /* Skip reserved */ 84 [--sp] = RETS; 85 r0 = RETI; 86 [--sp] = r0; 87 [--sp] = RETX; 88 [--sp] = RETN; 89 [--sp] = RETE; 90 [--sp] = SEQSTAT; 91 [--sp] = r0; /* Skip IPEND as well. */ 92 /* Switch to other method of keeping interrupts disabled. */ 93#ifdef CONFIG_DEBUG_HWERR 94 r0 = 0x3f; 95 sti r0; 96#else 97 cli r0; 98#endif 99 [--sp] = RETI; /*orig_pc*/ 100 /* Clear all L registers. */ 101 r0 = 0 (x); 102 l0 = r0; 103 l1 = r0; 104 l2 = r0; 105 l3 = r0; 106.endm 107 108.macro save_context_syscall 109 [--sp] = SYSCFG; 110 111 [--sp] = P0; /*orig_p0*/ 112 [--sp] = R0; /*orig_r0*/ 113 [--sp] = ( R7:0, P5:0 ); 114 [--sp] = fp; 115 [--sp] = usp; 116 117 [--sp] = i0; 118 [--sp] = i1; 119 [--sp] = i2; 120 [--sp] = i3; 121 122 [--sp] = m0; 123 [--sp] = m1; 124 [--sp] = m2; 125 [--sp] = m3; 126 127 [--sp] = l0; 128 [--sp] = l1; 129 [--sp] = l2; 130 [--sp] = l3; 131 132 [--sp] = b0; 133 [--sp] = b1; 134 [--sp] = b2; 135 [--sp] = b3; 136 [--sp] = a0.x; 137 [--sp] = a0.w; 138 [--sp] = a1.x; 139 [--sp] = a1.w; 140 141 [--sp] = LC0; 142 [--sp] = LC1; 143 [--sp] = LT0; 144 [--sp] = LT1; 145 [--sp] = LB0; 146 [--sp] = LB1; 147 148 [--sp] = ASTAT; 149 150 [--sp] = r0; /* Skip reserved */ 151 [--sp] = RETS; 152 r0 = RETI; 153 [--sp] = r0; 154 [--sp] = RETX; 155 [--sp] = RETN; 156 [--sp] = RETE; 157 [--sp] = SEQSTAT; 158 [--sp] = r0; /* Skip IPEND as well. */ 159 [--sp] = RETI; /*orig_pc*/ 160 /* Clear all L registers. */ 161 r0 = 0 (x); 162 l0 = r0; 163 l1 = r0; 164 l2 = r0; 165 l3 = r0; 166.endm 167 168.macro save_context_no_interrupts 169 [--sp] = SYSCFG; 170 [--sp] = P0; /* orig_p0 */ 171 [--sp] = R0; /* orig_r0 */ 172 [--sp] = ( R7:0, P5:0 ); 173 [--sp] = fp; 174 [--sp] = usp; 175 176 [--sp] = i0; 177 [--sp] = i1; 178 [--sp] = i2; 179 [--sp] = i3; 180 181 [--sp] = m0; 182 [--sp] = m1; 183 [--sp] = m2; 184 [--sp] = m3; 185 186 [--sp] = l0; 187 [--sp] = l1; 188 [--sp] = l2; 189 [--sp] = l3; 190 191 [--sp] = b0; 192 [--sp] = b1; 193 [--sp] = b2; 194 [--sp] = b3; 195 [--sp] = a0.x; 196 [--sp] = a0.w; 197 [--sp] = a1.x; 198 [--sp] = a1.w; 199 200 [--sp] = LC0; 201 [--sp] = LC1; 202 [--sp] = LT0; 203 [--sp] = LT1; 204 [--sp] = LB0; 205 [--sp] = LB1; 206 207 [--sp] = ASTAT; 208 209#ifdef CONFIG_KGDB 210 fp = 0(Z); 211 r1 = sp; 212 r1 += 60; 213 r1 += 60; 214 r1 += 60; 215 [--sp] = r1; 216#else 217 [--sp] = r0; /* Skip reserved */ 218#endif 219 [--sp] = RETS; 220 r0 = RETI; 221 [--sp] = r0; 222 [--sp] = RETX; 223 [--sp] = RETN; 224 [--sp] = RETE; 225 [--sp] = SEQSTAT; 226#ifdef CONFIG_KGDB 227 r1.l = lo(IPEND); 228 r1.h = hi(IPEND); 229 [--sp] = r1; 230#else 231 [--sp] = r0; /* Skip IPEND as well. */ 232#endif 233 [--sp] = r0; /*orig_pc*/ 234 /* Clear all L registers. */ 235 r0 = 0 (x); 236 l0 = r0; 237 l1 = r0; 238 l2 = r0; 239 l3 = r0; 240.endm 241 242.macro restore_context_no_interrupts 243 sp += 4; /* Skip orig_pc */ 244 sp += 4; /* Skip IPEND */ 245 SEQSTAT = [sp++]; 246 RETE = [sp++]; 247 RETN = [sp++]; 248 RETX = [sp++]; 249 r0 = [sp++]; 250 RETI = r0; /* Restore RETI indirectly when in exception */ 251 RETS = [sp++]; 252 253 sp += 4; /* Skip Reserved */ 254 255 ASTAT = [sp++]; 256 257 LB1 = [sp++]; 258 LB0 = [sp++]; 259 LT1 = [sp++]; 260 LT0 = [sp++]; 261 LC1 = [sp++]; 262 LC0 = [sp++]; 263 264 a1.w = [sp++]; 265 a1.x = [sp++]; 266 a0.w = [sp++]; 267 a0.x = [sp++]; 268 b3 = [sp++]; 269 b2 = [sp++]; 270 b1 = [sp++]; 271 b0 = [sp++]; 272 273 l3 = [sp++]; 274 l2 = [sp++]; 275 l1 = [sp++]; 276 l0 = [sp++]; 277 278 m3 = [sp++]; 279 m2 = [sp++]; 280 m1 = [sp++]; 281 m0 = [sp++]; 282 283 i3 = [sp++]; 284 i2 = [sp++]; 285 i1 = [sp++]; 286 i0 = [sp++]; 287 288 sp += 4; 289 fp = [sp++]; 290 291 ( R7 : 0, P5 : 0) = [ SP ++ ]; 292 sp += 8; /* Skip orig_r0/orig_p0 */ 293 SYSCFG = [sp++]; 294.endm 295 296.macro restore_context_with_interrupts 297 sp += 4; /* Skip orig_pc */ 298 sp += 4; /* Skip IPEND */ 299 SEQSTAT = [sp++]; 300 RETE = [sp++]; 301 RETN = [sp++]; 302 RETX = [sp++]; 303 RETI = [sp++]; 304 RETS = [sp++]; 305 306#ifdef CONFIG_SMP 307 GET_PDA(p0, r0); 308 r0 = [p0 + PDA_IRQFLAGS]; 309#else 310 p0.h = _bfin_irq_flags; 311 p0.l = _bfin_irq_flags; 312 r0 = [p0]; 313#endif 314 sti r0; 315 316 sp += 4; /* Skip Reserved */ 317 318 ASTAT = [sp++]; 319 320 LB1 = [sp++]; 321 LB0 = [sp++]; 322 LT1 = [sp++]; 323 LT0 = [sp++]; 324 LC1 = [sp++]; 325 LC0 = [sp++]; 326 327 a1.w = [sp++]; 328 a1.x = [sp++]; 329 a0.w = [sp++]; 330 a0.x = [sp++]; 331 b3 = [sp++]; 332 b2 = [sp++]; 333 b1 = [sp++]; 334 b0 = [sp++]; 335 336 l3 = [sp++]; 337 l2 = [sp++]; 338 l1 = [sp++]; 339 l0 = [sp++]; 340 341 m3 = [sp++]; 342 m2 = [sp++]; 343 m1 = [sp++]; 344 m0 = [sp++]; 345 346 i3 = [sp++]; 347 i2 = [sp++]; 348 i1 = [sp++]; 349 i0 = [sp++]; 350 351 sp += 4; 352 fp = [sp++]; 353 354 ( R7 : 0, P5 : 0) = [ SP ++ ]; 355 sp += 8; /* Skip orig_r0/orig_p0 */ 356 csync; 357 SYSCFG = [sp++]; 358 csync; 359.endm 360 361.macro save_context_cplb 362 [--sp] = (R7:0, P5:0); 363 [--sp] = fp; 364 365 [--sp] = a0.x; 366 [--sp] = a0.w; 367 [--sp] = a1.x; 368 [--sp] = a1.w; 369 370 [--sp] = LC0; 371 [--sp] = LC1; 372 [--sp] = LT0; 373 [--sp] = LT1; 374 [--sp] = LB0; 375 [--sp] = LB1; 376 377 [--sp] = RETS; 378.endm 379 380.macro restore_context_cplb 381 RETS = [sp++]; 382 383 LB1 = [sp++]; 384 LB0 = [sp++]; 385 LT1 = [sp++]; 386 LT0 = [sp++]; 387 LC1 = [sp++]; 388 LC0 = [sp++]; 389 390 a1.w = [sp++]; 391 a1.x = [sp++]; 392 a0.w = [sp++]; 393 a0.x = [sp++]; 394 395 fp = [sp++]; 396 397 (R7:0, P5:0) = [SP++]; 398.endm 399