Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002     .file   "reg_u_mul.S"
0003 /*---------------------------------------------------------------------------+
0004  |  reg_u_mul.S                                                              |
0005  |                                                                           |
0006  | Core multiplication routine                                               |
0007  |                                                                           |
0008  | Copyright (C) 1992,1993,1995,1997                                         |
0009  |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
0010  |                  E-mail   billm@suburbia.net                              |
0011  |                                                                           |
0012  |                                                                           |
0013  +---------------------------------------------------------------------------*/
0014 
0015 /*---------------------------------------------------------------------------+
0016  |   Basic multiplication routine.                                           |
0017  |   Does not check the resulting exponent for overflow/underflow            |
0018  |                                                                           |
0019  |   FPU_u_mul(FPU_REG *a, FPU_REG *b, FPU_REG *c, unsigned int cw);         |
0020  |                                                                           |
0021  |   Internal working is at approx 128 bits.                                 |
0022  |   Result is rounded to nearest 53 or 64 bits, using "nearest or even".    |
0023  +---------------------------------------------------------------------------*/
0024 
0025 #include "exception.h"
0026 #include "fpu_emu.h"
0027 #include "control_w.h"
0028 
0029 
0030 
0031 #ifndef NON_REENTRANT_FPU
0032 /*  Local storage on the stack: */
0033 #define FPU_accum_0 -4(%ebp)    /* ms word */
0034 #define FPU_accum_1 -8(%ebp)
0035 
0036 #else
0037 /*  Local storage in a static area: */
0038 .data
0039     .align 4,0
0040 FPU_accum_0:
0041     .long   0
0042 FPU_accum_1:
0043     .long   0
0044 #endif /* NON_REENTRANT_FPU */
0045 
0046 
0047 .text
0048 SYM_FUNC_START(FPU_u_mul)
0049     pushl   %ebp
0050     movl    %esp,%ebp
0051 #ifndef NON_REENTRANT_FPU
0052     subl    $8,%esp
0053 #endif /* NON_REENTRANT_FPU */ 
0054 
0055     pushl   %esi
0056     pushl   %edi
0057     pushl   %ebx
0058 
0059     movl    PARAM1,%esi
0060     movl    PARAM2,%edi
0061 
0062 #ifdef PARANOID
0063     testl   $0x80000000,SIGH(%esi)
0064     jz  L_bugged
0065     testl   $0x80000000,SIGH(%edi)
0066     jz  L_bugged
0067 #endif /* PARANOID */
0068 
0069     xorl    %ecx,%ecx
0070     xorl    %ebx,%ebx
0071 
0072     movl    SIGL(%esi),%eax
0073     mull    SIGL(%edi)
0074     movl    %eax,FPU_accum_0
0075     movl    %edx,FPU_accum_1
0076 
0077     movl    SIGL(%esi),%eax
0078     mull    SIGH(%edi)
0079     addl    %eax,FPU_accum_1
0080     adcl    %edx,%ebx
0081 /*  adcl    $0,%ecx     // overflow here is not possible */
0082 
0083     movl    SIGH(%esi),%eax
0084     mull    SIGL(%edi)
0085     addl    %eax,FPU_accum_1
0086     adcl    %edx,%ebx
0087     adcl    $0,%ecx
0088 
0089     movl    SIGH(%esi),%eax
0090     mull    SIGH(%edi)
0091     addl    %eax,%ebx
0092     adcl    %edx,%ecx
0093 
0094     /* Get the sum of the exponents. */
0095     movl    PARAM6,%eax
0096     subl    EXP_BIAS-1,%eax
0097 
0098     /* Two denormals can cause an exponent underflow */
0099     cmpl    EXP_WAY_UNDER,%eax
0100     jg  Exp_not_underflow
0101 
0102     /* Set to a really low value allow correct handling */
0103     movl    EXP_WAY_UNDER,%eax
0104 
0105 Exp_not_underflow:
0106 
0107 /*  Have now finished with the sources */
0108     movl    PARAM3,%edi /* Point to the destination */
0109     movw    %ax,EXP(%edi)
0110 
0111 /*  Now make sure that the result is normalized */
0112     testl   $0x80000000,%ecx
0113     jnz LResult_Normalised
0114 
0115     /* Normalize by shifting left one bit */
0116     shll    $1,FPU_accum_0
0117     rcll    $1,FPU_accum_1
0118     rcll    $1,%ebx
0119     rcll    $1,%ecx
0120     decw    EXP(%edi)
0121 
0122 LResult_Normalised:
0123     movl    FPU_accum_0,%eax
0124     movl    FPU_accum_1,%edx
0125     orl %eax,%eax
0126     jz  L_extent_zero
0127 
0128     orl $1,%edx
0129 
0130 L_extent_zero:
0131     movl    %ecx,%eax
0132     jmp fpu_reg_round
0133 
0134 
0135 #ifdef PARANOID
0136 L_bugged:
0137     pushl   EX_INTERNAL|0x205
0138     call    EXCEPTION
0139     pop %ebx
0140     jmp L_exit
0141 
0142 L_exit:
0143     popl    %ebx
0144     popl    %edi
0145     popl    %esi
0146     leave
0147     RET
0148 #endif /* PARANOID */ 
0149 
0150 SYM_FUNC_END(FPU_u_mul)