linux/arch/mips/kernel/octeon_switch.S
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * Copyright (C) 1994, 1995, 1996, 1998, 1999, 2002, 2003 Ralf Baechle
   7 * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
   8 * Copyright (C) 1994, 1995, 1996, by Andreas Busse
   9 * Copyright (C) 1999 Silicon Graphics, Inc.
  10 * Copyright (C) 2000 MIPS Technologies, Inc.
  11 *    written by Carsten Langgaard, carstenl@mips.com
  12 */
  13#include <asm/asm.h>
  14#include <asm/export.h>
  15#include <asm/asm-offsets.h>
  16#include <asm/mipsregs.h>
  17#include <asm/regdef.h>
  18#include <asm/stackframe.h>
  19
  20/*
  21 * task_struct *resume(task_struct *prev, task_struct *next,
  22 *                     struct thread_info *next_ti)
  23 */
  24        .align  7
  25        LEAF(resume)
  26        .set arch=octeon
  27        mfc0    t1, CP0_STATUS
  28        LONG_S  t1, THREAD_STATUS(a0)
  29        cpu_save_nonscratch a0
  30        LONG_S  ra, THREAD_REG31(a0)
  31
  32#if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0
  33        /* Check if we need to store CVMSEG state */
  34        dmfc0   t0, $11,7       /* CvmMemCtl */
  35        bbit0   t0, 6, 3f       /* Is user access enabled? */
  36
  37        /* Store the CVMSEG state */
  38        /* Extract the size of CVMSEG */
  39        andi    t0, 0x3f
  40        /* Multiply * (cache line size/sizeof(long)/2) */
  41        sll     t0, 7-LONGLOG-1
  42        li      t1, -32768      /* Base address of CVMSEG */
  43        LONG_ADDI t2, a0, THREAD_CVMSEG /* Where to store CVMSEG to */
  44        synciobdma
  452:
  46        .set noreorder
  47        LONG_L  t8, 0(t1)       /* Load from CVMSEG */
  48        subu    t0, 1           /* Decrement loop var */
  49        LONG_L  t9, LONGSIZE(t1)/* Load from CVMSEG */
  50        LONG_ADDU t1, LONGSIZE*2 /* Increment loc in CVMSEG */
  51        LONG_S  t8, 0(t2)       /* Store CVMSEG to thread storage */
  52        LONG_ADDU t2, LONGSIZE*2 /* Increment loc in thread storage */
  53        bnez    t0, 2b          /* Loop until we've copied it all */
  54         LONG_S t9, -LONGSIZE(t2)/* Store CVMSEG to thread storage */
  55        .set reorder
  56
  57        /* Disable access to CVMSEG */
  58        dmfc0   t0, $11,7       /* CvmMemCtl */
  59        xori    t0, t0, 0x40    /* Bit 6 is CVMSEG user enable */
  60        dmtc0   t0, $11,7       /* CvmMemCtl */
  61#endif
  623:
  63
  64#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
  65        PTR_LA  t8, __stack_chk_guard
  66        LONG_L  t9, TASK_STACK_CANARY(a1)
  67        LONG_S  t9, 0(t8)
  68#endif
  69
  70        /*
  71         * The order of restoring the registers takes care of the race
  72         * updating $28, $29 and kernelsp without disabling ints.
  73         */
  74        move    $28, a2
  75        cpu_restore_nonscratch a1
  76
  77        PTR_ADDU        t0, $28, _THREAD_SIZE - 32
  78        set_saved_sp    t0, t1, t2
  79
  80        mfc0    t1, CP0_STATUS          /* Do we really need this? */
  81        li      a3, 0xff01
  82        and     t1, a3
  83        LONG_L  a2, THREAD_STATUS(a1)
  84        nor     a3, $0, a3
  85        and     a2, a3
  86        or      a2, t1
  87        mtc0    a2, CP0_STATUS
  88        move    v0, a0
  89        jr      ra
  90        END(resume)
  91
  92/*
  93 * void octeon_cop2_save(struct octeon_cop2_state *a0)
  94 */
  95        .align  7
  96        .set push
  97        .set noreorder
  98        LEAF(octeon_cop2_save)
  99
 100        dmfc0   t9, $9,7        /* CvmCtl register. */
 101
 102        /* Save the COP2 CRC state */
 103        dmfc2   t0, 0x0201
 104        dmfc2   t1, 0x0202
 105        dmfc2   t2, 0x0200
 106        sd      t0, OCTEON_CP2_CRC_IV(a0)
 107        sd      t1, OCTEON_CP2_CRC_LENGTH(a0)
 108        /* Skip next instructions if CvmCtl[NODFA_CP2] set */
 109        bbit1   t9, 28, 1f
 110         sd     t2, OCTEON_CP2_CRC_POLY(a0)
 111
 112        /* Save the LLM state */
 113        dmfc2   t0, 0x0402
 114        dmfc2   t1, 0x040A
 115        sd      t0, OCTEON_CP2_LLM_DAT(a0)
 116
 1171:      bbit1   t9, 26, 3f      /* done if CvmCtl[NOCRYPTO] set */
 118         sd     t1, OCTEON_CP2_LLM_DAT+8(a0)
 119
 120        /* Save the COP2 crypto state */
 121        /* this part is mostly common to both pass 1 and later revisions */
 122        dmfc2   t0, 0x0084
 123        dmfc2   t1, 0x0080
 124        dmfc2   t2, 0x0081
 125        dmfc2   t3, 0x0082
 126        sd      t0, OCTEON_CP2_3DES_IV(a0)
 127        dmfc2   t0, 0x0088
 128        sd      t1, OCTEON_CP2_3DES_KEY(a0)
 129        dmfc2   t1, 0x0111                      /* only necessary for pass 1 */
 130        sd      t2, OCTEON_CP2_3DES_KEY+8(a0)
 131        dmfc2   t2, 0x0102
 132        sd      t3, OCTEON_CP2_3DES_KEY+16(a0)
 133        dmfc2   t3, 0x0103
 134        sd      t0, OCTEON_CP2_3DES_RESULT(a0)
 135        dmfc2   t0, 0x0104
 136        sd      t1, OCTEON_CP2_AES_INP0(a0)     /* only necessary for pass 1 */
 137        dmfc2   t1, 0x0105
 138        sd      t2, OCTEON_CP2_AES_IV(a0)
 139        dmfc2   t2, 0x0106
 140        sd      t3, OCTEON_CP2_AES_IV+8(a0)
 141        dmfc2   t3, 0x0107
 142        sd      t0, OCTEON_CP2_AES_KEY(a0)
 143        dmfc2   t0, 0x0110
 144        sd      t1, OCTEON_CP2_AES_KEY+8(a0)
 145        dmfc2   t1, 0x0100
 146        sd      t2, OCTEON_CP2_AES_KEY+16(a0)
 147        dmfc2   t2, 0x0101
 148        sd      t3, OCTEON_CP2_AES_KEY+24(a0)
 149        mfc0    v0, $15,0       /* Get the processor ID register */
 150        sd      t0, OCTEON_CP2_AES_KEYLEN(a0)
 151        li      v1, 0x000d0000  /* This is the processor ID of Octeon Pass1 */
 152        sd      t1, OCTEON_CP2_AES_RESULT(a0)
 153        /* Skip to the Pass1 version of the remainder of the COP2 state */
 154        beq     v0, v1, 2f
 155         sd     t2, OCTEON_CP2_AES_RESULT+8(a0)
 156
 157        /* the non-pass1 state when !CvmCtl[NOCRYPTO] */
 158        dmfc2   t1, 0x0240
 159        dmfc2   t2, 0x0241
 160        ori     v1, v1, 0x9500 /* lowest OCTEON III PrId*/
 161        dmfc2   t3, 0x0242
 162        subu    v1, v0, v1 /* prid - lowest OCTEON III PrId */
 163        dmfc2   t0, 0x0243
 164        sd      t1, OCTEON_CP2_HSH_DATW(a0)
 165        dmfc2   t1, 0x0244
 166        sd      t2, OCTEON_CP2_HSH_DATW+8(a0)
 167        dmfc2   t2, 0x0245
 168        sd      t3, OCTEON_CP2_HSH_DATW+16(a0)
 169        dmfc2   t3, 0x0246
 170        sd      t0, OCTEON_CP2_HSH_DATW+24(a0)
 171        dmfc2   t0, 0x0247
 172        sd      t1, OCTEON_CP2_HSH_DATW+32(a0)
 173        dmfc2   t1, 0x0248
 174        sd      t2, OCTEON_CP2_HSH_DATW+40(a0)
 175        dmfc2   t2, 0x0249
 176        sd      t3, OCTEON_CP2_HSH_DATW+48(a0)
 177        dmfc2   t3, 0x024A
 178        sd      t0, OCTEON_CP2_HSH_DATW+56(a0)
 179        dmfc2   t0, 0x024B
 180        sd      t1, OCTEON_CP2_HSH_DATW+64(a0)
 181        dmfc2   t1, 0x024C
 182        sd      t2, OCTEON_CP2_HSH_DATW+72(a0)
 183        dmfc2   t2, 0x024D
 184        sd      t3, OCTEON_CP2_HSH_DATW+80(a0)
 185        dmfc2   t3, 0x024E
 186        sd      t0, OCTEON_CP2_HSH_DATW+88(a0)
 187        dmfc2   t0, 0x0250
 188        sd      t1, OCTEON_CP2_HSH_DATW+96(a0)
 189        dmfc2   t1, 0x0251
 190        sd      t2, OCTEON_CP2_HSH_DATW+104(a0)
 191        dmfc2   t2, 0x0252
 192        sd      t3, OCTEON_CP2_HSH_DATW+112(a0)
 193        dmfc2   t3, 0x0253
 194        sd      t0, OCTEON_CP2_HSH_IVW(a0)
 195        dmfc2   t0, 0x0254
 196        sd      t1, OCTEON_CP2_HSH_IVW+8(a0)
 197        dmfc2   t1, 0x0255
 198        sd      t2, OCTEON_CP2_HSH_IVW+16(a0)
 199        dmfc2   t2, 0x0256
 200        sd      t3, OCTEON_CP2_HSH_IVW+24(a0)
 201        dmfc2   t3, 0x0257
 202        sd      t0, OCTEON_CP2_HSH_IVW+32(a0)
 203        dmfc2   t0, 0x0258
 204        sd      t1, OCTEON_CP2_HSH_IVW+40(a0)
 205        dmfc2   t1, 0x0259
 206        sd      t2, OCTEON_CP2_HSH_IVW+48(a0)
 207        dmfc2   t2, 0x025E
 208        sd      t3, OCTEON_CP2_HSH_IVW+56(a0)
 209        dmfc2   t3, 0x025A
 210        sd      t0, OCTEON_CP2_GFM_MULT(a0)
 211        dmfc2   t0, 0x025B
 212        sd      t1, OCTEON_CP2_GFM_MULT+8(a0)
 213        sd      t2, OCTEON_CP2_GFM_POLY(a0)
 214        sd      t3, OCTEON_CP2_GFM_RESULT(a0)
 215        bltz    v1, 4f
 216         sd     t0, OCTEON_CP2_GFM_RESULT+8(a0)
 217        /* OCTEON III things*/
 218        dmfc2   t0, 0x024F
 219        dmfc2   t1, 0x0050
 220        sd      t0, OCTEON_CP2_SHA3(a0)
 221        sd      t1, OCTEON_CP2_SHA3+8(a0)
 2224:
 223        jr      ra
 224         nop
 225
 2262:      /* pass 1 special stuff when !CvmCtl[NOCRYPTO] */
 227        dmfc2   t3, 0x0040
 228        dmfc2   t0, 0x0041
 229        dmfc2   t1, 0x0042
 230        dmfc2   t2, 0x0043
 231        sd      t3, OCTEON_CP2_HSH_DATW(a0)
 232        dmfc2   t3, 0x0044
 233        sd      t0, OCTEON_CP2_HSH_DATW+8(a0)
 234        dmfc2   t0, 0x0045
 235        sd      t1, OCTEON_CP2_HSH_DATW+16(a0)
 236        dmfc2   t1, 0x0046
 237        sd      t2, OCTEON_CP2_HSH_DATW+24(a0)
 238        dmfc2   t2, 0x0048
 239        sd      t3, OCTEON_CP2_HSH_DATW+32(a0)
 240        dmfc2   t3, 0x0049
 241        sd      t0, OCTEON_CP2_HSH_DATW+40(a0)
 242        dmfc2   t0, 0x004A
 243        sd      t1, OCTEON_CP2_HSH_DATW+48(a0)
 244        sd      t2, OCTEON_CP2_HSH_IVW(a0)
 245        sd      t3, OCTEON_CP2_HSH_IVW+8(a0)
 246        sd      t0, OCTEON_CP2_HSH_IVW+16(a0)
 247
 2483:      /* pass 1 or CvmCtl[NOCRYPTO] set */
 249        jr      ra
 250         nop
 251        END(octeon_cop2_save)
 252        .set pop
 253
 254/*
 255 * void octeon_cop2_restore(struct octeon_cop2_state *a0)
 256 */
 257        .align  7
 258        .set push
 259        .set noreorder
 260        LEAF(octeon_cop2_restore)
 261        /* First cache line was prefetched before the call */
 262        pref    4,  128(a0)
 263        dmfc0   t9, $9,7        /* CvmCtl register. */
 264
 265        pref    4,  256(a0)
 266        ld      t0, OCTEON_CP2_CRC_IV(a0)
 267        pref    4,  384(a0)
 268        ld      t1, OCTEON_CP2_CRC_LENGTH(a0)
 269        ld      t2, OCTEON_CP2_CRC_POLY(a0)
 270
 271        /* Restore the COP2 CRC state */
 272        dmtc2   t0, 0x0201
 273        dmtc2   t1, 0x1202
 274        bbit1   t9, 28, 2f      /* Skip LLM if CvmCtl[NODFA_CP2] is set */
 275         dmtc2  t2, 0x4200
 276
 277        /* Restore the LLM state */
 278        ld      t0, OCTEON_CP2_LLM_DAT(a0)
 279        ld      t1, OCTEON_CP2_LLM_DAT+8(a0)
 280        dmtc2   t0, 0x0402
 281        dmtc2   t1, 0x040A
 282
 2832:
 284        bbit1   t9, 26, done_restore    /* done if CvmCtl[NOCRYPTO] set */
 285         nop
 286
 287        /* Restore the COP2 crypto state common to pass 1 and pass 2 */
 288        ld      t0, OCTEON_CP2_3DES_IV(a0)
 289        ld      t1, OCTEON_CP2_3DES_KEY(a0)
 290        ld      t2, OCTEON_CP2_3DES_KEY+8(a0)
 291        dmtc2   t0, 0x0084
 292        ld      t0, OCTEON_CP2_3DES_KEY+16(a0)
 293        dmtc2   t1, 0x0080
 294        ld      t1, OCTEON_CP2_3DES_RESULT(a0)
 295        dmtc2   t2, 0x0081
 296        ld      t2, OCTEON_CP2_AES_INP0(a0) /* only really needed for pass 1 */
 297        dmtc2   t0, 0x0082
 298        ld      t0, OCTEON_CP2_AES_IV(a0)
 299        dmtc2   t1, 0x0098
 300        ld      t1, OCTEON_CP2_AES_IV+8(a0)
 301        dmtc2   t2, 0x010A                  /* only really needed for pass 1 */
 302        ld      t2, OCTEON_CP2_AES_KEY(a0)
 303        dmtc2   t0, 0x0102
 304        ld      t0, OCTEON_CP2_AES_KEY+8(a0)
 305        dmtc2   t1, 0x0103
 306        ld      t1, OCTEON_CP2_AES_KEY+16(a0)
 307        dmtc2   t2, 0x0104
 308        ld      t2, OCTEON_CP2_AES_KEY+24(a0)
 309        dmtc2   t0, 0x0105
 310        ld      t0, OCTEON_CP2_AES_KEYLEN(a0)
 311        dmtc2   t1, 0x0106
 312        ld      t1, OCTEON_CP2_AES_RESULT(a0)
 313        dmtc2   t2, 0x0107
 314        ld      t2, OCTEON_CP2_AES_RESULT+8(a0)
 315        mfc0    t3, $15,0       /* Get the processor ID register */
 316        dmtc2   t0, 0x0110
 317        li      v0, 0x000d0000  /* This is the processor ID of Octeon Pass1 */
 318        dmtc2   t1, 0x0100
 319        bne     v0, t3, 3f      /* Skip the next stuff for non-pass1 */
 320         dmtc2  t2, 0x0101
 321
 322        /* this code is specific for pass 1 */
 323        ld      t0, OCTEON_CP2_HSH_DATW(a0)
 324        ld      t1, OCTEON_CP2_HSH_DATW+8(a0)
 325        ld      t2, OCTEON_CP2_HSH_DATW+16(a0)
 326        dmtc2   t0, 0x0040
 327        ld      t0, OCTEON_CP2_HSH_DATW+24(a0)
 328        dmtc2   t1, 0x0041
 329        ld      t1, OCTEON_CP2_HSH_DATW+32(a0)
 330        dmtc2   t2, 0x0042
 331        ld      t2, OCTEON_CP2_HSH_DATW+40(a0)
 332        dmtc2   t0, 0x0043
 333        ld      t0, OCTEON_CP2_HSH_DATW+48(a0)
 334        dmtc2   t1, 0x0044
 335        ld      t1, OCTEON_CP2_HSH_IVW(a0)
 336        dmtc2   t2, 0x0045
 337        ld      t2, OCTEON_CP2_HSH_IVW+8(a0)
 338        dmtc2   t0, 0x0046
 339        ld      t0, OCTEON_CP2_HSH_IVW+16(a0)
 340        dmtc2   t1, 0x0048
 341        dmtc2   t2, 0x0049
 342        b done_restore   /* unconditional branch */
 343         dmtc2  t0, 0x004A
 344
 3453:      /* this is post-pass1 code */
 346        ld      t2, OCTEON_CP2_HSH_DATW(a0)
 347        ori     v0, v0, 0x9500 /* lowest OCTEON III PrId*/
 348        ld      t0, OCTEON_CP2_HSH_DATW+8(a0)
 349        ld      t1, OCTEON_CP2_HSH_DATW+16(a0)
 350        dmtc2   t2, 0x0240
 351        ld      t2, OCTEON_CP2_HSH_DATW+24(a0)
 352        dmtc2   t0, 0x0241
 353        ld      t0, OCTEON_CP2_HSH_DATW+32(a0)
 354        dmtc2   t1, 0x0242
 355        ld      t1, OCTEON_CP2_HSH_DATW+40(a0)
 356        dmtc2   t2, 0x0243
 357        ld      t2, OCTEON_CP2_HSH_DATW+48(a0)
 358        dmtc2   t0, 0x0244
 359        ld      t0, OCTEON_CP2_HSH_DATW+56(a0)
 360        dmtc2   t1, 0x0245
 361        ld      t1, OCTEON_CP2_HSH_DATW+64(a0)
 362        dmtc2   t2, 0x0246
 363        ld      t2, OCTEON_CP2_HSH_DATW+72(a0)
 364        dmtc2   t0, 0x0247
 365        ld      t0, OCTEON_CP2_HSH_DATW+80(a0)
 366        dmtc2   t1, 0x0248
 367        ld      t1, OCTEON_CP2_HSH_DATW+88(a0)
 368        dmtc2   t2, 0x0249
 369        ld      t2, OCTEON_CP2_HSH_DATW+96(a0)
 370        dmtc2   t0, 0x024A
 371        ld      t0, OCTEON_CP2_HSH_DATW+104(a0)
 372        dmtc2   t1, 0x024B
 373        ld      t1, OCTEON_CP2_HSH_DATW+112(a0)
 374        dmtc2   t2, 0x024C
 375        ld      t2, OCTEON_CP2_HSH_IVW(a0)
 376        dmtc2   t0, 0x024D
 377        ld      t0, OCTEON_CP2_HSH_IVW+8(a0)
 378        dmtc2   t1, 0x024E
 379        ld      t1, OCTEON_CP2_HSH_IVW+16(a0)
 380        dmtc2   t2, 0x0250
 381        ld      t2, OCTEON_CP2_HSH_IVW+24(a0)
 382        dmtc2   t0, 0x0251
 383        ld      t0, OCTEON_CP2_HSH_IVW+32(a0)
 384        dmtc2   t1, 0x0252
 385        ld      t1, OCTEON_CP2_HSH_IVW+40(a0)
 386        dmtc2   t2, 0x0253
 387        ld      t2, OCTEON_CP2_HSH_IVW+48(a0)
 388        dmtc2   t0, 0x0254
 389        ld      t0, OCTEON_CP2_HSH_IVW+56(a0)
 390        dmtc2   t1, 0x0255
 391        ld      t1, OCTEON_CP2_GFM_MULT(a0)
 392        dmtc2   t2, 0x0256
 393        ld      t2, OCTEON_CP2_GFM_MULT+8(a0)
 394        dmtc2   t0, 0x0257
 395        ld      t0, OCTEON_CP2_GFM_POLY(a0)
 396        dmtc2   t1, 0x0258
 397        ld      t1, OCTEON_CP2_GFM_RESULT(a0)
 398        dmtc2   t2, 0x0259
 399        ld      t2, OCTEON_CP2_GFM_RESULT+8(a0)
 400        dmtc2   t0, 0x025E
 401        subu    v0, t3, v0 /* prid - lowest OCTEON III PrId */
 402        dmtc2   t1, 0x025A
 403        bltz    v0, done_restore
 404         dmtc2  t2, 0x025B
 405        /* OCTEON III things*/
 406        ld      t0, OCTEON_CP2_SHA3(a0)
 407        ld      t1, OCTEON_CP2_SHA3+8(a0)
 408        dmtc2   t0, 0x0051
 409        dmtc2   t1, 0x0050
 410done_restore:
 411        jr      ra
 412         nop
 413        END(octeon_cop2_restore)
 414        .set pop
 415
 416/*
 417 * void octeon_mult_save()
 418 * sp is assumed to point to a struct pt_regs
 419 *
 420 * NOTE: This is called in SAVE_TEMP in stackframe.h. It can
 421 *       safely modify v1,k0, k1,$10-$15, and $24.  It will
 422 *       be overwritten with a processor specific version of the code.
 423 */
 424        .p2align 7
 425        .set push
 426        .set noreorder
 427        LEAF(octeon_mult_save)
 428        jr      ra
 429         nop
 430        .space 30 * 4, 0
 431octeon_mult_save_end:
 432        EXPORT(octeon_mult_save_end)
 433        END(octeon_mult_save)
 434
 435        LEAF(octeon_mult_save2)
 436        /* Save the multiplier state OCTEON II and earlier*/
 437        v3mulu  k0, $0, $0
 438        v3mulu  k1, $0, $0
 439        sd      k0, PT_MTP(sp)        /* PT_MTP    has P0 */
 440        v3mulu  k0, $0, $0
 441        sd      k1, PT_MTP+8(sp)      /* PT_MTP+8  has P1 */
 442        ori     k1, $0, 1
 443        v3mulu  k1, k1, $0
 444        sd      k0, PT_MTP+16(sp)     /* PT_MTP+16 has P2 */
 445        v3mulu  k0, $0, $0
 446        sd      k1, PT_MPL(sp)        /* PT_MPL    has MPL0 */
 447        v3mulu  k1, $0, $0
 448        sd      k0, PT_MPL+8(sp)      /* PT_MPL+8  has MPL1 */
 449        jr      ra
 450         sd     k1, PT_MPL+16(sp)     /* PT_MPL+16 has MPL2 */
 451octeon_mult_save2_end:
 452        EXPORT(octeon_mult_save2_end)
 453        END(octeon_mult_save2)
 454
 455        LEAF(octeon_mult_save3)
 456        /* Save the multiplier state OCTEON III */
 457        v3mulu  $10, $0, $0             /* read P0 */
 458        v3mulu  $11, $0, $0             /* read P1 */
 459        v3mulu  $12, $0, $0             /* read P2 */
 460        sd      $10, PT_MTP+(0*8)(sp)   /* store P0 */
 461        v3mulu  $10, $0, $0             /* read P3 */
 462        sd      $11, PT_MTP+(1*8)(sp)   /*  store P1 */
 463        v3mulu  $11, $0, $0             /* read P4 */
 464        sd      $12, PT_MTP+(2*8)(sp)   /* store P2 */
 465        ori     $13, $0, 1
 466        v3mulu  $12, $0, $0             /* read P5 */
 467        sd      $10, PT_MTP+(3*8)(sp)   /* store P3 */
 468        v3mulu  $13, $13, $0            /* P4-P0 = MPL5-MPL1, $13 = MPL0 */
 469        sd      $11, PT_MTP+(4*8)(sp)   /* store P4 */
 470        v3mulu  $10, $0, $0             /* read MPL1 */
 471        sd      $12, PT_MTP+(5*8)(sp)   /* store P5 */
 472        v3mulu  $11, $0, $0             /* read MPL2 */
 473        sd      $13, PT_MPL+(0*8)(sp)   /* store MPL0 */
 474        v3mulu  $12, $0, $0             /* read MPL3 */
 475        sd      $10, PT_MPL+(1*8)(sp)   /* store MPL1 */
 476        v3mulu  $10, $0, $0             /* read MPL4 */
 477        sd      $11, PT_MPL+(2*8)(sp)   /* store MPL2 */
 478        v3mulu  $11, $0, $0             /* read MPL5 */
 479        sd      $12, PT_MPL+(3*8)(sp)   /* store MPL3 */
 480        sd      $10, PT_MPL+(4*8)(sp)   /* store MPL4 */
 481        jr      ra
 482         sd     $11, PT_MPL+(5*8)(sp)   /* store MPL5 */
 483octeon_mult_save3_end:
 484        EXPORT(octeon_mult_save3_end)
 485        END(octeon_mult_save3)
 486        .set pop
 487
 488/*
 489 * void octeon_mult_restore()
 490 * sp is assumed to point to a struct pt_regs
 491 *
 492 * NOTE: This is called in RESTORE_TEMP in stackframe.h.
 493 */
 494        .p2align 7
 495        .set push
 496        .set noreorder
 497        LEAF(octeon_mult_restore)
 498        jr      ra
 499         nop
 500        .space 30 * 4, 0
 501octeon_mult_restore_end:
 502        EXPORT(octeon_mult_restore_end)
 503        END(octeon_mult_restore)
 504
 505        LEAF(octeon_mult_restore2)
 506        ld      v0, PT_MPL(sp)          /* MPL0 */
 507        ld      v1, PT_MPL+8(sp)        /* MPL1 */
 508        ld      k0, PT_MPL+16(sp)       /* MPL2 */
 509        /* Restore the multiplier state */
 510        ld      k1, PT_MTP+16(sp)       /* P2 */
 511        mtm0    v0                      /* MPL0 */
 512        ld      v0, PT_MTP+8(sp)        /* P1 */
 513        mtm1    v1                      /* MPL1 */
 514        ld      v1, PT_MTP(sp)          /* P0 */
 515        mtm2    k0                      /* MPL2 */
 516        mtp2    k1                      /* P2 */
 517        mtp1    v0                      /* P1 */
 518        jr      ra
 519         mtp0   v1                      /* P0 */
 520octeon_mult_restore2_end:
 521        EXPORT(octeon_mult_restore2_end)
 522        END(octeon_mult_restore2)
 523
 524        LEAF(octeon_mult_restore3)
 525        ld      $12, PT_MPL+(0*8)(sp)   /* read MPL0 */
 526        ld      $13, PT_MPL+(3*8)(sp)   /* read MPL3 */
 527        ld      $10, PT_MPL+(1*8)(sp)   /* read MPL1 */
 528        ld      $11, PT_MPL+(4*8)(sp)   /* read MPL4 */
 529        .word   0x718d0008
 530        /* mtm0 $12, $13                   restore MPL0 and MPL3 */
 531        ld      $12, PT_MPL+(2*8)(sp)   /* read MPL2 */
 532        .word   0x714b000c
 533        /* mtm1 $10, $11                   restore MPL1 and MPL4 */
 534        ld      $13, PT_MPL+(5*8)(sp)   /* read MPL5 */
 535        ld      $10, PT_MTP+(0*8)(sp)   /* read P0 */
 536        ld      $11, PT_MTP+(3*8)(sp)   /* read P3 */
 537        .word   0x718d000d
 538        /* mtm2 $12, $13                   restore MPL2 and MPL5 */
 539        ld      $12, PT_MTP+(1*8)(sp)   /* read P1 */
 540        .word   0x714b0009
 541        /* mtp0 $10, $11                   restore P0 and P3 */
 542        ld      $13, PT_MTP+(4*8)(sp)   /* read P4 */
 543        ld      $10, PT_MTP+(2*8)(sp)   /* read P2 */
 544        ld      $11, PT_MTP+(5*8)(sp)   /* read P5 */
 545        .word   0x718d000a
 546        /* mtp1 $12, $13                   restore P1 and P4 */
 547        jr      ra
 548        .word   0x714b000b
 549        /* mtp2 $10, $11                   restore P2 and P5 */
 550
 551octeon_mult_restore3_end:
 552        EXPORT(octeon_mult_restore3_end)
 553        END(octeon_mult_restore3)
 554        .set pop
 555