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

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

/* [<][>][^][v][top][bottom][index][help] */