home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / Runimage / Delphi50 / Source / Rtl / Sys / _LL.ASM next >
Encoding:
Assembly Source File  |  1999-08-11  |  17.4 KB  |  712 lines

  1. ;[]-----------------------------------------------------------------[]
  2. ;|   _LL.ASM -- 64-bit integer math helper functions                 |
  3. ;[]-----------------------------------------------------------------[]
  4. ;
  5. ; $Copyright: 1998$
  6. ; $Revision:   1.5  $
  7. ;
  8. ;
  9. ;  This is source for the compiler helper functions that manipulate
  10. ;  64-bit integers (__int64's in C & C++).
  11. ;
  12.             .386p
  13.  
  14. _TEXT        SEGMENT    DWORD PUBLIC USE32 'CODE'
  15.             ASSUME    CS:_TEXT
  16.  
  17.             PUBLIC    __llmul
  18.             PUBLIC    __lldiv
  19.             PUBLIC    __lludiv
  20.             PUBLIC    __llmod
  21.             PUBLIC    __llumod
  22.             PUBLIC    __llshl
  23.             PUBLIC    __llshr
  24.             PUBLIC    __llushr
  25.             PUBLIC    __lldivo    ; overflow check version
  26.             PUBLIC    __llmulo        ; overflow check version
  27.             PUBLIC    __llmodo    ; overflow check version
  28.  
  29. ;
  30. ; These functions always return the 64-bit result in EAX:EDX
  31. ;
  32.  
  33. ; ------------------------------------------------------------------------------
  34. ;    64-bit signed multiply
  35. ; ------------------------------------------------------------------------------
  36. ;
  37. ;  Param 1(EAX:EDX), Param 2([ESP+8]:[ESP+4])  ; before reg pushing
  38. ;
  39.  
  40. __llmul        PROC    near
  41.  
  42.         push        edx
  43.         push        eax
  44.         
  45.         ; Param2 : [ESP+16]:[ESP+12]  (hi:lo)
  46.         ; Param1 : [ESP+4]:[ESP]      (hi:lo)
  47.  
  48.         mov        eax, [esp+16]
  49.         mul        dword ptr [esp]
  50.         mov        ecx, eax
  51.         
  52.         mov        eax, [esp+4]
  53.         mul        dword ptr [esp+12]
  54.         add        ecx, eax
  55.         
  56.         mov        eax, [esp]
  57.         mul        dword ptr [esp+12]
  58.         add        edx, ecx
  59.  
  60.         pop        ecx
  61.         pop        ecx
  62.  
  63.         ret        8
  64.  
  65. __llmul        ENDP
  66.  
  67.  
  68. ; ------------------------------------------------------------------------------
  69. ;    64-bit signed multiply, with overflow check (98.05.15: overflow not supported yet)
  70. ; ------------------------------------------------------------------------------
  71. ;
  72. ;  Param1 ~= U   (Uh, Ul)
  73. ;  Param2 ~= V   (Vh, Vl)
  74. ;
  75. ;  Param 1(EAX:EDX), Param 2([ESP+8]:[ESP+4])  ; before reg pushing
  76. ;
  77. ;  compiler-helper function
  78. ;  O-flag set on exit   => result is invalid
  79. ;  O-flag clear on exit => result is valid
  80.  
  81. __llmulo    proc        near
  82.         push        edx
  83.         push        eax
  84.         
  85.         ; Param2 : [ESP+16]:[ESP+12]  (hi:lo)
  86.         ; Param1 : [ESP+4]:[ESP]      (hi:lo)
  87.  
  88.         mov        eax, [esp+16]
  89.         mul        dword ptr [esp]
  90.         mov        ecx, eax
  91.         
  92.         mov        eax, [esp+4]
  93.         mul        dword ptr [esp+12]
  94.         add        ecx, eax
  95.         
  96.         mov        eax, [esp]
  97.         mul        dword ptr [esp+12]
  98.         add        edx, ecx
  99.  
  100.         pop        ecx
  101.         pop        ecx
  102.  
  103.         ret        8
  104. __llmulo    endp
  105.  
  106. ; ------------------------------------------------------------------------------
  107. ;    64-bit signed division
  108. ; ------------------------------------------------------------------------------
  109.  
  110. ;
  111. ;  Dividend = Numerator, Divisor = Denominator
  112. ;
  113. ;  Dividend(EAX:EDX), Divisor([ESP+8]:[ESP+4])  ; before reg pushing
  114. ;
  115. ;
  116.  
  117. __lldiv        PROC    near
  118.  
  119.         push    ebp
  120.         push    ebx
  121.         push    esi
  122.         push    edi
  123.  
  124.         xor        edi,edi
  125.  
  126.         mov     ebx,20[esp]             ; get the divisor low dword
  127.         mov     ecx,24[esp]             ; get the divisor high dword
  128.  
  129.         or      ecx,ecx
  130.         jnz     @__lldiv@slow_ldiv      ; both high words are zero
  131.  
  132.         or      edx,edx
  133.         jz      @__lldiv@quick_ldiv
  134.  
  135.         or      ebx,ebx
  136.         jz      @__lldiv@quick_ldiv     ; if ecx:ebx == 0 force a zero divide
  137.                                         ; we don't expect this to actually
  138.                                         ; work
  139.  
  140. @__lldiv@slow_ldiv:
  141.  
  142. ;
  143. ;               Signed division should be done.  Convert negative
  144. ;               values to positive and do an unsigned division.
  145. ;               Store the sign value in the next higher bit of
  146. ;               di (test mask of 4).  Thus when we are done, testing
  147. ;               that bit will determine the sign of the result.
  148. ;
  149.         or      edx,edx                 ; test sign of dividend
  150.         jns     @__lldiv@onepos
  151.         neg     edx
  152.         neg     eax
  153.         sbb     edx,0                   ; negate dividend
  154.         or      edi,1
  155. @__lldiv@onepos:
  156.         or      ecx,ecx                 ; test sign of divisor
  157.         jns     @__lldiv@positive
  158.         neg     ecx
  159.         neg     ebx
  160.         sbb     ecx,0                   ; negate divisor
  161.         xor        edi,1
  162. @__lldiv@positive:
  163.         mov     ebp,ecx
  164.         mov     ecx,64                  ; shift counter
  165.         push    edi                     ; save the flags
  166. ;
  167. ;       Now the stack looks something like this:
  168. ;
  169. ;               24[esp]: divisor (high dword)
  170. ;               20[esp]: divisor (low dword)
  171. ;               16[esp]: return EIP
  172. ;               12[esp]: previous EBP
  173. ;                8[esp]: previous EBX
  174. ;                4[esp]: previous ESI
  175. ;                 [esp]: previous EDI
  176. ;
  177.         xor     edi,edi                 ; fake a 64 bit dividend
  178.         xor     esi,esi                 ;
  179. @__lldiv@xloop:
  180.         shl     eax,1                   ; shift dividend left one bit
  181.         rcl     edx,1
  182.         rcl     esi,1
  183.         rcl     edi,1
  184.         cmp     edi,ebp                 ; dividend larger?
  185.         jb      @__lldiv@nosub
  186.         ja      @__lldiv@subtract
  187.         cmp     esi,ebx                 ; maybe
  188.         jb      @__lldiv@nosub
  189. @__lldiv@subtract:
  190.         sub     esi,ebx
  191.         sbb     edi,ebp                 ; subtract the divisor
  192.         inc     eax                     ; build quotient
  193. @__lldiv@nosub:
  194.         loop    @__lldiv@xloop
  195. ;
  196. ;       When done with the loop the four registers values' look like:
  197. ;
  198. ;       |     edi    |    esi     |    edx     |    eax     |
  199. ;       |        remainder        |         quotient        |
  200. ;
  201.         pop     ebx                     ; get control bits
  202.         test    ebx,1                   ; needs negative
  203.         jz      @__lldiv@finish
  204.         neg     edx
  205.         neg     eax
  206.         sbb     edx,0                   ; negate
  207. @__lldiv@finish:
  208.         pop     edi
  209.         pop     esi
  210.         pop     ebx
  211.         pop     ebp
  212.         ret     8
  213.  
  214. @__lldiv@quick_ldiv:
  215.         div     ebx                     ; unsigned divide
  216.         xor     edx,edx
  217.         jmp     short @__lldiv@finish
  218.  
  219. __lldiv        ENDP
  220.  
  221.  
  222. ; ------------------------------------------------------------------------------
  223. ;    64-bit signed division with overflow check (98.05.15: not implementated yet)
  224. ; ------------------------------------------------------------------------------
  225.  
  226. ;
  227. ;  Dividend = Numerator, Divisor = Denominator
  228. ;
  229. ;  Dividend(EAX:EDX), Divisor([ESP+8]:[ESP+4])
  230. ;  Param 1 (EAX:EDX), Param 2([ESP+8]:[ESP+4])
  231. ;
  232. ;  Param1 ~= U   (Uh, Ul)
  233. ;  Param2 ~= V   (Vh, Vl)
  234. ;
  235. ;  compiler-helper function
  236. ;  O-flag set on exit   => result is invalid
  237. ;  O-flag clear on exit => result is valid
  238. ;
  239.  
  240. __lldivo    proc    near
  241.  
  242.         ; check for overflow condition: min(int64) DIV -1
  243.         
  244.         push    esi
  245.         
  246.         mov    esi, [esp+12]        ; Vh
  247.         and    esi, [esp+8]        ; Vl
  248.         cmp    esi, 0ffffffffh        ; V = -1?
  249.         jne    divok
  250.  
  251.         mov    esi, eax
  252.         or    esi, edx
  253.         cmp    esi, 80000000H        ; U = min(int64)?
  254.         jne    divok
  255.         
  256. divOvl:        mov    eax, esi
  257.         pop    esi
  258.         dec    eax                     ; turn on O-flag
  259.         ret    
  260.  
  261. divok:        pop    esi
  262.  
  263.             push    [esp+8]            ; Vh
  264.         push    [esp+8]            ; Vl (offset is changed from push)
  265.         call    __lldiv
  266.         and    eax, eax        ; turn off O-flag
  267.         ret    8
  268. __lldivo    endp
  269.  
  270. ; ------------------------------------------------------------------------------
  271. ;    64-bit unsigned division
  272. ; ------------------------------------------------------------------------------
  273.  
  274. ;  Dividend(EAX(hi):EDX(lo)), Divisor([ESP+8](hi):[ESP+4](lo))  ; before reg pushing
  275. __lludiv        PROC    near
  276.  
  277.         push    ebp
  278.         push    ebx
  279.         push    esi
  280.         push    edi
  281.  
  282. ;
  283. ;       Now the stack looks something like this:
  284. ;
  285. ;               24[esp]: divisor (high dword)
  286. ;               20[esp]: divisor (low dword)
  287. ;               16[esp]: return EIP
  288. ;               12[esp]: previous EBP
  289. ;                8[esp]: previous EBX
  290. ;                4[esp]: previous ESI
  291. ;                 [esp]: previous EDI
  292. ;
  293.  
  294. ;       dividend is pushed last, therefore the first in the args
  295. ;       divisor next.
  296. ;
  297.         mov     ebx,20[esp]             ; get the first low word
  298.         mov     ecx,24[esp]             ; get the first high word
  299.  
  300.         or      ecx,ecx
  301.         jnz     @__lludiv@slow_ldiv     ; both high words are zero
  302.  
  303.         or      edx,edx
  304.         jz      @__lludiv@quick_ldiv
  305.  
  306.         or      ebx,ebx
  307.         jz      @__lludiv@quick_ldiv    ; if ecx:ebx == 0 force a zero divide
  308.                                         ; we don't expect this to actually
  309.                                         ; work
  310.  
  311. @__lludiv@slow_ldiv:
  312.  
  313.         mov     ebp,ecx
  314.         mov     ecx,64                  ; shift counter
  315.  
  316.         xor     edi,edi                 ; fake a 64 bit dividend
  317.         xor     esi,esi                 ;
  318. @__lludiv@xloop:
  319.         shl     eax,1                   ; shift dividend left one bit
  320.         rcl     edx,1
  321.         rcl     esi,1
  322.         rcl     edi,1
  323.         cmp     edi,ebp                 ; dividend larger?
  324.         jb      @__lludiv@nosub
  325.         ja      @__lludiv@subtract
  326.         cmp     esi,ebx                 ; maybe
  327.         jb      @__lludiv@nosub
  328. @__lludiv@subtract:
  329.         sub     esi,ebx
  330.         sbb     edi,ebp                 ; subtract the divisor
  331.         inc     eax                     ; build quotient
  332. @__lludiv@nosub:
  333.         loop    @__lludiv@xloop
  334. ;
  335. ;       When done with the loop the four registers values' look like:
  336. ;
  337. ;       |     edi    |    esi     |    edx     |    eax     |
  338. ;       |        remainder        |         quotient        |
  339. ;
  340.  
  341. @__lludiv@finish:
  342.         pop     edi
  343.         pop     esi
  344.         pop     ebx
  345.         pop     ebp
  346.         ret     8
  347.  
  348. @__lludiv@quick_ldiv:
  349.         div     ebx                     ; unsigned divide
  350.         xor     edx,edx
  351.         jmp     short @__lludiv@finish
  352.  
  353. __lludiv        ENDP
  354.  
  355.  
  356. ; ------------------------------------------------------------------------------
  357. ;    64-bit modulo
  358. ; ------------------------------------------------------------------------------
  359.  
  360. ;  Dividend(EAX:EDX), Divisor([ESP+8]:[ESP+4])  ; before reg pushing
  361. __llmod        PROC    near
  362.  
  363.  
  364.         push    ebp
  365.         push    ebx
  366.         push    esi
  367.         push    edi
  368.  
  369.         xor        edi,edi
  370. ;
  371. ;       dividend is pushed last, therefore the first in the args
  372. ;       divisor next.
  373. ;
  374.         mov     ebx,20[esp]             ; get the first low word
  375.         mov     ecx,24[esp]             ; get the first high word
  376.  
  377.         or      ecx,ecx
  378.         jnz     @__llmod@slow_ldiv      ; both high words are zero
  379.  
  380.         or      edx,edx
  381.         jz      @__llmod@quick_ldiv
  382.  
  383.         or      ebx,ebx
  384.         jz      @__llmod@quick_ldiv     ; if ecx:ebx == 0 force a zero divide
  385.                                         ; we don't expect this to actually
  386.                                         ; work
  387.  
  388. @__llmod@slow_ldiv:
  389.  
  390. ;
  391. ;               Signed division should be done.  Convert negative
  392. ;               values to positive and do an unsigned division.
  393. ;               Store the sign value in the next higher bit of
  394. ;               di (test mask of 4).  Thus when we are done, testing
  395. ;               that bit will determine the sign of the result.
  396. ;
  397.         or      edx,edx                 ; test sign of dividend
  398.         jns     @__llmod@onepos
  399.         neg     edx
  400.         neg     eax
  401.         sbb     edx,0                   ; negate dividend
  402.         or      edi,1
  403. @__llmod@onepos:
  404.         or      ecx,ecx                 ; test sign of divisor
  405.         jns     @__llmod@positive
  406.         neg     ecx
  407.         neg     ebx
  408.         sbb     ecx,0                   ; negate divisor
  409.  
  410. @__llmod@positive:
  411.         mov     ebp,ecx
  412.         mov     ecx,64                  ; shift counter
  413.         push    edi                     ; save the flags
  414. ;
  415. ;       Now the stack looks something like this:
  416. ;
  417. ;               24[esp]: divisor (high dword)
  418. ;               20[esp]: divisor (low dword)
  419. ;               16[esp]: return EIP
  420. ;               12[esp]: previous EBP
  421. ;                8[esp]: previous EBX
  422. ;                4[esp]: previous ESI
  423. ;                 [esp]: previous EDI
  424. ;
  425.         xor     edi,edi                 ; fake a 64 bit dividend
  426.         xor     esi,esi                 ;
  427. @__llmod@xloop:
  428.         shl     eax,1                   ; shift dividend left one bit
  429.         rcl     edx,1
  430.         rcl     esi,1
  431.         rcl     edi,1
  432.         cmp     edi,ebp                 ; dividend larger?
  433.         jb      @__llmod@nosub
  434.         ja      @__llmod@subtract
  435.         cmp     esi,ebx                 ; maybe
  436.         jb      @__llmod@nosub
  437. @__llmod@subtract:
  438.         sub     esi,ebx
  439.         sbb     edi,ebp                 ; subtract the divisor
  440.         inc     eax                     ; build quotient
  441. @__llmod@nosub:
  442.         loop    @__llmod@xloop
  443. ;
  444. ;       When done with the loop the four registers values' look like:
  445. ;
  446. ;       |     edi    |    esi     |    edx     |    eax     |
  447. ;       |        remainder        |         quotient        |
  448. ;
  449.         mov     eax,esi
  450.         mov     edx,edi                 ; use remainder
  451.  
  452.         pop     ebx                     ; get control bits
  453.         test    ebx,1                   ; needs negative
  454.         jz      @__llmod@finish
  455.         neg     edx
  456.         neg     eax
  457.         sbb     edx,0                    ; negate
  458. @__llmod@finish:
  459.         pop     edi
  460.         pop     esi
  461.         pop     ebx
  462.         pop     ebp
  463.         ret     8
  464.  
  465. @__llmod@quick_ldiv:
  466.         div     ebx                     ; unsigned divide
  467.         xchg    eax,edx
  468.         xor     edx,edx
  469.         jmp     short @__llmod@finish
  470.  
  471. __llmod        ENDP
  472.  
  473.  
  474. ; ------------------------------------------------------------------------------
  475. ;    64-bit signed modulo with overflow (98.05.15: overflow not yet supported)
  476. ; ------------------------------------------------------------------------------
  477.  
  478. ;  Dividend(EAX:EDX), Divisor([ESP+8]:[ESP+4])
  479. ;  Param 1 (EAX:EDX), Param 2([ESP+8]:[ESP+4])
  480. ;
  481. ;  Param1 ~= U   (Uh, Ul)
  482. ;  Param2 ~= V   (Vh, Vl)
  483. ;
  484. ;  compiler-helper function
  485. ;  O-flag set on exit   => result is invalid
  486. ;  O-flag clear on exit => result is valid
  487. ;
  488.  
  489. __llmodo    proc    near
  490.  
  491.         ; check for overflow condition: min(int64) MOD -1
  492.         
  493.         push    esi
  494.         
  495.         mov    esi, [esp+12]        ; Vh
  496.         and    esi, [esp+8]        ; Vl
  497.         cmp    esi, 0ffffffffh        ; V = -1?
  498.         jne    modok
  499.  
  500.         mov    esi, eax
  501.         or    esi, edx
  502.         cmp    esi, 80000000H        ; U = min(int64)?
  503.         jne    modok
  504.         
  505. modOvl:        mov    eax, esi
  506.         pop    esi
  507.         dec    eax                     ; turn on O-flag
  508.         ret    
  509.  
  510. modok:        pop    esi
  511.  
  512.             push    [esp+8]            ; Vh
  513.         push    [esp+8]            ; Vl (offset is changed from push)
  514.         call    __llmod
  515.  
  516.         and    eax, eax        ; turn off O-flag
  517.         ret    8
  518. __llmodo    endp
  519.  
  520.  
  521. ; ------------------------------------------------------------------------------
  522. ;    64-bit unsigned modulo
  523. ; ------------------------------------------------------------------------------
  524. ;  Dividend(EAX(hi):EDX(lo)), Divisor([ESP+8](hi):[ESP+4](lo))  ; before reg pushing
  525.  
  526. __llumod    PROC    near
  527.  
  528.         push    ebp
  529.         push    ebx
  530.         push    esi
  531.         push    edi
  532.  
  533. ;
  534. ;       Now the stack looks something like this:
  535. ;
  536. ;               24[esp]: divisor (high dword)
  537. ;               20[esp]: divisor (low dword)
  538. ;               16[esp]: return EIP
  539. ;               12[esp]: previous EBP
  540. ;                8[esp]: previous EBX
  541. ;                4[esp]: previous ESI
  542. ;                 [esp]: previous EDI
  543. ;
  544.  
  545. ;       dividend is pushed last, therefore the first in the args
  546. ;       divisor next.
  547. ;
  548.         mov     ebx,20[esp]             ; get the first low word
  549.         mov     ecx,24[esp]             ; get the first high word
  550.  
  551.         or      ecx,ecx
  552.         jnz     @__llumod@slow_ldiv     ; both high words are zero
  553.  
  554.         or      edx,edx
  555.         jz      @__llumod@quick_ldiv
  556.  
  557.         or      ebx,ebx
  558.         jz      @__llumod@quick_ldiv    ; if ecx:ebx == 0 force a zero divide
  559.                                         ; we don't expect this to actually
  560.                                         ; work
  561.  
  562. @__llumod@slow_ldiv:
  563.  
  564.         mov     ebp,ecx
  565.         mov     ecx,64                  ; shift counter
  566.  
  567.         xor     edi,edi                 ; fake a 64 bit dividend
  568.         xor     esi,esi                 ;
  569. @__llumod@xloop:
  570.         shl     eax,1                   ; shift dividend left one bit
  571.         rcl     edx,1
  572.         rcl     esi,1
  573.         rcl     edi,1
  574.         cmp     edi,ebp                 ; dividend larger?
  575.         jb      @__llumod@nosub
  576.         ja      @__llumod@subtract
  577.         cmp     esi,ebx                 ; maybe
  578.         jb      @__llumod@nosub
  579. @__llumod@subtract:
  580.         sub     esi,ebx
  581.         sbb     edi,ebp                 ; subtract the divisor
  582.         inc     eax                     ; build quotient
  583. @__llumod@nosub:
  584.         loop    @__llumod@xloop
  585. ;
  586. ;       When done with the loop the four registers values' look like:
  587. ;
  588. ;       |     edi    |    esi     |    edx     |    eax     |
  589. ;       |        remainder        |         quotient        |
  590. ;
  591.  
  592.         mov     eax,esi
  593.         mov     edx,edi                 ; use remainder
  594.  
  595. @__llumod@finish:
  596.         pop     edi
  597.         pop     esi
  598.         pop     ebx
  599.         pop     ebp
  600.         ret     8
  601.  
  602. @__llumod@quick_ldiv:
  603.         div     ebx                     ; unsigned divide
  604.         xchg    eax,edx
  605.         xor     edx,edx
  606.         jmp     short @__llumod@finish
  607.  
  608. __llumod    ENDP
  609.  
  610. ; ------------------------------------------------------------------------------
  611. ;    64-bit shift left
  612. ; ------------------------------------------------------------------------------
  613.  
  614. ;
  615. ; target (EAX:EDX) count (ECX)
  616. ;
  617. __llshl        PROC    near
  618.  
  619.         cmp        cl, 32
  620.         jl        @__llshl@below32
  621.  
  622.         cmp        cl, 64
  623.         jl        @__llshl@below64
  624.  
  625.         xor        edx, edx
  626.         xor        eax, eax
  627.         ret
  628.  
  629. @__llshl@below64:
  630.  
  631.         mov        edx, eax
  632.         shl        edx, cl
  633.         xor        eax, eax
  634.         ret
  635.  
  636. @__llshl@below32:
  637.  
  638.         shld    edx, eax, cl
  639.         shl        eax, cl
  640.         ret
  641.  
  642. __llshl        ENDP
  643.  
  644. ; ------------------------------------------------------------------------------
  645. ;    64-bit signed shift right
  646. ; ------------------------------------------------------------------------------
  647. ; target (EAX:EDX) count (ECX)
  648.  
  649. __llshr        PROC    near
  650.  
  651.         cmp        cl, 32
  652.         jl        @__llshr@below32
  653.  
  654.         cmp        cl, 64
  655.         jl        @__llshr@below64
  656.  
  657.         sar        edx, 1fh
  658.         mov        eax,edx
  659.         ret
  660.  
  661. @__llshr@below64:
  662.  
  663.         mov        eax, edx
  664.         cdq
  665.         sar        eax,cl
  666.         ret
  667.  
  668. @__llshr@below32:
  669.  
  670.         shrd    eax, edx, cl
  671.         sar        edx, cl
  672.         ret
  673.  
  674. __llshr        ENDP
  675.  
  676. ; ------------------------------------------------------------------------------
  677. ;    64-bit unsigned shift right
  678. ; ------------------------------------------------------------------------------
  679.  
  680. ; target (EAX:EDX) count (ECX)
  681. __llushr     PROC    near
  682.  
  683.         cmp        cl, 32
  684.         jl        @__llushr@below32
  685.  
  686.         cmp        cl, 64
  687.         jl        @__llushr@below64
  688.  
  689.         xor        edx, edx
  690.         xor        eax, eax
  691.         ret
  692.  
  693. @__llushr@below64:
  694.  
  695.         mov        eax, edx
  696.         xor        edx, edx
  697.         shr        eax, cl
  698.         ret
  699.  
  700. @__llushr@below32:
  701.  
  702.         shrd    eax, edx, cl
  703.         shr        edx, cl
  704.         ret
  705.  
  706. __llushr     ENDP
  707.  
  708.  
  709.  
  710. _TEXT        ENDS
  711.  
  712.             END