/*
* linux/kernel/math/math_emulate.c
*
* (C) 1991 Linus Torvalds
*/

/*
* This directory should contain the math-emulation code.
* Currently only results in a signal.
*/
/*
* Ŀ¼Ӧðѧ롣Ŀǰһźš
*/

#include <signal.h>		// źͷļźŷųźŽṹԼźŲԭ͡

#include <linux/sched.h>	// ȳͷļṹtask_structʼ0 ݣ
// һЩйúͻȡǶʽຯ䡣
#include <linux/kernel.h>	// ںͷļһЩں˳úԭζ塣
#include <asm/segment.h>	// βͷļйضμĴǶʽຯ

//// Э溯
// жϴõC μ(kernel/math/system_call.s169 )
void
math_emulate (long edi, long esi, long ebp, long sys_call_ret,
	      long eax, long ebx, long ecx, long edx,
	      unsigned short fs, unsigned short es, unsigned short ds,
	      unsigned long eip, unsigned short cs, unsigned long eflags,
	      unsigned short ss, unsigned long esp)
{
  unsigned char first, second;

/* 0x0007 means user code space */
/* 0x0007 ʾûռ */
// ѡ0x000F ʾھֲֵ=1ռ䡣μĴcs 0x000F
// ʾcs һں˴ѡں˴ռ䣬ʾʱcs:eip ֵʾϢ
// ںҪѧ桱Ȼ״̬
  if (cs != 0x000F)
    {
      printk ("math_emulate: %04x:%08x\n\r", cs, eip);
      panic ("Math emulation needed in kernel");
    }
// ȡûջfirst secondʾЩݣø쳣źSIGFPE
  first = get_fs_byte ((char *) ((*&eip)++));
  second = get_fs_byte ((char *) ((*&eip)++));
  printk ("%04x:%08x %02x %02x\n\r", cs, eip - 2, first, second);
  current->signal |= 1 << (SIGFPE - 1);
}

//// Э
// жϴõC μ(kernel/math/system_call.s145 )
void
math_error (void)
{
// Эָ(Էǵȴʽ)쳣־æ־״̬λ7
  __asm__ ("fnclex");
// ϸʹùЭϸЭ쳣źš
  if (last_task_used_math)
    last_task_used_math->signal |= 1 << (SIGFPE - 1);
}
