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,1995                                              |
   8  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
   9  |                       Australia.  E-mail billm@jacobi.maths.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_emu.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 ENTRY(reg_u_mul)
  48         pushl   %ebp
  49         movl    %esp,%ebp
  50 #ifndef NON_REENTRANT_FPU
  51         subl    $8,%esp
  52 #endif NON_REENTRANT_FPU
  53 
  54         pushl   %esi
  55         pushl   %edi
  56         pushl   %ebx
  57 
  58         movl    PARAM1,%esi
  59         movl    PARAM2,%edi
  60 
  61 #ifdef PARANOID
  62         testl   $0x80000000,SIGH(%esi)
  63         jz      L_bugged
  64         testl   $0x80000000,SIGH(%edi)
  65         jz      L_bugged
  66 #endif PARANOID
  67 
  68 #ifdef DENORM_OPERAND
  69         movl    EXP(%esi),%eax
  70         cmpl    EXP_UNDER,%eax
  71         jg      xOp1_not_denorm
  72 
  73         call    SYMBOL_NAME(denormal_operand)
  74         orl     %eax,%eax
  75         jnz     fpu_Arith_exit
  76 
  77 xOp1_not_denorm:
  78         movl    EXP(%edi),%eax
  79         cmpl    EXP_UNDER,%eax
  80         jg      xOp2_not_denorm
  81 
  82         call    SYMBOL_NAME(denormal_operand)
  83         orl     %eax,%eax
  84         jnz     fpu_Arith_exit
  85 
  86 xOp2_not_denorm:
  87 #endif DENORM_OPERAND
  88 
  89         xorl    %ecx,%ecx
  90         xorl    %ebx,%ebx
  91 
  92         movl    SIGL(%esi),%eax
  93         mull    SIGL(%edi)
  94         movl    %eax,FPU_accum_0
  95         movl    %edx,FPU_accum_1
  96 
  97         movl    SIGL(%esi),%eax
  98         mull    SIGH(%edi)
  99         addl    %eax,FPU_accum_1
 100         adcl    %edx,%ebx
 101 /*      adcl    $0,%ecx         // overflow here is not possible */
 102 
 103         movl    SIGH(%esi),%eax
 104         mull    SIGL(%edi)
 105         addl    %eax,FPU_accum_1
 106         adcl    %edx,%ebx
 107         adcl    $0,%ecx
 108 
 109         movl    SIGH(%esi),%eax
 110         mull    SIGH(%edi)
 111         addl    %eax,%ebx
 112         adcl    %edx,%ecx
 113 
 114         movl    EXP(%esi),%eax  /* Compute the exponent */
 115         addl    EXP(%edi),%eax
 116         subl    EXP_BIAS-1,%eax
 117 
 118 /*  Have now finished with the sources */
 119         movl    PARAM3,%edi     /* Point to the destination */
 120         movl    %eax,EXP(%edi)
 121 
 122 /*  Now make sure that the result is normalized */
 123         testl   $0x80000000,%ecx
 124         jnz     LResult_Normalised
 125 
 126         /* Normalize by shifting left one bit */
 127         shll    $1,FPU_accum_0
 128         rcll    $1,FPU_accum_1
 129         rcll    $1,%ebx
 130         rcll    $1,%ecx
 131         decl    EXP(%edi)
 132 
 133 LResult_Normalised:
 134         movl    FPU_accum_0,%eax
 135         movl    FPU_accum_1,%edx
 136         orl     %eax,%eax
 137         jz      L_extent_zero
 138 
 139         orl     $1,%edx
 140 
 141 L_extent_zero:
 142         movl    %ecx,%eax
 143         jmp     fpu_reg_round
 144 
 145 
 146 #ifdef PARANOID
 147 L_bugged:
 148         pushl   EX_INTERNAL|0x205
 149         call    EXCEPTION
 150         pop     %ebx
 151         jmp     L_exit
 152 
 153 L_exit:
 154         popl    %ebx
 155         popl    %edi
 156         popl    %esi
 157         leave
 158         ret
 159 #endif PARANOID
 160 

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