home *** CD-ROM | disk | FTP | other *** search
- **********************************************************************
- *
- * $RCSfile: LMath.asm $
- * Description: Runtime support for the Oberon-A compiler
- *
- * Created by: fjc (Frank Copeland)
- * $Revision: 1.4 $
- * $Author: fjc $
- * $Date: 1995/06/29 19:03:32 $
- *
- * Copyright © 1994, Frank Copeland.
- * This file is part of the Oberon-A Library.
- * See Oberon-A.doc for conditions of use and distribution.
- *
- * Log entries are at the end of the file.
- *
- **********************************************************************
- *
- * Acknowledgements
- * ----------------
- *
- * The 32-bit multiply and divide procedures are from the runtime
- * library of Patrick Quaid's PCQ freeware Pascal compiler, which in
- * turn came from the runtime library of Sozobon C.
- *
- **********************************************************************
-
- **********
- * lmath.s
- **********
- * Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg
- *
- * Permission is granted to anyone to use this software for any purpose
- * on any computer system, and to redistribute it freely, with the
- * following restrictions:
- * 1) No charge may be made other than reasonable charges for
- * reproduction.
- * 2) Modified versions must be clearly marked as such.
- * 3) The authors are not responsible for any harmful consequences
- * of using this software, even if they result from defects in it.
- *
- *
- * For PCQ Pascal:
- * These are the 32-bit math functions from Sozobon-C,
- * as noted above. I changed the names of the routines to
- * be more similar to the rest of my library, and handle the
- * divide by zero condition differently. Other than that I
- * haven't changed the code a bit.
- *
- * For Oberon-A:
- * I have changed the names (again) and modified the
- * routines to accept parameters passed in registers instead of
- * on the stack, in keeping with the conventions I use in the
- * rest of the compiler.
- *
- **********************************************************************
-
- ;---------------------------------------------------------------------
- ; Program unit hunk name
-
- TTL Kernel
-
- ;---------------------------------------------------------------------
-
- ;----------------------------------------------------------------
- ; PROCEDURE Kernel_Mul32 (
- ; l1 {D0} : LONGINT;
- ; l2 {D1} : LONGINT)
- ; : LONGINT;
- ;
- ; Calculates l1 * l2, returning the result in D0.
- ;----------------------------------------------------------------
-
- SECTION Kernel,CODE
-
- XDEF Kernel_Mul32
- XREF Kernel_Halt
-
- Kernel_Mul32:
-
- movem.l d2-d4,-(a7)
- tst.l d0
- smi d4
- bpl lm1
- neg.l d0
- lm1:
- tst.l d1
- bpl lm2
- not.b d4
- neg.l d1
- lm2:
- move.w d1,d2
- mulu d0,d2 /* d2 = Al * Bl */
-
- move.l d1,d3
- swap d3
- mulu d0,d3 /* d3 = Al * Bh */
-
- swap d0
- mulu d1,d0 /* d0 = Ah * Bl */
-
- add.l d3,d0 /* d0 = (Ah*Bl + Al*Bh) */
- swap d0
- clr.w d0 /* d0 = (Ah*Bl + Al*Bh) << 16 */
-
- add.l d2,d0 /* d0 = A*B */
-
- tst.b d4
- beq lm3
- neg.l d0
- lm3:
- movem.l (a7)+,d2-d4
- rts
-
- ;---------------------------------------------------------------------
-
- ;----------------------------------------------------------------
- ; PROCEDURE Kernel_Div32
- ; l1 {D0} : LONGINT;
- ; l2 {D1} : LONGINT)
- ; : LONGINT;
- ;
- ; Calculates l1 DIV l2, returning the result in D0 (quotient) and
- ; D1 (remainder).
- ;----------------------------------------------------------------
-
- SECTION Kernel,CODE
-
- XDEF Kernel_Div32
- ; XREF Kernel.Halt
-
- Kernel_Div32:
-
- movem.l d2-d5,-(a7)
- tst.l d0
- smi d4
- bpl ld1
- neg.l d0
- ld1:
- tst.l d1
- smi d5
- bpl ld2
- neg.l d1
-
- ld2:
- tst.l d1
- bne.s nz1
-
- * divide by zero
- move.l #105,d0
- lea module,a0
- move.l (146*$10000)+19,d1
- jsr Kernel_Halt
- nz1:
- cmp.l d1,d0
- bhi norm
- beq is1
- * A<B, so ret 0, rem A
- move.l d0,d1
- clr.l d0
- bra.s ld5
- * A==B, so ret 1, rem 0
- is1:
- moveq.l #1,d0
- clr.l d1
- bra.s ld5
- * A>B and B is not 0
- norm:
- cmp.l #1,d1
- bne.s not1
- * B==1, so ret A, rem 0
- clr.l d1
- bra.s ld5
- * check for A short (implies B short also)
- not1:
- cmp.l #$ffff,d0
- bhi slow
- * A short and B short -- use 'divu'
- divu d1,d0 /* d0 = REM:ANS */
- swap d0 /* d0 = ANS:REM */
- clr.l d1
- move.w d0,d1 /* d1 = REM */
- clr.w d0
- swap d0
- bra.s ld5
- * check for B short
- slow:
- cmp.l #$ffff,d1
- bhi slower
- * A long and B short -- use special stuff from gnu
- move.l d0,d2
- clr.w d2
- swap d2
- divu d1,d2 /* d2 = REM:ANS of Ahi/B */
- clr.l d3
- move.w d2,d3 /* d3 = Ahi/B */
- swap d3
-
- move.w d0,d2 /* d2 = REM << 16 + Alo */
- divu d1,d2 /* d2 = REM:ANS of stuff/B */
-
- move.l d2,d1
- clr.w d1
- swap d1 /* d1 = REM */
-
- clr.l d0
- move.w d2,d0
- add.l d3,d0 /* d0 = ANS */
- bra.s ld5
- * A>B, B > 1
- slower:
- move.l #1,d2
- clr.l d3
- moreadj:
- cmp.l d0,d1
- bhi.s adj
- add.l d2,d2
- add.l d1,d1
- bpl moreadj
- * we shifted B until its >A or sign bit set
- * we shifted #1 (d2) along with it
- adj:
- cmp.l d0,d1
- bhi.s ltuns
- or.l d2,d3
- sub.l d1,d0
- ltuns:
- lsr.l #1,d1
- lsr.l #1,d2
- bne adj
- * d3=answer, d0=rem
- move.l d0,d1
- move.l d3,d0
-
- ld5:
- cmp.b d4,d5
- beq ld3
- neg.l d0
- ld3:
- tst.b d4
- beq ld4
- neg.l d1
- ld4:
- movem.l (a7)+,d2-d5
- rts
-
- module:
- DC.B "Kernel_Div32",0
-
- ;---------------------------------------------------------------------
-
- END ; Kernel
-
- **********************************************************************
- *
- * $Log: LMath.asm $
- ;; Revision 1.4 1995/06/29 19:03:32 fjc
- ;; - Release 1.6
- ;;
- ;; Revision 1.3 1995/01/26 00:37:31 fjc
- ;; - Release 1.5
- ;;
- ;; Revision 1.3 1995/01/26 00:37:31 fjc
- ;; - Release 1.5
- ;;
- **********************************************************************
-