home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / arch / i386 / math-emu / fpu_aux.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-02  |  3.7 KB  |  185 lines

  1. /*---------------------------------------------------------------------------+
  2.  |  fpu_aux.c                                                                |
  3.  |                                                                           |
  4.  | Code to implement some of the FPU auxiliary instructions.                 |
  5.  |                                                                           |
  6.  | Copyright (C) 1992,1993,1994                                              |
  7.  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
  8.  |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
  9.  |                                                                           |
  10.  |                                                                           |
  11.  +---------------------------------------------------------------------------*/
  12.  
  13. #include "fpu_system.h"
  14. #include "exception.h"
  15. #include "fpu_emu.h"
  16. #include "status_w.h"
  17. #include "control_w.h"
  18.  
  19.  
  20. static void fnop(void)
  21. {
  22. }
  23.  
  24. void fclex(void)
  25. {
  26.   partial_status &= ~(SW_Backward|SW_Summary|SW_Stack_Fault|SW_Precision|
  27.            SW_Underflow|SW_Overflow|SW_Zero_Div|SW_Denorm_Op|
  28.            SW_Invalid);
  29.   no_ip_update = 1;
  30. }
  31.  
  32. /* Needs to be externally visible */
  33. void finit()
  34. {
  35.   int r;
  36.   control_word = 0x037f;
  37.   partial_status = 0;
  38.   top = 0;            /* We don't keep top in the status word internally. */
  39.   for (r = 0; r < 8; r++)
  40.     {
  41.       regs[r].tag = TW_Empty;
  42.     }
  43.   /* The behaviour is different to that detailed in
  44.      Section 15.1.6 of the Intel manual */
  45.   operand_address.offset = 0;
  46.   operand_address.selector = 0;
  47.   instruction_address.offset = 0;
  48.   instruction_address.selector = 0;
  49.   instruction_address.opcode = 0;
  50.   no_ip_update = 1;
  51. }
  52.  
  53. /*
  54.  * These are nops on the i387..
  55.  */
  56. #define feni fnop
  57. #define fdisi fnop
  58. #define fsetpm fnop
  59.  
  60. static FUNC const finit_table[] = {
  61.   feni, fdisi, fclex, finit,
  62.   fsetpm, FPU_illegal, FPU_illegal, FPU_illegal
  63. };
  64.  
  65. void finit_()
  66. {
  67.   (finit_table[FPU_rm])();
  68. }
  69.  
  70.  
  71. static void fstsw_ax(void)
  72. {
  73.   *(short *) &FPU_EAX = status_word();
  74.   no_ip_update = 1;
  75. }
  76.  
  77. static FUNC const fstsw_table[] = {
  78.   fstsw_ax, FPU_illegal, FPU_illegal, FPU_illegal,
  79.   FPU_illegal, FPU_illegal, FPU_illegal, FPU_illegal
  80. };
  81.  
  82. void fstsw_()
  83. {
  84.   (fstsw_table[FPU_rm])();
  85. }
  86.  
  87.  
  88. static FUNC const fp_nop_table[] = {
  89.   fnop, FPU_illegal, FPU_illegal, FPU_illegal,
  90.   FPU_illegal, FPU_illegal, FPU_illegal, FPU_illegal
  91. };
  92.  
  93. void fp_nop()
  94. {
  95.   (fp_nop_table[FPU_rm])();
  96. }
  97.  
  98.  
  99. void fld_i_()
  100. {
  101.   FPU_REG *st_new_ptr;
  102.  
  103.   if ( STACK_OVERFLOW )
  104.     { stack_overflow(); return; }
  105.  
  106.   /* fld st(i) */
  107.   if ( NOT_EMPTY(FPU_rm) )
  108.     { reg_move(&st(FPU_rm), st_new_ptr); push(); }
  109.   else
  110.     {
  111.       if ( control_word & CW_Invalid )
  112.     {
  113.       /* The masked response */
  114.       stack_underflow();
  115.     }
  116.       else
  117.     EXCEPTION(EX_StackUnder);
  118.     }
  119.  
  120. }
  121.  
  122.  
  123. void fxch_i()
  124. {
  125.   /* fxch st(i) */
  126.   FPU_REG t;
  127.   register FPU_REG *sti_ptr = &st(FPU_rm), *st0_ptr = &st(0);
  128.  
  129.   if ( st0_ptr->tag == TW_Empty )
  130.     {
  131.       if ( sti_ptr->tag == TW_Empty )
  132.     {
  133.       stack_underflow();
  134.       stack_underflow_i(FPU_rm);
  135.       return;
  136.     }
  137.       if ( control_word & CW_Invalid )
  138.     reg_move(sti_ptr, st0_ptr);   /* Masked response */
  139.       stack_underflow_i(FPU_rm);
  140.       return;
  141.     }
  142.   if ( sti_ptr->tag == TW_Empty )
  143.     {
  144.       if ( control_word & CW_Invalid )
  145.     reg_move(st0_ptr, sti_ptr);   /* Masked response */
  146.       stack_underflow();
  147.       return;
  148.     }
  149.   clear_C1();
  150.   reg_move(st0_ptr, &t);
  151.   reg_move(sti_ptr, st0_ptr);
  152.   reg_move(&t, sti_ptr);
  153. }
  154.  
  155.  
  156. void ffree_()
  157. {
  158.   /* ffree st(i) */
  159.   st(FPU_rm).tag = TW_Empty;
  160. }
  161.  
  162.  
  163. void ffreep()
  164. {
  165.   /* ffree st(i) + pop - unofficial code */
  166.   st(FPU_rm).tag = TW_Empty;
  167.   pop();
  168. }
  169.  
  170.  
  171. void fst_i_()
  172. {
  173.   /* fst st(i) */
  174.   reg_move(&st(0), &st(FPU_rm));
  175. }
  176.  
  177.  
  178. void fstp_i()
  179. {
  180.   /* fstp st(i) */
  181.   reg_move(&st(0), &st(FPU_rm));
  182.   pop();
  183. }
  184.  
  185.