1 .file "wm_shrx.S" 2 /*---------------------------------------------------------------------------+ 3 | wm_shrx.S | 4 | | 5 | 64 bit right shift functions | 6 | | 7 | Copyright (C) 1992 W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | 8 | Australia. E-mail billm@vaxc.cc.monash.edu.au | 9 | | 10 | Call from C as: | 11 | unsigned shrx(void *arg1, unsigned arg2) | 12 | and | 13 | unsigned shrxs(void *arg1, unsigned arg2) | 14 | | 15 +---------------------------------------------------------------------------*/ 16 17 #include "fpu_asm.h" 18 19 .text 20 /*---------------------------------------------------------------------------+ 21 | unsigned shrx(void *arg1, unsigned arg2) | 22 | | 23 | Extended shift right function. | 24 | Fastest for small shifts. | 25 | Shifts the 64 bit quantity pointed to by the first arg (arg1) | 26 | right by the number of bits specified by the second arg (arg2). | 27 | Forms a 96 bit quantity from the 64 bit arg and eax: | 28 | [ 64 bit arg ][ eax ] | 29 | shift right ---------> | 30 | The eax register is initialized to 0 before the shifting. | 31 | Results returned in the 64 bit arg and eax. | 32 +---------------------------------------------------------------------------*/ 33 34 ENTRY(shrx) 35 push %ebp 36 movl %esp,%ebp 37 pushl %esi 38 movl PARAM2,%ecx 39 movl PARAM1,%esi 40 cmpl $32,%ecx /* shrd only works for 0..31 bits */ 41 jnc L_more_than_31 42 43 /* less than 32 bits */ 44 pushl %ebx 45 movl (%esi),%ebx /* lsl */ 46 movl 4(%esi),%edx /* msl */ 47 xorl %eax,%eax /* extension */ 48 shrd %cl,%ebx,%eax 49 shrd %cl,%edx,%ebx 50 shr %cl,%edx 51 movl %ebx,(%esi) 52 movl %edx,4(%esi) 53 popl %ebx 54 popl %esi 55 leave 56 ret 57 58 L_more_than_31: 59 cmpl $64,%ecx 60 jnc L_more_than_63 61 62 subb $32,%cl 63 movl (%esi),%eax /* lsl */ 64 movl 4(%esi),%edx /* msl */ 65 shrd %cl,%edx,%eax 66 shr %cl,%edx 67 movl %edx,(%esi) 68 movl $0,4(%esi) 69 popl %esi 70 leave 71 ret 72 73 L_more_than_63: 74 cmpl $96,%ecx 75 jnc L_more_than_95 76 77 subb $64,%cl 78 movl 4(%esi),%eax /* msl */ 79 shr %cl,%eax 80 xorl %edx,%edx 81 movl %edx,(%esi) 82 movl %edx,4(%esi) 83 popl %esi 84 leave 85 ret 86 87 L_more_than_95: 88 xorl %eax,%eax 89 movl %eax,(%esi) 90 movl %eax,4(%esi) 91 popl %esi 92 leave 93 ret 94 95 96 /*---------------------------------------------------------------------------+ 97 | unsigned shrxs(void *arg1, unsigned arg2) | 98 | | 99 | Extended shift right function (optimized for small floating point | 100 | integers). | 101 | Shifts the 64 bit quantity pointed to by the first arg (arg1) | 102 | right by the number of bits specified by the second arg (arg2). | 103 | Forms a 96 bit quantity from the 64 bit arg and eax: | 104 | [ 64 bit arg ][ eax ] | 105 | shift right ---------> | 106 | The eax register is initialized to 0 before the shifting. | 107 | The lower 8 bits of eax are lost and replaced by a flag which is | 108 | set (to 0x01) if any bit, apart from the first one, is set in the | 109 | part which has been shifted out of the arg. | 110 | Results returned in the 64 bit arg and eax. | 111 +---------------------------------------------------------------------------*/ 112 ENTRY(shrxs) 113 push %ebp 114 movl %esp,%ebp 115 pushl %esi 116 pushl %ebx 117 movl PARAM2,%ecx 118 movl PARAM1,%esi 119 cmpl $64,%ecx /* shrd only works for 0..31 bits */ 120 jnc Ls_more_than_63 121 122 cmpl $32,%ecx /* shrd only works for 0..31 bits */ 123 jc Ls_less_than_32 124 125 /* We got here without jumps by assuming that the most common requirement 126 is for small integers */ 127 /* Shift by [32..63] bits */ 128 subb $32,%cl 129 movl (%esi),%eax /* lsl */ 130 movl 4(%esi),%edx /* msl */ 131 xorl %ebx,%ebx 132 shrd %cl,%eax,%ebx 133 shrd %cl,%edx,%eax 134 shr %cl,%edx 135 orl %ebx,%ebx /* test these 32 bits */ 136 setne %bl 137 test $0x7fffffff,%eax /* and 31 bits here */ 138 setne %bh 139 orw %bx,%bx /* Any of the 63 bit set ? */ 140 setne %al 141 movl %edx,(%esi) 142 movl $0,4(%esi) 143 popl %ebx 144 popl %esi 145 leave 146 ret 147 148 /* Shift by [0..31] bits */ 149 Ls_less_than_32: 150 movl (%esi),%ebx /* lsl */ 151 movl 4(%esi),%edx /* msl */ 152 xorl %eax,%eax /* extension */ 153 shrd %cl,%ebx,%eax 154 shrd %cl,%edx,%ebx 155 shr %cl,%edx 156 test $0x7fffffff,%eax /* only need to look at eax here */ 157 setne %al 158 movl %ebx,(%esi) 159 movl %edx,4(%esi) 160 popl %ebx 161 popl %esi 162 leave 163 ret 164 165 /* Shift by [64..95] bits */ 166 Ls_more_than_63: 167 cmpl $96,%ecx 168 jnc Ls_more_than_95 169 170 subb $64,%cl 171 movl (%esi),%ebx /* lsl */ 172 movl 4(%esi),%eax /* msl */ 173 xorl %edx,%edx /* extension */ 174 shrd %cl,%ebx,%edx 175 shrd %cl,%eax,%ebx 176 shr %cl,%eax 177 orl %ebx,%edx 178 setne %bl 179 test $0x7fffffff,%eax /* only need to look at eax here */ 180 setne %bh 181 orw %bx,%bx 182 setne %al 183 xorl %edx,%edx 184 movl %edx,(%esi) /* set to zero */ 185 movl %edx,4(%esi) /* set to zero */ 186 popl %ebx 187 popl %esi 188 leave 189 ret 190 191 Ls_more_than_95: 192 /* Shift by [96..inf) bits */ 193 xorl %eax,%eax 194 movl (%esi),%ebx 195 orl 4(%esi),%ebx 196 setne %al 197 xorl %ebx,%ebx 198 movl %ebx,(%esi) 199 movl %ebx,4(%esi) 200 popl %ebx 201 popl %esi 202 leave 203 ret