Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * This file is subject to the terms and conditions of the GNU General Public
0003  * License.  See the file "COPYING" in the main directory of this archive
0004  * for more details.
0005  *
0006  * Copyright (C) 1994, 1995, 1996, 1998, 1999, 2002, 2003 Ralf Baechle
0007  * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
0008  * Copyright (C) 1994, 1995, 1996, by Andreas Busse
0009  * Copyright (C) 1999 Silicon Graphics, Inc.
0010  * Copyright (C) 2000 MIPS Technologies, Inc.
0011  *    written by Carsten Langgaard, carstenl@mips.com
0012  */
0013 #include <asm/asm.h>
0014 #include <asm/export.h>
0015 #include <asm/asm-offsets.h>
0016 #include <asm/mipsregs.h>
0017 #include <asm/regdef.h>
0018 #include <asm/stackframe.h>
0019 
0020 /*
0021  * task_struct *resume(task_struct *prev, task_struct *next,
0022  *             struct thread_info *next_ti)
0023  */
0024     .align  7
0025     LEAF(resume)
0026     .set arch=octeon
0027     mfc0    t1, CP0_STATUS
0028     LONG_S  t1, THREAD_STATUS(a0)
0029     cpu_save_nonscratch a0
0030     LONG_S  ra, THREAD_REG31(a0)
0031 
0032 #if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0
0033     /* Check if we need to store CVMSEG state */
0034     dmfc0   t0, $11,7   /* CvmMemCtl */
0035     bbit0   t0, 6, 3f   /* Is user access enabled? */
0036 
0037     /* Store the CVMSEG state */
0038     /* Extract the size of CVMSEG */
0039     andi    t0, 0x3f
0040     /* Multiply * (cache line size/sizeof(long)/2) */
0041     sll t0, 7-LONGLOG-1
0042     li  t1, -32768  /* Base address of CVMSEG */
0043     LONG_ADDI t2, a0, THREAD_CVMSEG /* Where to store CVMSEG to */
0044     synciobdma
0045 2:
0046     .set noreorder
0047     LONG_L  t8, 0(t1)   /* Load from CVMSEG */
0048     subu    t0, 1       /* Decrement loop var */
0049     LONG_L  t9, LONGSIZE(t1)/* Load from CVMSEG */
0050     LONG_ADDU t1, LONGSIZE*2 /* Increment loc in CVMSEG */
0051     LONG_S  t8, 0(t2)   /* Store CVMSEG to thread storage */
0052     LONG_ADDU t2, LONGSIZE*2 /* Increment loc in thread storage */
0053     bnez    t0, 2b      /* Loop until we've copied it all */
0054      LONG_S t9, -LONGSIZE(t2)/* Store CVMSEG to thread storage */
0055     .set reorder
0056 
0057     /* Disable access to CVMSEG */
0058     dmfc0   t0, $11,7   /* CvmMemCtl */
0059     xori    t0, t0, 0x40    /* Bit 6 is CVMSEG user enable */
0060     dmtc0   t0, $11,7   /* CvmMemCtl */
0061 #endif
0062 3:
0063 
0064 #if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_SMP)
0065     PTR_LA  t8, __stack_chk_guard
0066     LONG_L  t9, TASK_STACK_CANARY(a1)
0067     LONG_S  t9, 0(t8)
0068 #endif
0069 
0070     /*
0071      * The order of restoring the registers takes care of the race
0072      * updating $28, $29 and kernelsp without disabling ints.
0073      */
0074     move    $28, a2
0075     cpu_restore_nonscratch a1
0076 
0077     PTR_ADDU    t0, $28, _THREAD_SIZE - 32
0078     set_saved_sp    t0, t1, t2
0079 
0080     mfc0    t1, CP0_STATUS      /* Do we really need this? */
0081     li  a3, 0xff01
0082     and t1, a3
0083     LONG_L  a2, THREAD_STATUS(a1)
0084     nor a3, $0, a3
0085     and a2, a3
0086     or  a2, t1
0087     mtc0    a2, CP0_STATUS
0088     move    v0, a0
0089     jr  ra
0090     END(resume)
0091 
0092 /*
0093  * void octeon_cop2_save(struct octeon_cop2_state *a0)
0094  */
0095     .align  7
0096     .set push
0097     .set noreorder
0098     LEAF(octeon_cop2_save)
0099 
0100     dmfc0   t9, $9,7    /* CvmCtl register. */
0101 
0102     /* Save the COP2 CRC state */
0103     dmfc2   t0, 0x0201
0104     dmfc2   t1, 0x0202
0105     dmfc2   t2, 0x0200
0106     sd  t0, OCTEON_CP2_CRC_IV(a0)
0107     sd  t1, OCTEON_CP2_CRC_LENGTH(a0)
0108     /* Skip next instructions if CvmCtl[NODFA_CP2] set */
0109     bbit1   t9, 28, 1f
0110      sd t2, OCTEON_CP2_CRC_POLY(a0)
0111 
0112     /* Save the LLM state */
0113     dmfc2   t0, 0x0402
0114     dmfc2   t1, 0x040A
0115     sd  t0, OCTEON_CP2_LLM_DAT(a0)
0116 
0117 1:  bbit1   t9, 26, 3f  /* done if CvmCtl[NOCRYPTO] set */
0118      sd t1, OCTEON_CP2_LLM_DAT+8(a0)
0119 
0120     /* Save the COP2 crypto state */
0121     /* this part is mostly common to both pass 1 and later revisions */
0122     dmfc2   t0, 0x0084
0123     dmfc2   t1, 0x0080
0124     dmfc2   t2, 0x0081
0125     dmfc2   t3, 0x0082
0126     sd  t0, OCTEON_CP2_3DES_IV(a0)
0127     dmfc2   t0, 0x0088
0128     sd  t1, OCTEON_CP2_3DES_KEY(a0)
0129     dmfc2   t1, 0x0111          /* only necessary for pass 1 */
0130     sd  t2, OCTEON_CP2_3DES_KEY+8(a0)
0131     dmfc2   t2, 0x0102
0132     sd  t3, OCTEON_CP2_3DES_KEY+16(a0)
0133     dmfc2   t3, 0x0103
0134     sd  t0, OCTEON_CP2_3DES_RESULT(a0)
0135     dmfc2   t0, 0x0104
0136     sd  t1, OCTEON_CP2_AES_INP0(a0) /* only necessary for pass 1 */
0137     dmfc2   t1, 0x0105
0138     sd  t2, OCTEON_CP2_AES_IV(a0)
0139     dmfc2   t2, 0x0106
0140     sd  t3, OCTEON_CP2_AES_IV+8(a0)
0141     dmfc2   t3, 0x0107
0142     sd  t0, OCTEON_CP2_AES_KEY(a0)
0143     dmfc2   t0, 0x0110
0144     sd  t1, OCTEON_CP2_AES_KEY+8(a0)
0145     dmfc2   t1, 0x0100
0146     sd  t2, OCTEON_CP2_AES_KEY+16(a0)
0147     dmfc2   t2, 0x0101
0148     sd  t3, OCTEON_CP2_AES_KEY+24(a0)
0149     mfc0    v0, $15,0   /* Get the processor ID register */
0150     sd  t0, OCTEON_CP2_AES_KEYLEN(a0)
0151     li  v1, 0x000d0000  /* This is the processor ID of Octeon Pass1 */
0152     sd  t1, OCTEON_CP2_AES_RESULT(a0)
0153     /* Skip to the Pass1 version of the remainder of the COP2 state */
0154     beq v0, v1, 2f
0155      sd t2, OCTEON_CP2_AES_RESULT+8(a0)
0156 
0157     /* the non-pass1 state when !CvmCtl[NOCRYPTO] */
0158     dmfc2   t1, 0x0240
0159     dmfc2   t2, 0x0241
0160     ori v1, v1, 0x9500 /* lowest OCTEON III PrId*/
0161     dmfc2   t3, 0x0242
0162     subu    v1, v0, v1 /* prid - lowest OCTEON III PrId */
0163     dmfc2   t0, 0x0243
0164     sd  t1, OCTEON_CP2_HSH_DATW(a0)
0165     dmfc2   t1, 0x0244
0166     sd  t2, OCTEON_CP2_HSH_DATW+8(a0)
0167     dmfc2   t2, 0x0245
0168     sd  t3, OCTEON_CP2_HSH_DATW+16(a0)
0169     dmfc2   t3, 0x0246
0170     sd  t0, OCTEON_CP2_HSH_DATW+24(a0)
0171     dmfc2   t0, 0x0247
0172     sd  t1, OCTEON_CP2_HSH_DATW+32(a0)
0173     dmfc2   t1, 0x0248
0174     sd  t2, OCTEON_CP2_HSH_DATW+40(a0)
0175     dmfc2   t2, 0x0249
0176     sd  t3, OCTEON_CP2_HSH_DATW+48(a0)
0177     dmfc2   t3, 0x024A
0178     sd  t0, OCTEON_CP2_HSH_DATW+56(a0)
0179     dmfc2   t0, 0x024B
0180     sd  t1, OCTEON_CP2_HSH_DATW+64(a0)
0181     dmfc2   t1, 0x024C
0182     sd  t2, OCTEON_CP2_HSH_DATW+72(a0)
0183     dmfc2   t2, 0x024D
0184     sd  t3, OCTEON_CP2_HSH_DATW+80(a0)
0185     dmfc2   t3, 0x024E
0186     sd  t0, OCTEON_CP2_HSH_DATW+88(a0)
0187     dmfc2   t0, 0x0250
0188     sd  t1, OCTEON_CP2_HSH_DATW+96(a0)
0189     dmfc2   t1, 0x0251
0190     sd  t2, OCTEON_CP2_HSH_DATW+104(a0)
0191     dmfc2   t2, 0x0252
0192     sd  t3, OCTEON_CP2_HSH_DATW+112(a0)
0193     dmfc2   t3, 0x0253
0194     sd  t0, OCTEON_CP2_HSH_IVW(a0)
0195     dmfc2   t0, 0x0254
0196     sd  t1, OCTEON_CP2_HSH_IVW+8(a0)
0197     dmfc2   t1, 0x0255
0198     sd  t2, OCTEON_CP2_HSH_IVW+16(a0)
0199     dmfc2   t2, 0x0256
0200     sd  t3, OCTEON_CP2_HSH_IVW+24(a0)
0201     dmfc2   t3, 0x0257
0202     sd  t0, OCTEON_CP2_HSH_IVW+32(a0)
0203     dmfc2   t0, 0x0258
0204     sd  t1, OCTEON_CP2_HSH_IVW+40(a0)
0205     dmfc2   t1, 0x0259
0206     sd  t2, OCTEON_CP2_HSH_IVW+48(a0)
0207     dmfc2   t2, 0x025E
0208     sd  t3, OCTEON_CP2_HSH_IVW+56(a0)
0209     dmfc2   t3, 0x025A
0210     sd  t0, OCTEON_CP2_GFM_MULT(a0)
0211     dmfc2   t0, 0x025B
0212     sd  t1, OCTEON_CP2_GFM_MULT+8(a0)
0213     sd  t2, OCTEON_CP2_GFM_POLY(a0)
0214     sd  t3, OCTEON_CP2_GFM_RESULT(a0)
0215     bltz    v1, 4f
0216      sd t0, OCTEON_CP2_GFM_RESULT+8(a0)
0217     /* OCTEON III things*/
0218     dmfc2   t0, 0x024F
0219     dmfc2   t1, 0x0050
0220     sd  t0, OCTEON_CP2_SHA3(a0)
0221     sd  t1, OCTEON_CP2_SHA3+8(a0)
0222 4:
0223     jr  ra
0224      nop
0225 
0226 2:  /* pass 1 special stuff when !CvmCtl[NOCRYPTO] */
0227     dmfc2   t3, 0x0040
0228     dmfc2   t0, 0x0041
0229     dmfc2   t1, 0x0042
0230     dmfc2   t2, 0x0043
0231     sd  t3, OCTEON_CP2_HSH_DATW(a0)
0232     dmfc2   t3, 0x0044
0233     sd  t0, OCTEON_CP2_HSH_DATW+8(a0)
0234     dmfc2   t0, 0x0045
0235     sd  t1, OCTEON_CP2_HSH_DATW+16(a0)
0236     dmfc2   t1, 0x0046
0237     sd  t2, OCTEON_CP2_HSH_DATW+24(a0)
0238     dmfc2   t2, 0x0048
0239     sd  t3, OCTEON_CP2_HSH_DATW+32(a0)
0240     dmfc2   t3, 0x0049
0241     sd  t0, OCTEON_CP2_HSH_DATW+40(a0)
0242     dmfc2   t0, 0x004A
0243     sd  t1, OCTEON_CP2_HSH_DATW+48(a0)
0244     sd  t2, OCTEON_CP2_HSH_IVW(a0)
0245     sd  t3, OCTEON_CP2_HSH_IVW+8(a0)
0246     sd  t0, OCTEON_CP2_HSH_IVW+16(a0)
0247 
0248 3:  /* pass 1 or CvmCtl[NOCRYPTO] set */
0249     jr  ra
0250      nop
0251     END(octeon_cop2_save)
0252     .set pop
0253 
0254 /*
0255  * void octeon_cop2_restore(struct octeon_cop2_state *a0)
0256  */
0257     .align  7
0258     .set push
0259     .set noreorder
0260     LEAF(octeon_cop2_restore)
0261     /* First cache line was prefetched before the call */
0262     pref    4,  128(a0)
0263     dmfc0   t9, $9,7    /* CvmCtl register. */
0264 
0265     pref    4,  256(a0)
0266     ld  t0, OCTEON_CP2_CRC_IV(a0)
0267     pref    4,  384(a0)
0268     ld  t1, OCTEON_CP2_CRC_LENGTH(a0)
0269     ld  t2, OCTEON_CP2_CRC_POLY(a0)
0270 
0271     /* Restore the COP2 CRC state */
0272     dmtc2   t0, 0x0201
0273     dmtc2   t1, 0x1202
0274     bbit1   t9, 28, 2f  /* Skip LLM if CvmCtl[NODFA_CP2] is set */
0275      dmtc2  t2, 0x4200
0276 
0277     /* Restore the LLM state */
0278     ld  t0, OCTEON_CP2_LLM_DAT(a0)
0279     ld  t1, OCTEON_CP2_LLM_DAT+8(a0)
0280     dmtc2   t0, 0x0402
0281     dmtc2   t1, 0x040A
0282 
0283 2:
0284     bbit1   t9, 26, done_restore    /* done if CvmCtl[NOCRYPTO] set */
0285      nop
0286 
0287     /* Restore the COP2 crypto state common to pass 1 and pass 2 */
0288     ld  t0, OCTEON_CP2_3DES_IV(a0)
0289     ld  t1, OCTEON_CP2_3DES_KEY(a0)
0290     ld  t2, OCTEON_CP2_3DES_KEY+8(a0)
0291     dmtc2   t0, 0x0084
0292     ld  t0, OCTEON_CP2_3DES_KEY+16(a0)
0293     dmtc2   t1, 0x0080
0294     ld  t1, OCTEON_CP2_3DES_RESULT(a0)
0295     dmtc2   t2, 0x0081
0296     ld  t2, OCTEON_CP2_AES_INP0(a0) /* only really needed for pass 1 */
0297     dmtc2   t0, 0x0082
0298     ld  t0, OCTEON_CP2_AES_IV(a0)
0299     dmtc2   t1, 0x0098
0300     ld  t1, OCTEON_CP2_AES_IV+8(a0)
0301     dmtc2   t2, 0x010A          /* only really needed for pass 1 */
0302     ld  t2, OCTEON_CP2_AES_KEY(a0)
0303     dmtc2   t0, 0x0102
0304     ld  t0, OCTEON_CP2_AES_KEY+8(a0)
0305     dmtc2   t1, 0x0103
0306     ld  t1, OCTEON_CP2_AES_KEY+16(a0)
0307     dmtc2   t2, 0x0104
0308     ld  t2, OCTEON_CP2_AES_KEY+24(a0)
0309     dmtc2   t0, 0x0105
0310     ld  t0, OCTEON_CP2_AES_KEYLEN(a0)
0311     dmtc2   t1, 0x0106
0312     ld  t1, OCTEON_CP2_AES_RESULT(a0)
0313     dmtc2   t2, 0x0107
0314     ld  t2, OCTEON_CP2_AES_RESULT+8(a0)
0315     mfc0    t3, $15,0   /* Get the processor ID register */
0316     dmtc2   t0, 0x0110
0317     li  v0, 0x000d0000  /* This is the processor ID of Octeon Pass1 */
0318     dmtc2   t1, 0x0100
0319     bne v0, t3, 3f  /* Skip the next stuff for non-pass1 */
0320      dmtc2  t2, 0x0101
0321 
0322     /* this code is specific for pass 1 */
0323     ld  t0, OCTEON_CP2_HSH_DATW(a0)
0324     ld  t1, OCTEON_CP2_HSH_DATW+8(a0)
0325     ld  t2, OCTEON_CP2_HSH_DATW+16(a0)
0326     dmtc2   t0, 0x0040
0327     ld  t0, OCTEON_CP2_HSH_DATW+24(a0)
0328     dmtc2   t1, 0x0041
0329     ld  t1, OCTEON_CP2_HSH_DATW+32(a0)
0330     dmtc2   t2, 0x0042
0331     ld  t2, OCTEON_CP2_HSH_DATW+40(a0)
0332     dmtc2   t0, 0x0043
0333     ld  t0, OCTEON_CP2_HSH_DATW+48(a0)
0334     dmtc2   t1, 0x0044
0335     ld  t1, OCTEON_CP2_HSH_IVW(a0)
0336     dmtc2   t2, 0x0045
0337     ld  t2, OCTEON_CP2_HSH_IVW+8(a0)
0338     dmtc2   t0, 0x0046
0339     ld  t0, OCTEON_CP2_HSH_IVW+16(a0)
0340     dmtc2   t1, 0x0048
0341     dmtc2   t2, 0x0049
0342     b done_restore   /* unconditional branch */
0343      dmtc2  t0, 0x004A
0344 
0345 3:  /* this is post-pass1 code */
0346     ld  t2, OCTEON_CP2_HSH_DATW(a0)
0347     ori v0, v0, 0x9500 /* lowest OCTEON III PrId*/
0348     ld  t0, OCTEON_CP2_HSH_DATW+8(a0)
0349     ld  t1, OCTEON_CP2_HSH_DATW+16(a0)
0350     dmtc2   t2, 0x0240
0351     ld  t2, OCTEON_CP2_HSH_DATW+24(a0)
0352     dmtc2   t0, 0x0241
0353     ld  t0, OCTEON_CP2_HSH_DATW+32(a0)
0354     dmtc2   t1, 0x0242
0355     ld  t1, OCTEON_CP2_HSH_DATW+40(a0)
0356     dmtc2   t2, 0x0243
0357     ld  t2, OCTEON_CP2_HSH_DATW+48(a0)
0358     dmtc2   t0, 0x0244
0359     ld  t0, OCTEON_CP2_HSH_DATW+56(a0)
0360     dmtc2   t1, 0x0245
0361     ld  t1, OCTEON_CP2_HSH_DATW+64(a0)
0362     dmtc2   t2, 0x0246
0363     ld  t2, OCTEON_CP2_HSH_DATW+72(a0)
0364     dmtc2   t0, 0x0247
0365     ld  t0, OCTEON_CP2_HSH_DATW+80(a0)
0366     dmtc2   t1, 0x0248
0367     ld  t1, OCTEON_CP2_HSH_DATW+88(a0)
0368     dmtc2   t2, 0x0249
0369     ld  t2, OCTEON_CP2_HSH_DATW+96(a0)
0370     dmtc2   t0, 0x024A
0371     ld  t0, OCTEON_CP2_HSH_DATW+104(a0)
0372     dmtc2   t1, 0x024B
0373     ld  t1, OCTEON_CP2_HSH_DATW+112(a0)
0374     dmtc2   t2, 0x024C
0375     ld  t2, OCTEON_CP2_HSH_IVW(a0)
0376     dmtc2   t0, 0x024D
0377     ld  t0, OCTEON_CP2_HSH_IVW+8(a0)
0378     dmtc2   t1, 0x024E
0379     ld  t1, OCTEON_CP2_HSH_IVW+16(a0)
0380     dmtc2   t2, 0x0250
0381     ld  t2, OCTEON_CP2_HSH_IVW+24(a0)
0382     dmtc2   t0, 0x0251
0383     ld  t0, OCTEON_CP2_HSH_IVW+32(a0)
0384     dmtc2   t1, 0x0252
0385     ld  t1, OCTEON_CP2_HSH_IVW+40(a0)
0386     dmtc2   t2, 0x0253
0387     ld  t2, OCTEON_CP2_HSH_IVW+48(a0)
0388     dmtc2   t0, 0x0254
0389     ld  t0, OCTEON_CP2_HSH_IVW+56(a0)
0390     dmtc2   t1, 0x0255
0391     ld  t1, OCTEON_CP2_GFM_MULT(a0)
0392     dmtc2   t2, 0x0256
0393     ld  t2, OCTEON_CP2_GFM_MULT+8(a0)
0394     dmtc2   t0, 0x0257
0395     ld  t0, OCTEON_CP2_GFM_POLY(a0)
0396     dmtc2   t1, 0x0258
0397     ld  t1, OCTEON_CP2_GFM_RESULT(a0)
0398     dmtc2   t2, 0x0259
0399     ld  t2, OCTEON_CP2_GFM_RESULT+8(a0)
0400     dmtc2   t0, 0x025E
0401     subu    v0, t3, v0 /* prid - lowest OCTEON III PrId */
0402     dmtc2   t1, 0x025A
0403     bltz    v0, done_restore
0404      dmtc2  t2, 0x025B
0405     /* OCTEON III things*/
0406     ld  t0, OCTEON_CP2_SHA3(a0)
0407     ld  t1, OCTEON_CP2_SHA3+8(a0)
0408     dmtc2   t0, 0x0051
0409     dmtc2   t1, 0x0050
0410 done_restore:
0411     jr  ra
0412      nop
0413     END(octeon_cop2_restore)
0414     .set pop
0415 
0416 /*
0417  * void octeon_mult_save()
0418  * sp is assumed to point to a struct pt_regs
0419  *
0420  * NOTE: This is called in SAVE_TEMP in stackframe.h. It can
0421  *       safely modify v1,k0, k1,$10-$15, and $24.  It will
0422  *   be overwritten with a processor specific version of the code.
0423  */
0424     .p2align 7
0425     .set push
0426     .set noreorder
0427     LEAF(octeon_mult_save)
0428     jr  ra
0429      nop
0430     .space 30 * 4, 0
0431 octeon_mult_save_end:
0432     EXPORT(octeon_mult_save_end)
0433     END(octeon_mult_save)
0434 
0435     LEAF(octeon_mult_save2)
0436     /* Save the multiplier state OCTEON II and earlier*/
0437     v3mulu  k0, $0, $0
0438     v3mulu  k1, $0, $0
0439     sd  k0, PT_MTP(sp)        /* PT_MTP    has P0 */
0440     v3mulu  k0, $0, $0
0441     sd  k1, PT_MTP+8(sp)      /* PT_MTP+8  has P1 */
0442     ori k1, $0, 1
0443     v3mulu  k1, k1, $0
0444     sd  k0, PT_MTP+16(sp)     /* PT_MTP+16 has P2 */
0445     v3mulu  k0, $0, $0
0446     sd  k1, PT_MPL(sp)        /* PT_MPL    has MPL0 */
0447     v3mulu  k1, $0, $0
0448     sd  k0, PT_MPL+8(sp)      /* PT_MPL+8  has MPL1 */
0449     jr  ra
0450      sd k1, PT_MPL+16(sp)     /* PT_MPL+16 has MPL2 */
0451 octeon_mult_save2_end:
0452     EXPORT(octeon_mult_save2_end)
0453     END(octeon_mult_save2)
0454 
0455     LEAF(octeon_mult_save3)
0456     /* Save the multiplier state OCTEON III */
0457     v3mulu  $10, $0, $0     /* read P0 */
0458     v3mulu  $11, $0, $0     /* read P1 */
0459     v3mulu  $12, $0, $0     /* read P2 */
0460     sd  $10, PT_MTP+(0*8)(sp)   /* store P0 */
0461     v3mulu  $10, $0, $0     /* read P3 */
0462     sd  $11, PT_MTP+(1*8)(sp)   /*  store P1 */
0463     v3mulu  $11, $0, $0     /* read P4 */
0464     sd  $12, PT_MTP+(2*8)(sp)   /* store P2 */
0465     ori $13, $0, 1
0466     v3mulu  $12, $0, $0     /* read P5 */
0467     sd  $10, PT_MTP+(3*8)(sp)   /* store P3 */
0468     v3mulu  $13, $13, $0        /* P4-P0 = MPL5-MPL1, $13 = MPL0 */
0469     sd  $11, PT_MTP+(4*8)(sp)   /* store P4 */
0470     v3mulu  $10, $0, $0     /* read MPL1 */
0471     sd  $12, PT_MTP+(5*8)(sp)   /* store P5 */
0472     v3mulu  $11, $0, $0     /* read MPL2 */
0473     sd  $13, PT_MPL+(0*8)(sp)   /* store MPL0 */
0474     v3mulu  $12, $0, $0     /* read MPL3 */
0475     sd  $10, PT_MPL+(1*8)(sp)   /* store MPL1 */
0476     v3mulu  $10, $0, $0     /* read MPL4 */
0477     sd  $11, PT_MPL+(2*8)(sp)   /* store MPL2 */
0478     v3mulu  $11, $0, $0     /* read MPL5 */
0479     sd  $12, PT_MPL+(3*8)(sp)   /* store MPL3 */
0480     sd  $10, PT_MPL+(4*8)(sp)   /* store MPL4 */
0481     jr  ra
0482      sd $11, PT_MPL+(5*8)(sp)   /* store MPL5 */
0483 octeon_mult_save3_end:
0484     EXPORT(octeon_mult_save3_end)
0485     END(octeon_mult_save3)
0486     .set pop
0487 
0488 /*
0489  * void octeon_mult_restore()
0490  * sp is assumed to point to a struct pt_regs
0491  *
0492  * NOTE: This is called in RESTORE_TEMP in stackframe.h.
0493  */
0494     .p2align 7
0495     .set push
0496     .set noreorder
0497     LEAF(octeon_mult_restore)
0498     jr  ra
0499      nop
0500     .space 30 * 4, 0
0501 octeon_mult_restore_end:
0502     EXPORT(octeon_mult_restore_end)
0503     END(octeon_mult_restore)
0504 
0505     LEAF(octeon_mult_restore2)
0506     ld  v0, PT_MPL(sp)          /* MPL0 */
0507     ld  v1, PT_MPL+8(sp)        /* MPL1 */
0508     ld  k0, PT_MPL+16(sp)       /* MPL2 */
0509     /* Restore the multiplier state */
0510     ld  k1, PT_MTP+16(sp)       /* P2 */
0511     mtm0    v0          /* MPL0 */
0512     ld  v0, PT_MTP+8(sp)    /* P1 */
0513     mtm1    v1          /* MPL1 */
0514     ld  v1, PT_MTP(sp)      /* P0 */
0515     mtm2    k0          /* MPL2 */
0516     mtp2    k1          /* P2 */
0517     mtp1    v0          /* P1 */
0518     jr  ra
0519      mtp0   v1          /* P0 */
0520 octeon_mult_restore2_end:
0521     EXPORT(octeon_mult_restore2_end)
0522     END(octeon_mult_restore2)
0523 
0524     LEAF(octeon_mult_restore3)
0525     ld  $12, PT_MPL+(0*8)(sp)   /* read MPL0 */
0526     ld  $13, PT_MPL+(3*8)(sp)   /* read MPL3 */
0527     ld  $10, PT_MPL+(1*8)(sp)   /* read MPL1 */
0528     ld  $11, PT_MPL+(4*8)(sp)   /* read MPL4 */
0529     .word   0x718d0008
0530     /* mtm0 $12, $13           restore MPL0 and MPL3 */
0531     ld  $12, PT_MPL+(2*8)(sp)   /* read MPL2 */
0532     .word   0x714b000c
0533     /* mtm1 $10, $11           restore MPL1 and MPL4 */
0534     ld  $13, PT_MPL+(5*8)(sp)   /* read MPL5 */
0535     ld  $10, PT_MTP+(0*8)(sp)   /* read P0 */
0536     ld  $11, PT_MTP+(3*8)(sp)   /* read P3 */
0537     .word   0x718d000d
0538     /* mtm2 $12, $13           restore MPL2 and MPL5 */
0539     ld  $12, PT_MTP+(1*8)(sp)   /* read P1 */
0540     .word   0x714b0009
0541     /* mtp0 $10, $11           restore P0 and P3 */
0542     ld  $13, PT_MTP+(4*8)(sp)   /* read P4 */
0543     ld  $10, PT_MTP+(2*8)(sp)   /* read P2 */
0544     ld  $11, PT_MTP+(5*8)(sp)   /* read P5 */
0545     .word   0x718d000a
0546     /* mtp1 $12, $13           restore P1 and P4 */
0547     jr  ra
0548     .word   0x714b000b
0549     /* mtp2 $10, $11           restore P2 and P5 */
0550 
0551 octeon_mult_restore3_end:
0552     EXPORT(octeon_mult_restore3_end)
0553     END(octeon_mult_restore3)
0554     .set pop