linux/arch/blackfin/include/asm/context.S
<<
>>
Prefs
   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