linux/arch/mips/kernel/r2300_switch.S
<<
>>
Prefs
   1/*
   2 * r2300_switch.S: R2300 specific task switching code.
   3 *
   4 * Copyright (C) 1994, 1995, 1996, 1999 by Ralf Baechle
   5 * Copyright (C) 1994, 1995, 1996 by Andreas Busse
   6 *
   7 * Multi-cpu abstraction and macros for easier reading:
   8 * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
   9 *
  10 * Further modifications to make this work:
  11 * Copyright (c) 1998-2000 Harald Koerfgen
  12 */
  13#include <asm/asm.h>
  14#include <asm/cachectl.h>
  15#include <asm/fpregdef.h>
  16#include <asm/mipsregs.h>
  17#include <asm/asm-offsets.h>
  18#include <asm/page.h>
  19#include <asm/regdef.h>
  20#include <asm/stackframe.h>
  21#include <asm/thread_info.h>
  22
  23#include <asm/asmmacro.h>
  24
  25        .set    mips1
  26        .align  5
  27
  28/*
  29 * Offset to the current process status flags, the first 32 bytes of the
  30 * stack are not used.
  31 */
  32#define ST_OFF (_THREAD_SIZE - 32 - PT_SIZE + PT_STATUS)
  33
  34/*
  35 * FPU context is saved iff the process has used it's FPU in the current
  36 * time slice as indicated by TIF_USEDFPU.  In any case, the CU1 bit for user
  37 * space STATUS register should be 0, so that a process *always* starts its
  38 * userland with FPU disabled after each context switch.
  39 *
  40 * FPU will be enabled as soon as the process accesses FPU again, through
  41 * do_cpu() trap.
  42 */
  43
  44/*
  45 * task_struct *resume(task_struct *prev, task_struct *next,
  46 *                     struct thread_info *next_ti) )
  47 */
  48LEAF(resume)
  49        mfc0    t1, CP0_STATUS
  50        sw      t1, THREAD_STATUS(a0)
  51        cpu_save_nonscratch a0
  52        sw      ra, THREAD_REG31(a0)
  53
  54        /*
  55         * check if we need to save FPU registers
  56         */
  57        lw      t3, TASK_THREAD_INFO(a0)
  58        lw      t0, TI_FLAGS(t3)
  59        li      t1, _TIF_USEDFPU
  60        and     t2, t0, t1
  61        beqz    t2, 1f
  62        nor     t1, zero, t1
  63
  64        and     t0, t0, t1
  65        sw      t0, TI_FLAGS(t3)
  66
  67        /*
  68         * clear saved user stack CU1 bit
  69         */
  70        lw      t0, ST_OFF(t3)
  71        li      t1, ~ST0_CU1
  72        and     t0, t0, t1
  73        sw      t0, ST_OFF(t3)
  74
  75        fpu_save_single a0, t0                  # clobbers t0
  76
  771:
  78        /*
  79         * The order of restoring the registers takes care of the race
  80         * updating $28, $29 and kernelsp without disabling ints.
  81         */
  82        move    $28, a2
  83        cpu_restore_nonscratch a1
  84
  85        addiu   t1, $28, _THREAD_SIZE - 32
  86        sw      t1, kernelsp
  87
  88        mfc0    t1, CP0_STATUS          /* Do we really need this? */
  89        li      a3, 0xff01
  90        and     t1, a3
  91        lw      a2, THREAD_STATUS(a1)
  92        nor     a3, $0, a3
  93        and     a2, a3
  94        or      a2, t1
  95        mtc0    a2, CP0_STATUS
  96        move    v0, a0
  97        jr      ra
  98        END(resume)
  99
 100/*
 101 * Save a thread's fp context.
 102 */
 103LEAF(_save_fp)
 104        fpu_save_single a0, t1                  # clobbers t1
 105        jr      ra
 106        END(_save_fp)
 107
 108/*
 109 * Restore a thread's fp context.
 110 */
 111LEAF(_restore_fp)
 112        fpu_restore_single a0, t1               # clobbers t1
 113        jr      ra
 114        END(_restore_fp)
 115
 116/*
 117 * Load the FPU with signalling NANS.  This bit pattern we're using has
 118 * the property that no matter whether considered as single or as double
 119 * precision represents signaling NANS.
 120 *
 121 * We initialize fcr31 to rounding to nearest, no exceptions.
 122 */
 123
 124#define FPU_DEFAULT  0x00000000
 125
 126LEAF(_init_fpu)
 127        mfc0    t0, CP0_STATUS
 128        li      t1, ST0_CU1
 129        or      t0, t1
 130        mtc0    t0, CP0_STATUS
 131
 132        li      t1, FPU_DEFAULT
 133        ctc1    t1, fcr31
 134
 135        li      t0, -1
 136
 137        mtc1    t0, $f0
 138        mtc1    t0, $f1
 139        mtc1    t0, $f2
 140        mtc1    t0, $f3
 141        mtc1    t0, $f4
 142        mtc1    t0, $f5
 143        mtc1    t0, $f6
 144        mtc1    t0, $f7
 145        mtc1    t0, $f8
 146        mtc1    t0, $f9
 147        mtc1    t0, $f10
 148        mtc1    t0, $f11
 149        mtc1    t0, $f12
 150        mtc1    t0, $f13
 151        mtc1    t0, $f14
 152        mtc1    t0, $f15
 153        mtc1    t0, $f16
 154        mtc1    t0, $f17
 155        mtc1    t0, $f18
 156        mtc1    t0, $f19
 157        mtc1    t0, $f20
 158        mtc1    t0, $f21
 159        mtc1    t0, $f22
 160        mtc1    t0, $f23
 161        mtc1    t0, $f24
 162        mtc1    t0, $f25
 163        mtc1    t0, $f26
 164        mtc1    t0, $f27
 165        mtc1    t0, $f28
 166        mtc1    t0, $f29
 167        mtc1    t0, $f30
 168        mtc1    t0, $f31
 169        jr      ra
 170        END(_init_fpu)
 171