fpu.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:7k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id: fpu.c,v 1.29 2000/03/22 13:42:10 gniibe Exp $
  2.  *
  3.  * linux/arch/sh/kernel/fpu.c
  4.  *
  5.  * Save/restore floating point context for signal handlers.
  6.  *
  7.  * This file is subject to the terms and conditions of the GNU General Public
  8.  * License.  See the file "COPYING" in the main directory of this archive
  9.  * for more details.
  10.  *
  11.  * Copyright (C) 1999, 2000  Kaz Kojima & Niibe Yutaka
  12.  *
  13.  * FIXME! These routines can be optimized in big endian case.
  14.  */
  15. #include <linux/sched.h>
  16. #include <linux/signal.h>
  17. #include <asm/processor.h>
  18. #include <asm/io.h>
  19. void
  20. save_fpu(struct task_struct *tsk)
  21. {
  22. asm volatile("sts.l fpul, @-%0nt"
  23.      "sts.l fpscr, @-%0nt"
  24.      "lds %1, fpscrnt"
  25.      "frchgnt"
  26.      "fmov.s fr15, @-%0nt"
  27.      "fmov.s fr14, @-%0nt"
  28.      "fmov.s fr13, @-%0nt"
  29.      "fmov.s fr12, @-%0nt"
  30.      "fmov.s fr11, @-%0nt"
  31.      "fmov.s fr10, @-%0nt"
  32.      "fmov.s fr9, @-%0nt"
  33.      "fmov.s fr8, @-%0nt"
  34.      "fmov.s fr7, @-%0nt"
  35.      "fmov.s fr6, @-%0nt"
  36.      "fmov.s fr5, @-%0nt"
  37.      "fmov.s fr4, @-%0nt"
  38.      "fmov.s fr3, @-%0nt"
  39.      "fmov.s fr2, @-%0nt"
  40.      "fmov.s fr1, @-%0nt"
  41.      "fmov.s fr0, @-%0nt"
  42.      "frchgnt"
  43.      "fmov.s fr15, @-%0nt"
  44.      "fmov.s fr14, @-%0nt"
  45.      "fmov.s fr13, @-%0nt"
  46.      "fmov.s fr12, @-%0nt"
  47.      "fmov.s fr11, @-%0nt"
  48.      "fmov.s fr10, @-%0nt"
  49.      "fmov.s fr9, @-%0nt"
  50.      "fmov.s fr8, @-%0nt"
  51.      "fmov.s fr7, @-%0nt"
  52.      "fmov.s fr6, @-%0nt"
  53.      "fmov.s fr5, @-%0nt"
  54.      "fmov.s fr4, @-%0nt"
  55.      "fmov.s fr3, @-%0nt"
  56.      "fmov.s fr2, @-%0nt"
  57.      "fmov.s fr1, @-%0nt"
  58.      "fmov.s fr0, @-%0"
  59.      : /* no output */
  60.      : "r" ((char *)(&tsk->thread.fpu.hard.status)),
  61.        "r" (FPSCR_INIT)
  62.      : "memory");
  63. tsk->flags &= ~PF_USEDFPU;
  64. release_fpu();
  65. }
  66. static void
  67. restore_fpu(struct task_struct *tsk)
  68. {
  69. asm volatile("lds %1, fpscrnt"
  70.      "fmov.s @%0+, fr0nt"
  71.      "fmov.s @%0+, fr1nt"
  72.      "fmov.s @%0+, fr2nt"
  73.      "fmov.s @%0+, fr3nt"
  74.      "fmov.s @%0+, fr4nt"
  75.      "fmov.s @%0+, fr5nt"
  76.      "fmov.s @%0+, fr6nt"
  77.      "fmov.s @%0+, fr7nt"
  78.      "fmov.s @%0+, fr8nt"
  79.      "fmov.s @%0+, fr9nt"
  80.      "fmov.s @%0+, fr10nt"
  81.      "fmov.s @%0+, fr11nt"
  82.      "fmov.s @%0+, fr12nt"
  83.      "fmov.s @%0+, fr13nt"
  84.      "fmov.s @%0+, fr14nt"
  85.      "fmov.s @%0+, fr15nt"
  86.      "frchgnt"
  87.      "fmov.s @%0+, fr0nt"
  88.      "fmov.s @%0+, fr1nt"
  89.      "fmov.s @%0+, fr2nt"
  90.      "fmov.s @%0+, fr3nt"
  91.      "fmov.s @%0+, fr4nt"
  92.      "fmov.s @%0+, fr5nt"
  93.      "fmov.s @%0+, fr6nt"
  94.      "fmov.s @%0+, fr7nt"
  95.      "fmov.s @%0+, fr8nt"
  96.      "fmov.s @%0+, fr9nt"
  97.      "fmov.s @%0+, fr10nt"
  98.      "fmov.s @%0+, fr11nt"
  99.      "fmov.s @%0+, fr12nt"
  100.      "fmov.s @%0+, fr13nt"
  101.      "fmov.s @%0+, fr14nt"
  102.      "fmov.s @%0+, fr15nt"
  103.      "frchgnt"
  104.      "lds.l @%0+, fpscrnt"
  105.      "lds.l @%0+, fpulnt"
  106.      : /* no output */
  107.      : "r" (&tsk->thread.fpu), "r" (FPSCR_INIT)
  108.      : "memory");
  109. }
  110. /*
  111.  * Load the FPU with signalling NANS.  This bit pattern we're using
  112.  * has the property that no matter wether considered as single or as
  113.  * double precission represents signaling NANS.  
  114.  */
  115. void fpu_init(void)
  116. {
  117. asm volatile("lds %0, fpulnt"
  118.      "lds %1, fpscrnt"
  119.      "fsts fpul, fr0nt"
  120.      "fsts fpul, fr1nt"
  121.      "fsts fpul, fr2nt"
  122.      "fsts fpul, fr3nt"
  123.      "fsts fpul, fr4nt"
  124.      "fsts fpul, fr5nt"
  125.      "fsts fpul, fr6nt"
  126.      "fsts fpul, fr7nt"
  127.      "fsts fpul, fr8nt"
  128.      "fsts fpul, fr9nt"
  129.      "fsts fpul, fr10nt"
  130.      "fsts fpul, fr11nt"
  131.      "fsts fpul, fr12nt"
  132.      "fsts fpul, fr13nt"
  133.      "fsts fpul, fr14nt"
  134.      "fsts fpul, fr15nt"
  135.      "frchgnt"
  136.      "fsts fpul, fr0nt"
  137.      "fsts fpul, fr1nt"
  138.      "fsts fpul, fr2nt"
  139.      "fsts fpul, fr3nt"
  140.      "fsts fpul, fr4nt"
  141.      "fsts fpul, fr5nt"
  142.      "fsts fpul, fr6nt"
  143.      "fsts fpul, fr7nt"
  144.      "fsts fpul, fr8nt"
  145.      "fsts fpul, fr9nt"
  146.      "fsts fpul, fr10nt"
  147.      "fsts fpul, fr11nt"
  148.      "fsts fpul, fr12nt"
  149.      "fsts fpul, fr13nt"
  150.      "fsts fpul, fr14nt"
  151.      "fsts fpul, fr15nt"
  152.      "frchg"
  153.      : /* no output */
  154.      : "r" (0), "r" (FPSCR_INIT));
  155. }
  156. asmlinkage void
  157. do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7,
  158.      struct pt_regs regs)
  159. {
  160. struct task_struct *tsk = current;
  161. regs.pc += 2;
  162. grab_fpu();
  163. save_fpu(tsk);
  164. tsk->thread.trap_no = 11;
  165. tsk->thread.error_code = 0;
  166. force_sig(SIGFPE, tsk);
  167. }
  168. asmlinkage void
  169. do_fpu_state_restore(unsigned long r4, unsigned long r5, unsigned long r6,
  170.      unsigned long r7, struct pt_regs regs)
  171. {
  172. struct task_struct *tsk = current;
  173. if (!user_mode(&regs)) {
  174. if (tsk != &init_task) {
  175. unlazy_fpu(tsk);
  176. }
  177. tsk = &init_task;
  178. if (tsk->flags & PF_USEDFPU) {
  179. /*
  180.  * This weird situation can be occurred.
  181.  *
  182.  * There's race condition in __cli:
  183.  *
  184.  *   (1) SR --> register
  185.  *   (2) Set IMASK of register
  186.  *   (3) SR <-- register
  187.  *
  188.  * Between (1) and (2), or (2) and (3) getting
  189.  * interrupt, and interrupt handler (or
  190.  * softirq) may use FPU.
  191.  *
  192.  * Then, SR.FD is overwritten by (3).
  193.  *
  194.  * This results init_task.PF_USEDFPU is on,
  195.  * with SR.FD == 1.
  196.  *
  197.  */
  198. release_fpu();
  199. return;
  200. }
  201. }
  202. grab_fpu();
  203. if (tsk->used_math) {
  204. /* Using the FPU again.  */
  205. restore_fpu(tsk);
  206. } else {
  207. /* First time FPU user.  */
  208. fpu_init();
  209. tsk->used_math = 1;
  210. }
  211. tsk->flags |= PF_USEDFPU;
  212. release_fpu();
  213. }
  214. /*
  215.  * Change current FD flag to set FD flag back to exception
  216.  */
  217. asmlinkage void
  218. fpu_prepare_fd(unsigned long sr, unsigned long r5, unsigned long r6,
  219.        unsigned long r7, struct pt_regs regs)
  220. {
  221. __cli();
  222. if (!user_mode(&regs)) {
  223. if (init_task.flags & PF_USEDFPU)
  224. grab_fpu();
  225. else {
  226. if (!(sr & SR_FD)) {
  227. BUG();
  228. release_fpu();
  229. }
  230. }
  231. return;
  232. }
  233. if (sr & SR_FD) { /* Kernel doesn't grab FPU */
  234. if (current->flags & PF_USEDFPU)
  235. grab_fpu();
  236. else {
  237. if (init_task.flags & PF_USEDFPU) {
  238. /*
  239.  * This weird situation can be occurred.
  240.  * See the comment in do_fpu_state_restore.
  241.  */
  242. grab_fpu();
  243. save_fpu(&init_task);
  244. }
  245. }
  246. } else {
  247. if (init_task.flags & PF_USEDFPU)
  248. save_fpu(&init_task);
  249. else {
  250. BUG();
  251. release_fpu();
  252. }
  253. }
  254. }
  255. /* Short cut for the FPU exception */
  256. asmlinkage void
  257. enable_fpu_in_danger(void)
  258. {
  259. struct task_struct *tsk = current;
  260. if (tsk != &init_task)
  261. unlazy_fpu(tsk);
  262. tsk = &init_task;
  263. if (tsk->used_math) {
  264. /* Using the FPU again.  */
  265. restore_fpu(tsk);
  266. } else {
  267. /* First time FPU user.  */
  268. fpu_init();
  269. tsk->used_math = 1;
  270. }
  271. tsk->flags |= PF_USEDFPU;
  272. }