home *** CD-ROM | disk | FTP | other *** search
/ APDL Public Domain 1 / APDL_PD1A.iso / printing / ghostscrip / source / specific / asm / iutilasm < prev   
Encoding:
Text File  |  1991-10-26  |  5.3 KB  |  262 lines

  1. ;    Copyright (C) 1989, 1990, 1991 Aladdin Enterprises.  All rights reserved.
  2. ;    Distributed by Free Software Foundation, Inc.
  3. ;
  4. ; This file is part of Ghostscript.
  5. ;
  6. ; Ghostscript is distributed in the hope that it will be useful, but
  7. ; WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  8. ; to anyone for the consequences of using it or for whether it serves any
  9. ; particular purpose or works at all, unless he says so in writing.  Refer
  10. ; to the Ghostscript General Public License for full details.
  11. ;
  12. ; Everyone is granted permission to copy, modify and redistribute
  13. ; Ghostscript, but only under the conditions described in the Ghostscript
  14. ; General Public License.  A copy of this license is supposed to have been
  15. ; given to you along with Ghostscript so you can know your rights and
  16. ; responsibilities.  It should be in a file named COPYING.  Among other
  17. ; things, the copyright notice and this notice must be preserved on all
  18. ; copies.
  19.  
  20. ; iutilasm.asm
  21. ; Assembly code for Ghostscript interpreter on MS-DOS systems
  22.  
  23. utilasm_TEXT    SEGMENT    WORD PUBLIC 'CODE'
  24.     ASSUME    CS:utilasm_TEXT
  25.  
  26.  
  27.     ifdef    FOR80386
  28.  
  29.     .286c
  30.  
  31. ; Macro for 32-bit operand prefix.
  32. OP32    macro
  33.     db    66h
  34.     endm
  35.  
  36.     endif                    ; FOR80386
  37.  
  38.  
  39.     ifdef    FOR80386
  40.  
  41. ; Replace the multiply and divide routines in the Turbo C library
  42. ; if we are running on an 80386.
  43.  
  44. ; Macro to swap the halves of a 32-bit register.
  45. ; Unfortunately, masm won't allow a shift instruction with a count of 16,
  46. ; so we have to code it in hex.
  47. swap    macro    regno
  48.       OP32
  49.     db    0c1h,0c0h+regno,16        ; rol regno,16
  50.     endm
  51. regax    equ    0
  52. regcx    equ    1
  53. regdx    equ    2
  54. regbx    equ    3
  55.  
  56. ; Multiply (dx,ax) by (cx,bx) to (dx,ax).
  57.     PUBLIC    LXMUL@
  58. LXMUL@    proc    far
  59.     swap    regdx
  60.     mov    dx,ax
  61.     swap    regcx
  62.     mov    cx,bx
  63.       OP32
  64.     db    0fh,0afh,0d1h            ; imul dx,cx
  65.       OP32
  66.     mov    ax,dx
  67.     swap    regdx
  68.     ret
  69. LXMUL@    endp
  70.  
  71. ; Divide two stack operands, leave the result in (dx,ax).
  72. setup32    macro
  73.     mov    bx,sp
  74.       OP32
  75.     mov    ax,ss:[bx+4]            ; dividend
  76.     endm
  77.     PUBLIC    LDIV@, LUDIV@, LMOD@, LUMOD@
  78. LDIV@    proc    far
  79.     setup32
  80.       OP32
  81.     cwd
  82.       OP32
  83.     idiv    word ptr ss:[bx+8]        ; divisor
  84.       OP32
  85.     mov    dx,ax
  86.     swap    regdx
  87.     ret    8
  88. LDIV@    endp
  89. LUDIV@    proc    far
  90.     setup32
  91.       OP32
  92.     xor    dx,dx
  93.       OP32
  94.     div    word ptr ss:[bx+8]        ; divisor
  95.       OP32
  96.     mov    dx,ax
  97.     swap    regdx
  98.     ret    8
  99. LUDIV@    endp
  100. LMOD@    proc    far
  101.     setup32
  102.       OP32
  103.     cwd
  104.       OP32
  105.     idiv    word ptr ss:[bx+8]        ; divisor
  106.       OP32
  107.     mov    ax,dx
  108.     swap    regdx
  109.     ret    8
  110. LMOD@    endp
  111. LUMOD@    proc    far
  112.     setup32
  113.       OP32
  114.     xor    dx,dx
  115.       OP32
  116.     div    word ptr ss:[bx+8]        ; divisor
  117.       OP32
  118.     mov    ax,dx
  119.     swap    regdx
  120.     ret    8
  121. LUMOD@    endp
  122.  
  123.     else                    ; !FOR80386
  124.  
  125. ; Replace the unsigned divide routines in the Turbo C library,
  126. ; which do the division one bit at a time (!).  (We should replace
  127. ; the signed divide routines as well, but it's too much work.)
  128.  
  129.     PUBLIC    LUDIV@, LUMOD@
  130.  
  131. ; Divide two unsigned longs on the stack.
  132. ; Leave either the quotient or the remainder in (dx,ax).
  133.  
  134. ; We use an offset in bx distinguish div from mod.
  135. LUMOD@    proc    far
  136.     mov    bx,2
  137.     jmp    udiv
  138. LUMOD@    endp
  139. LUDIV@    proc    far
  140.     xor    bx,bx
  141. udiv:    push    bp
  142.     push    bx                ; 0 = div, 2 = mod
  143.     mov    bp,sp
  144. nlo    equ    8
  145. nhi    equ    10
  146. dlo    equ    12
  147. dhi    equ    14
  148.     mov    ax,[bp+nlo]
  149.     mov    dx,[bp+nhi]
  150.     mov    bx,[bp+dlo]
  151.     mov    cx,[bp+dhi]
  152. ; Now we are dividing dx:ax by cx:bx.
  153. ; Check to see whether this is really a 32/16 division.
  154.     or    cx,cx
  155.     jnz    div2
  156. ; 32/16, check for 16- vs. 32-bit quotient
  157.     cmp    dx,bx
  158.     jae    div1
  159. ; 32/16 with 16-bit quotient, just do it.
  160.     div    bx                ; ax = quo, dx = rem
  161.     pop    bx
  162.     pop    bp
  163.     jmp    cs:xx1[bx]
  164.     even
  165. xx1    dw    divx1
  166.     dw    modx1
  167. divx1:    xor    dx,dx
  168.     ret    8
  169. modx1:    mov    ax,dx
  170.     xor    dx,dx
  171.     ret    8
  172. ; 32/16 with 32-bit quotient, do in 2 parts.
  173. div1:    mov    cx,ax                ; save lo num
  174.     mov    ax,dx
  175.     xor    dx,dx
  176.     div    bx                ; ax = hi quo
  177.     xchg    cx,ax                ; save hi quo, get lo num
  178.     div    bx                ; ax = lo quo, dx = rem
  179.     pop    bx
  180.     pop    bp
  181.     jmp    cs:xx1a[bx]
  182.     even
  183. xx1a    dw    offset divx1a
  184.     dw    offset modx1
  185. divx1a:    mov    dx,cx                ; hi quo
  186.     ret    8
  187. ; This is really a 32/32 bit division.
  188. ; (Note that the quotient cannot exceed 16 bits.)
  189. ; The following algorithm is taken from pp. 235-240 of Knuth, vol. 2
  190. ; (first edition).
  191. ; Start by normalizing the numerator and denominator.
  192. div2:    or    ch,ch
  193.     jz    div21                ; ch == 0, but cl != 0
  194. ; Do 8 steps all at once.
  195.     mov    bl,bh
  196.     mov    bh,cl
  197.     mov    cl,ch
  198.     xor    ch,ch
  199.     mov    al,ah
  200.     mov    ah,dl
  201.     mov    dl,dh
  202.     xor    dh,dh
  203.     rol    bx,1                ; cancel following rcr
  204. div2a:    rcr    bx,1                ; finish previous shift
  205. div21:    shr    dx,1
  206.     rcr    ax,1
  207.     shr    cx,1
  208.     jnz    div2a
  209.     rcr    bx,1
  210. ; Now we can do a 32/16 divide.
  211. div2x:    div    bx                ; ax = quo, dx = rem
  212. ; Multiply by the denominator, and correct the result.
  213.     mov    cx,ax                ; save quotient
  214.     mul    word ptr [bp+dhi]
  215.     mov    bx,ax                ; save lo part of hi product
  216.     mov    ax,cx
  217.     mul    word ptr [bp+dlo]
  218.     add    dx,bx
  219. ; Now cx = trial quotient, (dx,ax) = cx * denominator.
  220.     not    dx
  221.     neg    ax
  222.     cmc
  223.     adc    dx,0                ; double-precision neg
  224.     jc    divz                ; zero quotient
  225.                         ; requires special handling
  226.     add    ax,[bp+nlo]
  227.     adc    dx,[bp+nhi]
  228.     jc    divx
  229. ; Quotient is too large, adjust it.
  230. div3:    dec    cx
  231.     add    ax,[bp+dlo]
  232.     adc    dx,[bp+dhi]
  233.     jnc    div3
  234. ; All done.  (dx,ax) = remainder, cx = lo quotient.
  235. divx:    pop    bx
  236.     pop    bp
  237.     jmp    cs:xx3[bx]
  238.     even
  239. xx3    dw    offset divx3
  240.     dw    offset modx3
  241. divx3:    mov    ax,cx
  242.     xor    dx,dx
  243. modx3:    ret    8
  244. ; Handle zero quotient specially.
  245. divz:    pop    bx
  246.     jmp    cs:xxz[bx]
  247.     even
  248. xxz    dw    offset divxz
  249.     dw    offset modxz
  250. divxz:    pop    bp
  251.     ret    8
  252. modxz:    mov    ax,[bp+nlo-2]            ; adjust for popf
  253.     mov    dx,[bp+nhi-2]
  254.     pop    bp
  255.     ret    8
  256. LUDIV@    endp
  257.  
  258.     endif                    ; FOR80386
  259.  
  260. utilasm_TEXT ENDS
  261.     END
  262.