mirror of https://github.com/nmlgc/ReC98.git
197 lines
6.1 KiB
NASM
197 lines
6.1 KiB
NASM
; *Not* the original file, but an edit to turn it into an includable slice.
|
|
; Changes include:
|
|
; * removal of RULES.ASI to eliminate redundancy
|
|
; * removal of the 'CODE' segment declaration (for obvious reasons)
|
|
; * the @@ prefix on any local labels to avoid name collisions with master.lib
|
|
|
|
;[]-----------------------------------------------------------------[]
|
|
;| H_LDIV.ASM -- long division routine |
|
|
;[]-----------------------------------------------------------------[]
|
|
|
|
;
|
|
; C/C++ Run Time Library - Version 5.0
|
|
;
|
|
; Copyright (c) 1987, 1992 by Borland International
|
|
; All Rights Reserved.
|
|
;
|
|
|
|
public LDIV@
|
|
public F_LDIV@
|
|
public N_LDIV@
|
|
public LUDIV@
|
|
public F_LUDIV@
|
|
public N_LUDIV@
|
|
public LMOD@
|
|
public F_LMOD@
|
|
public N_LMOD@
|
|
public LUMOD@
|
|
public F_LUMOD@
|
|
public N_LUMOD@
|
|
|
|
N_LDIV@:
|
|
pop cx ;fix up far return
|
|
push cs
|
|
push cx
|
|
LDIV@:
|
|
F_LDIV@:
|
|
xor cx,cx ; signed divide
|
|
jmp short common
|
|
|
|
N_LUDIV@:
|
|
pop cx ;fix up far return
|
|
push cs
|
|
push cx
|
|
LUDIV@:
|
|
F_LUDIV@:
|
|
mov cx,1 ; unsigned divide
|
|
jmp short common
|
|
|
|
N_LMOD@:
|
|
pop cx ;fix up far return
|
|
push cs
|
|
push cx
|
|
LMOD@:
|
|
F_LMOD@:
|
|
mov cx,2 ; signed remainder
|
|
jmp short common
|
|
|
|
N_LUMOD@:
|
|
pop cx ;fix up far return
|
|
push cs
|
|
push cx
|
|
LUMOD@:
|
|
F_LUMOD@:
|
|
mov cx,3 ; unsigned remainder
|
|
|
|
;
|
|
; di now contains a two bit control value. The low order
|
|
; bit (test mask of 1) is on if the operation is unsigned,
|
|
; signed otherwise. The next bit (test mask of 2) is on if
|
|
; the operation returns the remainder, quotient otherwise.
|
|
;
|
|
common:
|
|
push bp
|
|
push si
|
|
push di
|
|
mov bp,sp ; set up frame
|
|
mov di,cx
|
|
;
|
|
; dividend is pushed last, therefore the first in the args
|
|
; divisor next.
|
|
;
|
|
mov ax,10[bp] ; get the first low word
|
|
mov dx,12[bp] ; get the first high word
|
|
mov bx,14[bp] ; get the second low word
|
|
mov cx,16[bp] ; get the second high word
|
|
|
|
or cx,cx
|
|
jnz @@slow@ldiv ; both high words are zero
|
|
|
|
or dx,dx
|
|
jz @@quick@ldiv
|
|
|
|
or bx,bx
|
|
jz @@quick@ldiv ; if cx:bx == 0 force a zero divide
|
|
; we don't expect this to actually
|
|
; work
|
|
|
|
@@slow@ldiv:
|
|
|
|
test di,1 ; signed divide?
|
|
jnz @@positive ; no: skip
|
|
;
|
|
; Signed division should be done. Convert negative
|
|
; values to positive and do an unsigned division.
|
|
; Store the sign value in the next higher bit of
|
|
; di (test mask of 4). Thus when we are done, testing
|
|
; that bit will determine the sign of the result.
|
|
;
|
|
or dx,dx ; test sign of dividend
|
|
jns @@onepos
|
|
neg dx
|
|
neg ax
|
|
sbb dx,0 ; negate dividend
|
|
or di,0Ch
|
|
@@onepos:
|
|
or cx,cx ; test sign of divisor
|
|
jns @@positive
|
|
neg cx
|
|
neg bx
|
|
sbb cx,0 ; negate divisor
|
|
xor di,4
|
|
@@positive:
|
|
mov bp,cx
|
|
mov cx,32 ; shift counter
|
|
push di ; save the flags
|
|
;
|
|
; Now the stack looks something like this:
|
|
;
|
|
; 16[bp]: divisor (high word)
|
|
; 14[bp]: divisor (low word)
|
|
; 12[bp]: dividend (high word)
|
|
; 10[bp]: dividend (low word)
|
|
; 8[bp]: return CS
|
|
; 6[bp]: return IP
|
|
; 4[bp]: previous BP
|
|
; 2[bp]: previous SI
|
|
; [bp]: previous DI
|
|
; -2[bp]: control bits
|
|
; 01 - Unsigned divide
|
|
; 02 - Remainder wanted
|
|
; 04 - Negative quotient
|
|
; 08 - Negative remainder
|
|
;
|
|
xor di,di ; fake a 64 bit dividend
|
|
xor si,si ;
|
|
@@xloop:
|
|
shl ax,1 ; shift dividend left one bit
|
|
rcl dx,1
|
|
rcl si,1
|
|
rcl di,1
|
|
cmp di,bp ; dividend larger?
|
|
jb @@nosub
|
|
ja @@subtract
|
|
cmp si,bx ; maybe
|
|
jb @@nosub
|
|
@@subtract:
|
|
sub si,bx
|
|
sbb di,bp ; subtract the divisor
|
|
inc ax ; build quotient
|
|
@@nosub:
|
|
loop @@xloop
|
|
;
|
|
; When done with the loop the four register value look like:
|
|
;
|
|
; | di | si | dx | ax |
|
|
; | remainder | quotient |
|
|
;
|
|
pop bx ; get control bits
|
|
test bx,2 ; remainder?
|
|
jz @@usequo
|
|
mov ax,si
|
|
mov dx,di ; use remainder
|
|
shr bx,1 ; shift in the remainder sign bit
|
|
@@usequo:
|
|
test bx,4 ; needs negative
|
|
jz @@finish
|
|
neg dx
|
|
neg ax
|
|
sbb dx,0 ; negate
|
|
@@finish:
|
|
pop di
|
|
pop si
|
|
pop bp
|
|
retf 8
|
|
|
|
@@quick@ldiv:
|
|
div bx ; unsigned divide
|
|
; DX = remainder AX = quotient
|
|
test di,2 ; want remainder?
|
|
jz @@quick@quo
|
|
xchg ax,dx
|
|
|
|
@@quick@quo:
|
|
|
|
xor dx,dx
|
|
jmp short @@finish
|