root/kernel/FPU-emu/polynomial.S

/* [previous][next][first][last][top][bottom][index][help] */
   1 /*---------------------------------------------------------------------------+
   2  |  polynomial.S                                                             |
   3  |                                                                           |
   4  | Fixed point arithmetic polynomial evaluation.                             |
   5  |                                                                           |
   6  | Copyright (C) 1992,1993                                                   |
   7  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
   8  |                       Australia.  E-mail apm233m@vaxc.cc.monash.edu.au    |
   9  |                                                                           |
  10  | Call from C as:                                                           |
  11  |   void polynomial(unsigned accum[], unsigned x[], unsigned terms[][2],    |
  12  |                   int n)                                                  |
  13  |                                                                           |
  14  | Computes:                                                                 |
  15  | terms[0] + (terms[1] + (terms[2] + ... + (terms[n-1]*x)*x)*x)*x) ... )*x  |
  16  | The result is returned in accum.                                          |
  17  |                                                                           |
  18  +---------------------------------------------------------------------------*/
  19 
  20         .file   "fpolynom.s"
  21 
  22 #include "fpu_asm.h"
  23 
  24 
  25 //      #define EXTRA_PRECISE   // Do not use: not complete
  26 
  27 #define TERM_SIZE       $8
  28 #define SUM_MS          -20(%ebp)       /* sum ms long */
  29 #define SUM_MIDDLE      -24(%ebp)       /* sum middle long */
  30 #define SUM_LS          -28(%ebp)       /* sum ls long */
  31 #define SUM_LS_HI       -25(%ebp)       /* high byte of sum ls */
  32 #define ACCUM_MS        -4(%ebp)        /* accum ms long */
  33 #define ACCUM_MIDDLE    -8(%ebp)        /* accum middle long */
  34 #define ACCUM_LS        -12(%ebp)       /* accum ls long */
  35 #define ACCUM_LS_HI     -9(%ebp)        /* high byte of accum ls */
  36 
  37 .text
  38         .align 2,144
  39 .globl _polynomial
  40 _polynomial:
  41         pushl   %ebp
  42         movl    %esp,%ebp
  43         subl    $32,%esp
  44         pushl   %esi
  45         pushl   %edi
  46         pushl   %ebx
  47 
  48         movl    PARAM2,%esi             // x
  49         movl    PARAM3,%edi             // terms
  50 
  51         movl    TERM_SIZE,%eax
  52         mull    PARAM4                  // n
  53         addl    %eax,%edi
  54 
  55         movl    4(%edi),%edx            // terms[n]
  56         movl    %edx,SUM_MS
  57         movl    (%edi),%edx             // terms[n]
  58         movl    %edx,SUM_MIDDLE
  59         xor     %eax,%eax
  60         movl    %eax,SUM_LS
  61 
  62         subl    TERM_SIZE,%edi
  63         decl    PARAM4
  64         js      L_accum_done
  65 
  66 L_accum_loop:
  67         xor     %eax,%eax
  68         movl    %eax,ACCUM_MS
  69         movl    %eax,ACCUM_MIDDLE
  70 
  71         movl    SUM_MIDDLE,%eax
  72         mull    (%esi)                  // x ls long
  73 //      movl    %eax,-16(%ebp)          // Not needed
  74         movl    %edx,ACCUM_LS
  75 
  76         movl    SUM_MIDDLE,%eax
  77         mull    4(%esi)                 // x ms long
  78         addl    %eax,ACCUM_LS
  79         adcl    %edx,ACCUM_MIDDLE
  80         adcl    $0,ACCUM_MS
  81 
  82         movl    SUM_MS,%eax
  83         mull    (%esi)                  // x ls long
  84         addl    %eax,ACCUM_LS
  85         adcl    %edx,ACCUM_MIDDLE
  86         adcl    $0,ACCUM_MS
  87 
  88         movl    SUM_MS,%eax
  89         mull    4(%esi)                 // x ms long
  90         addl    %eax,ACCUM_MIDDLE
  91         adcl    %edx,ACCUM_MS
  92 
  93 // Now put the sum of next term and the accumulator
  94 // into the sum register
  95         movl    ACCUM_MIDDLE,%eax
  96         addl    (%edi),%eax             // term ls long
  97         movl    %eax,SUM_MIDDLE
  98         movl    ACCUM_MS,%eax
  99         adcl    4(%edi),%eax            // term ms long
 100         movl    %eax,SUM_MS
 101 
 102 #ifdef EXTRA_PRECISE
 103         movl    ACCUM_LS,%eax
 104         movl    %eax,SUM_LS
 105 #else
 106         testb   $0x80,ACCUM_LS_HI       // ms bit of ACCUM_LS
 107         je      L_no_poly_round
 108 
 109         addl    $1,SUM_MIDDLE
 110         adcl    $0,SUM_MS
 111 L_no_poly_round:
 112 #endif EXTRA_PRECISE
 113 
 114         subl    TERM_SIZE,%edi
 115         decl    PARAM4
 116         jns     L_accum_loop
 117 
 118 L_accum_done:
 119 #ifdef EXTRA_PRECISE
 120 /* And round the result */
 121         testb   $128,SUM_LS_HI
 122         je      L_poly_done
 123 
 124         addl    $1,SUM_MIDDLE
 125         adcl    $0,SUM_MS
 126 #endif EXTRA_PRECISE
 127 
 128 L_poly_done:
 129         movl    PARAM1,%edi             // accum
 130         movl    SUM_MIDDLE,%eax
 131         movl    %eax,(%edi)
 132         movl    SUM_MS,%eax
 133         movl    %eax,4(%edi)
 134 
 135         popl    %ebx
 136         popl    %edi
 137         popl    %esi
 138         leave
 139         ret

/* [previous][next][first][last][top][bottom][index][help] */