Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002     .file   "wm_shrx.S"
0003 /*---------------------------------------------------------------------------+
0004  |  wm_shrx.S                                                                |
0005  |                                                                           |
0006  | 64 bit right shift functions                                              |
0007  |                                                                           |
0008  | Copyright (C) 1992,1995                                                   |
0009  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
0010  |                       Australia.  E-mail billm@jacobi.maths.monash.edu.au |
0011  |                                                                           |
0012  | Call from C as:                                                           |
0013  |   unsigned FPU_shrx(void *arg1, unsigned arg2)                            |
0014  | and                                                                       |
0015  |   unsigned FPU_shrxs(void *arg1, unsigned arg2)                           |
0016  |                                                                           |
0017  +---------------------------------------------------------------------------*/
0018 
0019 #include "fpu_emu.h"
0020 
0021 .text
0022 /*---------------------------------------------------------------------------+
0023  |   unsigned FPU_shrx(void *arg1, unsigned arg2)                            |
0024  |                                                                           |
0025  |   Extended shift right function.                                          |
0026  |   Fastest for small shifts.                                               |
0027  |   Shifts the 64 bit quantity pointed to by the first arg (arg1)           |
0028  |   right by the number of bits specified by the second arg (arg2).         |
0029  |   Forms a 96 bit quantity from the 64 bit arg and eax:                    |
0030  |                [  64 bit arg ][ eax ]                                     |
0031  |            shift right  --------->                                        |
0032  |   The eax register is initialized to 0 before the shifting.               |
0033  |   Results returned in the 64 bit arg and eax.                             |
0034  +---------------------------------------------------------------------------*/
0035 
0036 SYM_FUNC_START(FPU_shrx)
0037     push    %ebp
0038     movl    %esp,%ebp
0039     pushl   %esi
0040     movl    PARAM2,%ecx
0041     movl    PARAM1,%esi
0042     cmpl    $32,%ecx    /* shrd only works for 0..31 bits */
0043     jnc L_more_than_31
0044 
0045 /* less than 32 bits */
0046     pushl   %ebx
0047     movl    (%esi),%ebx /* lsl */
0048     movl    4(%esi),%edx    /* msl */
0049     xorl    %eax,%eax   /* extension */
0050     shrd    %cl,%ebx,%eax
0051     shrd    %cl,%edx,%ebx
0052     shr %cl,%edx
0053     movl    %ebx,(%esi)
0054     movl    %edx,4(%esi)
0055     popl    %ebx
0056     popl    %esi
0057     leave
0058     RET
0059 
0060 L_more_than_31:
0061     cmpl    $64,%ecx
0062     jnc L_more_than_63
0063 
0064     subb    $32,%cl
0065     movl    (%esi),%eax /* lsl */
0066     movl    4(%esi),%edx    /* msl */
0067     shrd    %cl,%edx,%eax
0068     shr %cl,%edx
0069     movl    %edx,(%esi)
0070     movl    $0,4(%esi)
0071     popl    %esi
0072     leave
0073     RET
0074 
0075 L_more_than_63:
0076     cmpl    $96,%ecx
0077     jnc L_more_than_95
0078 
0079     subb    $64,%cl
0080     movl    4(%esi),%eax    /* msl */
0081     shr %cl,%eax
0082     xorl    %edx,%edx
0083     movl    %edx,(%esi)
0084     movl    %edx,4(%esi)
0085     popl    %esi
0086     leave
0087     RET
0088 
0089 L_more_than_95:
0090     xorl    %eax,%eax
0091     movl    %eax,(%esi)
0092     movl    %eax,4(%esi)
0093     popl    %esi
0094     leave
0095     RET
0096 SYM_FUNC_END(FPU_shrx)
0097 
0098 
0099 /*---------------------------------------------------------------------------+
0100  |   unsigned FPU_shrxs(void *arg1, unsigned arg2)                           |
0101  |                                                                           |
0102  |   Extended shift right function (optimized for small floating point       |
0103  |   integers).                                                              |
0104  |   Shifts the 64 bit quantity pointed to by the first arg (arg1)           |
0105  |   right by the number of bits specified by the second arg (arg2).         |
0106  |   Forms a 96 bit quantity from the 64 bit arg and eax:                    |
0107  |                [  64 bit arg ][ eax ]                                     |
0108  |            shift right  --------->                                        |
0109  |   The eax register is initialized to 0 before the shifting.               |
0110  |   The lower 8 bits of eax are lost and replaced by a flag which is        |
0111  |   set (to 0x01) if any bit, apart from the first one, is set in the       |
0112  |   part which has been shifted out of the arg.                             |
0113  |   Results returned in the 64 bit arg and eax.                             |
0114  +---------------------------------------------------------------------------*/
0115 SYM_FUNC_START(FPU_shrxs)
0116     push    %ebp
0117     movl    %esp,%ebp
0118     pushl   %esi
0119     pushl   %ebx
0120     movl    PARAM2,%ecx
0121     movl    PARAM1,%esi
0122     cmpl    $64,%ecx    /* shrd only works for 0..31 bits */
0123     jnc Ls_more_than_63
0124 
0125     cmpl    $32,%ecx    /* shrd only works for 0..31 bits */
0126     jc  Ls_less_than_32
0127 
0128 /* We got here without jumps by assuming that the most common requirement
0129    is for small integers */
0130 /* Shift by [32..63] bits */
0131     subb    $32,%cl
0132     movl    (%esi),%eax /* lsl */
0133     movl    4(%esi),%edx    /* msl */
0134     xorl    %ebx,%ebx
0135     shrd    %cl,%eax,%ebx
0136     shrd    %cl,%edx,%eax
0137     shr %cl,%edx
0138     orl %ebx,%ebx       /* test these 32 bits */
0139     setne   %bl
0140     test    $0x7fffffff,%eax    /* and 31 bits here */
0141     setne   %bh
0142     orw %bx,%bx         /* Any of the 63 bit set ? */
0143     setne   %al
0144     movl    %edx,(%esi)
0145     movl    $0,4(%esi)
0146     popl    %ebx
0147     popl    %esi
0148     leave
0149     RET
0150 
0151 /* Shift by [0..31] bits */
0152 Ls_less_than_32:
0153     movl    (%esi),%ebx /* lsl */
0154     movl    4(%esi),%edx    /* msl */
0155     xorl    %eax,%eax   /* extension */
0156     shrd    %cl,%ebx,%eax
0157     shrd    %cl,%edx,%ebx
0158     shr %cl,%edx
0159     test    $0x7fffffff,%eax    /* only need to look at eax here */
0160     setne   %al
0161     movl    %ebx,(%esi)
0162     movl    %edx,4(%esi)
0163     popl    %ebx
0164     popl    %esi
0165     leave
0166     RET
0167 
0168 /* Shift by [64..95] bits */
0169 Ls_more_than_63:
0170     cmpl    $96,%ecx
0171     jnc Ls_more_than_95
0172 
0173     subb    $64,%cl
0174     movl    (%esi),%ebx /* lsl */
0175     movl    4(%esi),%eax    /* msl */
0176     xorl    %edx,%edx   /* extension */
0177     shrd    %cl,%ebx,%edx
0178     shrd    %cl,%eax,%ebx
0179     shr %cl,%eax
0180     orl %ebx,%edx
0181     setne   %bl
0182     test    $0x7fffffff,%eax    /* only need to look at eax here */
0183     setne   %bh
0184     orw %bx,%bx
0185     setne   %al
0186     xorl    %edx,%edx
0187     movl    %edx,(%esi) /* set to zero */
0188     movl    %edx,4(%esi)    /* set to zero */
0189     popl    %ebx
0190     popl    %esi
0191     leave
0192     RET
0193 
0194 Ls_more_than_95:
0195 /* Shift by [96..inf) bits */
0196     xorl    %eax,%eax
0197     movl    (%esi),%ebx
0198     orl 4(%esi),%ebx
0199     setne   %al
0200     xorl    %ebx,%ebx
0201     movl    %ebx,(%esi)
0202     movl    %ebx,4(%esi)
0203     popl    %ebx
0204     popl    %esi
0205     leave
0206     RET
0207 SYM_FUNC_END(FPU_shrxs)