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