root/arch/i386/math-emu/reg_u_mul.S

/* [previous][next][first][last][top][bottom][index][help] */
   1         .file   "reg_u_mul.S"
   2 /*---------------------------------------------------------------------------+
   3  |  reg_u_mul.S                                                              |
   4  |                                                                           |
   5  | Core multiplication routine                                               |
   6  |                                                                           |
   7  | Copyright (C) 1992,1993                                                   |
   8  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
   9  |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
  10  |                                                                           |
  11  |                                                                           |
  12  +---------------------------------------------------------------------------*/
  13 
  14 /*---------------------------------------------------------------------------+
  15  |   Basic multiplication routine.                                           |
  16  |   Does not check the resulting exponent for overflow/underflow            |
  17  |                                                                           |
  18  |   reg_u_mul(FPU_REG *a, FPU_REG *b, FPU_REG *c, unsigned int cw);         |
  19  |                                                                           |
  20  |   Internal working is at approx 128 bits.                                 |
  21  |   Result is rounded to nearest 53 or 64 bits, using "nearest or even".    |
  22  +---------------------------------------------------------------------------*/
  23 
  24 #include "exception.h"
  25 #include "fpu_asm.h"
  26 #include "control_w.h"
  27 
  28 
  29 
  30 #ifndef NON_REENTRANT_FPU
  31 /*  Local storage on the stack: */
  32 #define FPU_accum_0     -4(%ebp)        /* ms word */
  33 #define FPU_accum_1     -8(%ebp)
  34 
  35 #else
  36 /*  Local storage in a static area: */
  37 .data
  38         .align 4,0
  39 FPU_accum_0:
  40         .long   0
  41 FPU_accum_1:
  42         .long   0
  43 #endif NON_REENTRANT_FPU
  44 
  45 
  46 .text
  47         .align 2,144
  48 
  49 .globl _reg_u_mul
  50 _reg_u_mul:
  51         pushl   %ebp
  52         movl    %esp,%ebp
  53 #ifndef NON_REENTRANT_FPU
  54         subl    $8,%esp
  55 #endif NON_REENTRANT_FPU
  56 
  57         pushl   %esi
  58         pushl   %edi
  59         pushl   %ebx
  60 
  61         movl    PARAM1,%esi
  62         movl    PARAM2,%edi
  63 
  64 #ifdef PARANOID
  65         testl   $0x80000000,SIGH(%esi)
  66         jz      L_bugged
  67         testl   $0x80000000,SIGH(%edi)
  68         jz      L_bugged
  69 #endif PARANOID
  70 
  71 #ifdef DENORM_OPERAND
  72         movl    EXP(%esi),%eax
  73         cmpl    EXP_UNDER,%eax
  74         jg      xOp1_not_denorm
  75 
  76         call    _denormal_operand
  77         orl     %eax,%eax
  78         jnz     fpu_Arith_exit
  79 
  80 xOp1_not_denorm:
  81         movl    EXP(%edi),%eax
  82         cmpl    EXP_UNDER,%eax
  83         jg      xOp2_not_denorm
  84 
  85         call    _denormal_operand
  86         orl     %eax,%eax
  87         jnz     fpu_Arith_exit
  88 
  89 xOp2_not_denorm:
  90 #endif DENORM_OPERAND
  91 
  92         xorl    %ecx,%ecx
  93         xorl    %ebx,%ebx
  94 
  95         movl    SIGL(%esi),%eax
  96         mull    SIGL(%edi)
  97         movl    %eax,FPU_accum_0
  98         movl    %edx,FPU_accum_1
  99 
 100         movl    SIGL(%esi),%eax
 101         mull    SIGH(%edi)
 102         addl    %eax,FPU_accum_1
 103         adcl    %edx,%ebx
 104 /*      adcl    $0,%ecx         // overflow here is not possible */
 105 
 106         movl    SIGH(%esi),%eax
 107         mull    SIGL(%edi)
 108         addl    %eax,FPU_accum_1
 109         adcl    %edx,%ebx
 110         adcl    $0,%ecx
 111 
 112         movl    SIGH(%esi),%eax
 113         mull    SIGH(%edi)
 114         addl    %eax,%ebx
 115         adcl    %edx,%ecx
 116 
 117         movl    EXP(%esi),%eax  /* Compute the exponent */
 118         addl    EXP(%edi),%eax
 119         subl    EXP_BIAS-1,%eax
 120 
 121 /*  Have now finished with the sources */
 122         movl    PARAM3,%edi     /* Point to the destination */
 123         movl    %eax,EXP(%edi)
 124 
 125 /*  Now make sure that the result is normalized */
 126         testl   $0x80000000,%ecx
 127         jnz     LResult_Normalised
 128 
 129         /* Normalize by shifting left one bit */
 130         shll    $1,FPU_accum_0
 131         rcll    $1,FPU_accum_1
 132         rcll    $1,%ebx
 133         rcll    $1,%ecx
 134         decl    EXP(%edi)
 135 
 136 LResult_Normalised:
 137         movl    FPU_accum_0,%eax
 138         movl    FPU_accum_1,%edx
 139         orl     %eax,%eax
 140         jz      L_extent_zero
 141 
 142         orl     $1,%edx
 143 
 144 L_extent_zero:
 145         movl    %ecx,%eax
 146         jmp     fpu_reg_round
 147 
 148 
 149 #ifdef PARANOID
 150 L_bugged:
 151         pushl   EX_INTERNAL|0x205
 152         call    EXCEPTION
 153         pop     %ebx
 154         jmp     L_exit
 155 
 156 L_exit:
 157         popl    %ebx
 158         popl    %edi
 159         popl    %esi
 160         leave
 161         ret
 162 #endif PARANOID
 163 

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