; Copyright (C) 1989, 1992 Aladdin Enterprises. All rights reserved.
; Distributed by Free Software Foundation, Inc.
; This file is part of Ghostscript.
; Ghostscript is distributed in the hope that it will be useful, but
; WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
; to anyone for the consequences of using it or for whether it serves any
; particular purpose or works at all, unless he says so in writing. Refer
; to the Ghostscript General Public License for full details.
; Everyone is granted permission to copy, modify and redistribute
; Ghostscript, but only under the conditions described in the Ghostscript
; General Public License. A copy of this license is supposed to have been
; given to you along with Ghostscript so you can know your rights and
; responsibilities. It should be in a file named COPYING. Among other
; things, the copyright notice and this notice must be preserved on all
; Assembly code for Ghostscript interpreter on MS-DOS systems
utilasm_TEXT SEGMENT WORD PUBLIC 'CODE'
; Macro for 32-bit operand prefix.
; Replace the multiply and divide routines in the Turbo C library
; if we are running on an 80386.
; Macro to swap the halves of a 32-bit register.
; Unfortunately, masm won't allow a shift instruction with a count of 16,
; so we have to code it in hex.
db 0c1h,0c0h+regno,16 ; rol regno,16
; Multiply (dx,ax) by (cx,bx) to (dx,ax).
db 0fh,0afh,0d1h ; imul dx,cx
; Divide two stack operands, leave the result in (dx,ax).
mov ax,ss:[bx+4] ; dividend
PUBLIC LDIV@, LUDIV@, LMOD@, LUMOD@
PUBLIC F_LDIV@, F_LUDIV@, F_LMOD@, F_LUMOD@
idiv word ptr ss:[bx+8] ; divisor
div word ptr ss:[bx+8] ; divisor
idiv word ptr ss:[bx+8] ; divisor
div word ptr ss:[bx+8] ; divisor
; Replace the unsigned divide routines in the Turbo C library,
; which do the division one bit at a time (!). (We should replace
; the signed divide routines as well, but it's too much work.)
PUBLIC F_LUDIV@, F_LUMOD@
; Divide two unsigned longs on the stack.
; Leave either the quotient or the remainder in (dx,ax).
; We use an offset in bx distinguish div from mod.
push bx ; 0 = div, 2 = mod
; Now we are dividing dx:ax by cx:bx.
; Check to see whether this is really a 32/16 division.
; 32/16, check for 16- vs. 32-bit quotient
; 32/16 with 16-bit quotient, just do it.
div bx ; ax = quo, dx = rem
; 32/16 with 32-bit quotient, do in 2 parts.
div1: mov cx,ax ; save lo num
xchg cx,ax ; save hi quo, get lo num
div bx ; ax = lo quo, dx = rem
divx1a: mov dx,cx ; hi quo
; This is really a 32/32 bit division.
; (Note that the quotient cannot exceed 16 bits.)
; The following algorithm is taken from pp. 235-240 of Knuth, vol. 2
; Start by normalizing the numerator and denominator.
jz div21 ; ch == 0, but cl != 0
; Do 8 steps all at once.
rol bx,1 ; cancel following rcr
div2a: rcr bx,1 ; finish previous shift
; Now we can do a 32/16 divide.
div2x: div bx ; ax = quo, dx = rem
; Multiply by the denominator, and correct the result.
mov cx,ax ; save quotient
mov bx,ax ; save lo part of hi product
; Now cx = trial quotient, (dx,ax) = cx * denominator.
adc dx,0 ; double-precision neg
; requires special handling
; Quotient is too large, adjust it.
; All done. (dx,ax) = remainder, cx = lo quotient.
; Handle zero quotient specially.
modxz: mov ax,[bp+nlo-2] ; adjust for popf
; Swap even and odd bytes from src to dest.
; See gsmisc.c for the C definition.
mov dx,ss:[bx+12] ; count
; Transpose an 8x8 bit matrix. See gsmisc.c for the algorithm in C.
; After pushing, the offsets of the parameters are:
; byte *inp=10, int line_size=14, byte *outp=16, int dist=20.
mov di,ss:[si+14] ; line_size
; We assign variables to registers as follows:
; ax = AE, bx = BF, cx (or di) = CG, dx = DH.
; Load the input data. Initially we assign
; ax = AB, bx = EF, cx (or di) = CD, dx = GH.
; Transposition macro, see C code for explanation.
trans macro reg1,reg2,shift,mask
mov di,cx ; we need cl for the shift count
mov di,cx ; need cl again
mov cx,di ; done shifting >1