;-*-Mode:LISP; base: 8; readtable: ZL-*-
;;;
;;; (c) Copyright 1984 - Lisp Machine, Inc.
;;;

(DEFCONST UC-ARITH '(
;;; NON-DESTINATION GROUP 1
;   E IN VMA, C(E) IN M-T, MOSTLY EXIT BY PUTTING RESULT ON STACK

;GET TWO PDL ARGUMENTS, FIRST TO M-1, SECOND TO M-2

FXGTPP	  (ERROR-TABLE RESTART FXGTPP)
	(DISPATCH (I-ARG DATA-TYPE-INVOKE-OP)		;GET PDL ARG
			Q-DATA-TYPE C-PDL-BUFFER-POINTER TRAP-UNLESS-FIXNUM)
	  (ERROR-TABLE ARGTYP FIXNUM PP 1 FXGTPP)
	((M-T) C-PDL-BUFFER-POINTER-POP)
	  (ERROR-TABLE RESTART FXGTP0)
	(DISPATCH (I-ARG DATA-TYPE-INVOKE-OP) Q-DATA-TYPE PDL-TOP TRAP-UNLESS-FIXNUM)
	  (ERROR-TABLE ARGTYP FIXNUM PP 0 FXGTP0)
	  (ERROR-TABLE ARG-POPPED 0 PP M-T)
	(POPJ-AFTER-NEXT
	  (M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
       ((M-2) OUTPUT-SELECTOR-EXTEND-25 M-T)

;FIXGET, FIXGET-1 not used on LAMBDA.


;;; MULTIPLY SUBROUTINE
;M-1 TIMES Q-R, RESULT TO Q-R, LEAVES CORRECT HIGH HALF IN M-2.
;CALLER MUST CHECK FOR OVERFLOW, IF SHE CARES.

MPY	((M-2) MULTIPLY-STEP A-1 M-ZERO)
(REPEAT 30. ((M-2) MULTIPLY-STEP M-2 A-1))
	(POPJ-IF-BIT-CLEAR-XCT-NEXT (BYTE-FIELD 1 0) Q-R)
       ((M-2) MULTIPLY-STEP M-2 A-1)
	(POPJ-AFTER-NEXT
	 (M-2) M-2 SUB A-1)		;FINAGLE IF NEGATIVE VALUE INITIALLY IN Q-R
       (NO-OP)

;;; DIVIDE SUBROUTINE
;   DIVIDEND IN M-1, DIVISOR IN M-2
;   QUOTIENT IN Q-R, REMAINDER IN M-1, CLOBBERS A-TEM1
#-lambda(begin-comment)
DIV     (declare (args a-1 a-2) (values a-1) (clobbers a-tem1))
	(JUMP-GREATER-OR-EQUAL-XCT-NEXT M-1 A-ZERO DIV1)
       ((M-TEM1 Q-R) M-1)	;Q GETS MAGNITUDE OF DIVIDEND, A-TEM1 SAVES ORIGINAL
	((Q-R) SUB M-ZERO A-TEM1)
DIV1	((M-1) DIVIDE-FIRST-STEP M-ZERO A-2)
DIV1A	(CALL-IF-BIT-SET (BYTE-FIELD 1 0) Q-R TRAP)	;DIVIDE OVERFLOW
  (ERROR-TABLE DIVIDE-BY-ZERO)
(REPEAT 31. ((M-1) DIVIDE-STEP M-1 A-2))
	((M-1) DIVIDE-LAST-STEP M-1 A-2)
	(JUMP-LESS-OR-EQUAL-XCT-NEXT M-ZERO A-TEM1 DIV2) ;JUMP IF POSITIVE DIVIDEND
       ((M-1) DIVIDE-REMAINDER-CORRECTION-STEP M-1 A-2) ;M-1 GETS MAGNITUDE OF REMAINDER
	((M-1) SUB M-ZERO A-1)		;NEGATIVE DIVIDEND => NEGATIVE REMAINDER
DIV2	((M-TEM1) XOR M-2 A-TEM1)	;IF SIGNS OF DIVIDEND AND DIVISOR ARE DIFFERENT,
	(POPJ-LESS-OR-EQUAL M-ZERO A-TEM1)
	(POPJ-AFTER-NEXT
	 (M-TEM1) Q-R)
       ((Q-R) SUB M-ZERO A-TEM1)	;THEN QUOTIENT IS NEGATIVE
#-lambda(end-comment)

#-exp(begin-comment)
DIV
	(Jump-greater-or-equal-xct-next M-1 A-Zero DIV1)
       ((M-TEM1 Q-R) M-1)
	((Q-R) SUB M-Zero A-tem1)
DIV1
#-exp(begin-comment)
	(Jump-greater-or-equal-xct-next M-2 A-Zero DIV-Not-Neg-2)
       ((m-tem2) M-2)
	((M-2) SUB M-Zero A-2)
DIV-Not-Neg-2
#-exp(end-comment)
	((M-1) Divide-First-Step M-Zero A-2)
DIV1A	(Call-If-Bit-Set (Byte-Field 1 0) Q-R TRAP)
  (ERROR-TABLE DIVIDE-BY-ZERO)
       (repeat 31. ((M-1) Divide-Step M-1 A-2))
	((M-1) Divide-Last-Step M-1 A-2)
	(Jump-Less-Or-Equal-Xct-Next M-Zero a-tem1 DIV2)
       ((M-1) Divide-Remainder-Correction-Step M-1 A-2)
	((M-1) SUB M-Zero A-1)
DIV2
#+exp	((M-2) m-tem2)
	((m-tem1) xor m-2 a-tem1)
	(popj-less-or-equal m-zero a-tem1)
	(popj-after-next (m-tem1) Q-R)
       ((Q-R) SUB M-zero a-tem1)
#-exp(end-comment)

;FIXNUM EXPONENTIATION ROUTINE.
;M-3 HOLDS THE EXPONENT, AND GETS SHIFTED AND TESTED.
;M-1 HOLDS THE FIRST ARG, SQUARED N TIMES.
;M-T HOLDS THE PARTIAL PRODUCTS

(ERROR-TABLE DEFAULT-ARG-LOCATIONS ^ PP PP)

XUPARROW (MISC-INST-ENTRY ^)
	((PDL-BUFFER-INDEX) SUB PDL-BUFFER-POINTER (A-CONSTANT 1))	;POINT TO FIRST ARG
	(jump-data-type-not-equal c-pdl-buffer-index
		 (a-constant (byte-value q-data-type dtp-fix)) xupout)
	(jump-data-type-not-equal c-pdl-buffer-pointer
		 (a-constant (byte-value q-data-type dtp-fix)) xupout)
	((m-2) output-selector-extend-25 c-pdl-buffer-pointer)
	((m-1) output-selector-extend-25 c-pdl-buffer-index)
	(JUMP-LESS-THAN M-2 A-ZERO XUP6)		;FIXNUM ^ -<FIXNUM> = 0 USUALLY
XUP5	((M-TEM) (A-CONSTANT 1))			;INITIALIZE RESULT
	(JUMP-EQUAL M-2 A-ZERO XUP4)			;ANYTHING ^ 0 = 1
	((M-3) M-2)					;SAVE THE EXPONENT
XUP1	(JUMP-IF-BIT-CLEAR (BYTE-FIELD 1 0) M-3 XUP2)
	(CALL-XCT-NEXT MPY)				;M-1 TIMES M-TEM TO Q-R
       ((Q-R) M-TEM)
	((M-2) SELECTIVE-DEPOSIT Q-R
	 (BYTE-FIELD (DIFFERENCE 33. Q-POINTER-WIDTH)
		     (DIFFERENCE Q-POINTER-WIDTH 1))
	 A-2)	;DISCARDED BITS AND SIGN
							;M-TEM IS 32 BITS, BUT FIXED BIN(23,0)
	(JUMP-EQUAL-XCT-NEXT M-2 A-ZERO XUP2)		;JUMP IF POSITIVE NO OVERFLOW
       ((M-TEM) Q-R)					;PRODUCT BACK TO M-TEM
	(JUMP-NOT-EQUAL M-2 (A-CONSTANT -1) XUPOUT)	;DROP THROUGH IF OK NEG, ELSE OVFL
XUP2	((M-3) M-3 OUTPUT-SELECTOR-RIGHTSHIFT-1)	;(SETQ M-3 (ASH M-3 -1))
	(JUMP-EQUAL M-3 A-ZERO XUP4)			;IF ZERO, RESULT IS IN M-TEM
	(CALL-XCT-NEXT MPY)				;OTHERWISE COMPUTE NEXT POWER
       ((Q-R) M-1)					;I.E. Q-R GETS M-1 TIMES M-1
	((M-2) SELECTIVE-DEPOSIT Q-R
	 (BYTE-FIELD (DIFFERENCE 33. Q-POINTER-WIDTH)
		     (DIFFERENCE Q-POINTER-WIDTH 1))
	 A-2)	;DISCARDED BITS AND SIGN
	(JUMP-NOT-EQUAL M-2 A-ZERO XUPOUT)		;OVERFLOW (RESULT IS ALWAYS POSITIVE)
	(JUMP-XCT-NEXT XUP1)
       ((M-1) Q-R)					;(SETQ M-1 (* M-1 M-1))

;;; Here if exponent is a negative integer.
;Result is a rational unless base (M-1) is 0, -1, or 1.
XUP6	(JUMP-GREATER-THAN M-1 (A-CONSTANT 1) XUP3)
	(JUMP-LESS-THAN M-1 (A-CONSTANT -1) XUP3)
	(CALL-EQUAL M-1 (A-CONSTANT 0) TRAP)		;0 ^ negative power is an error
	    (ERROR-TABLE DIVIDE-BY-ZERO)
	((M-TEM) M-1)
	(JUMP-IF-BIT-SET (BYTE-FIELD 1 0) M-2 XUP4)	;-1 ^ odd negative power is -1
	((M-TEM) (A-CONSTANT 1))			;-1 ^ even negative power is 1
	;drop into XUP4
;;; RETURN VALUE IN M-TEM AND POP OFF ARGUMENTS
XUP4	(POPJ-AFTER-NEXT (PDL-BUFFER-POINTER) SUB PDL-BUFFER-POINTER (A-CONSTANT 2))
       ((M-T) DPB M-TEM Q-POINTER (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))

XUP3	((M-2) SUB M-ZERO A-2)	;Make the exponent positive.
	(CALL XUP5)		;Exponentiate.
	((PDL-PUSH) M-T)	;This becomes the denominator.  The numerator is 1.
	(JUMP-IF-BIT-SET BOXED-SIGN-BIT M-T XUP3A)	;But may need to factor out -1.
	((PDL-PUSH) DPB M-MINUS-ONE (BYTE-FIELD 1 0) (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))
	(JUMP MAKE-RATIONAL)

XUP3A	(CALL XABS)		;Here for reciprocal of negative integer: make it positive
	((PDL-PUSH) M-T)	;and make rational with numerator -1.
	((PDL-PUSH) DPB M-MINUS-ONE Q-POINTER (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))
	(JUMP MAKE-RATIONAL)

;;; HERE CALL OUT TO MACRO CODE
XUPOUT	((M-A) C-PDL-BUFFER-POINTER-POP)	;The exponent
	((M-B) C-PDL-BUFFER-POINTER-POP)	;The base
	(CALL P3ZERO)				;Open micro-to-macro call
	((ARG-CALL REF-SUPPORT-VECTOR) (I-ARG SVC-EXPT))	;Get fctn cell of EXPT-HELP
	(DISPATCH TRANSPORT MD)
	((C-PDL-BUFFER-POINTER-PUSH) READ-MEMORY-DATA)	;Push function
	((C-PDL-BUFFER-POINTER-PUSH)		;Push the base
		Q-TYPED-POINTER M-B (A-CONSTANT (BYTE-VALUE Q-CDR-CODE CDR-NEXT)))
	((C-PDL-BUFFER-POINTER-PUSH)		;Push the exponent
		Q-TYPED-POINTER M-A (A-CONSTANT (BYTE-VALUE Q-CDR-CODE CDR-NIL)))
	((ARG-JUMP MMJCALL) (I-ARG 2))		;Call it tail-recursively


XGCD (MISC-INST-ENTRY INTERNAL-\\)		;GCD, STEIN'S ALGORITHM.
	(CALL-XCT-NEXT GET-FIX-OR-BIGNUM)	; SET UP FOR GCD'S BY GETTING 2 ARGS
       ((M-A) M-ZERO)				;THIS IS MAGIC INDEX ON TYPES OF ARGUMENTS
	(DISPATCH (BYTE-FIELD 2 0) M-A GCD-DISPATCH)

(LOCALITY D-MEM)
(START-DISPATCH 2)
GCD-DISPATCH
	(P-BIT R-BIT)		;FIXNUM-FIXNUM CASE (DROPS THROUGH)
	(INHIBIT-XCT-NEXT-BIT GCD-FIX-BIG)	;FIXNUM-BIGNUM CASE
	(INHIBIT-XCT-NEXT-BIT GCD-BIG-FIX)	;BIGNUM-FIXNUM CASE
	(INHIBIT-XCT-NEXT-BIT GCD-BIG-BIG)	;BIGNUM-BIGNUM CASE
(END-DISPATCH)
(LOCALITY I-MEM)

;;; DROP THROUGH ON FIX-FIX CASE (ARGUMENTS IN M-1 M-2)
;;; Clobbers M-1, M-2, M-A, Q-R, M-TEM, A-TEM1.
GCD-FIX-FIX
#+lambda((M-A Q-R) (A-CONSTANT (LOGAND 7777  ;ASSURE SAVE FOR TYPED REGISTER
				       (OA-LOW-CONTEXT ((BYTE-FIELD 32. 0))))))
#+exp	((m-a q-r) (a-constant 0)) ;byte-length & rot field for all bits, no shift
	(JUMP-GREATER-OR-EQUAL M-1 A-ZERO XGCD0)	;TAKE ABS OF ARGS
	((M-1) SUB M-ZERO A-1)
XGCD0	(JUMP-GREATER-OR-EQUAL M-2 A-ZERO XGCDL)
	((M-2) SUB M-ZERO A-2)
XGCDL	(JUMP-EQUAL M-2 A-ZERO XGCD5)
	(JUMP-GREATER-THAN M-1 A-2 XGCD1)
	((M-TEM) M-1)		;EXCHANGE ARGS SO M-1 IS THE BIGGER
	((M-1) M-2)
	((M-2) M-TEM)
XGCD1	(JUMP-IF-BIT-SET (BYTE-FIELD 1 0) M-1 XGCD2)
	(JUMP-IF-BIT-SET (BYTE-FIELD 1 0) M-2 XGCD3)
	((M-A) SUB M-A (A-CONSTANT 37))			;BOTH EVEN
							;ADD1 TO ROTATE FIELD, SUB1 FROM LENGTH
        ((M-2) M-2 OUTPUT-SELECTOR-RIGHTSHIFT-1)
XGCD3	(JUMP-XCT-NEXT XGCDL)				;M-1 EVEN
       ((M-1) M-1 OUTPUT-SELECTOR-RIGHTSHIFT-1)

XGCD2	(JUMP-IF-BIT-SET (BYTE-FIELD 1 0) M-2 XGCD4)
	(JUMP-XCT-NEXT XGCDL)				;M-2 EVEN
       ((M-2) M-2 OUTPUT-SELECTOR-RIGHTSHIFT-1)

XGCD4	((M-TEM) M-2)		;BOTH ODD
	((M-2) SUB M-1 A-2)
	(JUMP-XCT-NEXT XGCDL)
       ((M-1) M-TEM)

XGCD5
#+exp	((m-tem3) add m-a (a-constant 1_5))
		;Final shifting step
#+exp	((OA-REG-LOW) (Byte-Field 10. 0) M-A)
#+lambda((oa-reg-low) m-a)
	((M-1) DPB M-1 (BYTE-FIELD 0 0) A-ZERO)
	(JUMP RETURN-M-1)

;BIGNUM GCD MOVED TO UC-HACKS FILE.

;;;This takes a stream of 31. bit words and right justifies it
;;; into the bignum in M-S. You hand words in in M-2.
;;; After each call M-E "points" to the location about to be stored into or 0
;;; if no ones have been found, M-3 is the number of 31. bit words of zeros skipped,
;;; M-4 is the number of bits skipped mod 31. M-A and M-B are used for internal
;;; constants for ldbing and dpbing. Temporary things are kept in M-1 as well
;;; Inits: ((M-E) A-ZERO)	;flags that no 1s have been found.
;;;	   ((M-3) A-MINUS-ONE)	;Actually init to anything you want, it will be
;;;				; incremented N+1 times.
BIGNUM-RIGHT-JUST
	(JUMP-EQUAL M-E A-ZERO BIGNUM-RIGHT-JUST-FFO)
	(JUMP-EQUAL M-4 A-ZERO BIGNUM-RIGHT-JUST-PUNT)
#+exp	((m-tem3) add m-a (a-constant 1_5))
#+exp	((oa-reg-low) ldb (byte-field 10. 0) m-tem3)
#+lambda((OA-REG-LOW) M-A)
	((MD) DPB M-2 (BYTE-FIELD 0 0) A-1)
	((VMA-START-WRITE) ADD M-S A-E)
	(CHECK-PAGE-WRITE)
#+exp	((m-tem3) add m-b (a-constant 1_5))
#+exp	((oa-reg-low) ldb (byte-field 10. 0) m-tem3)
#+lambda((OA-REG-LOW) M-B)
	(POPJ-AFTER-NEXT (M-1) (BYTE-FIELD 0 0) M-2 A-ZERO)
       ((M-E) ADD M-E (A-CONSTANT 1))

BIGNUM-RIGHT-JUST-PUNT
	((MD) M-1)
	((VMA-START-WRITE) ADD M-S A-E)
	(CHECK-PAGE-WRITE)
	(POPJ-AFTER-NEXT (M-1) M-2)
       ((M-E) ADD M-E (A-CONSTANT 1))

BIGNUM-RIGHT-JUST-FFO
	(POPJ-EQUAL-XCT-NEXT M-2 A-ZERO)
       ((M-3) ADD M-3 (A-CONSTANT 1))
	((M-E) (A-CONSTANT 1))
	((M-4) A-MINUS-ONE)
	((M-2) DPB M-2 (BYTE-FIELD 31. 1) A-ZERO)
BIGNUM-RIGHT-JUST-FFO-1
	((M-2) (BYTE-FIELD 31. 1) M-2 A-ZERO)
	(JUMP-IF-BIT-CLEAR-XCT-NEXT (BYTE-FIELD 1 0) M-2 BIGNUM-RIGHT-JUST-FFO-1)
       ((M-4) ADD M-4 (A-CONSTANT 1))
	((M-1) M-2)
	;;Now for DPB (M-A) we need BYTL-1 = M-4 - 1   and MROT = 31. - M-4
	;;and for LDB (M-B) we need BYTL-1 = 30. - M-4 and MROT = 32. - M-4
	((M-TEM) (A-CONSTANT 30.))
	((M-TEM) SUB M-TEM A-4)			; 30. - M-4
	((M-A) ADD M-TEM (A-CONSTANT 1))
	((M-B) ADD M-TEM (A-CONSTANT 2))
#+exp	((M-TEM) M+1 M-TEM)
	((M-B) DPB M-TEM OAL-BYTL-1 A-B)
	(POPJ-AFTER-NEXT (M-TEM) SUB M-4 #+lambda (A-CONSTANT 1) #+exp a-zero)
       ((M-A) DPB M-TEM OAL-BYTL-1 A-A)

XREM (MISC-INST-ENTRY \)
	(CALL-XCT-NEXT XFLOOR-2-A)
       ((M-1) (A-CONSTANT 2))				;TRUNCATE opcode.
	(POPJ-AFTER-NEXT
	  (M-T) Q-TYPED-POINTER PDL-POP)
       ((M-GARBAGE) PDL-POP)

;	(CALL-XCT-NEXT GET-FIX-OR-BIGNUM)
;       ((M-A) M-ZERO)
;	(DISPATCH (BYTE-FIELD 2 0) M-A REMAINDER-DISPATCH)
;;;; DROP THROUGH ON FIX-FIX CASE
;REMAINDER-FIX-FIX
;	(CALL DIV)
;XREM1	(POPJ-AFTER-NEXT
;	 (M-T) DPB M-1 Q-POINTER (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))
;       (NO-OP)

;(LOCALITY D-MEM)
;(START-DISPATCH 2)
;REMAINDER-DISPATCH
;	(P-BIT R-BIT)		;FIXNUM-FIXNUM CASE (DROPS THROUGH)
;	(INHIBIT-XCT-NEXT-BIT REMAINDER-FIX-BIG)	;FIXNUM-BIGNUM CASE
;	(INHIBIT-XCT-NEXT-BIT REMAINDER-BIG-FIX)	;BIGNUM-FIXNUM CASE
;	(INHIBIT-XCT-NEXT-BIT REMAINDER-BIG-BIG)	;BIGNUM-BIGNUM CASE
;(END-DISPATCH)
;(LOCALITY I-MEM)

;;;; THE VALUE IS ALWAYS THE FIXNUM EXCEPT WHEN THE FIXNUM IS "SETZ" AND THE BIGNUM IS
;;;; POSITIVE "SETZ", IN WHICH CASE THE ANSWER IS 0 (THIS DEPENDS ON THE HEADER FOR THE
;;;; BIGNUM BEING IN MD)
;REMAINDER-FIX-BIG
;	(POPJ-NOT-EQUAL-XCT-NEXT M-2 (A-CONSTANT NEGATIVE-SETZ))
;       ((M-T) M-C)			;RESULT IS THE FIXNUM, USUALLY
;	((M-1) BIGNUM-HEADER-LENGTH MD)	;GET THE LENGTH OF THE BIGNUM
;	(POPJ-NOT-EQUAL M-1 (A-CONSTANT 1))
;	((VMA-START-READ) ADD M-B (A-CONSTANT 1))	;READ THE BIGNUM
;	(CHECK-PAGE-READ)
;	(POPJ-AFTER-NEXT
;	  POPJ-NOT-EQUAL MD (A-CONSTANT POSITIVE-SETZ))
;       ((M-T) (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))	;RESULT IS 0

;;; HERE THE BIGNUM IS IN M-B, FIXNUM IN M-2
;;; M-1 IS USED FOR ACCUMULATOR M-B IS THE POINTER TO THE
;;; BIGNUM, M-C IS THE LOOP COUNTER (INITED WITH THE LENGTH OF THE BIGNUM) (ALSO OFFSET)
;;; M-A IS THE SIGN BIT OF THE BIGNUM
;;; REMAINDER MUST BE LEFT IN M-1 FOR THE SAKE OF GCD-BIG-FIX AND REMAINDER-BIG-BIG
;;;People will want to call REMAINDER-BIG-FIX-1 with a fixnum in M-2 a bignum in M-B
;;; its length in M-C and sign bit in the low bit of M-A. REMAINDER-BIG-FIX-1 Doesn't
;;; work if the fixnum is 0! (You must deal with that yourself.)
REMAINDER-BIG-FIX
	(JUMP-EQUAL M-2 A-ZERO RETURN-M-B)
	((M-C) BIGNUM-HEADER-LENGTH MD)
	((M-A) BIGNUM-HEADER-SIGN MD)
REMAINDER-BIG-FIX-1
	(JUMP-GREATER-OR-EQUAL-XCT-NEXT M-2 A-ZERO REM-BIG-FIX-LOOP)
       ((M-1) SETZ)
	((M-2) SUB M-ZERO A-2)		;TAKE ABS OF DIVISOR
REM-BIG-FIX-LOOP
	((VMA-START-READ) ADD M-B A-C)
	(CHECK-PAGE-READ)
	((M-TEM1) SETZ)			;IMPLICIT ARGUMENT TO DIV1A
	((M-TEM) DPB M-1 (BYTE-FIELD 1 31.) A-ZERO)
	((Q-R) ADD MD A-TEM)
	(JUMP-IF-BIT-SET-XCT-NEXT (BYTE-FIELD 1 31.) M-TEM REM-BIG-FIX-OVFL)
       ((M-1) (BYTE-FIELD 31. 1) M-1)
	(JUMP-IF-BIT-CLEAR (BYTE-FIELD 1 31.) Q-R REM-BIG-FIX-OVFL)
	((M-1) ADD M-1 (A-CONSTANT 1))
;;; HERE M-1,,Q-R HAVE (M-1)*1_31.+MD
REM-BIG-FIX-OVFL
#-exp(begin-comment)
	(Jump-greater-or-equal-xct-next M-2 A-Zero REM-BIG-FIX-Not-Neg-2)
       ((m-tem2) M-2)
	((M-2) SUB M-Zero A-2)
REM-BIG-FIX-Not-Neg-2
#-exp(end-comment)
	(CALL-XCT-NEXT DIV1A)
       ((M-1) DIVIDE-FIRST-STEP M-1 A-2)
	(JUMP-NOT-EQUAL-XCT-NEXT M-C (A-CONSTANT 1) REM-BIG-FIX-LOOP)
       ((M-C) SUB M-C (A-CONSTANT 1))
	(POPJ-EQUAL-XCT-NEXT M-A A-ZERO)	;POPJ IF DIVIDEND POSITIVE
       ((M-T) DPB Q-POINTER M-1 (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))
	(POPJ-AFTER-NEXT (M-1) SUB M-ZERO A-1)
       ((M-T) DPB Q-POINTER M-1 (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))

RETURN-M-B
 	(POPJ-AFTER-NEXT (M-T) M-B)
       (NO-OP)

;;; RETURNS IN M-A BITS SAYING WHAT THE TWO ARGUMENTS ARE (FOR \ AND \\)
;;; IN FIXNUM-FIXNUM CASE RETURNS M-A UNCHANGED (0) AND FIXNUMS IN M-1 AND M-2 (SECOND)
;;; IN THE BIGNUM-FIXNUM AND FIXNUM-BIGNUM CASE, IT RETURNS THE FIXNUM IN M-2 AND THE
;;; BIGNUM IN M-B. IN THE BIGNUM-BIGNUM CASE, IT RETURNS THE BIGNUMS IN M-B AND M-C
;;; IN ANY CASE M-T IS THE SECOND ARGUMENT, M-C IS THE FIRST
GET-FIX-OR-BIGNUM
	((M-T) C-PDL-BUFFER-POINTER-POP)
	((M-1) SELECTIVE-DEPOSIT M-T Q-DATA-TYPE A-ZERO)
	(JUMP-NOT-EQUAL-XCT-NEXT M-1 (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX))
			GET-ANY-BIG)
       ((M-C) C-PDL-BUFFER-POINTER-POP)
GET-ANY-CHAR
#+lambda((OA-REG-HIGH) BOXED-SIGN-BIT M-T)		;SIGN EXTEND (MUNG M SOURCE)
#+exp	((m-tem3) boxed-sign-bit m-t)
#+exp	((oa-reg-high) dpb m-tem3 oah-m-src a-zero)
	((M-2) SELECTIVE-DEPOSIT M-ZERO Q-ALL-BUT-POINTER A-T)
	((M-1) SELECTIVE-DEPOSIT M-C Q-DATA-TYPE A-ZERO)
	(JUMP-NOT-EQUAL M-1 (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)) GET-BIG-FIX)
GET-CHAR-FIX
#+lambda(POPJ-AFTER-NEXT
	 (OA-REG-HIGH) BOXED-SIGN-BIT M-C)		;SIGN EXTEND (MUNG M SOURCE)
#+exp	((m-tem3) boxed-sign-bit m-c)
#+exp	(popj-after-next (oa-reg-high) dpb m-tem3 oah-m-src a-zero)
       ((M-1) SELECTIVE-DEPOSIT M-ZERO Q-ALL-BUT-POINTER A-C)
GET-FIX-ANY
#+lambda(POPJ-AFTER-NEXT
	 (OA-REG-HIGH) BOXED-SIGN-BIT M-C)		;SIGN EXTEND (MUNG M SOURCE)
#+exp	((m-tem3) boxed-sign-bit m-c)
#+exp	(popj-after-next (oa-reg-high) dpb m-tem3 oah-m-src a-zero)
       ((M-2) SELECTIVE-DEPOSIT M-ZERO Q-ALL-BUT-POINTER A-C)

GET-BIG-FIX
	(JUMP-EQUAL M-1 (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-CHARACTER)) GET-CHAR-FIX)
	((M-A) (A-CONSTANT 2))
	(CALL-XCT-NEXT ASSURE-BIGNUM)
       ((M-I) M-C)
    (ERROR-TABLE ARG-POPPED 0 M-C M-T)
	(POPJ-AFTER-NEXT
	 (M-C) M-I)
       ((M-B) M-I)

GET-ANY-BIG
	(JUMP-EQUAL M-1 (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-CHARACTER))
		    GET-ANY-CHAR)
	((M-A) (A-CONSTANT 1))
	(CALL-XCT-NEXT ASSURE-BIGNUM)
       ((M-I) M-T)
    (ERROR-TABLE ARG-POPPED 0 M-C M-T)
	((M-T) M-I)
	((M-1) SELECTIVE-DEPOSIT M-C Q-DATA-TYPE A-ZERO)
	(JUMP-EQUAL-XCT-NEXT M-1 (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX))
			GET-FIX-ANY)
       ((M-B) M-T)		;THIS IS THE SECOND ARGUMENT BIGNUM
	(JUMP-EQUAL M-1 (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-CHARACTER))
			GET-FIX-ANY)
;;; HERE THEY ARE BIG-BIG
	((M-A) (A-CONSTANT 3))
	(CALL-XCT-NEXT ASSURE-BIGNUM)
       ((M-I) M-C)
    (ERROR-TABLE ARG-POPPED 0 M-C M-T)
	(POPJ-AFTER-NEXT
	 (M-C) M-I)
	(NO-OP)

;;;   ASSURES THAT THE HEADER NOW BEING READ INTO MD POINTS TO A LEGAL BIGNUM HEADER
;;;   VMA AND M-I CONTAIN POINTER TO THE BIGNUM
;;; NOTE: This scheme didn't check the pointer data-type until after the memory cycle
;;; started.  Since other data-types (ie: small-flonum) occasionally elide previous
;;; type-checking, this marginality was not deemed acceptable.  The code now takes the
;;; argument in M-I, which is type-checked before it is referenced.  KHS 10/13/84.
ASSURE-BIGNUM
	(CALL-DATA-TYPE-NOT-EQUAL M-I
			(A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-EXTENDED-NUMBER)) TRAP)
		(ERROR-TABLE ARGTYP (FIXNUM BIGNUM) M-I NIL)
	((VMA-START-READ) M-I)
	(CHECK-PAGE-READ)			;CHECK FOR PAGE FAULTS
	(DISPATCH TRANSPORT-HEADER READ-MEMORY-DATA)
	((M-I) VMA)		;get transported number address 
	((M-TEM) SELECTIVE-DEPOSIT MD HEADER-TYPE-FIELD A-ZERO)
	(POPJ-EQUAL M-TEM (A-CONSTANT (BYTE-VALUE HEADER-TYPE-FIELD %HEADER-TYPE-BIGNUM)))
	(CALL TRAP)
		(ERROR-TABLE ARGTYP (FIXNUM BIGNUM) M-I NIL)

;;; Takes a fixnum or bignum argument on the stack and returns the low-order 32
;;; bits of it in M-1.  Bashes M-I, M-J only.
GET-32-BITS  (declare (values a-1) (clobbers a-i a-j))
	(JUMP-DATA-TYPE-EQUAL C-PDL-BUFFER-POINTER (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX))
		FXUNPK-P-1)
	(CALL-XCT-NEXT ASSURE-BIGNUM)
       ((M-I) C-PDL-BUFFER-POINTER-POP)
	((M-I) BIGNUM-HEADER-LENGTH MD)
	((M-J) BIGNUM-HEADER-SIGN MD)
	((VMA-START-READ) ADD VMA (A-CONSTANT 1))	;Low-order word
	(CHECK-PAGE-READ)
	(JUMP-LESS-THAN-XCT-NEXT M-I (A-CONSTANT 2) GET-32-BITS-1)
       ((M-1) READ-MEMORY-DATA)
	((VMA-START-READ) ADD VMA (A-CONSTANT 1))
	(CHECK-PAGE-READ)
	((M-1) DPB READ-MEMORY-DATA (BYTE-FIELD 1 31.) A-1)
GET-32-BITS-1
	(POPJ-AFTER-NEXT POPJ-EQUAL M-J A-ZERO)	
       ((M-1) SUB M-ZERO A-1)				;Negative

;;; Operations on unsigned quantities.

;TEMPORARY DOUBLE PRECISION KLUDGE.  DOESN'T CHECK FOR OVERFLOW (PRESUMABLY CAN'T ANYWAY!)
XMUL-FRACTIONS (MISC-INST-ENTRY %MULTIPLY-FRACTIONS)
	(CALL FXGTPP)
   (ERROR-TABLE CALLS-SUB %MULTIPLY-FRACTIONS)
	(CALL-XCT-NEXT MPY)
       ((Q-R) M-2)
	(POPJ-AFTER-NEXT
	 (M-T)
	 (BYTE-FIELD (DIFFERENCE 32. Q-POINTER-WIDTH)
		     (DIFFERENCE Q-POINTER-WIDTH 0))
	 Q-R (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))
       ((M-T) DPB M-2 (BYTE-FIELD (DIFFERENCE Q-POINTER-WIDTH
					      (DIFFERENCE 32. Q-POINTER-WIDTH))
				  (DIFFERENCE 32. Q-POINTER-WIDTH))
		  A-T)

XPOINTER-TIMES (MISC-INST-ENTRY %POINTER-TIMES)
	(CALL FXGTPP)
    (ERROR-TABLE CALLS-SUB %24-BIT-TIMES)
	(CALL-XCT-NEXT MPY)
       ((Q-R) M-2)
	(POPJ-AFTER-NEXT (M-T) DPB Q-R Q-POINTER (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))
       (NO-OP)

;SPECIAL NON-OVERFLOW-CHECKING FUNCTIONS FOR WEIRD HACKS
X24ADD (MISC-INST-ENTRY %24-BIT-PLUS)
	(CALL FXGTPP)
   (ERROR-TABLE CALLS-SUB %24-BIT-PLUS)
	(POPJ-AFTER-NEXT (M-1) ADD M-1 A-2)
       ((M-T) DPB M-1 (BYTE-FIELD 24. 0) (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))

X24SUB (MISC-INST-ENTRY %24-BIT-DIFFERENCE)
	(CALL FXGTPP)
   (ERROR-TABLE CALLS-SUB %24-BIT-DIFFERENCE)
	(POPJ-AFTER-NEXT (M-1) SUB M-1 A-2)
       ((M-T) DPB M-1 (BYTE-FIELD 24. 0) (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))

X24MUL (MISC-INST-ENTRY %24-BIT-TIMES)
	(CALL FXGTPP)
    (ERROR-TABLE CALLS-SUB %24-BIT-TIMES)
	(CALL-XCT-NEXT MPY)
       ((Q-R) M-2)
	(POPJ-AFTER-NEXT (M-T) DPB Q-R (BYTE-FIELD 24. 0) (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))
       (NO-OP)

XDIV-DOUBLE (MISC-INST-ENTRY %DIVIDE-DOUBLE)
	(CALL XDIVD1)					;CALL DOUBLE PRECISION DIVIDE
	(POPJ-AFTER-NEXT 		;DIVIDE CAN'T OVERFLOW
	 (M-T) DPB Q-R Q-POINTER (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))
       (NO-OP)

XREM-DOUBLE (MISC-INST-ENTRY %REMAINDER-DOUBLE)
	(call xdivd1)
	(popj-after-next
	  (m-t) dpb m-1 q-pointer (a-constant (byte-value q-data-type dtp-fix)))
	(no-op)

;	(JUMP-XCT-NEXT XREM1)
;       (CALL XDIVD1)					;CALL DOUBLE PRECISION DIVIDE
;XREM1	(POPJ-AFTER-NEXT
;	 (M-T) DPB M-1 Q-POINTER (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))
;       (NO-OP)

;DOUBLE PRECISION DIVIDE.  ARGS ON PDL ARE DIVIDEND HIGH, DIVIDEND LOW, DIVISOR
XDIVD1	(CALL FXGTPP)					;M-1 GETS DIVIDEND LOW, M-2 DIVISOR
	((M-A) M-1)					;SAVE DIVIDEND LOW
	(DISPATCH (I-ARG DATA-TYPE-INVOKE-OP)		 ;GET DIVIDEND HIGH.
			Q-DATA-TYPE C-PDL-BUFFER-POINTER TRAP-UNLESS-FIXNUM)
    (ERROR-TABLE ARGTYP FIXNUM PP 0)
    (ERROR-TABLE ARG-POPPED 0 PP M-A M-2)
	((m-1) output-selector-extend-25 c-pdl-buffer-pointer-pop)
	((M-TEM) DPB M-1
	 (BYTE-FIELD (DIFFERENCE 32. Q-POINTER-WIDTH)
		     (DIFFERENCE Q-POINTER-WIDTH 0))
	 A-A)	;LOW WORD HAS 32 BITS
	((M-A)
	 (BYTE-FIELD (DIFFERENCE Q-POINTER-WIDTH 0)
		     (DIFFERENCE 32. Q-POINTER-WIDTH))
	 M-1 A-1)		;ARITH SHIFT M-1 RIGHT 8 FOR HIGH WORD
	(JUMP-GREATER-OR-EQUAL M-1 A-ZERO XDIVD3)	;MAKE DIVIDEND POSITIVE
	(JUMP-NOT-EQUAL-XCT-NEXT M-TEM A-ZERO XDIVD2)	;DOUBLE PRECISION NEGATE M-A,,M-TEM
       ((M-TEM) SUB M-ZERO A-TEM)
	((M-A) SUB M-A (A-CONSTANT 1))			;BORROW IF LOW WORD IS ZERO
XDIVD2	((M-A) SETCM M-A)				;ONES COMPLEMENT HIGH WORD
XDIVD3	;DIVIDEND IS IN M-A (HIGH), M-TEM (LOW), DIVISOR IS IN M-2
	((M-TEM1) M-1)	;ORIGINAL SIGN OF DIVIDEND IS IN SIGN(M-TEM1) FOR DIVIDE
	((Q-R) M-TEM)					;LOW DIVIDEND TO Q-R FOR DIVIDE
#-exp(begin-comment)
	(Jump-greater-or-equal-xct-next M-2 A-Zero XDIVD3-Not-Neg-2)
       ((m-tem2) M-2)
	((M-2) SUB M-Zero A-2)
XDIVD3-Not-Neg-2
#-exp(end-comment)
	(JUMP-XCT-NEXT DIV1A)				;JOIN NORMAL DIVIDE ROUTINE
       ((M-1) DIVIDE-FIRST-STEP M-A A-2)		;BUT WITH DIFFERENT FIRST STEP

;;; ARITHMETIC MICROCODE.

;Generic operations save away one of these codes to indicate the operation to
;be performed, and then jump to routines that think about types and unpacking.
(ASSIGN ARITH-1ARG-ABS 0)
(ASSIGN ARITH-1ARG-MINUS 1)
(ASSIGN ARITH-1ARG-ZEROP 2)
(ASSIGN ARITH-1ARG-PLUSP 3)
(ASSIGN ARITH-1ARG-MINUSP 4)
(ASSIGN ARITH-1ARG-ADD1 5)
(ASSIGN ARITH-1ARG-SUB1 6)
(ASSIGN ARITH-1ARG-FIX 7)
(ASSIGN ARITH-1ARG-FLOAT 10)
(ASSIGN ARITH-1ARG-SMALL-FLOAT 11)
(ASSIGN ARITH-1ARG-HAULONG 12)
(ASSIGN ARITH-1ARG-LDB 13)	;DEALS WITH 2ND ARG ONLY.
(ASSIGN ARITH-1ARG-DPB 14)	;DEALS WITH 3RD ARG ONLY.
(ASSIGN ARITH-1ARG-ASH 15)
(ASSIGN ARITH-1ARG-ODDP 16)
(ASSIGN ARITH-1ARG-EVENP 17)
;HAIPART?
(ASSIGN NUM-UNUSED-ARITH-1ARGS 0)

;These go through the dispatches just like FIX,
;but the FIX routines do a subdispatch to decide how to round.
(ASSIGN ARITH-1ARG-FLOOR 7)
(ASSIGN ARITH-1ARG-CEIL 107)
(ASSIGN ARITH-1ARG-TRUNC 207)
(ASSIGN ARITH-1ARG-ROUND 307)
(DEF-DATA-FIELD ARITH-FIX-ROUNDING-MODE-FIELD 2 6)  ;these bits come from the destination field
		;of the INTERNAL-FLOOR-1 and INTERNAL-FLOOR-2 macroinstructions.

(ASSIGN ARITH-2ARG-ADD 0)
(ASSIGN ARITH-2ARG-SUB 1)
(ASSIGN ARITH-2ARG-MUL 2)
(ASSIGN ARITH-2ARG-IDIV 3)
(ASSIGN ARITH-2ARG-EQUAL 4)		;=
(ASSIGN ARITH-2ARG-GREATERP 5)
(ASSIGN ARITH-2ARG-LESSP 6)
(ASSIGN ARITH-2ARG-MIN 7)
(ASSIGN ARITH-2ARG-MAX 10)
(ASSIGN ARITH-2ARG-BOOLE 11)
(ASSIGN ARITH-2ARG-DIV 12)
(ASSIGN ARITH-2ARG-EQL 13)	;EQL.  Differs from = on complex numbers.
(ASSIGN NUM-UNUSED-ARITH-2ARGS 4)
;REMAINDER, EXPT?

;These codes are used to save the type of the first numeric argument in dyadic
;operations, so that the routines for handling various types of second arguments
;can dispatch on them.
(ASSIGN NUMBER-CODE-FIXNUM 0)
(ASSIGN NUMBER-CODE-SMALL-FLONUM 1)
(ASSIGN NUMBER-CODE-FLONUM 2)
(ASSIGN NUMBER-CODE-BIGNUM 3)
(ASSIGN NUM-UNUSED-NUMBER-CODES 4)

;This is the format of all DTP-HEADER words.
(DEF-DATA-FIELD HEADER-TYPE-FIELD 5 19.)
(DEF-DATA-FIELD HEADER-REST-FIELD 19. 0)
(ASSIGN-EVAL NUM-UNUSED-HEADER-TYPES (EVAL (- 32. (LENGTH Q-HEADER-TYPES))))

;This is how flonums are stored in a header, and how to convert from internal
;form (see below) back into flonum form.
(DEF-DATA-FIELD HEADER-FLONUM-EXPONENT 11. 8.)
(DEF-DATA-FIELD HEADER-FLONUM-HIGH-MANTISSA 8. 0)
(DEF-DATA-FIELD FLONUM-HEADER-HIGH-MANTISSA 8. 24.)
(DEF-DATA-FIELD FLONUM-HEADER-LOW-MANTISSA 24. 0)

;Small-flonum definitions.  These are inums, with a DTP-SMALL-FLONUM data type,
;an 8-bit excess-200 exponent (10^-38 to 10^+38 approximately), and a
;17-bit 2's complement normalized mantissa (5 digits approximately).  The
;sign bit is elided since it is always the complement of the high bit of
;the mantissa, except for zero, which is represented as an all-zero exponent
;and mantissa.

(DEF-DATA-FIELD SMALL-FLONUM-EXPONENT 8 17.)	;The exponent in a small-flonum
(ASSIGN SMALL-FLONUM-EXPONENT-OFFSET 1600)	;To convert from excess-200 to excess-2000
(ASSIGN SMALL-FLONUM-MAX-EXPONENT 377)		;Largest value that fits in exponent field
(DEF-DATA-FIELD FLONUM-SMALL-MANTISSA-FIELD 17. 14.) ;DPB here to put into low-level form
(DEF-DATA-FIELD FLONUM-SMALL-USELESS-BITS 14. 0) ;Low-order discarded bits of mantissa
(DEF-DATA-FIELD FLONUM-SMALL-ROUND-BIT 1 13.)	;Highest discarded bit
(DEF-DATA-FIELD FLONUM-SMALL-GUARD-BITS 13. 0)	;The remaining discarded bits
(DEF-DATA-FIELD FLONUM-SMALL-MANTISSA-LOW-BIT 1 14.)
(DEF-DATA-FIELD SMALL-FLONUM-MANTISSA-HIGH-BIT 1 16.)

;Both flonums and small flonums are converted to an internal
;format, on which the subrouines FADD, FSUB, FMPY, FDIV, etc. work.
;Those routines are also intended to be useful for hairier functions
;such as series expansions when written in microcode.

;These routines operate on numbers which consist of a 32-bit
;normalized 2's complement mantissa in M-1 or M-2 and an excess-2000
;exponent in M-I or M-J.  The binary point is just to the right
;of the sign (bit 31).  The range of mantissas is
;1/2 <= f < 1, -1/2 > f >= -1, except for zero which has a zero
;mantissa and a zero exponent.  All results are normalized and
;properly rounded, and returned in M-1 and M-I.  Overflow and underflow
;are not detected at this level, which is a feature.  Fuzz is not
;hacked.  Rounding is towards even if the discarded bits = exactly 1/2 lsb.

;Definitions for low-level form

(DEF-DATA-FIELD FLONUM-SIGN-BIT 1 31.)
(DEF-DATA-FIELD MANTISSA-HIGH-BIT 1 30.)
(ASSIGN FLONUM-EXPONENT-EXCESS 2000)	;The exponent is excess-2000.
(DEF-DATA-FIELD SIGN-BIT-AND-MANTISSA-HIGH-THREE 4 28.)
(DEF-DATA-FIELD SIGN-BIT-AND-MANTISSA-HIGH-TWO 3 29.)
(DEF-DATA-FIELD SIGN-BIT-AND-MANTISSA-HIGH-BIT 2 30.)

;;; Packing and unpacking fixnums.

FXUNPK-P-1
	(popj-after-next (M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
	(no-op)
SIGN-EXTEND-M-1
#+lambda(POPJ-AFTER-NEXT 
		(OA-REG-HIGH) BOXED-SIGN-BIT M-1)
#+exp	((m-tem3) boxed-sign-bit m-1)
#+exp	(popj-after-next (oa-reg-high) dpb m-tem3 oah-m-src a-zero)
       ((M-1) SELECTIVE-DEPOSIT M-ZERO Q-ALL-BUT-POINTER A-1)

FXUNPK-T-2
#+lambda(POPJ-AFTER-NEXT 
		(OA-REG-HIGH) BOXED-SIGN-BIT M-T)
#+exp	((m-tem3) boxed-sign-bit m-t)
#+exp	(popj-after-next (oa-reg-high) dpb m-tem3 oah-m-src a-zero)
       ((M-2) SELECTIVE-DEPOSIT M-ZERO Q-ALL-BUT-POINTER A-T)

;;; Come to one of these to return a fixnum in M-1.
;;; Checks for fixnum overflow, and adds data type DTP-FIX.
;;; Result goes to M-T, and FIXPACK-P also pushes it on the PDL.

;;; Return the number in M-1 as either a fixnum or a bignum depending on its magnitude
;;; Returns it via M-T
RETURN-M-1
	(JUMP-LESS-THAN M-1 (A-CONSTANT NEGATIVE-SETZ) FIX-OVERFLOW-1)
	(JUMP-GREATER-OR-EQUAL M-1 (A-CONSTANT POSITIVE-SETZ) FIX-OVERFLOW-1)
	;drop into FIXPACK-T

;;; Return it via M-T checking only for single-bit overflow.  This is also open coded.
FIXPACK-T
	(DISPATCH-POPJ-XCT-NEXT (I-ARG 0) 
	 (BYTE-FIELD 2 (DIFFERENCE Q-POINTER-WIDTH 1))
	 M-1 D-FXOVCK)
       ((M-T) DPB M-1 Q-POINTER (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))

;;; Return it via pdl checking only for single-bit overflow
FIXPACK-P
	(DISPATCH-POPJ-XCT-NEXT (I-ARG 1) 
	 (BYTE-FIELD 2 (DIFFERENCE Q-POINTER-WIDTH 1))
	 M-1 D-FXOVCK)
       ((C-PDL-BUFFER-POINTER-PUSH M-T) DPB M-1 Q-POINTER
		(A-CONSTANT (PLUS (BYTE-VALUE Q-DATA-TYPE DTP-FIX)
				  (BYTE-VALUE Q-CDR-CODE CDR-NEXT))))
(LOCALITY D-MEM)
;DISPATCH TABLE FOR CHECKING FOR SINGLE-BIT ADD/SUBTRACT-TYPE FIXNUM OVERFLOW
;ON VALUE WHICH IS UNBOXED IN M-1.  DISPATCH ON SIGN BIT AND LOW DATA TYPE BIT.
;I-ARG SHOULD BE 0 IF RESULT ONLY TO M-T, OR 1 IF ALSO TO PDL.  
;IN ANY CASE, DOES ESSENTIALLY POPJ-XCT-NEXT.
;NEXT SHOULD BE INSTRUCTION TO BOX M-1 AS A FIXNUM.
(START-DISPATCH 2 0)
D-FXOVCK	
	(R-BIT)					 ;BITS AGREE NO OVERFLOW
	(FIX-OVERFLOW INHIBIT-XCT-NEXT-BIT)	 ;DISAGREE => OVERFLOW
	(FIX-OVERFLOW INHIBIT-XCT-NEXT-BIT)	 ;DISAGREE => OVERFLOW
	(R-BIT)					 ;BITS AGREE NO OVERFLOW
(END-DISPATCH)

(begin-comment)	;this is part of the scheme that unfortunately doesnt work out.
;This one used after doing OUTPUT-SELECTOR-MASK-25 ADD or SUB.  Q has full result,
;M-T and C-PDL-BUFFER-POINTER have DTP-FIX and low 25 bits of result. Before the operation,
;the data types of both operands were known to be DTP-FIX. 
;  Consider add:  There are two cases, either the operands were the same sign or not.
;If the original operands were the same sign, it is possible to have a real overflow, otherwise
;not.  Note that Q.25 is a true sum bit
;(not interfered with by the data-types).  (On an ADD the tag field has been shifted 
;left one.  On a SUB it has been cancelled out).  On overflow then, Q.25 should be replicated
;in bits 31. thru 25. of M-T, and the result made into a bignum.  I-ARG should be 1
;as result is desired both on PDL and in M-T.  Note, however, that a semi-garbage result
;is ALREADY on PDL at this time.  (In case of D-FXOVCK, the INHIBIT-XCT-NEXT-BIT stops
;the semi-garbage result from getting to the PDL, but that doesnt work out here.)
;If the original operands were of opposite signs, there is no possibility of a real overflow.
;However, since we are adding 25 bit non-sign-extended quantities, our test to detect 
;overflow that boxed sign bit and the bit above it are different may go off.

(start-dispatch 2 0)
d-lambda-fast-overflow-check
	(r-bit)
	(lambda-fast-fix-overflow inhibit-xct-next-bit)
	(lambda-fast-fix-overflow inhibit-xct-next-bit)
	(r-bit)
(end-dispatch)
(end-comment)
(LOCALITY I-MEM)

;;; This is called from the fixnum packing routines. M-1 contains a unboxed number
;;; IARG is 0 if the result is to go only to M-T, and 1 if it should also go to the
;;; PDL
FIX-OVERFLOW
	(JUMP-EQUAL READ-I-ARG A-ZERO FIX-OVERFLOW-1)
	((MICRO-STACK-DATA-PUSH) (A-CONSTANT (I-MEM-LOC M-T-TO-CPDL)))
FIX-OVERFLOW-1	;Enter directly here with unboxed number in M-1.  Returns bignum in M-T.
	((M-C) M-ZERO)				;sign bit
	(JUMP-GREATER-THAN-XCT-NEXT M-1 A-ZERO OVERFLOW-BIGNUM-CREATE)
       ((M-2) M-ZERO)
	(JUMP-XCT-NEXT OVERFLOW-BIGNUM-CREATE-NEGATIVE)
       ((M-1) SUB M-ZERO A-1)

RETURN-M-1-UNSIGNED
	(JUMP-LESS-THAN M-1 A-ZERO FIX-OVERFLOW-1-UNSIGNED)	;ANY NEGATIVE NUMBER
	(JUMP-GREATER-OR-EQUAL M-1 (A-CONSTANT POSITIVE-SETZ) FIX-OVERFLOW-1-UNSIGNED)
	(POPJ-AFTER-NEXT
         (M-T) DPB M-1 Q-POINTER (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))
       (NO-OP)
	  
FIX-OVERFLOW-1-UNSIGNED	;Enter directly here with unboxed number in M-1.  Returns bignum in M-T.
	((M-C) M-ZERO)				;sign bit
	(JUMP-XCT-NEXT M-1 A-ZERO OVERFLOW-BIGNUM-CREATE)
       ((M-2) M-ZERO)

(begin-comment)	;this is part of the scheme that unfortunately doesnt win.
lambda-fast-fix-overflow
	((m-2) xor m-1 a-t)		;xor signs of original operands.
	(popj-if-bit-set-xct-next boxed-sign-bit m-2)  ;return on false overflow, all ok.
       ((m-t) q-typed-pointer c-pdl-buffer-pointer)
	((MICRO-STACK-DATA-PUSH) SETA C-PDL-BUFFER-POINTER-POP  ;FLUSH SEMI-GARBAGE.
		(A-CONSTANT (I-MEM-LOC M-T-TO-CPDL)))
  ;Q.25 has true sum bit, replicate it.
#+lambda((OA-REG-HIGH) BIT-ABOVE-BOXED-SIGN-BIT Q-R)		;SIGN EXTEND (MUNG M SOURCE)
#+exp	((m-tem3) bit-above-boxed-sign-bit q-r)
#+exp	((oa-reg-high) dpb m-tem3 oah-m-src a-zero)
	((M-1) SELECTIVE-DEPOSIT M-ZERO Q-ALL-BUT-POINTER A-T)
	((M-C) M-ZERO)				;sign bit
	(JUMP-GREATER-THAN-XCT-NEXT M-1 A-ZERO OVERFLOW-BIGNUM-CREATE)
       ((M-2) M-ZERO)
	(JUMP-XCT-NEXT OVERFLOW-BIGNUM-CREATE-NEGATIVE)
       ((M-1) SUB M-ZERO A-1)
(end-comment)
	
;;; These return here before returning a value. This puts value from M-T
;;; also on stack for those that need it
M-T-TO-CPDL
	(POPJ-AFTER-NEXT
	 (C-PDL-BUFFER-POINTER-PUSH) DPB M-T Q-ALL-BUT-CDR-CODE 
					 (A-CONSTANT (BYTE-VALUE Q-CDR-CODE CDR-NEXT))) 
       (NO-OP)

;;; This is called from the fixnum multiply. M-2 contains the high product
;;; and M-1 the low product. Result is to go to the PDL and M-T.
FIX-2-WORD-OVERFLOW
	((MICRO-STACK-DATA-PUSH) (A-CONSTANT (I-MEM-LOC M-T-TO-CPDL)))
FIX-2-WORD-OVERFLOW-TO-M-T
	(JUMP-GREATER-OR-EQUAL-XCT-NEXT M-2 A-ZERO OVERFLOW-BIGNUM-CREATE)
       ((M-C) M-ZERO)				;sign bit
	((M-1) SUB M-ZERO A-1)
	(JUMP-NOT-EQUAL-XCT-NEXT M-1 A-ZERO OVERFLOW-BIGNUM-CREATE-NEGATIVE)
       ((M-2) M-A-1 M-ZERO A-2)		;ONE'S COMPLEMENT
	((M-2) ADD M-2 (A-CONSTANT 1))	;CARRY FROM LOW TO HIGH WORD
					;DROPS THROUGH
;;; M-2,,M-1 HAS A 64 BIT POSITIVE NUMBER THAT IS A MAX OF 47 BITS OF PRECISION
;;; M-C GETS THE SIGN BIT
;;; M-J GETS LENGTH OF BIGNUM
OVERFLOW-BIGNUM-CREATE-NEGATIVE
	((M-C) SELECTIVE-DEPOSIT M-MINUS-ONE BIGNUM-HEADER-SIGN A-ZERO)
OVERFLOW-BIGNUM-CREATE
	;; We need a 2-word bignum if non-zero bits above the low 31. 
	(JUMP-NOT-EQUAL-XCT-NEXT M-2 A-ZERO OVERFLOW-BIGNUM-CREATE-1)
       ((M-J) (A-CONSTANT 2))
	(JUMP-IF-BIT-SET (BYTE-FIELD 1 31.) M-1 OVERFLOW-BIGNUM-CREATE-1)
	((M-J) (A-CONSTANT 1))
OVERFLOW-BIGNUM-CREATE-1
	(CALL-XCT-NEXT BNCONS)			;Cons up a bignum
       ((M-B) ADD M-J (A-CONSTANT 1))
	((VMA) ADD M-T (A-CONSTANT 1))
	((WRITE-MEMORY-DATA-START-WRITE) (BYTE-FIELD 31. 0) M-1)  ;Low 31. bits
	(CHECK-PAGE-WRITE)
	(POPJ-EQUAL M-J (A-CONSTANT 1))
	((M-TEM) (BYTE-FIELD 1 31.) M-1)
	((VMA) ADD VMA (A-CONSTANT 1))
	((WRITE-MEMORY-DATA-START-WRITE) DPB M-2 (BYTE-FIELD 31. 1) A-TEM)
	(CHECK-PAGE-WRITE)
	(POPJ) ;NO POPJ-AFTER-NEXT, MAY BE RETURNING TO MAIN-LOOP

;;; Packing and unpacking small flonums.

;Unpack from C-PDL-BUFFER-POINTER-POP into M-1 and M-I.
SFLUNPK-P-1
	((M-I) SMALL-FLONUM-EXPONENT C-PDL-BUFFER-POINTER)
	(POPJ-EQUAL-XCT-NEXT M-I A-ZERO FLZERO)		;zero exponent => this is 0.0
       ((M-1) DPB C-PDL-BUFFER-POINTER-POP FLONUM-SMALL-MANTISSA-FIELD A-ZERO)
	((M-I) ADD M-I (A-CONSTANT SMALL-FLONUM-EXPONENT-OFFSET))
	(POPJ-AFTER-NEXT POPJ-IF-BIT-SET MANTISSA-HIGH-BIT M-1)
       ((M-1) DPB (M-CONSTANT -1) FLONUM-SIGN-BIT A-1)  ;negative => set sign bit

;Unpack from M-T into M-2 and M-J.
SFLUNPK-T-2
	((M-J) SMALL-FLONUM-EXPONENT M-T)
	(POPJ-EQUAL-XCT-NEXT M-J A-ZERO)	;zero exponent => this is 0.0
       ((M-2) DPB M-T FLONUM-SMALL-MANTISSA-FIELD A-ZERO)
	((M-J) ADD M-J (A-CONSTANT SMALL-FLONUM-EXPONENT-OFFSET))
	(POPJ-AFTER-NEXT POPJ-IF-BIT-SET SMALL-FLONUM-MANTISSA-HIGH-BIT M-T)
       ((M-2) DPB (M-CONSTANT -1) FLONUM-SIGN-BIT A-2)

;Pack from M-1 and M-I into C-PDL-BUFFER-POINTER-PUSH and M-T, rounding.
SFLPACK-P
	(JUMP-IF-BIT-CLEAR FLONUM-SMALL-ROUND-BIT M-1 SFLPCK1)	;Jump if no rounding required
	((M-T) FLONUM-SMALL-GUARD-BITS M-1)	;Discarded fraction exactly 1/2 lsb?
	(JUMP-NOT-EQUAL M-T A-ZERO SFLPCK0)	;No, round.
	(JUMP-IF-BIT-CLEAR FLONUM-SMALL-MANTISSA-LOW-BIT M-1 SFLPCK1) ;Yes, round towards even.
SFLPCK0	(CALL-XCT-NEXT FRND1)			;Round and renormalize (may bring in two
       ((M-1) ADD M-1 (A-CONSTANT (BYTE-MASK FLONUM-SMALL-ROUND-BIT))	; garbage bits from Q)
		OUTPUT-SELECTOR-RIGHTSHIFT-1)
SFLPCK1	((M-1) DPB M-ZERO FLONUM-SMALL-USELESS-BITS A-1) ;clear low-order bits so can test zero
	(POPJ-EQUAL-XCT-NEXT M-1 A-ZERO)	;Special case 0.0, which has 0 in exponent
       ((M-T C-PDL-BUFFER-POINTER-PUSH) 	;Store mantissa and data-type fields
		FLONUM-SMALL-MANTISSA-FIELD M-1
		(A-CONSTANT (PLUS (BYTE-VALUE Q-DATA-TYPE DTP-SMALL-FLONUM)
				  (BYTE-VALUE Q-CDR-CODE CDR-NEXT))))
	((M-I) SUB M-I (A-CONSTANT SMALL-FLONUM-EXPONENT-OFFSET))
	(JUMP-LESS-OR-EQUAL M-I A-ZERO SFL-E-UND)	;Underflow.  ZUNDERFLOW?
	(POPJ-AFTER-NEXT
	 (M-T C-PDL-BUFFER-POINTER) DPB M-I SMALL-FLONUM-EXPONENT A-T)
       (CALL-GREATER-THAN M-I (A-CONSTANT SMALL-FLONUM-MAX-EXPONENT) SFL-E-OV) ;Overflow

SFL-E-UND
	((M-TEM) DPB M-ZERO Q-ALL-BUT-TYPED-POINTER A-ZUNDERFLOW)
	(CALL-EQUAL M-TEM A-V-NIL TRAP)
	    (ERROR-TABLE FLOATING-EXPONENT-UNDERFLOW SFL)
	(POPJ-AFTER-NEXT				;Return 0.0s0 instead or if continued
	 (M-T C-PDL-BUFFER-POINTER)
		(A-CONSTANT (PLUS (BYTE-VALUE Q-DATA-TYPE DTP-SMALL-FLONUM)
				  (BYTE-VALUE Q-CDR-CODE CDR-NEXT))))
       (NO-OP)

SFL-E-OV (CALL TRAP)
   (ERROR-TABLE FLOATING-EXPONENT-OVERFLOW SFL)

;Pack from M-1 and M-I into M-T, rounding.
SFLPACK-T
	(CALL SFLPACK-P)
	(POPJ-AFTER-NEXT (M-GARBAGE) C-PDL-BUFFER-POINTER-POP)
       (NO-OP)

;;; Packing flonums.

;;; Note: the code to unpack flonums only exists at ARITH-FLO-ANY
;;; and ARITH-ANY-FLO, and is written there.  There is also GET-FLONUM,
;;; a general routine which is not used by the normal arithmetic path. 

;;; Take a flonum in M-1/M-I, and return a DTP-EXTENDED-NUMBER to it.
FLOPACK-T
	(CALL FLOPACK)
	(POPJ)  ;May be returning to main loop, can't popj and start-write together

FLOPACK-P
	((MICRO-STACK-DATA-PUSH) (A-CONSTANT (I-MEM-LOC M-T-TO-STACK)))
FLOPACK	(CALL-LESS-OR-EQUAL M-I A-ZERO FLOPACK-UNDERFLOW)
 	(CALL-GREATER-OR-EQUAL M-I (A-CONSTANT 4000) TRAP)
	    (ERROR-TABLE FLOATING-EXPONENT-OVERFLOW FLO)

     ;; Allocate two boxed words of structure storage in the number-cons area.
        ((m-b) seta (a-constant 2))
        (call-xct-next allocate-extended-number-storage)
       ((m-a) m-b)

	((VMA) ADD M-T (A-CONSTANT 1))		;Write the second word
	((MD-START-WRITE)
		FLONUM-HEADER-LOW-MANTISSA M-1
		(A-CONSTANT (PLUS (BYTE-VALUE Q-DATA-TYPE DTP-FIX)
				  (BYTE-VALUE Q-CDR-CODE CDR-NIL))))
	(CHECK-PAGE-WRITE)
	((M-TEM) FLONUM-HEADER-HIGH-MANTISSA M-1
		(A-CONSTANT (PLUS (BYTE-VALUE Q-DATA-TYPE DTP-HEADER)
				  (BYTE-VALUE Q-CDR-CODE CDR-NEXT)
				  (BYTE-VALUE HEADER-TYPE-FIELD %HEADER-TYPE-FLONUM))))
	((VMA M-T) Q-POINTER M-T
		(A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-EXTENDED-NUMBER)))
	(POPJ-AFTER-NEXT (MD-START-WRITE) DPB M-I HEADER-FLONUM-EXPONENT A-TEM)
       (CHECK-PAGE-WRITE)
	
FLOPACK-UNDERFLOW
	(POPJ-EQUAL M-1 A-ZERO)		;0.0 case: M-I has zero, don't trap
	((M-TEM) DPB M-ZERO Q-ALL-BUT-TYPED-POINTER A-ZUNDERFLOW)
	(CALL-EQUAL M-TEM A-V-NIL TRAP)
	    (ERROR-TABLE FLOATING-EXPONENT-UNDERFLOW FLO)
	(POPJ-AFTER-NEXT (M-I) A-ZERO)	;Return 0.0 instead
       ((M-1) A-ZERO)

;;; Given something on stack, return a flonum unpacked into M-I and M-1, doing coercions.
;;; Clobbers only M-T, M-TEM, M-4, M-3 (inside FLOAT-A-BIGNUM)
GET-FLONUM  (ERROR-TABLE RESTART GET-FLONUM)
	(JUMP-DATA-TYPE-NOT-EQUAL C-PDL-BUFFER-POINTER
		 (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-EXTENDED-NUMBER)) GET-FLONUM-1)
	((VMA-START-READ) C-PDL-BUFFER-POINTER-POP)
	(CHECK-PAGE-READ)
	(DISPATCH TRANSPORT-HEADER READ-MEMORY-DATA)
	((M-TEM) HEADER-TYPE-FIELD READ-MEMORY-DATA)
	(JUMP-NOT-EQUAL M-TEM (A-CONSTANT (EVAL %HEADER-TYPE-FLONUM)) GET-FLONUM-2)
	((M-I) HEADER-FLONUM-EXPONENT READ-MEMORY-DATA)
	((M-1) DPB READ-MEMORY-DATA FLONUM-HEADER-HIGH-MANTISSA A-ZERO)
	((VMA-START-READ) ADD VMA (A-CONSTANT 1))
	(CHECK-PAGE-READ)
	(POPJ-AFTER-NEXT NO-OP)
       ((M-1) SELECTIVE-DEPOSIT READ-MEMORY-DATA FLONUM-HEADER-LOW-MANTISSA A-1)

GET-FLONUM-1
	(JUMP-DATA-TYPE-EQUAL C-PDL-BUFFER-POINTER
		(A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-SMALL-FLONUM)) SFLUNPK-P-1)
	(JUMP-DATA-TYPE-EQUAL C-PDL-BUFFER-POINTER 
		(A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-CHARACTER)) GET-FLONUM-1-CHAR)
	(CALL-DATA-TYPE-NOT-EQUAL C-PDL-BUFFER-POINTER
		(A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)) TRAP)
	    (ERROR-TABLE ARGTYP NUMBER PP T GET-FLONUM)
GET-FLONUM-1-CHAR
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
       ((M-I) (A-CONSTANT 2036))
	(JUMP-XCT-NEXT FNORM)
       ((Q-R) M-ZERO)

GET-FLONUM-2
	(CALL-NOT-EQUAL M-TEM (A-CONSTANT (EVAL %HEADER-TYPE-BIGNUM)) ILLOP) ;unknown type?
	((C-PDL-BUFFER-POINTER-PUSH) M-Q)
	((C-PDL-BUFFER-POINTER-PUSH) M-C)
	((C-PDL-BUFFER-POINTER-PUSH) M-K)
	((M-Q) VMA)
	((M-C) Q-POINTER READ-MEMORY-DATA)
	((M-I) BIGNUM-HEADER-LENGTH M-C)
	(CALL FLOAT-A-BIGNUM)
	((M-K) C-PDL-BUFFER-POINTER-POP)
	(POPJ-AFTER-NEXT (M-C) C-PDL-BUFFER-POINTER-POP)
       ((M-Q) C-PDL-BUFFER-POINTER-POP)

XFLOAT-FRACTION (MISC-INST-ENTRY FLOAT-FRACTION)
	(CALL GET-FLONUM)
	(JUMP-XCT-NEXT FLOPACK-T)
       ((M-I) (A-CONSTANT 2000))

XFLOAT-EXPONENT (MISC-INST-ENTRY FLOAT-EXPONENT)
	(CALL GET-FLONUM)
	((M-1) SUB M-I (A-CONSTANT 2000))
	(DISPATCH-POPJ-XCT-NEXT (I-ARG 0) 
	 (BYTE-FIELD 2 (DIFFERENCE Q-POINTER-WIDTH 1))
	 M-1 D-FXOVCK)
       ((M-T) DPB M-1 Q-POINTER (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))

XSCALE-FLOAT (MISC-INST-ENTRY SCALE-FLOAT)
	(DISPATCH Q-DATA-TYPE PDL-TOP TRAP-UNLESS-FIXNUM)
    (ERROR-TABLE ARGTYP FIXNUM M-T 2)
	(CALL-XCT-NEXT GET-FLONUM)
       ((M-A) Q-TYPED-POINTER PDL-POP)
	((M-2) OUTPUT-SELECTOR-EXTEND-25 M-A)
	((M-I) ADD M-I A-2)
		;make result small float if arg was.
	(JUMP-DATA-TYPE-EQUAL M-A
		(A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-SMALL-FLONUM)) SFLPACK-T)
	(JUMP FLOPACK-T)		;pack M-1/M-I

;;; Simple one-argument operations.

XABS (MISC-INST-ENTRY ABS) (ERROR-TABLE RESTART XABS)
	(DISPATCH-XCT-NEXT Q-DATA-TYPE C-PDL-BUFFER-POINTER D-NUMARG)
    (ERROR-TABLE ARGTYP NUMBER PP T XABS)
    (ERROR-TABLE ARG-POPPED 0 PP)
       ((M-A) (A-CONSTANT ARITH-1ARG-ABS))
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
	(JUMP-GREATER-OR-EQUAL M-1 A-ZERO FIXPACK-T)
	((M-1) SUB M-ZERO A-1)
	(DISPATCH-POPJ-XCT-NEXT (I-ARG 0) 
	 (BYTE-FIELD 2 (DIFFERENCE Q-POINTER-WIDTH 1))
	 M-1 D-FXOVCK)
       ((M-T) DPB M-1 Q-POINTER (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))

XMINUS (MISC-INST-ENTRY MINUS) (ERROR-TABLE RESTART XMINUS)
	(DISPATCH-XCT-NEXT Q-DATA-TYPE C-PDL-BUFFER-POINTER D-NUMARG)
    (ERROR-TABLE ARGTYP NUMBER PP T XMINUS)
    (ERROR-TABLE ARG-POPPED 0 PP)
       ((M-A) (A-CONSTANT ARITH-1ARG-MINUS))
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
       ((M-1) SUB M-ZERO A-1)
	(DISPATCH-POPJ-XCT-NEXT (I-ARG 0) 
	 (BYTE-FIELD 2 (DIFFERENCE Q-POINTER-WIDTH 1))
	 M-1 D-FXOVCK)
       ((M-T) DPB M-1 Q-POINTER (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))

XZEROP (MISC-INST-ENTRY ZEROP) (ERROR-TABLE RESTART XZEROP)
	(DISPATCH-XCT-NEXT Q-DATA-TYPE C-PDL-BUFFER-POINTER D-NUMARG)
    (ERROR-TABLE ARGTYP NUMBER PP T XZEROP zerop)
    (ERROR-TABLE ARG-POPPED 0 PP)
       ((M-A) (A-CONSTANT ARITH-1ARG-ZEROP))
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
FLONUM-ZEROP
	((M-T) A-V-TRUE)
	(POPJ-AFTER-NEXT POPJ-EQUAL M-1 A-ZERO)
       ((M-T) A-V-NIL)

XPLUSP (MISC-INST-ENTRY PLUSP) (ERROR-TABLE RESTART XPLUSP)
	(DISPATCH-XCT-NEXT Q-DATA-TYPE C-PDL-BUFFER-POINTER D-NUMARG)
    (ERROR-TABLE ARGTYP NUMBER PP T XPLUSP)
    (ERROR-TABLE ARG-POPPED 0 PP)
       ((M-A) (A-CONSTANT ARITH-1ARG-PLUSP))
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
FLONUM-PLUSP
	((M-T) A-V-TRUE)
	(POPJ-AFTER-NEXT POPJ-GREATER-THAN M-1 A-ZERO)
       ((M-T) A-V-NIL)

XMINUSP (MISC-INST-ENTRY MINUSP) (ERROR-TABLE RESTART XMINUSP)
	(DISPATCH-XCT-NEXT Q-DATA-TYPE C-PDL-BUFFER-POINTER D-NUMARG)
    (ERROR-TABLE ARGTYP NUMBER PP T XMINUSP)
    (ERROR-TABLE ARG-POPPED 0 PP)
       ((M-A) (A-CONSTANT ARITH-1ARG-MINUSP))
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
FLONUM-MINUSP
	((M-T) A-V-TRUE)
	(POPJ-AFTER-NEXT POPJ-LESS-THAN M-1 A-ZERO)
       ((M-T) A-V-NIL)

XODDP (MISC-INST-ENTRY ODDP) (ERROR-TABLE RESTART XODDP)
	(DISPATCH-XCT-NEXT Q-DATA-TYPE C-PDL-BUFFER-POINTER D-NUMARG)
    (ERROR-TABLE ARGTYP NUMBER PP T XODDP)
    (ERROR-TABLE ARG-POPPED 0 PP)
       ((M-A) (A-CONSTANT ARITH-1ARG-ODDP))
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
	((M-T) A-V-TRUE)
	(POPJ-AFTER-NEXT POPJ-IF-BIT-SET (BYTE-FIELD 1 0) M-1)
       ((M-T) A-V-NIL)

XEVENP (MISC-INST-ENTRY EVENP) (ERROR-TABLE RESTART XEVENP)
	(DISPATCH-XCT-NEXT Q-DATA-TYPE C-PDL-BUFFER-POINTER D-NUMARG)
    (ERROR-TABLE ARGTYP NUMBER PP T XEVENP)
    (ERROR-TABLE ARG-POPPED 0 PP)
       ((M-A) (A-CONSTANT ARITH-1ARG-EVENP))
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
	((M-T) A-V-TRUE)
	(POPJ-AFTER-NEXT POPJ-IF-BIT-CLEAR (BYTE-FIELD 1 0) M-1)
       ((M-T) A-V-NIL)

X1PLS (MISC-INST-ENTRY 1+) ;ADD1 GETS FSET TO THIS
	    (ERROR-TABLE RESTART X1PLS)
	(DISPATCH-XCT-NEXT Q-DATA-TYPE C-PDL-BUFFER-POINTER D-NUMARG)
    (ERROR-TABLE ARGTYP NUMBER PP T X1PLS)
    (ERROR-TABLE ARG-POPPED 0 PP)
       ((M-A) (A-CONSTANT ARITH-1ARG-ADD1))
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
	((M-1) ADD M-1 (A-CONSTANT 1))
	(DISPATCH-POPJ-XCT-NEXT (I-ARG 0) 
	 (BYTE-FIELD 2 (DIFFERENCE Q-POINTER-WIDTH 1))
	 M-1 D-FXOVCK)
       ((M-T) DPB M-1 Q-POINTER (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))

X1MNS (MISC-INST-ENTRY 1-) ;SUB1 GETS FSET TO THIS
	    (ERROR-TABLE RESTART X1MNS)
	(DISPATCH-XCT-NEXT Q-DATA-TYPE C-PDL-BUFFER-POINTER D-NUMARG)
    (ERROR-TABLE ARGTYP NUMBER PP T X1MNS)
    (ERROR-TABLE ARG-POPPED 0 PP)
       ((M-A) (A-CONSTANT ARITH-1ARG-SUB1))
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
	((M-1) SUB M-1 (A-CONSTANT 1))
	(DISPATCH-POPJ-XCT-NEXT (I-ARG 0) 
	 (BYTE-FIELD 2 (DIFFERENCE Q-POINTER-WIDTH 1))
	 M-1 D-FXOVCK)
       ((M-T) DPB M-1 Q-POINTER (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))

XFIX (MISC-INST-ENTRY FIX) (ERROR-TABLE RESTART XFIX)
	(DISPATCH-XCT-NEXT Q-DATA-TYPE C-PDL-BUFFER-POINTER D-NUMARG)
    (ERROR-TABLE ARGTYP NUMBER PP T XFIX)
    (ERROR-TABLE ARG-POPPED 0 PP)
       ((M-A) (A-CONSTANT ARITH-1ARG-FIX))
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
	(DISPATCH-POPJ-XCT-NEXT (I-ARG 0) 
	 (BYTE-FIELD 2 (DIFFERENCE Q-POINTER-WIDTH 1))
	 M-1 D-FXOVCK)
       ((M-T) DPB M-1 Q-POINTER (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))

XINTERNAL-FLOAT (MISC-INST-ENTRY INTERNAL-FLOAT)
XFLOAT (MISC-INST-ENTRY FLOAT) (ERROR-TABLE RESTART XFLOAT)
	(DISPATCH-XCT-NEXT Q-DATA-TYPE C-PDL-BUFFER-POINTER D-NUMARG)
    (ERROR-TABLE ARGTYP NUMBER PP T XFLOAT)
    (ERROR-TABLE ARG-POPPED 0 PP)
       ((M-A) (A-CONSTANT ARITH-1ARG-FLOAT))
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
	((M-I) (A-CONSTANT 2036))
	(CALL-XCT-NEXT FNORM)
       ((Q-R) M-ZERO)
	(JUMP FLOPACK-T)

XSMALL-FLOAT (MISC-INST-ENTRY SMALL-FLOAT) (ERROR-TABLE RESTART XSMALL-FLOAT)
	(DISPATCH-XCT-NEXT Q-DATA-TYPE C-PDL-BUFFER-POINTER D-NUMARG)
    (ERROR-TABLE ARGTYP NUMBER PP T XSMALL-FLOAT)
    (ERROR-TABLE ARG-POPPED 0 PP)
       ((M-A) (A-CONSTANT ARITH-1ARG-SMALL-FLOAT))
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
	((M-I) (A-CONSTANT 2036))
	(CALL-XCT-NEXT FNORM)
       ((Q-R) M-ZERO)
	(JUMP SFLPACK-T)

XHAUL (MISC-INST-ENTRY HAULONG)	;TAKES ONE ARG, RETURNS # SIGNIFICANT BITS
	    (ERROR-TABLE RESTART XHAUL)
	(DISPATCH-XCT-NEXT Q-DATA-TYPE C-PDL-BUFFER-POINTER D-NUMARG)
    (ERROR-TABLE ARGTYP NUMBER PP T XHAUL)
    (ERROR-TABLE ARG-POPPED 0 PP)
       ((M-A) (A-CONSTANT ARITH-1ARG-HAULONG))
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
	(JUMP-GREATER-OR-EQUAL-XCT-NEXT M-1 A-ZERO XHAUL1)
       ((M-T) (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))
	((M-1) SUB M-ZERO A-1)
XHAUL1	(POPJ-EQUAL M-1 A-ZERO)
	((M-T) ADD M-T (A-CONSTANT 1))
	(JUMP-XCT-NEXT XHAUL1)
       ((M-1) (BYTE-FIELD 31. 1) M-1)		;SHIFT RIGHT

XHAULFLO (CALL FLOPACK-P)	;HAULONG or LDB of a flonum.  Argument is unpacked.
	(CALL TRAP)		;Repack and hope don't mind if SFL became FLO in the process.
	    (ERROR-TABLE ARGTYP INTEGER PP T)

;;; Simple two-argument operations.

;;; Generic addition.
XMADD (MISC-INST-ENTRY M-+)
	((M-T) Q-TYPED-POINTER C-PDL-BUFFER-POINTER-POP)
XTCADD  ((MICRO-STACK-DATA-PUSH) (A-CONSTANT (I-MEM-LOC POPTJ)))	;MC-LINKAGE
QIADD		(ERROR-TABLE RESTART QIADD)
	(jump-data-type-not-equal c-pdl-buffer-pointer a-t qiadd-hard)
	(jump-data-type-not-equal m-t
		(a-constant (byte-value q-data-type dtp-fix)) qiadd-hard)
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
	((M-2) OUTPUT-SELECTOR-EXTEND-25 M-T)
	((M-1) ADD M-1 A-2)
	(DISPATCH-POPJ-XCT-NEXT (I-ARG 1) 	;duplicate FIXPACK-P
	 (BYTE-FIELD 2 (DIFFERENCE Q-POINTER-WIDTH 1))
	 M-1 D-FXOVCK)
       ((C-PDL-BUFFER-POINTER-PUSH M-T) DPB M-1 Q-POINTER
		(A-CONSTANT (PLUS (BYTE-VALUE Q-DATA-TYPE DTP-FIX)
				  (BYTE-VALUE Q-CDR-CODE CDR-NEXT))))

qiadd-hard
	(DISPATCH-XCT-NEXT Q-DATA-TYPE C-PDL-BUFFER-POINTER D-NUMARG1)
    (ERROR-TABLE ARGTYP NUMBER PP 0 QIADD)
    (ERROR-TABLE ARG-POPPED 0 PP M-T)
       ((M-A) (A-CONSTANT ARITH-2ARG-ADD))
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
		(ERROR-TABLE RESTART QIADD0)
	(DISPATCH Q-DATA-TYPE M-T D-FIXNUM-NUMARG2 (I-ARG NUMBER-CODE-FIXNUM))
    (ERROR-TABLE ARGTYP NUMBER M-T 1 QIADD0)
    (ERROR-TABLE ARG-POPPED 0 M-1 M-T)
	((M-2) OUTPUT-SELECTOR-EXTEND-25 M-T)
	(JUMP-XCT-NEXT FIXPACK-P)
       ((M-1) ADD M-1 A-2)

;;; Generic subtraction.
XMSUB (MISC-INST-ENTRY M--)
	((M-T) Q-TYPED-POINTER C-PDL-BUFFER-POINTER-POP)
XTCSUB	((MICRO-STACK-DATA-PUSH) (A-CONSTANT (I-MEM-LOC POPTJ)))	;MC-LINKAGE
QISUB		(ERROR-TABLE RESTART QISUB)
	(jump-data-type-not-equal c-pdl-buffer-pointer a-t qisub-hard)
	(jump-data-type-not-equal m-t
		 (a-constant (byte-value q-data-type dtp-fix)) qisub-hard)
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
	((M-2) OUTPUT-SELECTOR-EXTEND-25 M-T)
	((M-1) SUB M-1 A-2)
	(DISPATCH-POPJ-XCT-NEXT (I-ARG 1) 	;duplicate FIXPACK-P
	 (BYTE-FIELD 2 (DIFFERENCE Q-POINTER-WIDTH 1))
	 M-1 D-FXOVCK)
       ((C-PDL-BUFFER-POINTER-PUSH M-T) DPB M-1 Q-POINTER
		(A-CONSTANT (PLUS (BYTE-VALUE Q-DATA-TYPE DTP-FIX)
				  (BYTE-VALUE Q-CDR-CODE CDR-NEXT))))
qisub-hard
	(DISPATCH-XCT-NEXT Q-DATA-TYPE C-PDL-BUFFER-POINTER D-NUMARG1)
    (ERROR-TABLE ARGTYP NUMBER PP 0 QISUB)
    (ERROR-TABLE ARG-POPPED 0 PP M-T)
       ((M-A) (A-CONSTANT ARITH-2ARG-SUB))
		(ERROR-TABLE RESTART QISUB0)
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
	(DISPATCH Q-DATA-TYPE M-T D-FIXNUM-NUMARG2 (I-ARG NUMBER-CODE-FIXNUM))
    (ERROR-TABLE ARGTYP NUMBER M-T 1 QISUB0)
    (ERROR-TABLE ARG-POPPED 0 M-1 M-T)
	((M-2) OUTPUT-SELECTOR-EXTEND-25 M-T)
	((M-1) SUB M-1 A-2)
	(DISPATCH-POPJ-XCT-NEXT (I-ARG 1) 	;duplicate FIXPACK-P
	 (BYTE-FIELD 2 (DIFFERENCE Q-POINTER-WIDTH 1))
	 M-1 D-FXOVCK)
       ((C-PDL-BUFFER-POINTER-PUSH M-T) DPB M-1 Q-POINTER
		(A-CONSTANT (PLUS (BYTE-VALUE Q-DATA-TYPE DTP-FIX)
				  (BYTE-VALUE Q-CDR-CODE CDR-NEXT))))

;;; Generic multiplication.
XMMUL (MISC-INST-ENTRY M-*)
	((M-T) Q-TYPED-POINTER C-PDL-BUFFER-POINTER-POP)
XTCMUL	((MICRO-STACK-DATA-PUSH) (A-CONSTANT (I-MEM-LOC POPTJ)))	;MC-LINKAGE
QIMUL		(ERROR-TABLE RESTART QIMUL)
	(DISPATCH-XCT-NEXT Q-DATA-TYPE C-PDL-BUFFER-POINTER D-NUMARG1)
    (ERROR-TABLE ARGTYP NUMBER PP 0 QIMUL)
    (ERROR-TABLE ARG-POPPED 0 PP M-T)
       ((M-A) (A-CONSTANT ARITH-2ARG-MUL))
		(ERROR-TABLE RESTART QIMUL0)
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
	(DISPATCH Q-DATA-TYPE M-T D-FIXNUM-NUMARG2 (I-ARG NUMBER-CODE-FIXNUM))
    (ERROR-TABLE ARGTYP NUMBER M-T 1 QIMUL0)
    (ERROR-TABLE ARG-POPPED 0 M-1 M-T)
	((M-2) OUTPUT-SELECTOR-EXTEND-25 M-T)  ;CAN NOT BUM THIS BECAUSE Q LOADS DIRECTLY FROM ALU
	(CALL-XCT-NEXT MPY)	;LOW PRODUCT TO Q-R, HIGH TO M-2
       ((Q-R) M-2)
	((M-TEM) SELECTIVE-DEPOSIT Q-R
	 (BYTE-FIELD (DIFFERENCE 33. Q-POINTER-WIDTH)
		     (DIFFERENCE Q-POINTER-WIDTH 1))
	 A-2)	;DISCARDED BITS AND SIGN
	(JUMP-EQUAL-XCT-NEXT M-TEM A-ZERO FIXPACK-P)   ;JUMP IF NON-OVERFLOWING POSITIVE RESULT
       ((M-1) Q-POINTER Q-R A-TEM)		     ;SIGN EXTEND (IF NON-OVERFLOWING)
	(JUMP-EQUAL M-TEM (A-CONSTANT -1) FIXPACK-P)   ;JUMP IF NON-OVERFLOWING NEGATIVE
	(JUMP-XCT-NEXT FIX-2-WORD-OVERFLOW)
       ((M-1) Q-R)

;;; Generic division, producing integer result with integer arguments.
XMDIV (MISC-INST-ENTRY M-//)
	((M-T) Q-TYPED-POINTER C-PDL-BUFFER-POINTER-POP)
XTCDIV	((MICRO-STACK-DATA-PUSH) (A-CONSTANT (I-MEM-LOC POPTJ)))	;MC-LINKAGE
;Division, with args on stack and in M-T, value on stack.
QIDIV		(ERROR-TABLE RESTART QIDIV)
	(DISPATCH-XCT-NEXT Q-DATA-TYPE C-PDL-BUFFER-POINTER D-NUMARG1)
    (ERROR-TABLE ARGTYP NUMBER PP 0 QIDIV)
    (ERROR-TABLE ARG-POPPED 0 PP M-T)
       ((M-A) (A-CONSTANT ARITH-2ARG-IDIV))
		(ERROR-TABLE RESTART QIDIV0)
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
	(DISPATCH Q-DATA-TYPE M-T D-FIXNUM-NUMARG2 (I-ARG NUMBER-CODE-FIXNUM))
    (ERROR-TABLE ARGTYP NUMBER M-T 1 QIDIV0)
    (ERROR-TABLE ARG-POPPED 0 M-1 M-T)
	((M-2) OUTPUT-SELECTOR-EXTEND-25 M-T)
	(CALL DIV)
	(JUMP-XCT-NEXT FIXPACK-P)	;DIVIDE CAN'T OVERFLOW EXCEPT FOR SETZ/-1
       ((M-1) Q-R)

;args on PDL, single result ALWAYS to PDL.  Destination field used to decode rounding mode:
; 0 -> FLOOR, 1 -> CEIL, 2 -> TRUNC, 3 -> ROUND
XFLOOR-1 (MISC-INST-ENTRY INTERNAL-FLOOR-1)
	;this must be only place it extracts destination.
	((M-1) MACRO-IR-DEST)
	(JUMP-EQUAL M-1 A-ZERO XFLOOR-1-C)
	((M-GARBAGE) MICRO-STACK-DATA-POP)	;Don't store in our destination.
XFLOOR-1-C
	((MICRO-STACK-DATA-PUSH) (A-CONSTANT (I-MEM-LOC M-T-TO-CPDL)))
xfloor-1-uc-entry		;microcompiled code enters here.
	((M-T) Q-TYPED-POINTER PDL-POP)
				;MC-LINKAGE
;Given args on stack and M-T, return first value of FLOOR, in M-T.
;M-1 has rounding code.
XFLOOR-1-INTERNAL
	(JUMP-EQUAL M-T (A-CONSTANT (PLUS (BYTE-VALUE Q-DATA-TYPE DTP-FIX) 1))
		XFLOOR-1-A)
	(DISPATCH (BYTE-FIELD 2 0) M-1 D-XFLOOR-1)
    (ERROR-TABLE ILLEGAL-INSTRUCTION)
XFLOOR-1-ROUND	;m-1 must have "rounding mode"
	((micro-stack-data-push) m-1)
	(CALL QDIV)  ;Clobbers M-INST-DEST, and all M-registers, if calls out to macrocode.
	((M-1) MICRO-STACK-DATA-POP)
;	(NO-OP)   ;QDIV returns while pushing; avoid screw from missing pass-around path.
;This code is copied from FIX, but we put the DEST field into part of M-A
;to tell the fix routine how to round.
;The DEST field should be in M-1 on arrival here.
XFLOOR-1-A
	(JUMP-DATA-TYPE-EQUAL PDL-TOP (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX))
		XFLOOR-1-B)
	(DISPATCH-XCT-NEXT Q-DATA-TYPE C-PDL-BUFFER-POINTER D-NUMARG)
    (ERROR-TABLE ARGTYP NUMBER PP T XFIX)
    (ERROR-TABLE ARG-POPPED 0 PP)
       ((M-A) DPB M-1 ARITH-FIX-ROUNDING-MODE-FIELD (A-CONSTANT ARITH-1ARG-FIX))
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
	(DISPATCH-POPJ-XCT-NEXT (I-ARG 0) 
	 (BYTE-FIELD 2 (DIFFERENCE Q-POINTER-WIDTH 1))
	 M-1 D-FXOVCK)
       ((M-T) DPB M-1 Q-POINTER (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))

XFLOOR-1-B
	(POPJ-XCT-NEXT)
       ((M-T) Q-TYPED-POINTER PDL-POP)

;; Decide how to divide, if the second arg is not 1, based on type of rounding desired.
;; We could simply use QDIV, but in the case of two fixnum args
;; it is much faster to do some rounding in the division process itself
;; and avoid creating a rationalnum.
(LOCALITY D-MEM)
(START-DISPATCH 2 0)
D-XFLOOR-1
	(INHIBIT-XCT-NEXT-BIT XFLOOR-1-FLOOR)
	(INHIBIT-XCT-NEXT-BIT XFLOOR-1-CEIL)
	(INHIBIT-XCT-NEXT-BIT XFLOOR-1-TRUNC)
	(P-BIT R-BIT)
(END-DISPATCH)
(LOCALITY I-MEM)

;;Return nonzero in M-1 unless both M-T and PDL-TOP are fixnums.
;XFLOOR-BOTH-ARGS-FIXNUMS
;#+CADR	((M-2) Q-DATA-TYPE M-T)
;#+CADR	(POPJ-NOT-EQUAL-XCT-NEXT M-2 (A-CONSTANT (EVAL DTP-FIX)))
;#+LAMBDA(POPJ-DATA-TYPE-NOT-EQUAL-XCT-NEXT M-T (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))
;       ((M-1) A-MINUS-ONE)
;#+CADR	((M-2) Q-DATA-TYPE PDL-TOP)
;#+CADR	(POPJ-NOT-EQUAL M-2 (A-CONSTANT (EVAL DTP-FIX)))
;#+LAMBDA(POPJ-DATA-TYPE-NOT-EQUAL PDL-TOP (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))
;	(POPJ-XCT-NEXT)
;	((M-1) A-ZERO)

XFLOOR-1-CEIL
 ;	(CALL XFLOOR-BOTH-ARGS-FIXNUMS)  -- loses clobbers code in M-1.
 ;	(JUMP-NOT-EQUAL M-1 A-ZERO XFLOOR-1-ROUND)
	(jump-data-type-not-equal m-t (a-constant (byte-value q-data-type dtp-fix))
		xfloor-1-round)
	(jump-data-type-not-equal pdl-top (a-constant (byte-value q-data-type dtp-fix))
		xfloor-1-round)
	;; CEIL and TRUNC are the same if the arg signs don't match.
	((M-1) XOR PDL-TOP A-T)
	(JUMP-IF-BIT-SET BOXED-SIGN-BIT M-1 XFLOOR-1-TRUNC)
;Replace the dividend with dividend+divisor-1.  (This cannot change the sign).
;(Actually, it's hairier than that.  We change dividend to dividend+divisor
;and then move back by 1 toward the original dividend.
;The amount of change is thus |divisor|-1).
	((M-2) OUTPUT-SELECTOR-EXTEND-25 M-T)
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
	((M-1) ADD M-1 A-2)
	((M-1) SUB M-1 (A-CONSTANT 1))
	(JUMP-GREATER-THAN M-2 A-ZERO XFLOOR-1-CEIL-POSITIVE)
	((M-1) ADD M-1 (A-CONSTANT 2))
XFLOOR-1-CEIL-POSITIVE
	(CALL DIV)
		;DIVIDE CAN'T OVERFLOW EXCEPT FOR SETZ/-1
	((M-1) Q-R)
	(DISPATCH-POPJ-XCT-NEXT (I-ARG 0) 
	 (BYTE-FIELD 2 (DIFFERENCE Q-POINTER-WIDTH 1))
	 M-1 D-FXOVCK)
       ((M-T) DPB M-1 Q-POINTER (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))

XFLOOR-1-TRUNC
	((micro-stack-data-push) m-1)
	(CALL QIDIV)
	((M-1) MICRO-STACK-DATA-POP)
	(JUMP XFLOOR-1-A)

XFLOOR-1-FLOOR
;	(CALL XFLOOR-BOTH-ARGS-FIXNUMS)
;	(JUMP-NOT-EQUAL M-1 A-ZERO XFLOOR-1-ROUND)
	(jump-data-type-not-equal m-t (a-constant (byte-value q-data-type dtp-fix))
		xfloor-1-round)
	(jump-data-type-not-equal pdl-top (a-constant (byte-value q-data-type dtp-fix))
		xfloor-1-round)
	;; FLOOR and TRUNC are the same if the arg signs match.
	((M-1) XOR PDL-TOP A-T)
	(JUMP-IF-BIT-CLEAR BOXED-SIGN-BIT M-1 XFLOOR-1-TRUNC)
;Replace the dividend with dividend-divisor+1.  (This cannot change the sign).
	((M-2) OUTPUT-SELECTOR-EXTEND-25 M-T)
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
	((M-1) SUB M-1 A-2)
	((M-1) ADD M-1 (A-CONSTANT 1))
	(JUMP-GREATER-THAN M-2 A-ZERO XFLOOR-1-CEIL-POSITIVE)
	((M-1) SUB M-1 (A-CONSTANT 2))
	(JUMP XFLOOR-1-CEIL-POSITIVE)		;ok not to have rounding mode in M-1
	
;Given two args on the stack, return two values on the stack.
;The destination field only says how to round (floor vs ceil vs trunc vs round).
XFLOOR-2 (MISC-INST-ENTRY INTERNAL-FLOOR-2)
		;this should be only place destination is extracted.
	((M-1) MACRO-IR-DEST)
	(JUMP-EQUAL M-1 A-ZERO XFLOOR-2-A)
	((M-GARBAGE) MICRO-STACK-DATA-POP)	;Don't store in our destination.
XFLOOR-2-A
xfloor-2-uc-entry				;microcompiled code enters here.
	((M-T) Q-TYPED-POINTER PDL-POP)
				;MC-LINKAGE
	((M-A) PDL-TOP)
	((PDL-PUSH) M-A)
	((PDL-PUSH) M-T)
	((PDL-PUSH) M-A)
	(CALL XFLOOR-1-INTERNAL)
;Stack has empty slot, dividend, divisor.
;M-T has the quotient -- the correct first value of FLOOR.
;Put it in the empty slot.
	((PDL-INDEX) SUB PDL-POINTER (A-CONSTANT 2))
	((C-PDL-BUFFER-INDEX) M-T)
;Stack has 1st value, dividend, divisor.  M-T has 1st value (quotient).
;Multiply divisor and quotient, result on stack and in M-T.
	(CALL QIMUL)
	(PDL-POP)
;Subtract product from dividend, result on stack and in M-T.
	(JUMP QISUB)

;;; Generic division, producing rational result with integer arguments.
XDIV (MISC-INST-ENTRY %DIV)
	((M-T) Q-TYPED-POINTER C-PDL-BUFFER-POINTER-POP)
	((MICRO-STACK-DATA-PUSH) (A-CONSTANT (I-MEM-LOC POPTJ)))	;MC-LINKAGE
;Division, with args on stack and in M-T, value on stack.
QDIV		(ERROR-TABLE RESTART QDIV)
	(DISPATCH-XCT-NEXT Q-DATA-TYPE C-PDL-BUFFER-POINTER D-NUMARG1)
    (ERROR-TABLE ARGTYP NUMBER PP 0 QDIV)
    (ERROR-TABLE ARG-POPPED 0 PP M-T)
       ((M-A) (A-CONSTANT ARITH-2ARG-DIV))
		(ERROR-TABLE RESTART QDIV0)
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
	(DISPATCH Q-DATA-TYPE M-T D-FIXNUM-NUMARG2 (I-ARG NUMBER-CODE-FIXNUM))
    (ERROR-TABLE ARGTYP NUMBER M-T 1 QDIV0)
    (ERROR-TABLE ARG-POPPED 0 M-1 M-T)
	((M-2) OUTPUT-SELECTOR-EXTEND-25 M-T)
;The args are two fixnums, now unpacked in M-1 and M-2.  Second arg packed is in M-T.
	(JUMP-EQUAL M-1 A-ZERO QDIV-ZERO)
	(JUMP-EQUAL M-2 (A-CONSTANT 1) FIXPACK-P)
	(JUMP-GREATER-OR-EQUAL M-2 A-ZERO QDIV-SIGNS-RIGHT)
	((M-1) SUB M-ZERO A-1)
	((M-2) SUB M-ZERO A-2)
QDIV-SIGNS-RIGHT
	((M-B) M-1)
	((M-C) M-2)
;First just check to see if the result comes out even.
	(CALL DIV)
;(Remainder is in M-1, quotient in Q-R.)
	(JUMP-EQUAL-XCT-NEXT M-1 A-ZERO QDIV-EVEN)
;It doesn't, but save a step in the GCD by using this remainder instead of the first arg.
	((M-2) M-C)
	(CALL GCD-FIX-FIX)
	(JUMP-EQUAL-XCT-NEXT M-T (A-CONSTANT (PLUS (BYTE-VALUE Q-DATA-TYPE DTP-FIX) 1))
		QDIV-REL-PRIME)
       ((M-1) M-C)
;Get the denominator and the GCD in M-1 and M-2.  Save the GCD in M-D.
	((M-2) OUTPUT-SELECTOR-EXTEND-25 M-T)
	((M-D) M-2)
	(CALL DIV)
;Save denominator/gcd in M-E, and divide numerator by the gcd.
	((M-E) Q-R)
	((M-2) M-D)
	((M-1) M-B)
	(CALL DIV)
	((M-1) M-E)
;Now make a rational from numerator in Q-R and denominator in M-1.
QDIV-REL-PRIME-1
	(CALL FIXPACK-P)
	((M-1) Q-R)
	(CALL FIXPACK-P)
	(CALL MAKE-RATIONAL)
	(POPJ-AFTER-NEXT
	 (PDL-PUSH) M-T)
       (NO-OP)

QDIV-REL-PRIME
	(JUMP-XCT-NEXT QDIV-REL-PRIME-1)
       ((Q-R) M-B)

QDIV-ZERO
	(JUMP-XCT-NEXT FIXPACK-P)
       ((M-1) A-ZERO)

;Here if the division comes out even: return the quotient, as an integer.
QDIV-EVEN
	(JUMP-XCT-NEXT FIXPACK-P)	;DIVIDE CAN'T OVERFLOW EXCEPT FOR SETZ/-1
       ((M-1) Q-R)
	
XRATIO-CONS (MISC-INST-ENTRY %RATIO-CONS)
	((M-A) PDL-POP)
	((M-B) PDL-POP)
	((PDL-PUSH) M-A)
	((PDL-PUSH) M-B)

;Construct a rational from DENOMINATOR and NUMERATOR on the stack,
;and return it in M-T.  Notice that the args are not in the order you would expect!
MAKE-RATIONAL
     ;; Allocate 3 boxed words of structure storage in the number-cons area.
        ((m-b) (a-constant 3))
        (call-xct-next allocate-extended-number-storage)
       ((m-a) m-b)

	((VMA) ADD M-T (A-CONSTANT 1))		;Write the numerator.
	((MD-START-WRITE) PDL-POP)
	(CHECK-PAGE-WRITE)
	((WRITE-MEMORY-DATA) PDL-POP)
	((VMA-START-WRITE) ADD VMA (A-CONSTANT 1))
	(CHECK-PAGE-WRITE)
;Write the header word.
	((VMA M-T) Q-POINTER M-T
		(A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-EXTENDED-NUMBER)))
	(POPJ-AFTER-NEXT
	 (MD-START-WRITE)
	 (A-CONSTANT (PLUS (BYTE-VALUE Q-DATA-TYPE DTP-HEADER)
			   (BYTE-VALUE HEADER-TYPE-FIELD %HEADER-TYPE-RATIONAL)
			   0)))
       (CHECK-PAGE-WRITE)

;EQL is EQ, except = for numbers of matching type.
XEQL (MISC-INST-ENTRY EQL)
	((M-T) Q-TYPED-POINTER PDL-POP)
;Args in M-T and on stack.
XEQL1
	(JUMP-DATA-TYPE-NOT-EQUAL PDL-TOP A-T POP-THEN-XFALSE)
	(JUMP-DATA-TYPE-NOT-EQUAL M-T (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-EXTENDED-NUMBER))
		QMEQ)
;; Both args are extended numbers.
;; Are they the same kind?
	((VMA-START-READ) M-T)
	(CHECK-PAGE-READ)
	(DISPATCH TRANSPORT-HEADER MD)
	((M-1) Q-TYPED-POINTER MD)
	((VMA-START-READ) PDL-TOP)
	(CHECK-PAGE-READ)
	(DISPATCH TRANSPORT-HEADER MD)
	((M-2) Q-TYPED-POINTER MD)
	(JUMP-NOT-EQUAL M-1 A-2 POP-THEN-XFALSE)
;; Yes.  Do numeric comparison.
;; Not quite the same as =, because for complex numbers
;; EQL is T only if the types of the components match.	
    (ERROR-TABLE RESTART XEQL)
	(DISPATCH-XCT-NEXT Q-DATA-TYPE C-PDL-BUFFER-POINTER D-NUMARG1)
    (ERROR-TABLE ARGTYP NUMBER PP 0 XEQL)
    (ERROR-TABLE ARG-POPPED 0 PP M-T)
       ((M-A) (A-CONSTANT ARITH-2ARG-EQL))
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
	(JUMP XEQL2)

;;; Generic numeric equality (the "=" function).
XMEQL (MISC-INST-ENTRY M-=)
	((M-T) Q-TYPED-POINTER C-PDL-BUFFER-POINTER-POP)
QMEQL					    ;MC-LINKAGE
QIEQL		(ERROR-TABLE RESTART QIEQL)
	(DISPATCH-XCT-NEXT Q-DATA-TYPE C-PDL-BUFFER-POINTER D-NUMARG1)
    (ERROR-TABLE ARGTYP NUMBER PP 0 QIEQL)
    (ERROR-TABLE ARG-POPPED 0 PP M-T)
       ((M-A) (A-CONSTANT ARITH-2ARG-EQUAL))
		(ERROR-TABLE RESTART QIEQL0)
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
XEQL2 ;; Enter from EQL, with ARITH-2ARG-EQL in M-A.
	(DISPATCH Q-DATA-TYPE M-T D-FIXNUM-NUMARG2 (I-ARG NUMBER-CODE-FIXNUM))
    (ERROR-TABLE ARGTYP NUMBER M-T 1 QIEQL0)
    (ERROR-TABLE ARG-POPPED 0 M-1 M-T)
	((M-2) OUTPUT-SELECTOR-EXTEND-25 M-T)
	((M-T) A-V-NIL)
	(POPJ-AFTER-NEXT POPJ-NOT-EQUAL M-1 A-2)
       ((M-T) A-V-TRUE)

;;; Generic numeric GREATERP
XMGRTH (MISC-INST-ENTRY M->)
	((M-T) Q-TYPED-POINTER C-PDL-BUFFER-POINTER-POP)
QMGRP					     ;MC-LINKAGE
QIGRP		(ERROR-TABLE RESTART QIGRP)
	(DISPATCH-XCT-NEXT Q-DATA-TYPE C-PDL-BUFFER-POINTER D-NUMARG1)
    (ERROR-TABLE ARGTYP NUMBER PP 0 QIGRP)
    (ERROR-TABLE ARG-POPPED 0 PP M-T)
       ((M-A) (A-CONSTANT ARITH-2ARG-GREATERP))
		(ERROR-TABLE RESTART QIGRP0)
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
	(DISPATCH Q-DATA-TYPE M-T D-FIXNUM-NUMARG2 (I-ARG NUMBER-CODE-FIXNUM))
    (ERROR-TABLE ARGTYP NUMBER M-T 1 QIGRP0)
    (ERROR-TABLE ARG-POPPED 0 M-1 M-T)
	((M-2) OUTPUT-SELECTOR-EXTEND-25 M-T)
	((M-T) A-V-NIL)
	(POPJ-AFTER-NEXT POPJ-LESS-OR-EQUAL M-1 A-2)
       ((M-T) A-V-TRUE)

;;; Generic numeric LESSP
XMLESS (MISC-INST-ENTRY M-<)
	((M-T) Q-TYPED-POINTER C-PDL-BUFFER-POINTER-POP)
QMLSP					      ;MC-LINKAGE
QILSP		(ERROR-TABLE RESTART QILSP)
	(DISPATCH-XCT-NEXT Q-DATA-TYPE C-PDL-BUFFER-POINTER D-NUMARG1)
    (ERROR-TABLE ARGTYP NUMBER PP 0 QILSP)
    (ERROR-TABLE ARG-POPPED 0 PP M-T)
       ((M-A) (A-CONSTANT ARITH-2ARG-LESSP))
		(ERROR-TABLE RESTART QILSP0)
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
	(DISPATCH Q-DATA-TYPE M-T D-FIXNUM-NUMARG2 (I-ARG NUMBER-CODE-FIXNUM))
    (ERROR-TABLE ARGTYP NUMBER M-T 1 QILSP0)
    (ERROR-TABLE ARG-POPPED 0 M-1 M-T)
	((M-2) OUTPUT-SELECTOR-EXTEND-25 M-T)
	((M-T) A-V-NIL)
	(POPJ-AFTER-NEXT POPJ-GREATER-OR-EQUAL M-1 A-2)
       ((M-T) A-V-TRUE)

XMAX (MISC-INST-ENTRY *MAX)
	((M-T) Q-TYPED-POINTER C-PDL-BUFFER-POINTER-POP)
		(ERROR-TABLE RESTART XMAX)
	(DISPATCH-XCT-NEXT Q-DATA-TYPE C-PDL-BUFFER-POINTER D-NUMARG1)
    (ERROR-TABLE ARGTYP NUMBER PP 0 XMAX)
    (ERROR-TABLE ARG-POPPED 0 PP M-T)
       ((M-A) (A-CONSTANT ARITH-2ARG-MAX))
		(ERROR-TABLE RESTART XMAX0)
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
	(DISPATCH Q-DATA-TYPE M-T D-FIXNUM-NUMARG2 (I-ARG NUMBER-CODE-FIXNUM))
    (ERROR-TABLE ARGTYP NUMBER M-T 1 XMAX0)
    (ERROR-TABLE ARG-POPPED 0 M-1 M-T)
	((M-2) OUTPUT-SELECTOR-EXTEND-25 M-T)
	(JUMP-GREATER-OR-EQUAL M-1 A-2 FIXPACK-T)
	((M-1) A-2)
	(DISPATCH-POPJ-XCT-NEXT (I-ARG 0) 
	 (BYTE-FIELD 2 (DIFFERENCE Q-POINTER-WIDTH 1))
	 M-1 D-FXOVCK)
       ((M-T) DPB M-1 Q-POINTER (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))

XMIN (MISC-INST-ENTRY *MIN)
	((M-T) Q-TYPED-POINTER C-PDL-BUFFER-POINTER-POP)
		(ERROR-TABLE RESTART XMIN)
	(DISPATCH-XCT-NEXT Q-DATA-TYPE C-PDL-BUFFER-POINTER D-NUMARG1)
    (ERROR-TABLE ARGTYP NUMBER PP 0 XMIN)
    (ERROR-TABLE ARG-POPPED 0 PP M-T)
       ((M-A) (A-CONSTANT ARITH-2ARG-MIN))
		(ERROR-TABLE RESTART XMIN0)
	((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP)
	(DISPATCH Q-DATA-TYPE M-T D-FIXNUM-NUMARG2 (I-ARG NUMBER-CODE-FIXNUM))
    (ERROR-TABLE ARGTYP NUMBER M-T 1 XMIN0)
    (ERROR-TABLE ARG-POPPED 0 M-1 M-T)
	((M-2) OUTPUT-SELECTOR-EXTEND-25 M-T)
	(JUMP-LESS-OR-EQUAL M-1 A-2 FIXPACK-T)
	((M-1) A-2)
	(DISPATCH-POPJ-XCT-NEXT (I-ARG 0) 
	 (BYTE-FIELD 2 (DIFFERENCE Q-POINTER-WIDTH 1))
	 M-1 D-FXOVCK)
       ((M-T) DPB M-1 Q-POINTER (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))


;;; Data-type dispatches for arithmetic.

;;; Dispatch on the type of a one-argument numeric function.
;;; DTP-FIX unpacks and then drops through; eveything else jumps.
;;; On LAMBDA, DTP-FIX does nothing and drops thru.
(LOCALITY D-MEM)
(START-DISPATCH 5 0)
D-NUMARG
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;TRAP
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;NULL
	(P-BIT INHIBIT-XCT-NEXT-BIT UNRECONCILED-ILLOP)	;UNRECONCILED
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;SYMBOL
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;SYMBOL HEADER
#+cadr	(P-BIT FXUNPK-P-1)			;FIX
#+lambda(P-BIT R-BIT)
#+exp   (P-BIT R-BIT)
	(ARITH-XNM)				;EXTENDED NUMBER
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;HEADER
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;GC-FORWARD
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;EXTERNAL-VALUE-CELL-POINTER
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;ONE-Q-FORWARD
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;HEADER-FORWARD
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;BODY-FORWARD
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;LOCATIVE
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;LIST
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;U CODE ENTRY
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;FEF
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;ARRAY-POINTER
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;ARRAY-HEADER
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;STACK-GROUP
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;CLOSURE
	(ARITH-SFL)				;SMALL-FLONUM
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;SELECT-METHOD
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;INSTANCE
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;INSTANCE-HEADER
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;ENTITY
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;STACK-CLOSURE
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;SELF-REF-POINTER
#+cadr	(P-BIT FXUNPK-P-1)			;CHARACTER
#+lambda(P-BIT R-BIT)
#+exp	(P-BIT R-BIT)
        (p-bit n-bit illop)	;rplacd-forward
 (REPEAT NQZUSD (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP))
(END-DISPATCH)

;;; Dispatch on the type of the first numeric arg.
;;; DTP-FIX unpacks and then drops through; eveything else jumps.
;;; On LAMBDA, DTP-FIX just drops thru.
(START-DISPATCH 5 0)
D-NUMARG1
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;TRAP
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;NULL
	(P-BIT INHIBIT-XCT-NEXT-BIT UNRECONCILED-ILLOP)	;UNRECONCILED
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;SYMBOL
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;SYMBOL HEADER
#+cadr	(P-BIT FXUNPK-P-1)			;FIX
#+lambda(P-BIT R-BIT)
#+exp	(P-BIT R-BIT)
	(ARITH-XNM-ANY)				;EXTENDED NUMBER
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;HEADER
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;GC-FORWARD
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;EXTERNAL-VALUE-CELL-POINTER
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;ONE-Q-FORWARD
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;HEADER-FORWARD
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;BODY-FORWARD
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;LOCATIVE
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;LIST
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;U CODE ENTRY
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;FEF
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;ARRAY-POINTER
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;ARRAY-HEADER
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;STACK-GROUP
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;CLOSURE
	(ARITH-SFL-ANY)				;SMALL-FLONUM
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;SELECT-METHOD
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;INSTANCE
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;INSTANCE-HEADER
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;ENTITY
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;STACK-CLOSURE
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;SELF-REF-POINTER
#+CADR	(P-BIT FXUNPK-P-1)			;CHARACTER
#+LAMBDA(P-BIT R-BIT)
#+exp	(P-BIT R-BIT)
        (p-bit n-bit illop)	;rplacd-forward
 (REPEAT NQZUSD (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP))
(END-DISPATCH)

;;; Data type dispatch on second numeric arg, when first one was a DTP-FIXNUM.
;;; DTP-FIXNUM unpacks and drops through; everything else jumps.  First arg
;;; is unpacked into M-1.  Second arg in M-T.
;;; On LAMBDA, DTP-FIX just drops thru.
(START-DISPATCH 5 0)
D-FIXNUM-NUMARG2
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;TRAP
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;NULL
	(P-BIT INHIBIT-XCT-NEXT-BIT UNRECONCILED-ILLOP)	;UNRECONCILED
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;SYMBOL
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;SYMBOL HEADER
#+CADR	(P-BIT INHIBIT-XCT-NEXT-BIT FXUNPK-T-2)	;FIX
#+LAMBDA(P-BIT R-BIT)
#+exp	(P-BIT R-BIT)
	(INHIBIT-XCT-NEXT-BIT ARITH-ANY-XNM)	;EXTENDED NUMBER
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;HEADER
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;GC-FORWARD
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;EXTERNAL-VALUE-CELL-POINTER
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;ONE-Q-FORWARD
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;HEADER-FORWARD
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;BODY-FORWARD
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;LOCATIVE
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;LIST
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;U CODE ENTRY
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;FEF
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;ARRAY-POINTER
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;ARRAY-HEADER
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;STACK-GROUP
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;CLOSURE
	(INHIBIT-XCT-NEXT-BIT ARITH-FIX-SFL)	;SMALL-FLONUM
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;SELECT-METHOD
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;INSTANCE
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;INSTANCE-HEADER
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;ENTITY
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;STACK-CLOSURE
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;SELF-REF-POINTER
#+CADR	(P-BIT INHIBIT-XCT-NEXT-BIT FXUNPK-T-2)	;CHARACTER
#+LAMBDA(P-BIT R-BIT)
#+exp	(P-BIT R-BIT)
        (p-bit n-bit illop)	                ;rplacd-forward
 (REPEAT NQZUSD (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP))
(END-DISPATCH)

;;; Data type dispatch for second numeric arg when first was NOT DTP-FIXNUM
;;; DTP-SMALL-FLONUM unpacks and drops through; everything else jumps.
;;; During this dispatch, the I-ARG contains a number code.
;;; The first arg has been unpacked as follows:
;;;  If BIGNUM, M-Q has BIGNUM pointer, M-C HEADER, M-I LENGTH.
;;;  If FLONUM, M-Q has FLONUM pointer, M-C HEADER, M-I exponent, M-1 mantissa.
;;;  If SMALL-FLONUM, M-Q has SMALL-FLONUM pointer, M-I has exponent, M-1 mantissa.
;;;  Also, the original pointer is kept in M-J.
(START-DISPATCH 5 0)
D-NUMARG2
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;TRAP
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;NULL
	(P-BIT INHIBIT-XCT-NEXT-BIT UNRECONCILED-ILLOP)	;UNRECONCILED
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;SYMBOL
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;SYMBOL HEADER
	(ARITH-ANY-FIX)				;FIX
	(ARITH-ANY-XNM)				;EXTENDED NUMBER
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;HEADER
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;GC-FORWARD
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;EXTERNAL-VALUE-CELL-POINTER
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;ONE-Q-FORWARD
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;HEADER-FORWARD
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;BODY-FORWARD
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;LOCATIVE
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;LIST
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;U CODE ENTRY
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;FEF
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;ARRAY-POINTER
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;ARRAY-HEADER
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;STACK-GROUP
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;CLOSURE
	(P-BIT SFLUNPK-T-2)			;SMALL-FLONUM
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;SELECT-METHOD
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;INSTANCE
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;INSTANCE-HEADER
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;ENTITY
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;STACK-CLOSURE
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;SELF-REF-POINTER
	(ARITH-ANY-FIX)				;CHARACTER
        (p-bit n-bit illop)	                ;rplacd-forward
 (REPEAT NQZUSD (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP))
(END-DISPATCH)
(LOCALITY I-MEM)

;;; One-argument function.
ARITH-SFL
	(CALL SFLUNPK-P-1)
	(DISPATCH (BYTE-FIELD 4 0) M-A D-FLONUM-1ARG)
       ((MICRO-STACK-DATA-PUSH) (A-CONSTANT (I-MEM-LOC SFLPACK-T)))

ARITH-XNM
	((VMA-START-READ M-I) C-PDL-BUFFER-POINTER-POP)
	(CHECK-PAGE-READ)
	(DISPATCH TRANSPORT-HEADER READ-MEMORY-DATA)
	((M-Q) VMA)		;get transported number address 
	(CALL-DATA-TYPE-NOT-EQUAL MD (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-HEADER)) ILLOP)
	(DISPATCH-XCT-NEXT HEADER-TYPE-FIELD MD D-XNM-ARG)
       ((M-C) HEADER-REST-FIELD MD)

(LOCALITY D-MEM)
(START-DISPATCH 5 0)
D-XNM-ARG
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;%HEADER-TYPE-ERROR
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;%HEADER-TYPE-FEF
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;%HEADER-TYPE-ARRAY-LEADER
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;%HEADER-TYPE-UNUSED
	(ARITH-FLO)				;%HEADER-TYPE-FLONUM
	(ARITH-OUT)				;%HEADER-TYPE-COMPLEX
	(ARITH-BIG)				;%HEADER-TYPE-BIGNUM
	(ARITH-OUT)				;%HEADER-TYPE-RATIONAL
        (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;%HEADER-TYPE-FAST-FEF-FIXED-ARGS-NO-LOCALS
        (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;%HEADER-TYPE-FAST-FEF-VAR-ARGS-NO-LOCALS
        (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;%HEADER-TYPE-FAST-FEF-FIXED-ARGS-WITH-LOCALS
        (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;%HEADER-TYPE-FAST-FEF-VAR-ARGS-WITH-LOCALS
 (REPEAT NUM-UNUSED-HEADER-TYPES (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP))
(END-DISPATCH)
(LOCALITY I-MEM)

ARITH-FLO
	((VMA-START-READ) ADD M-Q (A-CONSTANT 1))
	(CHECK-PAGE-READ)
	((M-I) HEADER-FLONUM-EXPONENT M-C)
	((M-1) DPB M-C FLONUM-HEADER-HIGH-MANTISSA A-ZERO)
	((M-1) SELECTIVE-DEPOSIT MD FLONUM-HEADER-LOW-MANTISSA A-1)
	(DISPATCH (BYTE-FIELD 4 0) M-A D-FLONUM-1ARG)
       ((MICRO-STACK-DATA-PUSH) (A-CONSTANT (I-MEM-LOC FLOPACK-T)))

;; Call out to macro-code.
ARITH-OUT
	(CALL P3ZERO)
	((ARG-CALL REF-SUPPORT-VECTOR) (I-ARG SVC-NUM1))
	(DISPATCH TRANSPORT MD)
	((C-PDL-BUFFER-POINTER-PUSH) READ-MEMORY-DATA)	;Push function
	((C-PDL-BUFFER-POINTER-PUSH)		;Push the function code.
		Q-POINTER M-A (A-CONSTANT (PLUS (BYTE-VALUE Q-CDR-CODE CDR-NEXT)
						(BYTE-VALUE Q-DATA-TYPE DTP-FIX))))
	((C-PDL-BUFFER-POINTER-PUSH)		;Push the number.
		Q-TYPED-POINTER M-I (A-CONSTANT (BYTE-VALUE Q-CDR-CODE CDR-NIL)))
	((ARG-JUMP MMJCALL) (I-ARG 2))		;Call tail-recursively.

;;; This dispatch SOMETIMES executes next: viz., when the result will be a number.
;;; Dispatchers can push a PACK routine in the xct-next cycle.
(LOCALITY D-MEM)
(START-DISPATCH 4 0)
D-FLONUM-1ARG
	(FLONUM-ABS)
	(FLONUM-MINUS)
	(INHIBIT-XCT-NEXT-BIT FLONUM-ZEROP)
	(INHIBIT-XCT-NEXT-BIT FLONUM-PLUSP)
	(INHIBIT-XCT-NEXT-BIT FLONUM-MINUSP)
	(FLONUM-ADD1)
	(FLONUM-SUB1)
	(INHIBIT-XCT-NEXT-BIT FLONUM-FIX)
	(INHIBIT-XCT-NEXT-BIT FLOPACK-T)
	(INHIBIT-XCT-NEXT-BIT SFLPACK-T)
	(P-BIT INHIBIT-XCT-NEXT-BIT XHAULFLO)	;HAULONG DOESN'T WORK FOR FLONUMS
	(P-BIT INHIBIT-XCT-NEXT-BIT XHAULFLO)	;LDB DOESNT EITHER.
	(P-BIT INHIBIT-XCT-NEXT-BIT XHAULFLO)	;NOR DPB.
	(FLONUM-ASH)				;ASH OF A FLONUM = FSC
	(P-BIT INHIBIT-XCT-NEXT-BIT XHAULFLO)	;ODDP ILLEGAL
	(P-BIT INHIBIT-XCT-NEXT-BIT XHAULFLO)	;EVENP ILLEGAL
 (REPEAT NUM-UNUSED-ARITH-1ARGS (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP))
(END-DISPATCH)
(LOCALITY I-MEM)


FLONUM-ABS
	(POPJ-IF-BIT-CLEAR FLONUM-SIGN-BIT M-1)
	(JUMP FNEG1)

;FLONUM-MINUS is the same as FNEG1, see below.

;FLONUM-ZEROP, FLONUM-PLUSP and FLONUM-MINUSP are up with the fixnum cases,
;see above.

FLONUM-ADD1
	((M-2) DPB M-MINUS-ONE MANTISSA-HIGH-BIT A-ZERO);10_33
	(JUMP-XCT-NEXT FADD)
       ((M-J) M+A+1 M-ZERO (A-CONSTANT 2000))		;2001

FLONUM-SUB1
	((M-2) DPB M-MINUS-ONE FLONUM-SIGN-BIT A-ZERO)	;20_33
	(JUMP-XCT-NEXT FADD)
       ((M-J) (A-CONSTANT 2000))			;2000

FLONUM-FIX
	(DISPATCH ARITH-FIX-ROUNDING-MODE-FIELD M-A D-FLONUM-FIX)

(LOCALITY D-MEM)
(START-DISPATCH 2 INHIBIT-XCT-NEXT-BIT)
D-FLONUM-FIX
	(FLONUM-FIX-FLOOR)
	(FLONUM-FIX-CEIL)
	(FLONUM-FIX-TRUNC)
	(FLONUM-FIX-ROUND)
(END-DISPATCH)
(LOCALITY I-MEM)

FLONUM-FIX-ROUND
	((M-TEM) SUB M-I (A-CONSTANT 2000))	;Number of bits before binary point.
	;; If expt is so big that there are no fractional bits left, just take floor.
	(JUMP-LESS-OR-EQUAL (M-CONSTANT 40) A-TEM FLONUM-FIX-FLOOR)
	;; If -.5 <= x < .5, just go return zero -- the binary point is outside the word.
	(JUMP-LESS-THAN M-TEM A-ZERO FLONUM-FIX-ZERO)
	((M-TEM) SUB (M-CONSTANT 40) A-TEM)
	((M-TEM) SUB M-TEM (A-CONSTANT 2))	;Number of bits to right of binary point, -1.
;M-TEM has position (from bottom).
	((OA-REG-LOW) oal-mrot m-TEM)
		;M-2 gets a 1 in first bit after binary point.
	((M-2) DPB (Byte-Field 1 0) M-MINUS-ONE A-ZERO)
;What follows is like FADD2, except that we clear out Q to prevent rounding up.
	((M-1) ADD M-1 A-2 OUTPUT-SELECTOR-RIGHTSHIFT-1	;Do the add, collect
		SHIFT-Q-RIGHT)	; the overflow, discarded bits to Q
	((Q-R) A-ZERO)
	(CALL FNORM)
;Now see if it's exactly an integer (that is, if it was exactly half way between before)
;Note M-I may be different now.
	((M-TEM) SUB M-I (A-CONSTANT 2000))	;Number of bits before binary point.
	(JUMP-LESS-OR-EQUAL (M-CONSTANT 40) A-TEM FLONUM-FIX-FLOOR)
	;; If -.5 <= x < .5 NOW, then the floor is certainly right.
	(JUMP-LESS-THAN M-TEM A-ZERO FLONUM-FIX-FLOOR)
	((M-TEM) SUB (M-CONSTANT 40) A-TEM)
		;Number of bits to right of binary point, -1.
	((M-TEM) SUB M-TEM (A-CONSTANT 2))
#+exp	((m-tem3) add m-tem (a-constant 1))
	((OA-REG-LOW) DPB #+lambda M-TEM #+exp m-tem3 A-ZERO OAL-BYTL-1)
       ((M-2) BYTE-INST M-1 A-ZERO)
	(JUMP-NOT-EQUAL M-2 A-ZERO FLONUM-FIX-FLOOR)
;If it is an exact integer,
;clear out the bit just before the binary point to make the result even.
;However, the integer -1.0 must be treated specially since in that case
;the only bit before the binary point is the sign bit and clearing it gives 0, not -2.0!
	(JUMP-EQUAL M-I (A-CONSTANT 2000) FLONUM-FIX-ROUND-MINUS-ONE)
#+exp	((m-tem3) add m-tem (a-constant 1))
#+exp	((oa-reg-low) oal-mrot m-tem3)
#+lambda((OA-REG-LOW) ADD M-TEM (A-CONSTANT 1))
       ((M-1) DPB (Byte-Field 1 0) M-ZERO A-1)
	(JUMP FLONUM-FIX-FLOOR)

FLONUM-FIX-CEIL-SMALL
	(JUMP-LESS-OR-EQUAL M-1 A-ZERO FLONUM-FIX-ZERO)
FLONUM-FIX-ONE
	(POPJ-AFTER-NEXT)
       ((M-T) (A-CONSTANT (PLUS (BYTE-VALUE Q-DATA-TYPE DTP-FIX) 1)))

FLONUM-FIX-ZERO
	(POPJ-AFTER-NEXT)
       ((M-T) (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))
	
;Change -1.0 into -2.0.
FLONUM-FIX-ROUND-MINUS-ONE
	((M-I) ADD M-I (A-CONSTANT 1))
	(JUMP FLONUM-FIX-FLOOR)

FLONUM-FIX-TRUNC
;TRUNC is FLOOR for positive numbers, CEIL for negative ones.
	(JUMP-IF-BIT-CLEAR FLONUM-SIGN-BIT M-1 FLONUM-FIX-FLOOR)
FLONUM-FIX-CEIL
;Add .99999999 to the number, then take the floor.
	((M-TEM) SUB M-I (A-CONSTANT 2000))	;Number of bits before binary point.
	;; If expt is so big that there are no fractional bits left, just take floor.
	(JUMP-LESS-OR-EQUAL (M-CONSTANT 40) A-TEM FLONUM-FIX-FLOOR)
	;; If -5. <= x < .5, just return 0 or 1 according to sign.
	;; The normal path would lose since the highest fractional bit doesn't exist.
	(JUMP-LESS-THAN M-TEM A-ZERO FLONUM-FIX-CEIL-SMALL)
	((M-TEM) SUB (M-CONSTANT 40) A-TEM)
		;Number of bits to right of binary point, -1.
	((M-TEM) SUB M-TEM (A-CONSTANT 2))
#+exp	((m-tem3) add m-tem (a-constant 1))
	((OA-REG-LOW) DPB #+lambda M-TEM #+exp m-tem3 OAL-BYTL-1 A-ZERO)
	((M-2) DPB M-MINUS-ONE A-ZERO)
;What follows is like FADD2, except that we clear out Q to prevent rounding up.
	((M-1) ADD M-1 A-2 OUTPUT-SELECTOR-RIGHTSHIFT-1	;Do the add, collect
		SHIFT-Q-RIGHT)	; the overflow, discarded bits to Q
	((Q-R) A-ZERO)
	(CALL FNORM)
FLONUM-FIX-FLOOR
	((m-t) flonum-sign-bit m-1)			;M-T gets 0 if arg positive,
	((oa-reg-high) oah-m-src m-t)			;return 0 or -1 if fractional
       ((m-t) ldb q-pointer m-zero (a-constant (byte-value q-data-type dtp-fix)))
	(POPJ-LESS-OR-EQUAL M-I (A-CONSTANT 2000))
		;jump if big enough to be bignum
	(JUMP-GREATER-OR-EQUAL M-I (A-CONSTANT (PLUS 2000 Q-POINTER-WIDTH)) FLONUM-BIGFIX)
		;Byte length - 1 (maximum byte length 23.)
	((M-A) M-A-1 M-I (A-CONSTANT 2000))
	((M-B) ADD M-A (A-CONSTANT 2))		;Leftward rotation of M-1.
#+exp	((m-tem3) add m-a (a-constant 1))
	(POPJ-AFTER-NEXT (OA-REG-LOW) DPB #+lambda M-A #+exp m-tem3 OAL-BYTL-1 A-B)
       ((M-T) (BYTE-FIELD 0 0) M-1 A-T)		;A boxed signed fixnum!

FLONUM-BIGFIX
	((M-C) DPB M-T BIGNUM-HEADER-SIGN A-ZERO)	;Save sign
	(CALL FLONUM-ABS)
	((M-4) M-1)				;Save magnitude of mantissa
	((M-1) SUB M-I (A-CONSTANT (DIFFERENCE 2000 30.)))	;Compute bignum length
	(CALL-XCT-NEXT DIV)			;Q-R gets number of words,
       ((M-2) (A-CONSTANT 31.))			;M-1 gets bits minus one in last word
	((M-2) M-4)				;Restore mantissa magnitude
	((M-I) Q-R)				;Bignum length
	(CALL-XCT-NEXT BNCONS)			;Allocate a bignum result
       ((M-B) ADD Q-R (A-CONSTANT 1))
	((M-3) SUB M-I (A-CONSTANT 2))		;Zero out all but high 2 words of bignum
	(JUMP-LESS-OR-EQUAL M-3 A-ZERO FLONUM-BIGFIX1)
	((WRITE-MEMORY-DATA) M-ZERO)
FLONUM-BIGFIX0
	((VMA-START-WRITE) ADD M-T A-3)
	(CHECK-PAGE-WRITE)
	(JUMP-GREATER-THAN-XCT-NEXT M-3 (A-CONSTANT 1) FLONUM-BIGFIX0)
       ((M-3) SUB M-3 (A-CONSTANT 1))
FLONUM-BIGFIX1
	((M-3) ADD M-1 (A-CONSTANT 2))		;Get high-order word of result
		;[Right-justify high (M-1)+1 bits of 31.]
#+exp	((m-tem3) add m-1 (a-constant 1))
	((OA-REG-LOW) DPB #+lambda M-1 #+exp m-tem3 OAL-BYTL-1 A-3)
	((WRITE-MEMORY-DATA) (BYTE-FIELD 0 0) M-2)
	((VMA-START-WRITE) ADD M-T A-I)
	(CHECK-PAGE-WRITE)
	(JUMP-LESS-THAN M-I (A-CONSTANT 2) BIGNUM-DPB-CLEANUP)	;No low-order word
		;Get low-order word (may be garbage)
	((M-3) M-A-1 (M-CONSTANT 32.) A-3)
	((M-1) ADD M-1 (A-CONSTANT 1))		;[Left-justify low 30.-(M-1) bits in 31.]
#+exp	((m-tem3) add m-3 (a-constant 1))
	((OA-REG-LOW) DPB #+lambda M-3 #+exp m-tem3 OAL-BYTL-1 A-1)
	((WRITE-MEMORY-DATA) DPB M-2 (BYTE-FIELD 0 0) A-ZERO)
	((VMA-START-WRITE) SUB VMA (A-CONSTANT 1))
	(CHECK-PAGE-WRITE)
	(JUMP BIGNUM-DPB-CLEANUP)		;Might really be a fixnum after all! (SETZ)

;;; Two-argument functions.

;;; The first arg, which is on the PDL, is a SMALL-FLONUM.  ARITH-2ARG is in M-A.
ARITH-SFL-ANY		(ERROR-TABLE RESTART ARITH-SFL-ANY)
	((M-Q) Q-TYPED-POINTER C-PDL-BUFFER-POINTER)	;Save arg in case error.
	((M-J) M-Q)			;Save arg in case of call-out.
	(DISPATCH-XCT-NEXT Q-DATA-TYPE M-T D-NUMARG2 (I-ARG NUMBER-CODE-SMALL-FLONUM))
    (ERROR-TABLE ARGTYP NUMBER M-T 1 ARITH-SFL-ANY)
       (CALL SFLUNPK-P-1)
	;; If it comes back here, both flonums are unpacked.
	(DISPATCH (BYTE-FIELD 4 0) M-A D-FORWARD-FLONUM-OPS)
    (ERROR-TABLE ARGTYP INTEGER M-T 1)	;not easily continuable
    (ERROR-TABLE ARG-POPPED 0 M-Q M-T)
       ((MICRO-STACK-DATA-PUSH) (A-CONSTANT (I-MEM-LOC SFLPACK-P)))

;;; Second arg was a fixnum, but first wasn't.
;;; I-ARG contains type of first argument, M-A contains operation.
ARITH-ANY-FIX
	(DISPATCH-XCT-NEXT (BYTE-FIELD 3 0) READ-I-ARG D-ARITH-ANY-FIX)
       ((M-2) OUTPUT-SELECTOR-EXTEND-25 M-T)

(LOCALITY D-MEM)
(START-DISPATCH 3 0)
D-ARITH-ANY-FIX
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;FIX, SHOULN'T GET HERE.
	(ARITH-SFL-FIX)				;SMALL FLONUM
	(ARITH-FLO-FIX)				;FLONUM
	(ARITH-BIG-FIX)				;BIGNUM
 (REPEAT NUM-UNUSED-NUMBER-CODES (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP))
(END-DISPATCH)
(LOCALITY I-MEM)

;;; First arg is a fixnum unpacked.  Second arg is a small flonum, packed.
ARITH-FIX-SFL
	(CALL-XCT-NEXT SFLUNPK-T-2)
       ((M-I) (A-CONSTANT 2036))
	(CALL-XCT-NEXT FNORM)
       ((Q-R) M-ZERO)
	(DISPATCH (BYTE-FIELD 4 0) M-A D-FORWARD-FLONUM-OPS)
    (ERROR-TABLE ARGTYP INTEGER M-T 1)
    (ERROR-TABLE ARG-POPPED 0 M-1 M-T)
       ((MICRO-STACK-DATA-PUSH) (A-CONSTANT (I-MEM-LOC SFLPACK-P)))

;;; We have a small flonum in M-1,M-I and a fixnum in M-2.
;;; Reverse the order, normalize the fixnum to a flonum, and call reverse operator.
ARITH-SFL-FIX
	((M-TEM) M-2)
	((M-2) M-1)
	((M-1) M-TEM)
	((M-J) M-I)
	((Q-R) M-ZERO)
	(CALL-XCT-NEXT FNORM)
       ((M-I) (A-CONSTANT 2036))
	(DISPATCH (BYTE-FIELD 4 0) M-A D-REVERSE-FLONUM-OPS)
    (ERROR-TABLE FLONUM-NO-GOOD)	;ARGTYP not usable, arg not saved
    (ERROR-TABLE ARG-POPPED 0 M-Q M-T)
       ((MICRO-STACK-DATA-PUSH) (A-CONSTANT (I-MEM-LOC SFLPACK-P)))

;;; We have a flonum in M-1/M-I and a fixnum in M-2.  This is just like the above.
ARITH-FLO-FIX
	((M-TEM) M-2)
	((M-2) M-1)
	((M-1) M-TEM)
	((M-J) M-I)
	((Q-R) M-ZERO)
	(CALL-XCT-NEXT FNORM)
       ((M-I) (A-CONSTANT 2036))
	(DISPATCH (BYTE-FIELD 4 0) M-A D-REVERSE-FLONUM-OPS)
    (ERROR-TABLE FLONUM-NO-GOOD)	;ARGTYP not usable, arg not saved
    (ERROR-TABLE ARG-POPPED M-Q M-T)
       ((MICRO-STACK-DATA-PUSH) (A-CONSTANT (I-MEM-LOC FLOPACK-P)))

;;; Routines that look at the contents of M-A and act on it.

(LOCALITY D-MEM)
(START-DISPATCH 4 0)
D-FORWARD-FLONUM-OPS
	(FADD)			;ADD
	(FSUB)			;SUB
	(FMPY)			;MUL
	(FDIV)			;IDIV
	(INHIBIT-XCT-NEXT-BIT FEQL)	;=
	(INHIBIT-XCT-NEXT-BIT FGRP)	;>
	(INHIBIT-XCT-NEXT-BIT FLSP)	;<
	(FMIN)			;MIN
	(FMAX)			;MAX
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;BOOLE
	(FDIV)			;DIV
	(INHIBIT-XCT-NEXT-BIT FEQL)	;EQL
 (REPEAT NUM-UNUSED-ARITH-2ARGS (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP))
(END-DISPATCH)

(START-DISPATCH 4 0)
D-REVERSE-FLONUM-OPS
	(FADD)			;REVERSE ADD
	(FSUB-REVERSE)		;REVERSE SUB
	(FMPY)			;REVERSE MPY
	(FDIV-REVERSE)		;REVERSE IDIVIDE
	(INHIBIT-XCT-NEXT-BIT FEQL)	;REVERSE =
	(INHIBIT-XCT-NEXT-BIT FLSP)	;REVERSE >
	(INHIBIT-XCT-NEXT-BIT FGRP)	;REVERSE <
	(FMIN)			;REVERSE MIN
	(FMAX)			;REVERSE MAX
	(P-BIT INHIBIT-XCT-NEXT-BIT TRAP)	;BOOLE
	(FDIV-REVERSE)		;REVERSE DIVIDE
	(INHIBIT-XCT-NEXT-BIT FEQL)	;REVERSE EQL
(REPEAT NUM-UNUSED-ARITH-2ARGS (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP))
(END-DISPATCH)
(LOCALITY I-MEM)

FSUB-REVERSE
	(JUMP-XCT-NEXT FADD)
       (CALL FNEG1)

FDIV-REVERSE
	(JUMP-XCT-NEXT FDIV)
       (CALL SWAP-FLONUMS)

SWAP-FLONUMS
	((M-TEM) M-I)
	((M-I) M-J)
	((M-J) M-TEM)
	((M-TEM) M-1)
	(POPJ-AFTER-NEXT (M-1) M-2)
       ((M-2) M-TEM)

;;; Extended numbers.

;;; The first arg is an XNUM.  Arith op in M-A.
ARITH-XNM-ANY
	((VMA-START-READ M-J) C-PDL-BUFFER-POINTER-POP)
	(CHECK-PAGE-READ)
	(DISPATCH TRANSPORT-HEADER READ-MEMORY-DATA)
	((M-Q) Q-TYPED-POINTER VMA)		;get transported number address 
	(CALL-DATA-TYPE-NOT-EQUAL MD (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-HEADER)) ILLOP)
	(DISPATCH-XCT-NEXT HEADER-TYPE-FIELD MD D-XNM-ARG-1)
       ((M-C) HEADER-REST-FIELD MD)

(LOCALITY D-MEM)
(START-DISPATCH 5 0)
D-XNM-ARG-1
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;%HEADER-TYPE-ERROR
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;%HEADER-TYPE-FEF
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;%HEADER-TYPE-ARRAY-LEADER
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;%HEADER-TYPE-UNUSED
	(ARITH-FLO-ANY)				;%HEADER-TYPE-FLONUM
	(ARITH-OUT-ANY)				;%HEADER-TYPE-COMPLEX
	(ARITH-BIG-ANY)				;%HEADER-TYPE-BIGNUM
	(ARITH-OUT-ANY)				;%HEADER-TYPE-RATIONAL
        (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;%HEADER-TYPE-FAST-FEF-FIXED-ARGS-NO-LOCALS
        (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;%HEADER-TYPE-FAST-FEF-VAR-ARGS-NO-LOCALS
        (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;%HEADER-TYPE-FAST-FEF-FIXED-ARGS-WITH-LOCALS
        (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;%HEADER-TYPE-FAST-FEF-VAR-ARGS-WITH-LOCALS
 (REPEAT NUM-UNUSED-HEADER-TYPES (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP))
(END-DISPATCH)

;This dispatch is used to push a return address of M-T-TO-CPDL if the
;instruction wants its result on the pdl (rather than in M-T).
;In any case we go to MMJCALL to activate the call to the macrocode routine.
(START-DISPATCH 4 0)
D-ARITH-OUT-RETURN
	(MMJCALL)		;ADD
	(MMJCALL)		;SUB
	(MMJCALL)		;MUL
	(MMJCALL)		;IDIV
	(INHIBIT-XCT-NEXT-BIT MMJCALL)	;=
	(INHIBIT-XCT-NEXT-BIT MMJCALL)	;>
	(INHIBIT-XCT-NEXT-BIT MMJCALL)	;<
	(INHIBIT-XCT-NEXT-BIT MMJCALL)	;MIN
	(INHIBIT-XCT-NEXT-BIT MMJCALL)	;MAX
	(INHIBIT-XCT-NEXT-BIT MMJCALL)	;BOOLE
	(MMJCALL)		;DIV
	(INHIBIT-XCT-NEXT-BIT MMJCALL)	;EQL
 (REPEAT NUM-UNUSED-ARITH-2ARGS (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP))
(END-DISPATCH)
(LOCALITY I-MEM)

;;; First argument is handled by macrocode.  Call out.
ARITH-OUT-ANY
	(CALL P3ZERO)
	((ARG-CALL REF-SUPPORT-VECTOR) (I-ARG SVC-NUM2))
	(DISPATCH TRANSPORT MD)
	((C-PDL-BUFFER-POINTER-PUSH) READ-MEMORY-DATA)	;Push function
	((C-PDL-BUFFER-POINTER-PUSH)		;Push the function code.
		Q-POINTER M-A (A-CONSTANT (PLUS (BYTE-VALUE Q-CDR-CODE CDR-NEXT)
					        (BYTE-VALUE Q-DATA-TYPE DTP-FIX))))
	((C-PDL-BUFFER-POINTER-PUSH)		;Push the first number.
		Q-TYPED-POINTER M-J (A-CONSTANT (BYTE-VALUE Q-CDR-CODE CDR-NEXT)))
	((C-PDL-BUFFER-POINTER-PUSH)		;Push the second number.
		Q-TYPED-POINTER M-T (A-CONSTANT (BYTE-VALUE Q-CDR-CODE CDR-NIL)))
	(DISPATCH (BYTE-FIELD 4 0) M-A D-ARITH-OUT-RETURN (I-ARG 3))	;Call tail-recursively.
       ((MICRO-STACK-DATA-PUSH) (A-CONSTANT (I-MEM-LOC M-T-TO-CPDL)))

;;; First arg is a real flonum.  Pointer in M-Q, header-rest in M-C, op in M-A.
ARITH-FLO-ANY
	((VMA-START-READ) M-Q ADD (A-CONSTANT 1))
	(CHECK-PAGE-READ)
	((M-I) HEADER-FLONUM-EXPONENT M-C)
	((M-1) DPB M-C FLONUM-HEADER-HIGH-MANTISSA A-ZERO)
    (ERROR-TABLE RESTART ARITH-FLO-ANY)
	(DISPATCH-XCT-NEXT Q-DATA-TYPE M-T D-NUMARG2 (I-ARG NUMBER-CODE-FLONUM))
    (ERROR-TABLE ARGTYP NUMBER M-T 1 ARITH-FLO-ANY)
       ((M-1) SELECTIVE-DEPOSIT MD FLONUM-HEADER-LOW-MANTISSA A-1)
	;; If falls through, second arg is a small flonum, already unpacked.
ARITH-FLO-SFL ;This label is not used.  It is here for completeness.
	(DISPATCH (BYTE-FIELD 4 0) M-A D-FORWARD-FLONUM-OPS)
    (ERROR-TABLE ARGTYP INTEGER M-Q 0)	;not easily continuable
    (ERROR-TABLE ARG-POPPED 0 M-Q M-T)
       ((MICRO-STACK-DATA-PUSH) (A-CONSTANT (I-MEM-LOC FLOPACK-P)))

;;; The second arg is an extended number.  First arg is unpacked, type in I-ARG.
;;; Arith op in M-A.
ARITH-ANY-XNM
	((VMA-START-READ) M-T)
	((M-R) READ-I-ARG)			;Get number code of first arg.
	(CHECK-PAGE-READ)
	(DISPATCH TRANSPORT-HEADER READ-MEMORY-DATA)
	((M-T) VMA)		;get transported number address 
	(CALL-DATA-TYPE-NOT-EQUAL MD (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-HEADER)) ILLOP)
	(DISPATCH-XCT-NEXT HEADER-TYPE-FIELD MD D-XNM-ARG-2)
       ((M-D) HEADER-REST-FIELD MD)

(LOCALITY D-MEM)
(START-DISPATCH 5 0)
D-XNM-ARG-2
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;%HEADER-TYPE-ERROR
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;%HEADER-TYPE-FEF
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;%HEADER-TYPE-ARRAY-LEADER
	(P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;%HEADER-TYPE-UNUSED
	(ARITH-ANY-FLO)				;%HEADER-TYPE-FLONUM
	(ARITH-ANY-OUT)				;%HEADER-TYPE-COMPLEX
	(ARITH-ANY-BIG)				;%HEADER-TYPE-BIGNUM
	(ARITH-ANY-OUT)				;%HEADER-TYPE-RATIONAL
        (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;%HEADER-TYPE-FAST-FEF-FIXED-ARGS-NO-LOCALS
        (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;%HEADER-TYPE-FAST-FEF-VAR-ARGS-NO-LOCALS
        (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;%HEADER-TYPE-FAST-FEF-FIXED-ARGS-WITH-LOCALS
        (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP)	;%HEADER-TYPE-FAST-FEF-VAR-ARGS-WITH-LOCALS
 (REPEAT NUM-UNUSED-HEADER-TYPES (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP))
(END-DISPATCH)
(LOCALITY I-MEM)

;;; The second arg requires calling-out to macrocode.  The first
;;; argument is in M-J, unless it was a fixnum in which case
;;; it has been unpacked into M-1.  Second arg is in M-T.
ARITH-ANY-OUT
	(JUMP-NOT-EQUAL M-R (A-CONSTANT NUMBER-CODE-FIXNUM) ARITH-ANY-OUT-1)
	(CALL-XCT-NEXT FIXPACK-T)
       ((C-PDL-BUFFER-POINTER-PUSH) M-T)
	((M-J) M-T)
	((M-T) C-PDL-BUFFER-POINTER-POP)
ARITH-ANY-OUT-1
	(CALL P3ZERO)
	((ARG-CALL REF-SUPPORT-VECTOR) (I-ARG SVC-NUM2))
	(DISPATCH TRANSPORT MD)
	((C-PDL-BUFFER-POINTER-PUSH) READ-MEMORY-DATA)	;Push function
	((C-PDL-BUFFER-POINTER-PUSH)		;Push the function code.
		Q-POINTER M-A (A-CONSTANT (PLUS (BYTE-VALUE Q-CDR-CODE CDR-NEXT)
					        (BYTE-VALUE Q-DATA-TYPE DTP-FIX))))
	((C-PDL-BUFFER-POINTER-PUSH)		;Push the first number.
		Q-TYPED-POINTER M-J (A-CONSTANT (BYTE-VALUE Q-CDR-CODE CDR-NEXT)))
	((C-PDL-BUFFER-POINTER-PUSH)		;Push the second number.
		Q-TYPED-POINTER M-T (A-CONSTANT (BYTE-VALUE Q-CDR-CODE CDR-NIL)))
	(DISPATCH (BYTE-FIELD 4 0) M-A D-ARITH-OUT-RETURN (I-ARG 3))	;Call tail-recursively.
       ((MICRO-STACK-DATA-PUSH) (A-CONSTANT (I-MEM-LOC M-T-TO-CPDL)))

;;; Number code of first arg in M-R.
;;; If is is a fixnum, small flonum, or flonum, it is unpacked in M-1/M-I.
;;; Our header rest field in M-D, our pointer in M-T.
ARITH-ANY-FLO
	((VMA-START-READ) M-T ADD (A-CONSTANT 1))
	(CHECK-PAGE-READ)
	((M-J) HEADER-FLONUM-EXPONENT M-D)
	((M-2) DPB M-D FLONUM-HEADER-HIGH-MANTISSA A-ZERO)
	(DISPATCH-XCT-NEXT (BYTE-FIELD 3 0) M-R D-ARITH-ANY-FLO)
       ((M-2) SELECTIVE-DEPOSIT MD FLONUM-HEADER-LOW-MANTISSA A-2)

(LOCALITY D-MEM)
(START-DISPATCH 3 0)
D-ARITH-ANY-FLO
	(ARITH-FIX-FLO)
	(ARITH-SFL-FLO)
	(ARITH-FLO-FLO)
	(ARITH-BIG-FLO)
 (REPEAT NUM-UNUSED-NUMBER-CODES (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP))
(END-DISPATCH)
(LOCALITY I-MEM)

ARITH-FIX-FLO
	((M-Q) M-1)
	((M-I) (A-CONSTANT 2036))
	(CALL-XCT-NEXT FNORM)
       ((Q-R) M-ZERO)
	;drop in
ARITH-SFL-FLO 
ARITH-FLO-FLO
	(DISPATCH (BYTE-FIELD 4 0) M-A D-FORWARD-FLONUM-OPS)
    (ERROR-TABLE FLONUM-NO-GOOD)	;ARGTYP not usable, I think I lost the arg
    (ERROR-TABLE ARG-POPPED 0 M-Q M-T)
       ((MICRO-STACK-DATA-PUSH) (A-CONSTANT (I-MEM-LOC FLOPACK-P)))

;Flonum arithmetic routines.

;These routines bash M-J, M-2, M-TEM, Q-R, A-TEMn, M-K.
;M-ZERO is an even address in M-memory.  It contains zeros, and the following
;location contains a -1.  This is used to get A-TEM1 below by hacking
;the low bit of the OA-REG-HIGH, which is the low bit of the M-source field,
;to get either a word of zeros or a word of ones depending on the sign bit
;of M-2.

;Floating Subtract.  This changes the sign of M-2 and turns into Add.
FSUB	(CALL FNEG2)
	;drop through

;Floating Add.
FADD	(JUMP-EQUAL-XCT-NEXT M-I A-J FADD2)	;Jump if exponents equal, no shifting
       ((Q-R) M-ZERO)				;Initialize discarded bits.
	(CALL-LESS-THAN-XCT-NEXT M-I A-J FADD1)	;If M-1 to shift right, exchange args
       ((M-TEM) M-A-1 M-I A-J)			;Amt to shift M-2 right minus one
	(JUMP-GREATER-OR-EQUAL M-TEM (A-CONSTANT 37) FADD3)
#+lambda((OA-REG-HIGH) FLONUM-SIGN-BIT M-2)	;Sign-extend M-2
#+exp	((m-tem3) flonum-sign-bit m-2)
#+exp	((oa-reg-high) dpb m-tem3 oah-m-src a-zero)
       ((M-TEM1) M-ZERO)			;Gets either all zeros or all ones.
	((M-J) M-A-1 (M-CONSTANT 40) A-TEM)	;40 minus exponent difference
#+exp	((m-tem3) add m-tem (a-constant 1))
	((OA-REG-LOW) DPB #+lambda M-TEM #+exp m-tem3 OAL-BYTL-1 A-J)	; becomes m-rotate
       ((M-TEM2) DPB M-2 (BYTE-FIELD 0 0) A-ZERO) ;Get bits shifted off right end of M-2
	((Q-R) A-TEM2)				;Put them in Q-R where they belong
	((M-TEM) SUB M-J (A-CONSTANT 1))	;Byte length minus one
#+exp	((m-tem3) add m-tem (a-constant 1))
	((OA-REG-LOW) DPB #+lambda M-TEM #+exp m-tem3 OAL-BYTL-1 A-J)
       ((M-2) (BYTE-FIELD 0 0) M-2 A-TEM1)	;Arithmetically shift M-2 right
FADD2	((M-1) ADD M-1 A-2 OUTPUT-SELECTOR-RIGHTSHIFT-1	;Do the add, collect
		SHIFT-Q-RIGHT)	; the overflow, discarded bits to Q
;Normalizing loop
FNORM	(DISPATCH SIGN-BIT-AND-MANTISSA-HIGH-THREE M-1 D-FNORM) ;Maybe xct-next
       ((M-I) ADD M-I (A-CONSTANT 1))		;Adjust exponent for right shift

(LOCALITY D-MEM)
(START-DISPATCH 4 0)	;s.xyz high 4 bits of sum to be normalized
D-FNORM	(INHIBIT-XCT-NEXT-BIT FNORM3)	;0.000 shift left at least 3
	(FNORM2)			;0.001 shift left 2
	(FNORM1)			;0.010 shift left 1
	(FNORM1)			;0.011 shift left 1
	(FRND)				;0.100 OK
	(FRND)				;0.101 OK
	(FRND)				;0.110 OK
	(FRND)				;0.111 OK
	(FRND)				;1.000 OK
	(FRND)				;1.001 OK
	(FRND)				;1.010 OK
	(FRND)				;1.011 OK
	(FNORM1)			;1.100 shift left 1
	(FNORM1)			;1.101 shift left 1
	(FNORM2)			;1.110 shift left 2
	(INHIBIT-XCT-NEXT-BIT FNORM3)	;1.111 shift left at least 3
(END-DISPATCH)
(LOCALITY I-MEM)

FNORM3	((M-1) M-1 OUTPUT-SELECTOR-LEFTSHIFT-1 SHIFT-Q-LEFT)
	((M-1) M-1 OUTPUT-SELECTOR-LEFTSHIFT-1 SHIFT-Q-LEFT)
	((M-1) M-1 OUTPUT-SELECTOR-LEFTSHIFT-1 SHIFT-Q-LEFT)
	((Q-R) ANDCA Q-R (A-CONSTANT 7))	;Zero the bits brought into Q
	(JUMP-NOT-EQUAL-XCT-NEXT M-1 A-ZERO FNORM) ;Break the loop if trying
       ((M-I) SUB M-I (A-CONSTANT 3))		   ; to normalize zero
;Return a floating-point zero (in internal form)
FLZERO  (declare (values a-i a-1))
	(POPJ-AFTER-NEXT (M-I) A-ZERO)
       ((M-1) A-ZERO)

;If M-2 seems to pale into insignificance, it might be SETZ, which doesn't
FADD3	(POPJ-GREATER-THAN M-TEM (A-CONSTANT 37))
	(POPJ-NOT-EQUAL M-2 (A-CONSTANT (BYTE-MASK FLONUM-SIGN-BIT)))
	(JUMP-XCT-NEXT FADD2)
       ((M-2) (M-CONSTANT -1))

FNORM2	((M-1) M-1 OUTPUT-SELECTOR-LEFTSHIFT-1 SHIFT-Q-LEFT)
	((M-1) M-1 OUTPUT-SELECTOR-LEFTSHIFT-1 SHIFT-Q-LEFT)
	((Q-R) ANDCA Q-R (A-CONSTANT 3))	;Zero the bits brought into Q
	(JUMP-XCT-NEXT FRND)
       ((M-I) SUB M-I (A-CONSTANT 2))

FNORM1	((M-1) M-1 OUTPUT-SELECTOR-LEFTSHIFT-1 SHIFT-Q-LEFT)
	((Q-R) ANDCA Q-R (A-CONSTANT 1))	;Zero the bit brought into Q
	((M-I) SUB M-I (A-CONSTANT 1))
	;drops through
;Floating-point rounding routine.
;Get here with normalized mantissa in M-1, corresponding exponent in M-I,
;residual bits in Q-R.  Rounding cannot produce zero unless given zero,
;since the input is normalized.  Do not come here with zero in M-1
;unless M-I is zero and Q-R is non-negative, or an unnormalized
;result will be returned.
;After rounding, we renormalize with a 3-bit normalize since the rounding
;can make a positive number slightly bigger and a negative number slightly smaller,
;requiring a shift of 0, 1 right, or 1 left.
FRND	(POPJ-GREATER-OR-EQUAL Q-R A-ZERO)	;Return if discarded bits < 1/2 lsb, no rounding required.
	(JUMP-NOT-EQUAL Q-R (A-CONSTANT 1_31.) FRND2)	;If discarded bits = 1/2 lsb exactly,
	(POPJ-IF-BIT-CLEAR (BYTE-FIELD 1 0) M-1) ; then round to even
FRND2	((M-1) ADD M-1 (A-CONSTANT 1)		;Add 1 lsb to mantissa, and
		OUTPUT-SELECTOR-RIGHTSHIFT-1 SHIFT-Q-RIGHT) ; capture overflow
FRND1	(DISPATCH SIGN-BIT-AND-MANTISSA-HIGH-TWO M-1 D-FRND) ;Renormalize & popj
	((M-I) ADD M-I (A-CONSTANT 1))		;Right shift was good, fix exponent, popj

;This code is heavily bummed.  Beware.
;Note that Q normally has full low-order word.  From SFLPACK has garbage but won't be used.
FRND3	((M-1) M-1 OUTPUT-SELECTOR-LEFTSHIFT-1 SHIFT-Q-LEFT)	;Restores the LSB from the Q.
FRND4	(POPJ-AFTER-NEXT (M-I) SUB M-I (A-CONSTANT 1))
       ((M-1) M-1 OUTPUT-SELECTOR-LEFTSHIFT-1)	;Restores the LSB from the Q.

(LOCALITY D-MEM)
(START-DISPATCH 3 0)  ;s.xx renormalize after round
D-FRND	(INHIBIT-XCT-NEXT-BIT FRND3)	;0.00 shift left two
	(FRND4)				;0.01 shift left one
	(R-BIT)				;0.10 OK
	(R-BIT)				;0.11 OK
	(R-BIT)				;1.00 OK
	(R-BIT)				;1.01 OK
	(FRND4)				;1.10 shift left one
	(INHIBIT-XCT-NEXT-BIT FRND3)	;1.11 shift left two
(END-DISPATCH)
(LOCALITY I-MEM)

;Exchange the arguments to FADD when the second has bigger exponent
FADD1	((M-I) M-J)		;Result exponent is exp of 2nd arg
	((M-TEM) M-A-1 (M-CONSTANT -1) A-TEM)	;Repair exponent difference
	((M-4) M-2)		;Exchange mantissas
	(POPJ-AFTER-NEXT (M-2) M-1)
       ((M-1) M-4)

;Negate operand 1.  
;Normally just change the sign of the mantissa, but note that
;to retain normalization 1/2 becomes -1 and -1 becomes 1/2, with adjustment of the exponent
FLONUM-MINUS 
FNEG1	(declare (args a-i a-1) (values a-i a-1))
        (JUMP-GREATER-OR-EQUAL-XCT-NEXT M-1 A-ZERO FNEG1A)	;Jump if input positive
       ((M-1) SUB M-ZERO A-1)				;Change sign of mantissa
	(POPJ-IF-BIT-CLEAR FLONUM-SIGN-BIT M-1)		;Return if negative became positive
	(POPJ-AFTER-NEXT				;Otherwise generate 1/2 and increase
	 (M-1) DPB (M-CONSTANT -1) MANTISSA-HIGH-BIT A-ZERO) ; exponent since it must have
       ((M-I) ADD M-I (A-CONSTANT 1))			     ; been -1 which is "SETZ"
	
FNEG1A	(POPJ-NOT-EQUAL M-1 (A-CONSTANT (BYTE-MASK SIGN-BIT-AND-MANTISSA-HIGH-BIT)))
	(POPJ-AFTER-NEXT			;If result is -1/2,
	 (M-1) DPB (M-CONSTANT -1) FLONUM-SIGN-BIT A-ZERO)	;Turn it into -1
       ((M-I) SUB M-I (A-CONSTANT 1))		;and decrease exponent

;Negate operand 2.  
;Normally just change the sign of the mantissa, but note that
;to retain normalization 1/2 becomes -1 and -1 becomes 1/2, with adjustment of the exponent
FNEG2	(JUMP-GREATER-OR-EQUAL-XCT-NEXT M-2 A-ZERO FNEG2A)	;Jump if input positive
       ((M-2) SUB M-ZERO A-2)				;Change sign of mantissa
	(POPJ-IF-BIT-CLEAR FLONUM-SIGN-BIT M-2)		;Return if negative became positive
	(POPJ-AFTER-NEXT				;Otherwise generate 1/2 and increase
	 (M-2) DPB (M-CONSTANT -1) MANTISSA-HIGH-BIT A-ZERO) ; exponent since it must have
       ((M-J) ADD M-J (A-CONSTANT 1))			     ; been -1 which is "SETZ"
	
FNEG2A	(POPJ-NOT-EQUAL M-2 (A-CONSTANT (BYTE-MASK SIGN-BIT-AND-MANTISSA-HIGH-BIT)))
	(POPJ-AFTER-NEXT			;If result is -1/2,
	 (M-2) DPB (M-CONSTANT -1) FLONUM-SIGN-BIT A-ZERO)	;Turn it into -1
       ((M-J) SUB M-J (A-CONSTANT 1))		;and decrease exponent

;Floating Division.
;First, make both arguments positive, and remember if the result is to
;be negative.  Also handle arguments of zero at this stage.  Then,
;arrange for the quotient to always be normalized by dividing the
;dividend by 2 if it is greater than the divisor.  This makes the
;result mantissa be between 1/2 and 1.  Note that if the dividend and
;divisor are equal, dividing the dividend by 2 could end up producing
;an unnormalized quotient less than 1/2 because of truncation error.
;We fix this by checking specially for the case of dividend and divisor
;equal.  To get a properly-scaled quotient, we shift the dividend left
;31. bits, plus 1 more bit to get it to a word boundary.  The extra bit
;is compensated for by doing one less divide step.  After dividing, we
;do stable rounding by comparing the remainder against half the
;divisor.  Recall that divide overflow occurs if the high word of the
;dividend is greater than or equal to the divisor.
FDIV	(CALL-EQUAL M-2 A-ZERO TRAP)
		(ERROR-TABLE DIVIDE-BY-ZERO)
		(ERROR-TABLE ARG-POPPED 0 M-Q M-T)
	(POPJ-EQUAL M-1 A-ZERO)			;(// 0.0 non-0) = 0.0
	(JUMP-LESS-THAN M-2 A-ZERO FDIV3)	;Jump if divisor negative
	(JUMP-LESS-THAN M-1 A-ZERO FDIV4)	;Jump if dividend negative
FDIV1	((M-I) M-I ADD (A-CONSTANT FLONUM-EXPONENT-EXCESS))
	(JUMP-LESS-THAN-XCT-NEXT M-1 A-2 FDIV2)	;If dividend >= divisor,
       ((M-I) SUB M-I A-J)
	(JUMP-EQUAL M-1 A-2 FDIV7)
	((M-1) (BYTE-FIELD 31. 1) M-1)		;shift dividend right 1,
	((M-I) ADD M-I (A-CONSTANT 1))		;and increase exponent of result
FDIV2	((Q-R) M-ZERO)				;Low bits of dividend
	((M-1) DIVIDE-FIRST-STEP M-1 A-2)	;Do the division, doesn't call DIV due to
(REPEAT 30. ((M-1) DIVIDE-STEP M-1 A-2))	; register conflicts and orneriness
	((M-1) DIVIDE-LAST-STEP M-1 A-2)
	((M-TEM) DIVIDE-REMAINDER-CORRECTION-STEP M-1 A-2)
	;At this point, the normalized positive quotient is in Q-R, remainder is in M-TEM
	;We'd like to shift the remainder left and do an unsigned compare, but that
	;operation isn't available so we shift the divisor right and lose a bit.
	((M-TEM1) (BYTE-FIELD 31. 1) M-2)
	(POPJ-LESS-THAN-XCT-NEXT M-TEM A-TEM1)	;Round down if remainder < 1/2 divisor
       ((M-1) Q-R)
	(JUMP-GREATER-THAN M-TEM A-TEM1 FDIV6)	;Round up if remainder > 1/2 divisor
	(POPJ-IF-BIT-CLEAR (BYTE-FIELD 1 0) M-1);Round to even lsb if remainder = 1/2 divisor
FDIV6	(JUMP-XCT-NEXT FRND1)			;Duplicate instruction at FRND2 for speed
       ((M-1) ADD M-1 (A-CONSTANT 1)		;Add 1 lsb to mantissa, and
		OUTPUT-SELECTOR-RIGHTSHIFT-1 SHIFT-Q-RIGHT) ; capture overflow

;Divisor is negative.  Change its sign and check sign of dividend
FDIV3	(JUMP-GREATER-THAN-XCT-NEXT M-1 A-ZERO FDIV5)	;Jump on positive dividend
       (CALL FNEG2)
	(JUMP-XCT-NEXT FDIV1)			;Both negative, result is positive
       (CALL FNEG1)

;Divisor is positive but dividend is negative.  Result is negative.
FDIV4	(CALL FNEG1)				;Change sign of dividend
FDIV5	(JUMP-XCT-NEXT FNEG1)			;Result is negative, get positive
       (CALL FDIV1)				; quotient and return it negated.

;Dividend and divisor mantissas equal.  Quotient mantissa is 1/2.
FDIV7	(POPJ-AFTER-NEXT (M-1) DPB (M-CONSTANT -1) MANTISSA-HIGH-BIT A-ZERO)
       ((M-I) ADD M-I (A-CONSTANT 1))

;Floating Multiplication.
FMPY	(CALL-XCT-NEXT MPY)	;Product of mantissas to M-2(high), Q-R(low)
       ((Q-R) M-2)
	(JUMP-EQUAL M-2 A-ZERO FLZERO) ;If high product of normalized operands is zero, the
				; whole product is zero.  Return proper zero.
	((M-1) M-2)		;Get result of MPY into M-1
	((M-I) M-I SUB (A-CONSTANT FLONUM-EXPONENT-EXCESS))
	(DISPATCH-XCT-NEXT SIGN-BIT-AND-MANTISSA-HIGH-TWO
			M-1 D-FMPY) ;Normalize.  May need 0, 1, or 2 left shifts
       ((M-I) M+A+1 M-I A-J)	;Exponent of product if no shifts

(LOCALITY D-MEM)
(START-DISPATCH 3 0)	;s.xy high bits of product
D-FMPY	(FNORM2)	;0.00 shift left 2
	(FNORM1)	;0.01 shift left 1
	(FRND)		;0.10 OK
	(FRND)		;0.11 OK
	(FRND)		;1.00 OK
	(FRND)		;1.01 OK
	(FNORM1)	;1.10 shift left 1
	(FNORM2)	;1.11 shift left 2
(END-DISPATCH)
(LOCALITY I-MEM)

;= for flonums.
FEQL	(POPJ-NOT-EQUAL-XCT-NEXT M-I A-J)
       ((M-T) A-V-NIL)
	(POPJ-AFTER-NEXT POPJ-NOT-EQUAL M-1 A-2)
       ((M-T) A-V-TRUE)

FGRP	(JUMP-IF-BIT-SET FLONUM-SIGN-BIT M-1 FGRP-1)
	(JUMP-IF-BIT-SET FLONUM-SIGN-BIT M-2 XTRUE)
	;; Both operands to GREATERP positive
	(JUMP-GREATER-THAN M-I A-J XTRUE)
	(POPJ-LESS-THAN-XCT-NEXT M-I A-J)
       ((M-T) A-V-NIL)	
	(POPJ-AFTER-NEXT POPJ-LESS-OR-EQUAL M-1 A-2)
       ((M-T) A-V-TRUE)

FGRP-1	(JUMP-IF-BIT-CLEAR FLONUM-SIGN-BIT M-2 XFALSE)
	;; Both operands to GREATERP negative
	(JUMP-LESS-THAN M-I A-J XTRUE)
	(POPJ-GREATER-THAN-XCT-NEXT M-I A-J)
       ((M-T) A-V-NIL)	
	(POPJ-AFTER-NEXT POPJ-LESS-OR-EQUAL M-1 A-2)
       ((M-T) A-V-TRUE)

FLSP	(JUMP-IF-BIT-SET FLONUM-SIGN-BIT M-1 FLSP-1)
	(JUMP-IF-BIT-SET FLONUM-SIGN-BIT M-2 XFALSE)
	;; Both operands to LESSP positive
	(JUMP-LESS-THAN M-I A-J XTRUE)
	(POPJ-GREATER-THAN-XCT-NEXT M-I A-J)
       ((M-T) A-V-NIL)	
	(POPJ-AFTER-NEXT POPJ-GREATER-OR-EQUAL M-1 A-2)
       ((M-T) A-V-TRUE)

FLSP-1	(JUMP-IF-BIT-CLEAR FLONUM-SIGN-BIT M-2 XTRUE)
	;; Both operands to LESSP negative
	(JUMP-GREATER-THAN M-I A-J XTRUE)
	(POPJ-LESS-THAN-XCT-NEXT M-I A-J)
       ((M-T) A-V-NIL)	
	(POPJ-AFTER-NEXT POPJ-GREATER-OR-EQUAL M-1 A-2)
       ((M-T) A-V-TRUE)

FMAX	(CALL FLSP)
	(JUMP-EQUAL M-T A-V-NIL FIX-FMAX-FMIN-RETURN-ADDRESS)
	((M-1) M-2)
	((M-I) M-J)
FIX-FMAX-FMIN-RETURN-ADDRESS
	((M-TEM) MICRO-STACK-PC-DATA-POP)
	(JUMP-EQUAL M-TEM (A-CONSTANT (I-MEM-LOC SFLPACK-P)) SFLPACK-T)
	(JUMP FLOPACK-T)

FMIN	(CALL FGRP)
	(JUMP-EQUAL M-T A-V-NIL FIX-FMAX-FMIN-RETURN-ADDRESS)
	((M-1) M-2)
	(JUMP-XCT-NEXT FIX-FMAX-FMIN-RETURN-ADDRESS)
       ((M-I) M-J)

XFLOAT-DOUBLE (MISC-INST-ENTRY %FLOAT-DOUBLE)
	(CALL FXGTPP)
	((M-1) DPB M-1
	 (BYTE-FIELD (DIFFERENCE Q-POINTER-WIDTH 0)
		     (DIFFERENCE 31. Q-POINTER-WIDTH))
	 A-ZERO)
	((M-1)
	 (BYTE-FIELD (DIFFERENCE 31. Q-POINTER-WIDTH)
		     (DIFFERENCE Q-POINTER-WIDTH
				 (DIFFERENCE 31. Q-POINTER-WIDTH)))
	 M-2 A-1)
	(JUMP-EQUAL M-1 A-ZERO FLOAT-DOUBLE-2)
	((M-TEM) DPB M-2
	 (BYTE-FIELD (DIFFERENCE Q-POINTER-WIDTH
				 (DIFFERENCE 31. Q-POINTER-WIDTH))
		     (DIFFERENCE 32.
				 (DIFFERENCE Q-POINTER-WIDTH
					     (DIFFERENCE 31. Q-POINTER-WIDTH))))
	 A-ZERO)
	((Q-R) M-TEM)
	((M-I) (A-CONSTANT (PLUS 2000 Q-POINTER-WIDTH Q-POINTER-WIDTH -1)))
FLOAT-DOUBLE-1
	(JUMP-XCT-NEXT FLOPACK-T)
       (CALL FNORM)

FLOAT-DOUBLE-2
	((M-1) DPB M-2
	 (BYTE-FIELD (DIFFERENCE Q-POINTER-WIDTH 0)
		     (DIFFERENCE 31. Q-POINTER-WIDTH))
	 A-ZERO)
	((Q-R) A-ZERO)
	(JUMP-XCT-NEXT FLOAT-DOUBLE-1)
       ((M-I) (A-CONSTANT (PLUS 2000 Q-POINTER-WIDTH -1)))

;;;  Bignum arithmetic.

(DEF-DATA-FIELD BIGNUM-HEADER-SIGN 1 18.)
(DEF-DATA-FIELD BIGNUM-HEADER-LENGTH 18. 0)

ARITH-BIG-ANY
	(DISPATCH-XCT-NEXT Q-DATA-TYPE M-T D-NUMARG2 (I-ARG NUMBER-CODE-BIGNUM))
    (ERROR-TABLE ARGTYP NUMBER M-T 1)	;not continuable, bignum could move
    (ERROR-TABLE ARG-POPPED 0 M-Q M-T)
       ((M-I) BIGNUM-HEADER-LENGTH M-C)
ARITH-BIG-SFL 
ARITH-BIG-FLO
	(CALL FLOAT-A-BIGNUM)
	(DISPATCH (BYTE-FIELD 4 0) M-A D-FORWARD-FLONUM-OPS)
    (ERROR-TABLE ARGTYP INTEGER M-Q 0)
    (ERROR-TABLE ARG-POPPED 0 M-Q M-T)
       ((MICRO-STACK-DATA-PUSH) (A-CONSTANT (I-MEM-LOC FLOPACK-P)))

ARITH-ANY-BIG
	(DISPATCH-XCT-NEXT (BYTE-FIELD 3 0) M-R D-ARITH-ANY-BIG)
       ((M-J) BIGNUM-HEADER-LENGTH M-D)

(LOCALITY D-MEM)
(START-DISPATCH 3 0)
D-ARITH-ANY-BIG
	(ARITH-FIX-BIG)
	(ARITH-SFL-BIG)
	(ARITH-FLO-BIG)
	(ARITH-BIG-BIG)
 (REPEAT NUM-UNUSED-NUMBER-CODES (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP))
(END-DISPATCH)
(LOCALITY I-MEM)

ARITH-SFL-BIG 
ARITH-FLO-BIG
	((M-TEM) M-I)
	((M-I) M-J)
	((M-J) M-TEM)
	((C-PDL-BUFFER-POINTER-PUSH) M-Q)
	((M-Q) M-T)
	((M-C) M-D)
	(CALL-XCT-NEXT FLOAT-A-BIGNUM)
       ((M-2) M-1)
	((M-T) C-PDL-BUFFER-POINTER-POP)
	(DISPATCH (BYTE-FIELD 4 0) M-A D-REVERSE-FLONUM-OPS)
    (ERROR-TABLE ARGTYP INTEGER M-T 1)
    (ERROR-TABLE ARG-POPPED 0 M-T M-Q)
       ((MICRO-STACK-DATA-PUSH) (A-CONSTANT (I-MEM-LOC FLOPACK-P)))
	
ARITH-BIG
	(DISPATCH-XCT-NEXT (BYTE-FIELD 4 0) M-A D-BIGNUM-1ARG)
       ((M-I) BIGNUM-HEADER-LENGTH M-C)

(LOCALITY D-MEM)
(START-DISPATCH 4 0)
D-BIGNUM-1ARG
	(BIGNUM-ABS)
	(BIGNUM-MINUS)
	(XFALSE)		;ZEROP OF A BIGNUM!!!!!
	(BIGNUM-PLUSP)
	(BIGNUM-MINUSP)
	(BIGNUM-ADD1)
	(BIGNUM-SUB1)
	(BIGNUM-FIX)
	(BIGNUM-FLOAT)
	(BIGNUM-SMALL-FLOAT)
	(BIGNUM-HAULONG)
	(BIGNUM-LDB)
	(BIGNUM-DPB)
	(BIGASH)
	(BIGNUM-ODDP)
	(BIGNUM-EVENP)
 (REPEAT NUM-UNUSED-ARITH-1ARGS (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP))
(END-DISPATCH)
(LOCALITY I-MEM)

;;; Cons up a bignum.
;;; Inputs: M-B length+1, M-C sign in BIGNUM-HEADER-SIGN position
;;; Outputs: M-T boxed bignum, M-C sign/length part of header, M-E,M-K,M-S bashed
;;	     M-3, M-4, q-r also bashed.
;;;          VMA same as M-T, MD header
;;; Note that M-1 and M-2 are preserved
BNCONS ;(CALL SCONS-T)				;Cons in structure space, extra-pdl
        (call allocate-bignum-storage)
	((M-TEM) SUB M-B (A-CONSTANT 1))	;Length to go in header
	((M-C) SELECTIVE-DEPOSIT M-C BIGNUM-HEADER-SIGN A-TEM)	;Incorporate sign
	((WRITE-MEMORY-DATA) ADD M-C		;Make rest of header
		(A-CONSTANT (PLUS (BYTE-VALUE Q-DATA-TYPE DTP-HEADER)
				  (BYTE-VALUE HEADER-TYPE-FIELD %HEADER-TYPE-BIGNUM))))
	(POPJ-AFTER-NEXT (VMA-START-WRITE M-T)	;Store header, fix M-T data type
		Q-POINTER M-T (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-EXTENDED-NUMBER)))
       (CHECK-PAGE-WRITE)

;; MD has the header of the bignum whether got here from ABS or from GCD
BIGNUM-ABS
	(JUMP-IF-BIT-SET-XCT-NEXT BIGNUM-HEADER-SIGN MD BIGNUM-COPY)
       ((M-C) M-I)				;Positive-signed header
RETURN-M-Q
 	(POPJ-AFTER-NEXT (M-T) M-Q)
       (NO-OP)

BIGNUM-MINUS
	(JUMP-NOT-EQUAL M-C (A-CONSTANT (BYTE-VALUE BIGNUM-HEADER-LENGTH 1))
			BIGNUM-MINUS-1)	;check for +setzness
	((VMA-START-READ) ADD M-Q (A-CONSTANT 1))
	(CHECK-PAGE-READ)
	(JUMP-NOT-EQUAL MD (A-CONSTANT POSITIVE-SETZ) BIGNUM-MINUS-1)
	(POPJ-AFTER-NEXT (M-T) (A-CONSTANT (PLUS (BYTE-VALUE Q-DATA-TYPE DTP-FIX)
						 POSITIVE-SETZ)))
       (NO-OP)
BIGNUM-MINUS-1
	((M-C) XOR M-C (A-CONSTANT (BYTE-MASK BIGNUM-HEADER-SIGN)))
;bignum in M-Q, new header(sign) in M-C, Length in M-I. Result in M-T.
BIGNUM-COPY
	(CALL-XCT-NEXT BNCONS)			;ALLOCATE IN STRUCTURE EXTRA-PDL
       ((M-B) ADD M-I (A-CONSTANT 1))
BIGNUM-COPY-L
	((VMA-START-READ) ADD M-Q A-I)
	(CHECK-PAGE-READ)
	((VMA-START-WRITE) ADD M-T A-I)
	(CHECK-PAGE-WRITE)
	(JUMP-GREATER-THAN-XCT-NEXT M-I (A-CONSTANT 1) BIGNUM-COPY-L)
       ((M-I) SUB M-I (A-CONSTANT 1))
	(POPJ)

DPB-BIGNUM-SETUP  ;CALL HERE TO SET UP FOR DOING A DPB, SEE RELEVANT CODE.
	((M-K) (BYTE-FIELD 6 0) C-PDL-BUFFER-POINTER)
	((M-E) (BYTE-FIELD (DIFFERENCE Q-POINTER-WIDTH (PLUS 1 6)) 6) C-PDL-BUFFER-POINTER)
	((M-1) ADD M-K A-E)			;COMPUTE BIT POSITION OF LEFT EDGE OF BYTE
	((M-1) ADD M-1 (A-CONSTANT 31.))	;ROUND UP
		;Note the inclusion of one extra bit.  This is in case we produce
		;a negative "SETZ", which is 1 bit longer in sign-and-magnitude than
		;in 2's complement.
	(CALL-XCT-NEXT DIV)	;DIVIDE BY 31. TO GET NUMBER OF WORDS IN BIGNUM
       ((M-2) (A-CONSTANT 31.))	;RETURN QUOTIENT IN Q-R
	((M-B) Q-R)		;NEED AT LEAST THIS MANY WORDS.
BIGNUM-COPY-EXPAND   ;Copy bignum.  Resulting bignum to have at least M-B words of
		     ;significance.  Start with bignum in M-Q, header in M-C, current
		     ;length in M-I.  Result in M-T.  As a special hack, if M-I is zero,
		     ;just allocate a 0 bignum.
	(JUMP-GREATER-OR-EQUAL M-I A-B BIGNUM-COPY)     ;No expansion needed, just copy
	(CALL-XCT-NEXT BNCONS)				;Allocate in structure extra-pdl
       ((M-B) ADD M-B (A-CONSTANT 1))    		;Plus one for header
	((M-B) SUB M-B (A-CONSTANT 1))
	(CALL-NOT-EQUAL-XCT-NEXT M-I A-ZERO BIGNUM-COPY-L)	;Copy the number part (if any)
       ((M-ZR) SUB M-B A-I)		;Save how many words to zero
	((MD) A-ZERO)
BCE2	((VMA-START-WRITE) ADD M-T A-B)	;Zero out the new words.
	(CHECK-PAGE-WRITE)
	((M-ZR) SUB M-ZR (A-CONSTANT 1))
	(JUMP-GREATER-THAN-XCT-NEXT M-ZR A-ZERO BCE2)
       ((M-B) SUB M-B (A-CONSTANT 1))
	(POPJ)

BIGNUM-PLUSP
	((M-T) A-V-TRUE)		;CORRECT SINCE NO BIGNUM ZERO
	(POPJ-AFTER-NEXT POPJ-IF-BIT-CLEAR BIGNUM-HEADER-SIGN M-C)
       ((M-T) A-V-NIL)

BIGNUM-MINUSP
	((M-T) A-V-TRUE)
	(POPJ-AFTER-NEXT POPJ-IF-BIT-SET BIGNUM-HEADER-SIGN M-C)
       ((M-T) A-V-NIL)

BIGNUM-FIX
	(POPJ-AFTER-NEXT (M-T) M-Q)
       (NO-OP)

BIGNUM-HAULONG
	((VMA-START-READ) ADD M-Q A-I)	;GET HIGH ORDER WORD
	(CHECK-PAGE-READ)
	;; (length - 1) * 31. =  (length * 32.) - length - 31.
	;; XHAUL1 wants this in M-T  and the high bits in M-1.
	((M-T) DPB M-I (BYTE-FIELD (DIFFERENCE Q-POINTER-WIDTH (PLUS 1 5)) 5.)
	 (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))
	((M-T) SUB M-T A-I)
	((M-T) SUB M-T (A-CONSTANT 31.))
	(JUMP-XCT-NEXT XHAUL1)
       ((M-1) MD)

BIGNUM-FLOAT
	(JUMP-XCT-NEXT FLOPACK-T)
       (CALL FLOAT-A-BIGNUM)

BIGNUM-SMALL-FLOAT
	(JUMP-XCT-NEXT SFLPACK-T)
       (CALL FLOAT-A-BIGNUM)

BIGNUM-ODDP
	((VMA-START-READ) ADD M-Q (A-CONSTANT 1))	;Low-order word
	(CHECK-PAGE-READ)
	(JUMP-XCT-NEXT XFALSE)
       (JUMP-IF-BIT-SET (BYTE-FIELD 1 0) READ-MEMORY-DATA XTRUE)

BIGNUM-EVENP
	((VMA-START-READ) ADD M-Q (A-CONSTANT 1))	;Low-order word
	(CHECK-PAGE-READ)
	(JUMP-XCT-NEXT XFALSE)
       (JUMP-IF-BIT-CLEAR (BYTE-FIELD 1 0) READ-MEMORY-DATA XTRUE)

;;; Convert a bignum to a flonum.  Takes the length of the bignum in M-I,
;;; the bignum pointer in M-Q, the rest-of-header in M-C.  Leaves an internal-format
;;; flonum in M-I and M-1.  Clobbers M-4, M-3, M-1, M-K, M-TEM, M-T.  Must NOT clobber
;;; M-A, M-2 and M-J!
FLOAT-A-BIGNUM
	;; First get the second-to-highest order word into M-3.
	;; (If there is only one word, get zeroes.)
	(JUMP-EQUAL-XCT-NEXT M-I (A-CONSTANT 1) FLOAT-A-BIGNUM-X)
       ((M-3) A-ZERO)
	((M-TEM) SUB M-I (A-CONSTANT 1))
	((VMA-START-READ) ADD M-Q A-TEM)
	(CHECK-PAGE-READ)
	((M-3) MD)
FLOAT-A-BIGNUM-X
	;; Now get the highest order word in M-1 and get its length in M-T.
	((VMA-START-READ) ADD M-Q A-I)
	(CHECK-PAGE-READ)
	((M-T) A-ZERO)
	(CALL-XCT-NEXT XHAUL1)
       ((M-1 C-PDL-BUFFER-POINTER-PUSH) MD) ;EVIL ON PDL BUFFER, BUT WILL BE POPPED SOON
	;; If M-T contains 31. then the mantissa is on the pdl
	;; no need to ldb/dpb anything (in fact it won't work!)
	(JUMP-EQUAL M-T (A-CONSTANT 31.) FLOAT-A-BIGNUM-31)
	;; Now piece together the mantissa of the flonum into M-1.
	;; First LDB from M-3, with:
	;;		BYTL-1 = (30. - M-T)	MROT = (32. - M-T)
	;; Then DPB from C-PDL-BUFFER-POINTER-POP into M-1, with:
	;;		BYTL-1 = (M-T - 1)	MROT = (31. - M-T)
	((M-TEM) SUB (M-CONSTANT 32.) A-T)
	((M-4) SUB M-TEM (A-CONSTANT 2))
#+exp	((m-tem3) add m-4 (a-constant 1))
	((OA-REG-LOW) DPB #+lambda M-4 #+exp m-tem3 OAL-BYTL-1 A-TEM)
	((M-1) (BYTE-FIELD 0 0) M-3 A-ZERO)
	((OA-REG-LOW) #+exp oal-mrot M-TEM)	;Rotate first dropped bit into sign of M-3
	((M-3) (BYTE-FIELD 32. 0) M-3)
	((M-K) SUB M-T (A-CONSTANT 1))
	((M-TEM) ADD M-4 (A-CONSTANT 1))
#+exp	((m-tem3) add m-k (a-constant 1))
	((OA-REG-LOW) DPB #+lambda M-K #+exp m-tem3 OAL-BYTL-1 A-TEM)
	((M-1) DPB C-PDL-BUFFER-POINTER-POP (BYTE-FIELD 0 0) A-1)
FLOAT-A-BIGNUM-DONE
	;; length in M-I   nbits (sig bits in high order word) in M-T
	;; (length - 1) * 31. + nbits + 2000 =  
	;;       (length * 32. + nbits) - length + 1741
	((M-T) DPB M-I (BYTE-FIELD 27. 5.) A-T) ;Clears data-type
	(JUMP-IF-BIT-CLEAR-XCT-NEXT (BYTE-FIELD 1 31.) M-3 FLOAT-A-BIGNUM-EXIT)
       ((M-T) SUB M-T A-I)
	((M-1) ADD M-1 (A-CONSTANT 1))		;First dropped bit was a 1, round up
	(JUMP-IF-BIT-CLEAR (BYTE-FIELD 1 31.) M-1 FLOAT-A-BIGNUM-EXIT)
	((M-1) (BYTE-FIELD 31. 1) M-1)		;Overflowed, shift right and
	((M-T) ADD M-T (A-CONSTANT 1))		; increase exponent
FLOAT-A-BIGNUM-EXIT
	(POPJ-AFTER-NEXT (M-I) ADD M-T (A-CONSTANT 1741))
       (CALL-IF-BIT-SET BIGNUM-HEADER-SIGN M-C FNEG1)

FLOAT-A-BIGNUM-31
	(JUMP-XCT-NEXT FLOAT-A-BIGNUM-DONE)
       ((M-1) C-PDL-BUFFER-POINTER-POP)


ARITH-BIG-BIG
	(DISPATCH-XCT-NEXT (BYTE-FIELD 4 0) M-A D-FORWARD-BIGNUM-OPS)
       ((M-B) M-T)

(LOCALITY D-MEM)
;BIGNUMS IN M-B AND M-T, M-Q.  THEIR HEADERS IN M-D, M-C.  LENGTHS IN M-J, M-I.
(START-DISPATCH 4 0)
D-FORWARD-BIGNUM-OPS
	(BADD)
	(BSUB)
	(BMPY)
	(BIDIV)
	(BEQL)
	(BGRP)
	(BLSP)
	(BMIN)
	(BMAX)
	(BBOOLE)
	(BDIV)
	(BEQL)
 (REPEAT NUM-UNUSED-ARITH-2ARGS (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP))
(END-DISPATCH)
(LOCALITY I-MEM)

BEQL	(POPJ-NOT-EQUAL-XCT-NEXT M-C A-D)
       ((M-T) A-V-NIL)
BEQL1	((VMA-START-READ) ADD M-Q A-I)
	(CHECK-PAGE-READ)
	((M-1) MD)
	((VMA-START-READ) ADD M-B A-I)
	(CHECK-PAGE-READ)
	(POPJ-NOT-EQUAL MD A-1)
	(JUMP-GREATER-THAN-XCT-NEXT M-I (A-CONSTANT 1) BEQL1)
       ((M-I) SUB M-I (A-CONSTANT 1))
	(POPJ-AFTER-NEXT (M-T) A-V-TRUE)
       (NO-OP)

;; this loops over two bignum's magnitudes (in M-Q,M-C,M-I and M-B,M-D,M-J) does nothing
;; if the first is larger than the second, puts M-E in M-T if they are equal
;; else moves M-A into M-T.  In any case POPJing out. Smashes M-I (which better equal M-J
;; anyway!!!!)

BSHFFL	((VMA-START-READ) ADD M-Q A-I)
	(CHECK-PAGE-READ)
	((M-1) MD)
	((VMA-START-READ) ADD M-B A-I)
	(CHECK-PAGE-READ)
	(POPJ-LESS-THAN MD A-1)			;first is bigger so popj
	(JUMP-NOT-EQUAL MD A-1 BSHFFL-1)	;second is bigger, move and popj
	;equal continue looping
	(JUMP-GREATER-THAN-XCT-NEXT M-I (A-CONSTANT 1) BSHFFL)
       ((M-I) SUB M-I (A-CONSTANT 1))
	(POPJ-AFTER-NEXT (M-T) M-E)		;all equal return M-E
       (NO-OP)

BSHFFL-1
	(POPJ-AFTER-NEXT NO-OP)
       ((M-T) M-A)

;; compare two bignums (in M-Q,M-C,M-I and M-B,M-D,M-J) and return T if first
;; is bigger than the second. Uses M-A and M-T and M-E
BGRP	(JUMP-IF-BIT-SET-XCT-NEXT BIGNUM-HEADER-SIGN M-C BGRP-1)
       ((M-E) A-V-NIL)				;Value to return if equal
	(POPJ-IF-BIT-SET-XCT-NEXT BIGNUM-HEADER-SIGN M-D)
       ((M-T) A-V-TRUE)				;First is pos., second is neg.
	(POPJ-GREATER-THAN M-I A-J)		;Both pos. First longer.
	(JUMP-EQUAL-XCT-NEXT M-I A-J BSHFFL)	;Both pos. Same length so loop.
       ((M-A) A-V-NIL)				;M-A gets alternate answer
	(POPJ-AFTER-NEXT (M-T) A-V-NIL)		;Both pos. Second longer.
       (NO-OP)

BGRP-1	(POPJ-IF-BIT-CLEAR-XCT-NEXT BIGNUM-HEADER-SIGN M-D)
       ((M-T) A-V-NIL)				;First is neg. second is pos.
	(POPJ-GREATER-THAN M-I A-J)		;both neg. First longer.
	(JUMP-EQUAL-XCT-NEXT M-I A-J BSHFFL)	;both neg. same length so loop.
       ((M-A) A-V-TRUE)				;M-A gets other answer
	(POPJ-AFTER-NEXT (M-T) A-V-TRUE)	;both neg. second longer.
       (NO-OP)

;; compare two bignums (in M-Q,M-C,M-I and M-B,M-D,M-J) and return T if second
;; is bigger than the first. Uses M-A and M-T and M-E
BLSP	(JUMP-IF-BIT-SET-XCT-NEXT BIGNUM-HEADER-SIGN M-C BLSP-1)
       ((M-E) A-V-NIL)				;Value to return if equal
	(POPJ-IF-BIT-SET-XCT-NEXT BIGNUM-HEADER-SIGN M-D)
       ((M-T) A-V-NIL)				;First is pos., second is neg.
	(POPJ-GREATER-THAN M-I A-J)		;Both pos. First longer.
	(JUMP-EQUAL-XCT-NEXT M-I A-J BSHFFL)	;Both pos. Same length so loop.
       ((M-A) A-V-TRUE)				;M-A gets alternate answer
	(POPJ-AFTER-NEXT (M-T) A-V-TRUE)	;Both pos. Second longer.
       (NO-OP)

BLSP-1	(POPJ-IF-BIT-CLEAR-XCT-NEXT BIGNUM-HEADER-SIGN M-D)
       ((M-T) A-V-TRUE)				;First is neg. second is pos.
	(POPJ-GREATER-THAN M-I A-J)		;both neg. First longer.
	(JUMP-EQUAL-XCT-NEXT M-I A-J BSHFFL)	;both neg. same length so loop.
       ((M-A) A-V-NIL)				;M-A gets other answer
	(POPJ-AFTER-NEXT (M-T) A-V-NIL)		;both neg. second longer.
       (NO-OP)

;; compare two bignums (in M-Q,M-C,M-I and M-B,M-D,M-J) and return the bigger one.
;; Uses M-A and M-T and M-E
BMAX	(JUMP-IF-BIT-SET-XCT-NEXT BIGNUM-HEADER-SIGN M-C BMAX-1)
       ((M-E) M-Q)				;Value to return if equal
	(POPJ-IF-BIT-SET-XCT-NEXT BIGNUM-HEADER-SIGN M-D)
       ((M-T) M-Q)				;First is pos., second is neg.
	(POPJ-GREATER-THAN M-I A-J)		;Both pos. First longer.
	(JUMP-EQUAL-XCT-NEXT M-I A-J BSHFFL)	;Both pos. Same length so loop.
       ((M-A) M-B)				;M-A gets alternate answer
	(POPJ-AFTER-NEXT (M-T) M-B)		;Both pos. Second longer.
       (NO-OP)

BMAX-1	(POPJ-IF-BIT-CLEAR-XCT-NEXT BIGNUM-HEADER-SIGN M-D)
       ((M-T) M-B)				;First is neg. second is pos.
	(POPJ-GREATER-THAN M-I A-J)		;both neg. First longer.
	(JUMP-EQUAL-XCT-NEXT M-I A-J BSHFFL)	;both neg. same length so loop.
       ((M-A) M-Q)				;M-A gets other answer
	(POPJ-AFTER-NEXT (M-T) M-Q)		;both neg. second longer.
       (NO-OP)

;; compare two bignums (in M-Q,M-C,M-I and M-B,M-D,M-J) and return the smaller one.
;; Uses M-A and M-T and M-E
BMIN	(JUMP-IF-BIT-SET-XCT-NEXT BIGNUM-HEADER-SIGN M-C BMIN-1)
       ((M-E) M-Q)				;Value to return if equal
	(POPJ-IF-BIT-SET-XCT-NEXT BIGNUM-HEADER-SIGN M-D)
       ((M-T) M-B)				;First is pos., second is neg.
	(POPJ-GREATER-THAN M-I A-J)		;Both pos. First longer.
	(JUMP-EQUAL-XCT-NEXT M-I A-J BSHFFL)	;Both pos. Same length so loop.
       ((M-A) M-Q)				;M-A gets alternate answer
	(POPJ-AFTER-NEXT (M-T) M-Q)		;Both pos. Second longer.
       (NO-OP)

BMIN-1	(POPJ-IF-BIT-CLEAR-XCT-NEXT BIGNUM-HEADER-SIGN M-D)
       ((M-T) M-Q)				;First is neg. second is pos.
	(POPJ-GREATER-THAN M-I A-J)		;both neg. First longer.
	(JUMP-EQUAL-XCT-NEXT M-I A-J BSHFFL)	;both neg. same length so loop.
       ((M-A) M-B)				;M-A gets other answer
	(POPJ-AFTER-NEXT (M-T) M-B)		;both neg. second longer.
       (NO-OP)

;; For add and subtract build the answer in M-T,M-K . sign of answer is expected to
;; be the sign bit in M-C. First arg in M-Q,M-I second in M-R,M-J (note the move to M-R)

;; For addition we want the longest BIGNUM in M-R,M-J

BADD	((M-TEM) XOR M-C A-D)
	(JUMP-IF-BIT-SET BIGNUM-HEADER-SIGN M-TEM BSUB1) ;signs don't agree so subtract
BADD1	(JUMP-GREATER-OR-EQUAL-XCT-NEXT M-J A-I BADD2)
       ((M-2) A-ZERO)				;M-2 gets the carry
	((M-TEM) M-I)				;Swap if second isn't largest.
	((M-I) M-J)
	((M-J) M-TEM)
	((M-B) M-Q)				;M-T and M-B contain the same thing!
	((M-Q) M-T)
BADD2	((M-R) M-B)
	(CALL-XCT-NEXT BNCONS)			;Allocate result bignum
       ((M-B) ADD M-J (A-CONSTANT 2))
	((C-PDL-BUFFER-POINTER-PUSH) DPB M-T Q-ALL-BUT-CDR-CODE 
					 (A-CONSTANT (BYTE-VALUE Q-CDR-CODE CDR-NEXT)))
	((M-D) (A-CONSTANT 1))			;M-D counts up
BADD3	((VMA-START-READ) ADD M-Q A-D)
	(CHECK-PAGE-READ)
	((M-1) ADD MD A-2)			;M-2 has carry from last round
	((VMA-START-READ) ADD M-R A-D)
	(CHECK-PAGE-READ)
	((M-1) ADD MD A-1)			;M-1 now has sum (carry and 31 bits out)
	((MD) (BYTE-FIELD 31. 0) M-1 A-ZERO)	;Write 31 bits
	((M-2) (BYTE-FIELD 1 31.) M-1 A-ZERO)	;save carry
	((VMA-START-WRITE) ADD M-T A-D)
	(CHECK-PAGE-WRITE)
	(JUMP-LESS-THAN-XCT-NEXT M-D A-I BADD3)
       ((M-D) ADD M-D (A-CONSTANT 1))
	(JUMP-GREATER-THAN M-D A-J BADD4)	;Jump if lengths (M-I,M-J) were equal,
						; there are no more words to add in
;;FIXNUM - BIGNUM addition joins us here (can drop in)
;; Bignum in M-R,M-J. 1 (sometimes) in M-D. Fixnum in M-2. Answer in M-T with header in M-C.
BADD5	((VMA-START-READ) ADD M-R A-D)
	(CHECK-PAGE-READ)
	((M-1) ADD MD A-2)			;M-2 has carry
	((MD) (BYTE-FIELD 31. 0) M-1 A-ZERO)
	((M-2) (BYTE-FIELD 1 31.) M-1 A-ZERO)
	((VMA-START-WRITE) ADD M-T A-D)
	(CHECK-PAGE-WRITE)
	(JUMP-LESS-THAN-XCT-NEXT M-D A-J BADD5)	;M-J'th word is last in M-R bignum
       ((M-D) ADD M-D (A-CONSTANT 1))
BADD4	(JUMP-GREATER-THAN M-2 A-ZERO BADD6)	;There was some carry, so store in last word.
	((M-C) SUB M-C (A-CONSTANT 1))		;no carry so give word back.
	((MD) ADD M-C (A-CONSTANT (PLUS (BYTE-VALUE Q-DATA-TYPE DTP-HEADER)
					(BYTE-VALUE HEADER-TYPE-FIELD %HEADER-TYPE-BIGNUM))))
	((VMA-START-WRITE) M-T)
	(CHECK-PAGE-WRITE)
	((M-1) ADD M-T A-D)
	(JUMP-XCT-NEXT UN-CONS)
       ((M-2) (A-CONSTANT 1))

BADD6	((MD) M-2)
	((VMA-START-WRITE) ADD M-T A-D)
	(CHECK-PAGE-WRITE)
	(POPJ)		;NO POPJ-AFTER-NEXT, COULD BE RETURNING TO MAIN LOOP

;; Subtraction:
BSUB	((M-TEM) XOR M-C A-D)
	(JUMP-IF-BIT-SET BIGNUM-HEADER-SIGN M-TEM BADD1)	;signs don't agree so add
;; first we shuffle the bignums around to be sure of subtracting the smaller magnitude
;; from the larger. Note that if we switch them then we must complement the sign bit in M-C.
BSUB1	((MICRO-STACK-DATA-PUSH) (A-CONSTANT (I-MEM-LOC M-T-TO-CPDL)))
	((M-R) M-T)				;will need M-T for answer
	(JUMP-GREATER-THAN-XCT-NEXT M-I A-J BSUB-OK)
       ((M-D) M-I)				;M-D gets the number of the last different word
	(JUMP-LESS-THAN M-I A-J BSUB-SWITCH)
	;drops in
;; they are the same length so count M-D down until you find a word that is different.
;; M-J is also kept equal to M-D since there is no need to remember the words out there
;; if when you subtract them you get zero.  (7623456123-7623456032 is the same as 123-032 !)
BSUB-L	((VMA-START-READ) ADD M-Q A-D)
	(CHECK-PAGE-READ)
	((M-J) M-D)
	((M-1) MD)
	((VMA-START-READ) ADD M-R A-D)
	(CHECK-PAGE-READ)
	(JUMP-LESS-THAN MD A-1 BSUB-OK)
	(JUMP-GREATER-THAN MD A-1 BSUB-SWITCH-1)
	(JUMP-GREATER-THAN-XCT-NEXT M-D (A-CONSTANT 1) BSUB-L)
       ((M-D) SUB M-D (A-CONSTANT 1))
	(POPJ-AFTER-NEXT
	 (M-T) (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))	;EQUAL!
       (NO-OP)

BSUB-SWITCH
	((M-TEM) M-I)				;Switch (but nobody cares about M-I)
	((M-D) M-J)
	((M-J) M-TEM)
BSUB-SWITCH-1
	((M-C) XOR M-C (A-CONSTANT (BYTE-MASK BIGNUM-HEADER-SIGN)))	;Switch sign bit.
	((M-R) M-Q)
	((M-Q) M-T)				;M-T still contains the original thing!

;; we have now cleverly arranged for M-D to be the length of the longest possible answer
;; M-Q,(M-I *) contain the bigger magnitude bignum M-R,M-J the smaller
;; correct sign bit of answer is in M-C, answer to be built in M-T,M-C (sign bit kept
;; in M-C)
;; (* note that we really don't care about M-I so we havn't actually made sure it contains
;; the correct thing)
BSUB-OK	(CALL-XCT-NEXT BNCONS)
       ((M-B) ADD M-D (A-CONSTANT 1))
	((M-2) A-ZERO)				;borrow
	((M-B) (A-CONSTANT 1))			;counter
BSUB-IT	((VMA-START-READ) ADD M-R A-B)
	(CHECK-PAGE-READ)
	((M-1) ADD MD A-2)
	((VMA-START-READ) ADD M-Q A-B)
	(CHECK-PAGE-READ)
	((M-1) SUB MD A-1)
	((MD M-3) (BYTE-FIELD 31. 0) M-1 A-ZERO)
	((VMA-START-WRITE) ADD M-T A-B)
	(CHECK-PAGE-WRITE)
	(JUMP-EQUAL-XCT-NEXT M-3 A-ZERO BSUB-IT1)
       ((M-2) (BYTE-FIELD 1 31.) M-1 A-ZERO)
	((M-E) M-B)				;M-E gets number of last non-zero word stored
BSUB-IT1
	(JUMP-LESS-THAN-XCT-NEXT M-B A-J BSUB-IT)
       ((M-B) ADD M-B (A-CONSTANT 1))
	(JUMP-GREATER-THAN M-B A-D BCLEANUP)	;Jump if no more words to borrow into
;;FIXNUM - BIGNUM subtraction joins us here.
;; Bignum in M-Q,M-D (yes M-D!). 1 in M-B. Fixnum in M-2. Answer in M-T with header in M-C.
;; 1 should be in M-E (despite the fact that that might be wrong, the answer will be
;; spotted as a fixnum zero anyway!)
BSUB-C	((VMA-START-READ) ADD M-Q A-B)
	(CHECK-PAGE-READ)
	((M-1) SUB MD A-2)
	((MD M-3) (BYTE-FIELD 31. 0) M-1 A-ZERO)
	((VMA-START-WRITE) ADD M-T A-B)
	(CHECK-PAGE-WRITE)
	(JUMP-EQUAL-XCT-NEXT M-3 A-ZERO BSUB-C1)
       ((M-2) (BYTE-FIELD 1 31.) M-1 A-ZERO)
	((M-E) M-B)				;Index of last non-zero word
BSUB-C1 (JUMP-LESS-THAN-XCT-NEXT M-B A-D BSUB-C)
       ((M-B) ADD M-B (A-CONSTANT 1))
	(JUMP BCLEANUP)

;; multiply two bignums.
BMPY	((M-R) M-T)
	((M-K) ADD M-I A-J)	;Possible length of answer
	((M-C) XOR M-C A-D)	;Sign in C is correct
	(CALL-XCT-NEXT BNCONS)
       ((M-B) ADD M-K (A-CONSTANT 1))
	((M-K) BIGNUM-HEADER-LENGTH M-C)		;M-K was smashed by SCONS
	((C-PDL-BUFFER-POINTER-PUSH) DPB M-T Q-ALL-BUT-CDR-CODE 
					 (A-CONSTANT (BYTE-VALUE Q-CDR-CODE CDR-NEXT)))

;; Now we have first arg in M-Q,M-I  second in M-R,M-J .  We are building the answer in
;; M-T,M-K .  The correct header for the answer lives in M-C.
;; M-S will index into the answer, M-D into first arg, M-E + 1 into second.
;; it must be true that M-D + M-E = M-S
;; the running total is kept in M-A,M-2,M-1
;; M-B gets M-J - 1 for comparison
;; M-ZR gets M-K - 1 for comparison
	((M-B) SUB M-J (A-CONSTANT 1))
	((M-ZR) SUB M-K (A-CONSTANT 1))
	((M-S) (A-CONSTANT 1))
	((M-A) A-ZERO)
	((M-1) A-ZERO)
	((M-2) A-ZERO)
BMPY-LOOP
	(JUMP-GREATER-THAN-XCT-NEXT M-S A-I BMPY-LOOP-1)
       ((M-D) M-I)
	((M-D) M-S)		;M-D gets min{M-I,M-S}
BMPY-LOOP-1
	((VMA-START-READ) ADD M-Q A-D)
	(CHECK-PAGE-READ)
	((M-E) SUB M-S A-D)
	((M-3) MD)
	((VMA-START-READ) M+A+1 M-R A-E)
	(CHECK-PAGE-READ)
	((Q-R) MD)
	;; Having loaded the 2 31 bit things to be multiplied into Q-R and M-3
	;; this will multiply them and add the result into M-A,M-2,M-1
	;; (31 bits in M-1 and M-2, less than 24 in M-A)
(REPEAT 31. ((M-1) MULTIPLY-STEP M-1 A-3))
	((M-1) ADD M-1 A-2)
	(JUMP-IF-BIT-CLEAR-XCT-NEXT (BYTE-FIELD 1 31.) M-1 BMPY-C)
       ((M-2) (BYTE-FIELD 31. 0) M-1 A-ZERO)
	((M-A) ADD M-A (A-CONSTANT 1))
BMPY-C	(JUMP-GREATER-OR-EQUAL-XCT-NEXT M-E A-B BMPY-LOOP-1-DONE)	;M-B = M-J - 1
       ((M-1) (BYTE-FIELD 31. 1) Q-R A-ZERO)
	(JUMP-GREATER-THAN-XCT-NEXT M-D (A-CONSTANT 1) BMPY-LOOP-1)
       ((M-D) SUB M-D (A-CONSTANT 1))
BMPY-LOOP-1-DONE
	((MD) M-1)
	((VMA-START-WRITE) ADD M-T A-S)
	(CHECK-PAGE-WRITE)
	((M-1) M-2)
	((M-2) M-A)
	((M-A) A-ZERO)
	(JUMP-LESS-THAN-XCT-NEXT M-S A-ZR BMPY-LOOP)	;M-ZR = M-K - 1
       ((M-S) ADD M-S (A-CONSTANT 1))
	(JUMP-NOT-EQUAL M-1 A-ZERO BMPY-FULL)
	((M-C) SUB M-C (A-CONSTANT 1))		;Result 1 word shorter than expected
	((MD) ADD M-C (A-CONSTANT (PLUS (BYTE-VALUE Q-DATA-TYPE DTP-HEADER)
					(BYTE-VALUE HEADER-TYPE-FIELD %HEADER-TYPE-BIGNUM))))
	((VMA-START-WRITE) M-T)
	(CHECK-PAGE-WRITE)
	((M-1) ADD M-T A-K)
	(JUMP-XCT-NEXT UN-CONS)
       ((M-2) (A-CONSTANT 1))

BMPY-FULL
	((MD) M-1)
	((VMA-START-WRITE) ADD M-T A-S)
	(CHECK-PAGE-WRITE)
	(POPJ)		;NO POPJ-AFTER-NEXT, MIGHT BE RETURNING TO MAIN LOOP

;;; Bignum - Bignum division: (algorithm from Knuth Vol 2)
BIDIV
	;;If second bignum is longer than the first bignum then the answer is 0
	(JUMP-GREATER-THAN M-J A-I RETURN-ZERO)
	;;Get sign of answer into M-C by xoring with M-D
	((M-D) SELECTIVE-DEPOSIT BIGNUM-HEADER-SIGN M-D A-ZERO)
	((M-C) XOR M-C A-D)
	;;If second is one word long then we can do Bignum - Fixnum division
	(JUMP-GREATER-THAN-XCT-NEXT M-J (A-CONSTANT 1) BIDIV-1)
       ((M-R) M-T)
	((VMA-START-READ) ADD M-T (A-CONSTANT 1))
	(CHECK-PAGE-READ)
	(JUMP-XCT-NEXT BFXIDIV)
       ((M-2) MD)

BIDIV-1
	((MICRO-STACK-DATA-PUSH) (A-CONSTANT (I-MEM-LOC M-T-TO-CPDL)))
	;;Allocate a bignum for the answer: (put it in M-A)
	((M-A) SUB M-I A-J)
	((M-A) ADD M-A (A-CONSTANT 1))	;Possible length of answer.
	(CALL-XCT-NEXT BNCONS)
       ((M-B) ADD M-A (A-CONSTANT 1))
	(CALL-XCT-NEXT BIDIV-REMAINDER-COMMON)
       ((M-A) M-T)
	;;M-Q,(M-I + 1) contains garbage. M-T,M-K contains the answer (with perhaps
	;; a zero in the top word). M-C has the correct sign bit for the answer.
	((M-1) M-Q)
	((M-2) ADD M-I (A-CONSTANT 2))
	(CALL-XCT-NEXT UN-CONS)
       ((M-Q) A-V-NIL)				;clear pointer to possible garbage
	((VMA-START-READ) ADD M-T A-K)		;Quotient may be 1 too long.
	(CHECK-PAGE-READ)
	((M-D) M-K)
	((M-E) M-D)
	(JUMP-NOT-EQUAL-XCT-NEXT MD A-ZERO BCLEANUP)
       ((M-C) SELECTIVE-DEPOSIT M-C BIGNUM-HEADER-SIGN A-K)
	(JUMP-XCT-NEXT BCLEANUP)
       ((M-E) SUB M-E (A-CONSTANT 1))

;Bignum-bignum remainder
; We enter with the first bignum in M-C the second in M-B and the header
; of the first still in MD.
REMAINDER-BIG-BIG
	((M-Q) M-C)
	((M-C) HEADER-REST-FIELD MD)
	((VMA-START-READ) M-B)
	(CHECK-PAGE-READ)
	((M-R) M-B)
	((M-I) BIGNUM-HEADER-LENGTH M-C)
	((M-J) BIGNUM-HEADER-LENGTH MD)
	;;If second bignum is longer than the first bignum then the answer is the first
	(JUMP-GREATER-THAN M-J A-I RETURN-M-Q)
	;;Sign of answer is already in M-C
	;;If second is one word long then do Bignum - Fixnum remainder
	(JUMP-GREATER-THAN M-J (A-CONSTANT 1) BIDIVR-2)
	((VMA-START-READ) ADD M-R (A-CONSTANT 1))
	(CHECK-PAGE-READ)
	((M-B) M-Q)
	((M-2) MD)
	((M-A) BIGNUM-HEADER-SIGN M-C)
	((M-C) BIGNUM-HEADER-LENGTH M-C)
	(CALL REMAINDER-BIG-FIX-1)
	(JUMP RETURN-M-1)

BIDIVR-2
	(CALL-XCT-NEXT BIDIV-REMAINDER-COMMON)
       ((M-A) A-ZERO)		;Indicate that quotient is not being saved.
	;;Now we have the remainder in M-Q,(M-I + 1) possibly shifted by
	;; an amount determined by
	;; the haulong still(!) in M-D. Sign of answer is still in M-C
	;;To shift back we perform an operation similar to BIDIV-NORMALIZE:
	;; First we LDB from the current word with: (M-K)
	;;		BYTL-1 = Haulong - 1
	;;		MROT = Haulong + 1
	;; Then we DPB into that from the next higher word with: (M-S)
	;;		BYTL-1 = 30. - haulong
	;;		MROT = Haulong
	(JUMP-EQUAL-XCT-NEXT M-D (A-CONSTANT 31.) BIDIVR-3)
       ((M-T) M-Q)
	((M-K) ADD M-D (A-CONSTANT 1))		;MROT
	((M-TEM) SUB M-D (A-CONSTANT 1))	;BYTL-1
	((M-K) DPB M-TEM OAL-BYTL-1 A-K)	;For LDB
	((M-TEM) (A-CONSTANT 30.))
	((M-TEM) SUB M-TEM A-D)			;BYTL-1, MROT in M-D
	((M-S) DPB M-TEM OAL-BYTL-1 A-D)	;For DPB
	((M-D) (A-CONSTANT 1))			;Counts through the bignum
	((M-E) (A-CONSTANT 1))			;Gets number of last non-zero word
	((VMA-START-READ) ADD M-T A-D)
	(CHECK-PAGE-READ)
	((M-1) MD)				;M-1 has word from last round.
BIDIVR-UNNORMALIZE-LOOP
	((VMA-START-READ) M+A+1 M-T A-D)
	(CHECK-PAGE-READ)
#+exp	((m-tem3) add m-k (a-constant 1_5))
#+exp	((oa-reg-low) (byte-field 10. 0) m-tem3)
#+lambda((OA-REG-LOW) M-K)
	((M-2) (BYTE-FIELD 0 0) M-1 A-ZERO)	;LDB out of lower word
	((M-1) MD)
#+exp	((m-tem3) add m-s (a-constant 1_5))
#+exp	((oa-reg-low) (byte-field 10. 0) m-tem3)
#+lambda((OA-REG-LOW) M-S)
	((MD M-2) DPB M-1 (BYTE-FIELD 0 0) A-2)	;DPB in from higher word
	((VMA-START-WRITE) ADD M-T A-D)		;Put back into lower word
	(CHECK-PAGE-WRITE)
	(JUMP-EQUAL M-2 A-ZERO BIDIVR-UNNORMALIZE-1)
	((M-E) M-D)
BIDIVR-UNNORMALIZE-1
	(JUMP-LESS-THAN-XCT-NEXT M-D A-I BIDIVR-UNNORMALIZE-LOOP)
       ((M-D) ADD M-D (A-CONSTANT 1))
	(JUMP-XCT-NEXT BCLEANUP)
       ((M-C) SELECTIVE-DEPOSIT BIGNUM-HEADER-SIGN M-C A-D)

BIDIVR-3	;;In this case (no shifting necessary) we must loop downward looking
	;; for the first non-zero word.  Cannot share code with BIGNUM-DPB-CLEANUP.
	((M-D) ADD M-I (A-CONSTANT 1))
	((M-C) SELECTIVE-DEPOSIT BIGNUM-HEADER-SIGN M-C A-D)
	((M-E) M-D)				;Counts down bignum
BIDIVR-4	((VMA-START-READ) ADD M-T A-E)
	(CHECK-PAGE-READ)
	(JUMP-NOT-EQUAL MD A-ZERO BCLEANUP)
	(JUMP-GREATER-THAN-XCT-NEXT M-E (A-CONSTANT 2) BIDIVR-4)
       ((M-E) SUB M-E (A-CONSTANT 1))
	(JUMP BCLEANUP)			;Only one significant word

BIDIV-REMAINDER-COMMON 
	;;allocate a temporary bignum one word longer than first arg (put it in M-D)
	;; If Bignum remainder got us here then this bignum will BE the answer
	(call-xct-next allocate-bignum-storage)
       ((m-b) add m-i (a-constant 2))
	((M-TEM) ADD M-I (A-CONSTANT 1))
	((MD) ADD M-TEM (A-CONSTANT (PLUS (BYTE-VALUE Q-DATA-TYPE DTP-HEADER)
					  (BYTE-VALUE HEADER-TYPE-FIELD %HEADER-TYPE-BIGNUM))))
	((VMA-START-WRITE M-D) Q-POINTER M-T
			       (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-EXTENDED-NUMBER)))
	(CHECK-PAGE-WRITE)
	;;Now do a haulong on the high order word of second arg (for normalization)
	;; note that if the answer is 31. then there is no need to normalize or allocate
	;; a second temporary bignum
	((VMA-START-READ) ADD M-R A-J)
	(CHECK-PAGE-READ)
	((M-T) A-ZERO)
	(CALL-XCT-NEXT XHAUL1)
       ((M-1) MD)
	(JUMP-EQUAL-XCT-NEXT M-T (A-CONSTANT 31.) BIDIV-PUNT-NORMALIZING)
       ((M-1) M-T)		;hide away haulong for later
	;;allocate another temporary bignum as long as the second and keep it in M-T
	(call-xct-next allocate-bignum-storage)
       ((m-b) add m-j (a-constant 1))
	((MD) ADD M-J (A-CONSTANT (PLUS (BYTE-VALUE Q-DATA-TYPE DTP-HEADER)
					(BYTE-VALUE HEADER-TYPE-FIELD %HEADER-TYPE-BIGNUM))))
	((VMA-START-WRITE M-T) Q-POINTER M-T
			       (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-EXTENDED-NUMBER)))
	(CHECK-PAGE-WRITE)
	;;So now we build the proper constants from saved haulong in M-1
	;; for ldbing (in M-K) and dpbing (in M-S) to normalize (see comment in front
	;; of BIDIV-NORMALIZE)
	(CALL BIDIV-NORMALIZE-ENCODE-SHIFT)
	;;Perform normalization (subroutine takes old bignum in M-B and new in M-D
	;; steps length in M-ZR, bashes M-4)
	((M-E) A-ZERO)		;No offset for BIDIV-NORMALIZE.
	((M-B) M-Q)
	((M-ZR) M-I)
	(CALL-XCT-NEXT BIDIV-NORMALIZE)
       ((M-2) A-ZERO)
	((M-Q) M-D)		;Replace original dividend with copy
	;;Prepare to call it again:
	((VMA-START-READ) ADD M-R A-J)
	(CHECK-PAGE-READ)
	((M-D) M-T)
	((M-B) M-R)
#+exp	((m-tem3) add m-s (a-constant 1_5))
#+exp	((oa-reg-low) (byte-field 10. 0) m-tem3)
#+lambda((OA-REG-LOW) M-S)
	((M-2) DPB MD (BYTE-FIELD 0 0) A-ZERO)
	(CALL-XCT-NEXT BIDIV-NORMALIZE)
       ((M-ZR) SUB M-J (A-CONSTANT 1))
	(JUMP-XCT-NEXT BIDIV-READY)
       ((M-R) M-D)		;Replace original divisor with copy

BIDIV-PUNT-NORMALIZING
	;;In this case all we do is copy the first arg:
	((M-ZR) M-I)
BIDIV-PUNT-NORMALIZING-1
	((VMA-START-READ) ADD M-Q A-ZR)
	(CHECK-PAGE-READ)
	((WRITE-MEMORY-DATA) READ-MEMORY-DATA)
	((VMA-START-WRITE) ADD M-D A-ZR)
	(CHECK-PAGE-WRITE)
	(JUMP-GREATER-THAN-XCT-NEXT M-ZR (A-CONSTANT 1) BIDIV-PUNT-NORMALIZING-1)
       ((M-ZR) SUB M-ZR (A-CONSTANT 1))
	((MD) A-ZERO)
	((VMA-START-WRITE) M+A+1 M-D A-I)
	(CHECK-PAGE-WRITE)
	((M-Q) M-D)		;Replace original dividend with copy
BIDIV-READY
	((M-T) M-A)		;Answer will wind up in M-T so why not now?
				;If remainder then this is a zero.
	((M-K) SUB M-I A-J)
	((M-K) ADD M-K (A-CONSTANT 1))
	((C-PDL-BUFFER-POINTER-PUSH) M-1)		;Saved haulong
	;;So now the situation is as follows: The sign of the answer is in
	;; BIGNUM-HEADER-SIGN in M-C. The old haulong of the top word of the second
	;; argument is on top of the PDL (We have to save
	;; that information so we know wether or not to un-cons!) We have a bignum
	;; in M-Q,(M-I + 1) that we are dividing by a normalized bignum in M-R,M-J.
	;; Answer is being built in M-T,M-K. (M-T = 0 if remaindering.)
	((M-S) M-K)			;M-S will count down through the answer
	((M-E) M-I)			;M-E will step down bignum in M-Q
	((VMA-START-READ) ADD M-R A-J)
	(CHECK-PAGE-READ)
	((A-BIDIV-V1) MD)				;V1
	((VMA-START-READ) SUB VMA (A-CONSTANT 1))
	(CHECK-PAGE-READ)
	((A-BIDIV-V2) MD)				;V2
BIDIV-LOOP
	;;Now we are ready to make an estimate of what that first 31. bits will be.
	;;Comments are notation from Knuth.
	((VMA-START-READ) M+A+1 M-Q A-E)
	(CHECK-PAGE-READ)
	((M-3) MD)					;U0
	((VMA-START-READ) ADD M-Q A-E)
	(CHECK-PAGE-READ)
	(JUMP-EQUAL M-3 A-BIDIV-V1 BIDIV-SIMPLE-CASE)
	((M-TEM) DPB M-3 (BYTE-FIELD 1 31.) A-ZERO)
	((Q-R) IOR MD A-TEM)				;low 32. bits of U0 * B + U1
	((M-3) (BYTE-FIELD 30. 1) M-3 A-ZERO)		;high 30. bits of same
	((M-1) A-BIDIV-V1)				;Divide by V1
	;; Compute QHAT = Floor((U0 * B + U1) / V1) and RHAT = U0 * B + U1 - QHAT * V1
	((M-3) DIVIDE-FIRST-STEP M-3 A-1)
(REPEAT 31. ((M-3) DIVIDE-STEP M-3 A-1))
	((M-3) DIVIDE-LAST-STEP M-3 A-1)
	((M-3) DIVIDE-REMAINDER-CORRECTION-STEP M-3 A-1);RHAT
	(JUMP-XCT-NEXT BIDIV-OPTIMIZE-QHAT)
       ((M-1) Q-R)					;QHAT

BIDIV-SIMPLE-CASE
	((M-1) (A-CONSTANT 17777777777))		;QHAT = B - 1
	((M-3) ADD MD A-BIDIV-V1)			;RHAT = U1 + V1
	;; If sign bit of M-3 is set then we know that RHAT * B + U2 is greater
	;; than QHAT * V2:
	(JUMP-IF-BIT-SET (BYTE-FIELD 1 31.) M-3 BIDIV-QHAT-IS-GOOD)
BIDIV-OPTIMIZE-QHAT
	;;Now in order to check if RHAT * B + U2 < QHAT * V2 we first read in U2
	;; and then compute QHAT * V2 .
	((M-TEM) SUB M-E (A-CONSTANT 1))
	((VMA-START-READ) ADD M-Q A-TEM)
	(CHECK-PAGE-READ)
	((Q-R) A-BIDIV-V2)
	(CALL-XCT-NEXT MPY)
       ((M-4) MD)					;U2
	((M-2) M-2 OUTPUT-SELECTOR-LEFTSHIFT-1)		;BRING IN HIGH BIT OF Q
	;;Now M-2 = High(QHAT * V2)
	;;    M-3 = RHAT = High(RHAT * B + U2)
	;;    M-4 = U2 = Low(RHAT * B + U2)
	;;    M-1 = QHAT
	;;    Q-R = Low(QHAT * V2) plus junk in sign bit
	(JUMP-GREATER-THAN M-3 A-2 BIDIV-QHAT-IS-GOOD)
	((M-TEM) (BYTE-FIELD 31. 0) Q-R A-ZERO)		;Low(QHAT * V2)
	(JUMP-LESS-THAN M-3 A-2 BIDIV-OPTIMIZE-QHAT-SUB1)
	(JUMP-GREATER-OR-EQUAL M-4 A-TEM BIDIV-QHAT-IS-GOOD)
BIDIV-OPTIMIZE-QHAT-SUB1
	;; So QHAT must be decremented and other quantities adjusted:
	((M-TEM) SUB M-TEM A-BIDIV-V2)
	(JUMP-IF-BIT-CLEAR-XCT-NEXT (BYTE-FIELD 1 31.) M-TEM BIDIV-2);carry into High(QHAT * V2)
       ((M-3) ADD M-3 A-BIDIV-V1)			;Adjust RHAT
	((M-TEM) (BYTE-FIELD 31. 0) M-TEM A-ZERO)
	((M-2) SUB M-2 (A-CONSTANT 1))
BIDIV-2
 	;;If M-3 is negative then RHAT * B + U2 overflew and must be greater than
	;; QHAT * V2
	(JUMP-IF-BIT-SET-XCT-NEXT (BYTE-FIELD 1 31.) M-3 BIDIV-QHAT-IS-GOOD)
       ((M-1) SUB M-1 (A-CONSTANT 1))			;Decrement QHAT
	(JUMP-GREATER-THAN M-3 A-2 BIDIV-QHAT-IS-GOOD)
	(JUMP-LESS-THAN M-3 A-2 BIDIV-OPTIMIZE-QHAT-SUB2)
	(JUMP-GREATER-OR-EQUAL M-4 A-TEM BIDIV-QHAT-IS-GOOD)
BIDIV-OPTIMIZE-QHAT-SUB2
	((M-1) SUB M-1 (A-CONSTANT 1))			;Decrement QHAT second time.
BIDIV-QHAT-IS-GOOD
	;;QHAT contains the wrong thing only once every 716 million times!
	;;We multiply divisor by QHAT and subtract from dividend
	((M-A) (A-CONSTANT 1))			;steps through M-R
	((M-B) SUB M-E A-J)
	((M-B) ADD M-B (A-CONSTANT 1))		;steps through M-Q
	((M-ZR) A-ZERO)				;borrow from last round
	((M-2) A-ZERO)				;for multiplication scratch
BIDIV-MPY-LOOP
	((VMA-START-READ) ADD M-R A-A)
	(CHECK-PAGE-READ)
	((Q-R) MD)
(REPEAT 31. ((M-2) MULTIPLY-STEP M-2 A-1))
	((M-D) (BYTE-FIELD 31. 1) Q-R A-ZERO)	;Now M-D might contain gubbish.
	((VMA-START-READ) ADD M-Q A-B)
	(CHECK-PAGE-READ)
	((M-TEM) SUB MD A-D)
	((M-TEM) SUB M-TEM A-ZR)
	((MD) (BYTE-FIELD 31. 0) M-TEM A-ZERO)
	((M-ZR) (BYTE-FIELD 1 31.) M-TEM A-ZERO)
	((VMA-START-WRITE) ADD M-Q A-B)
	(CHECK-PAGE-WRITE)
	((M-A) ADD M-A (A-CONSTANT 1))
	(JUMP-LESS-THAN-XCT-NEXT M-B A-E BIDIV-MPY-LOOP)
       ((M-B) ADD M-B (A-CONSTANT 1))
	((VMA-START-READ) ADD M-Q A-B)
	(CHECK-PAGE-READ)
	((M-4) SUB MD A-2)
	((MD-START-WRITE M-4) SUB M-4 A-ZR)
	(CHECK-PAGE-WRITE)
	(CALL-IF-BIT-SET (BYTE-FIELD 1 31.) M-4 BIDIV-ONCE-IN-716MILLION) ;DAMN! QHAT too big.
	(JUMP-EQUAL-XCT-NEXT M-T A-ZERO BIDIV-DONT-STORE)	;write QHAT into quotient
       ((M-E) SUB M-E (A-CONSTANT 1))				;If not remaindering
	((MD) M-1)
	((VMA-START-WRITE) ADD M-T A-S)
	(CHECK-PAGE-WRITE)
BIDIV-DONT-STORE
	(JUMP-GREATER-THAN-XCT-NEXT M-S (A-CONSTANT 1) BIDIV-LOOP)
       ((M-S) SUB M-S (A-CONSTANT 1))
	;;Now we have the answer so we give up any temp. storage and cleanup the answer.
	((M-D) C-PDL-BUFFER-POINTER-POP)	;Clears any gubbish from M-D
	;;Now M-D contains the haulong of high word of original M-R
	(POPJ-EQUAL M-D (A-CONSTANT 31.))
	((M-1) M-R)
	((M-2) ADD M-J (A-CONSTANT 1))
	(JUMP-XCT-NEXT UN-CONS)			;Tail recursive call
       ((M-R) A-V-NIL)				;clear pointer to possible garbage

;;We come here in the case where QHAT was 1 too large, we must add divisor back into
;; dividend once.
BIDIV-ONCE-IN-716MILLION
	((M-A) (A-CONSTANT 1))			;steps through M-R
	((M-B) SUB M-E A-J)
	((M-B) ADD M-B (A-CONSTANT 1))		;steps through M-Q
	((M-ZR) A-ZERO)				;carry
BIDIV-ONCE-IN-716MILLION-1
	((VMA-START-READ) ADD M-R A-A)
	(CHECK-PAGE-READ)
	((M-4) ADD MD A-ZR)
	((VMA-START-READ) ADD M-Q A-B)
	(CHECK-PAGE-READ)
	((M-4) ADD MD A-4)
	((M-ZR) (BYTE-FIELD 1 31.) M-4 A-ZERO)
	((MD-START-WRITE) (BYTE-FIELD 31. 0) M-4 A-ZERO)
	(CHECK-PAGE-WRITE)
	((M-A) ADD M-A (A-CONSTANT 1))
	(JUMP-LESS-THAN-XCT-NEXT M-B A-E BIDIV-ONCE-IN-716MILLION-1)
       ((M-B) ADD M-B (A-CONSTANT 1))
	((MD) A-ZERO)		;Keep remainder correct.
	((VMA-START-WRITE) ADD M-Q A-B)
	(CHECK-PAGE-WRITE)
	(POPJ-AFTER-NEXT (M-1) SUB M-1 (A-CONSTANT 1))	;decrement QHAT
       (NO-OP)

;;; Set up args for the below from shift in M-1
BIDIV-NORMALIZE-ENCODE-SHIFT
	((M-TEM) SUB (M-CONSTANT 32.) A-1)	;MROT = 32. - Haulong
	((M-K) SUB M-TEM (A-CONSTANT 2))	;BYTL-1 = 30. - Haulong
	((M-K) DPB M-K OAL-BYTL-1 A-TEM)	;M-K constant for LDBing
	((M-TEM) SUB M-TEM (A-CONSTANT 1))	;MROT = 31. -Haulong
	(POPJ-AFTER-NEXT
	 (M-S) SUB M-1 (A-CONSTANT 1))		;BYTL-1 = Haulong - 1
       ((M-S) DPB M-S OAL-BYTL-1 A-TEM)		;M-S constant for DPBing

;;; Subroutine for normalizing bignums:
;;; Does a left shift using M-K to ldb from C(M-B + M-ZR) into M-2 and stored at
;;; (M-D + A-ZR + 1 + M-E), and then dpb using M-S from C(M-B + M-ZR) into M-2 for the
;;; next time around:
;;;
;;;	|0| X |  Y  |	becomes:	|0|  Y  |   |  ;left in M-2 for next round.
;;;	|0|   |     |			|0|     | X |  ;written out with high half
;;;						       ; from last round.
;;; 
;;; M-K is the LDB pointer for X.  The thing initially in M-1 is the width of Y.
;;; M-S is the DPB pointer for Y.
;;;
;;; M-4 is bashed. M-2 can be loaded with whatever you want in the high part of the
;;; first word written (at M-D + M-ZR + 1 + M-E), you also load M-ZR
;;;Note that M-E is an offset in words to shift the bignum, that many words of zeros
;;; will be placed in the low bits of the bignum in M-D.
;;;This is crocked to work if M-E is 0, but not if it is negative!
;;; But -1 in M-E causes the bottom word (the final Y) of the bignum
;;; in M-D to disappear (for ASH).
BIDIV-NORMALIZE
	(JUMP-EQUAL M-ZR A-ZERO BIDIV-NORMALIZE-0)
	((VMA-START-READ) ADD M-B A-ZR)
	(CHECK-PAGE-READ)
#+exp	((m-tem3) add m-k (a-constant 1_5))
#+exp	((oa-reg-low) (byte-field 10. 0) m-tem3)
#+lambda((OA-REG-LOW) M-K)
	((M-4) (BYTE-FIELD 0 0) MD A-2)
#+exp	((m-tem3) add m-s (a-constant 1_5))
#+exp	((oa-reg-low) (byte-field 10. 0) m-tem3)
#+lambda((OA-REG-LOW) M-S)
	((M-2) DPB MD (BYTE-FIELD 0 0) A-ZERO)
	((MD) M-4)
	((M-4) ADD M-ZR A-E)
	((VMA-START-WRITE) M+A+1 M-D A-4)
	(CHECK-PAGE-WRITE)
	(JUMP-GREATER-THAN-XCT-NEXT M-ZR (A-CONSTANT 1) BIDIV-NORMALIZE)
       ((M-ZR) SUB M-ZR (A-CONSTANT 1))
BIDIV-NORMALIZE-0
	(POPJ-LESS-THAN M-E A-ZERO)
	((MD) M-2)
	((VMA-START-WRITE) M+A+1 M-D A-E)
       	(CHECK-PAGE-WRITE)
	(POPJ-EQUAL M-E A-ZERO)
	((MD) A-ZERO)
BIDIV-NORMALIZE-1
	((VMA-START-WRITE) ADD M-D A-E)
	(CHECK-PAGE-WRITE)
	(JUMP-GREATER-THAN-XCT-NEXT M-E (A-CONSTANT 1) BIDIV-NORMALIZE-1)
       ((M-E) SUB M-E (A-CONSTANT 1))
	(POPJ)

ARITH-FIX-BIG
	((M-2) M-1)	;UNPACKED FIXNUM ARG
	((M-Q) M-T)	;BIGNUM ITSELF (SECOND ARG)
	((M-C) M-D)	;BIGNUM HEADER
	(DISPATCH-XCT-NEXT (BYTE-FIELD 4 0) M-A D-FIXNUM-BIGNUM-OPS)
       ((M-I) M-J)      ;BIGNUM LENGTH

(LOCALITY D-MEM)
;FIXNUM IN BOTH M-1, M-2.  BIGNUM IN BOTH M-Q, M-T.  HEADER IN M-C, M-D.  LENGTH IN M-I, M-J.
(START-DISPATCH 4 0)
D-FIXNUM-BIGNUM-OPS
	(FXBADD)
	(FXBSUB)
	(FXBMPY)
	(FXBIDIV)
	(XFALSE)			;Fixnum = Bignum ???
	(FXBGRP)
	(FXBLSP)
	(FXBMIN)
	(FXBMAX)
	(FXBBOOLE)
	(FXBDIV)
	(XFALSE)			;Fixnum = Bignum ???
 (REPEAT NUM-UNUSED-ARITH-2ARGS (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP))
(END-DISPATCH)
(LOCALITY I-MEM)

ARITH-BIG-FIX
	(DISPATCH-XCT-NEXT (BYTE-FIELD 4 0) M-A D-BIGNUM-FIXNUM-OPS)
       (NO-OP)

(LOCALITY D-MEM)
;FIXNUM IN M-T, UNPACKED INTO M-2.
;BIGNUM IN M-Q, HEADER IN M-C, LENGTH IN M-I.
(START-DISPATCH 4 0)
D-BIGNUM-FIXNUM-OPS
	(BFXADD)
	(BFXSUB)
	(BFXMPY)
	(BFXIDIV)
	(XFALSE)			;Bignum = Fixnum ???
	(BFXGRP)
	(BFXLSP)
	(BFXMIN)
	(BFXMAX)
	(BFXBOOLE)
	(BFXDIV)
	(XFALSE)			;Bignum = Fixnum ???
 (REPEAT NUM-UNUSED-ARITH-2ARGS (P-BIT INHIBIT-XCT-NEXT-BIT ILLOP))
(END-DISPATCH)
(LOCALITY I-MEM)

FXBSUB	(JUMP-XCT-NEXT FXBADD0)
       ((M-C) XOR M-C (A-CONSTANT (BYTE-VALUE BIGNUM-HEADER-SIGN 1)))

FXBRETQ	(POPJ-AFTER-NEXT	;RETURN BIGNUM ARG.
	 (M-T) Q-TYPED-POINTER M-Q)
       ((C-PDL-BUFFER-POINTER-PUSH) DPB M-T Q-ALL-BUT-CDR-CODE   ;LEAVE RESULT BOTH PLACES
			 (A-CONSTANT (BYTE-VALUE Q-CDR-CODE CDR-NEXT)))  ;FOR GOOD MEASURE.

BFXSUB	((M-2) SUB M-ZERO A-2)	;NO SETZ PROBLEMS!
BFXADD 
FXBADD	(JUMP-EQUAL M-2 A-ZERO FXBRETQ)  ;SPECIAL CASE IF ADDING ZERO, JUST RETURN OTHER GUY
FXBADD0	(JUMP-GREATER-OR-EQUAL-XCT-NEXT M-2 A-ZERO BFXADD-1)
       ((MICRO-STACK-DATA-PUSH) (A-CONSTANT (I-MEM-LOC M-T-TO-CPDL)))
	((M-2) SUB M-ZERO A-2)			;Make positive
	(JUMP-IF-BIT-SET BIGNUM-HEADER-SIGN M-C BFXADD-ADD)
BFXADD-SUB	;M-Q/M-I bignum, M-2 positive number to be subtracted
	(CALL-XCT-NEXT BNCONS)
       ((M-B) ADD M-I (A-CONSTANT 1))
	((M-D) M-I)
	((M-B) (A-CONSTANT 1))
	(JUMP-XCT-NEXT BSUB-C)
       ((M-E) (A-CONSTANT 1))

BFXADD-1
	(JUMP-IF-BIT-SET BIGNUM-HEADER-SIGN M-C BFXADD-SUB)
BFXADD-ADD	;M-Q/M-I bignum, M-2 positive number to be added
	(CALL-XCT-NEXT BNCONS)			;ALLOCATE IN STRUCTURE EXTRA-PDL
       ((M-B) ADD M-I (A-CONSTANT 2))
	((M-I) ADD M-I (A-CONSTANT 1))
	((M-R) M-Q)
	((M-J) SUB M-I (A-CONSTANT 1)) ;Recover length of bignum in M-Q (M-R)
	(JUMP-XCT-NEXT BADD5)
       ((M-D) (A-CONSTANT 1))

BIGNUM-ADD1
	(JUMP-IF-BIT-CLEAR-XCT-NEXT BIGNUM-HEADER-SIGN M-C BFXADD-ADD)
       ((M-2) (A-CONSTANT 1))
	(JUMP BFXADD-SUB)

BIGNUM-SUB1
	(JUMP-IF-BIT-CLEAR-XCT-NEXT BIGNUM-HEADER-SIGN M-C BFXADD-SUB)
       ((M-2) (A-CONSTANT 1))
	(JUMP BFXADD-ADD)

RETURN-ZERO
	(POPJ-AFTER-NEXT (M-T C-PDL-BUFFER-POINTER-PUSH)
		(A-CONSTANT (PLUS (BYTE-VALUE Q-CDR-CODE CDR-NEXT)
				  (BYTE-VALUE Q-DATA-TYPE DTP-FIX))))
       (NO-OP)

;; A fixnum multiplied by a bignum can yield a fixnum in just two cases(!):
BFXMPY 
FXBMPY	(JUMP-EQUAL M-2 A-ZERO RETURN-ZERO)	;0*X=0
	(JUMP-NOT-EQUAL M-2 A-MINUS-ONE BFXMPY-OK)	;(-1)*(+SETZ)=(-SETZ)
	(JUMP-NOT-EQUAL M-I (A-CONSTANT 1) BFXMPY-OK)
	((VMA-START-READ) ADD M-Q A-I)
	(CHECK-PAGE-READ)
	(JUMP-NOT-EQUAL MD (A-CONSTANT POSITIVE-SETZ) BFXMPY-OK)
	(POPJ-AFTER-NEXT (M-T C-PDL-BUFFER-POINTER-PUSH)
		Q-POINTER MD (A-CONSTANT (PLUS (BYTE-VALUE Q-CDR-CODE CDR-NEXT)
					       (BYTE-VALUE Q-DATA-TYPE DTP-FIX))))
       (NO-OP)

BFXMPY-OK
	(JUMP-GREATER-OR-EQUAL M-2 A-ZERO BFXMPY-1)
	((M-2) SUB M-ZERO A-2)			;NEGATIVE FIXNUM, CHANGE SIGN OF RESULT
	((M-C) XOR M-C (A-CONSTANT (BYTE-VALUE BIGNUM-HEADER-SIGN 1)))
BFXMPY-1
	(CALL-XCT-NEXT BNCONS)
       ((M-B) ADD M-I (A-CONSTANT 2))
	((C-PDL-BUFFER-POINTER-PUSH) DPB M-T Q-ALL-BUT-CDR-CODE 
					 (A-CONSTANT (BYTE-VALUE Q-CDR-CODE CDR-NEXT)))
	(CALL-XCT-NEXT MULTIPLY-ONCE)
       ((M-1) A-ZERO)
	((MD) M-1)
	((VMA-START-WRITE) ADD M-T A-D)
	(CHECK-PAGE-WRITE)
	(POPJ-NOT-EQUAL M-1 A-ZERO)
	((M-C) SUB M-C (A-CONSTANT 1))
	((MD) ADD M-C (A-CONSTANT (PLUS (BYTE-VALUE Q-DATA-TYPE DTP-HEADER)
					(BYTE-VALUE HEADER-TYPE-FIELD %HEADER-TYPE-BIGNUM))))
	((VMA-START-WRITE) M-T)
	(CHECK-PAGE-WRITE)
	((M-1) ADD M-T A-D)
	(JUMP-XCT-NEXT UN-CONS)
       ((M-2) (A-CONSTANT 1))

;; MULTIPLY-ONCE multiplies a bignum in M-Q,M-I by a fixnum in M-2 and adds the fixnum in M-1.
;; Writes answer M-T (as if it is a bignum). Leaves last word (not written) in M-1.
;; Bashes M-D to be M-I + 1
MULTIPLY-ONCE
	((M-D) (A-CONSTANT 1))
BFXMPY-LOOP
	((VMA-START-READ) ADD M-Q A-D)
	(CHECK-PAGE-READ)
	((Q-R) MD)
(REPEAT 31. ((M-1) MULTIPLY-STEP M-1 A-2))
	((M-1) (BYTE-FIELD 31. 0) M-1)
	((MD) (BYTE-FIELD 31. 1) Q-R)
	((VMA-START-WRITE) ADD M-T A-D)
	(CHECK-PAGE-WRITE)
	(JUMP-LESS-THAN-XCT-NEXT M-D A-I BFXMPY-LOOP)
       ((M-D) ADD M-D (A-CONSTANT 1))
	(POPJ)

;Bignum in M-Q divided by bignum in M-B to give rational, returned on stack.
BDIV
	((PDL-PUSH) M-Q)
	((PDL-PUSH) M-B)
	((PDL-PUSH) M-Q)
	((PDL-PUSH) M-B)
;This really should do the division once getting a quotient and remainder
;so it only has to be done once if the quotient comes out even.
	(CALL XGCD)		;Get GCD into M-T.
	(JUMP NORMALIZED-RATIONAL-TO-STACK)

;Fixnum (unpacked in M-2) divided by bignum (in M-T and M-Q) to give a rational (on stack).
;The bignum's header is in M-C.
FXBDIV
	(JUMP-EQUAL M-2 A-ZERO QDIV-ZERO)
	((M-1) M-2)
	(CALL FIXPACK-P)	;Push packed fixnum, then push the bignum.
	((PDL-PUSH) M-Q)
	((VMA-START-READ M-B) M-Q)
	(CHECK-PAGE-READ)
	(CALL GCD-FIX-BIG)
	(JUMP NORMALIZED-RATIONAL-TO-STACK)
	
;Bignum (in M-Q) divided by fixnum (unpacked in M-2) to give rational (on stack).
BFXDIV
	((M-T PDL-PUSH) Q-TYPED-POINTER M-Q);Must not push after popj'ing since next insn may pop.
	(POPJ-EQUAL M-2 (A-CONSTANT 1))
	((M-1) M-2)
	(CALL FIXPACK-P)	;Put fixnum on stack and in M-T.
	((PDL-PUSH) M-Q)
	(CALL BFXDIV1)
	(PDL-POP)
;If remainder is 0, just return the quotient (which is in M-T).
	(JUMP-EQUAL M-3 A-ZERO BFXDIV-EVEN)
;Stack now has bignum, fixnum.  M-3 has remainder from division.
	((M-1) M-3)
	((M-2) OUTPUT-SELECTOR-EXTEND-25 PDL-TOP)
	(CALL GCD-FIX-FIX)
	(JUMP NORMALIZED-RATIONAL-TO-STACK)

BFXDIV-EVEN
	(POPJ-AFTER-NEXT PDL-POP)
       ((PDL-TOP) M-T)

;Make a rational number from two nonzero boxed args (num and denom) on the stack,
;given their gcd in M-T.  The value is returned on the stack.
NORMALIZED-RATIONAL-TO-STACK
	(JUMP-EQUAL-XCT-NEXT M-T (A-CONSTANT (PLUS (BYTE-VALUE Q-DATA-TYPE DTP-FIX) 1))
		NORMALIZED-RATIONAL-ALREADY)
       ((M-A) PDL-POP)
	((PDL-PUSH) M-T)
	((PDL-PUSH) M-A)
;Stack now has arg 1, gcd, arg 2.  M-T has gcd.
	(CALL QIDIV)
;Stack now has arg 1, gcd, final denominator.
	((M-A) SETA PDL-POP A-T)	;Pop stack, get value from M-T.
				;The same value is in both places, but pdl was just written.
	((M-A) Q-TYPED-POINTER M-A)
	((M-T) PDL-POP)
	((M-1) PDL-POP)
	(JUMP-EQUAL M-A (A-CONSTANT (PLUS (BYTE-VALUE Q-DATA-TYPE DTP-FIX) 1))
		NORMALIZED-RATIONAL-IS-INTEGER)
	(JUMP-EQUAL M-A (A-CONSTANT (PLUS (BYTE-VALUE Q-DATA-TYPE DTP-FIX)
					  (BYTE-MASK BOXED-SIGN-BIT)
					  (BYTE-MASK BOXED-NUM-EXCEPT-SIGN-BIT)))
		NORMALIZED-RATIONAL-IS-INTEGER-BUT-NEGATE)
	((PDL-PUSH) M-A)
	((PDL-PUSH) M-1)
;Stack now has final denominator, arg 1; M-T has gcd.
	(CALL QIDIV)
;Stack now has final denominator, final numerator.  Numerator also in M-T.
;If denominator is negative, change both signs.
NORMALIZED-RATIONAL-FIX-SIGNS
	((M-J) SETA PDL-POP A-T)	;Pop stack, but get from M-T
				;since the stack was possibly pushed on previous cycle.
	((PDL-PUSH) PDL-TOP)
	(CALL XMINUSP)
	(JUMP-EQUAL M-T A-V-NIL NORMALIZED-RATIONAL-RIGHT-SIGNS)
	(CALL XMINUS)
	((PDL-PUSH) M-T)
	((PDL-PUSH) M-J)
	(CALL XMINUS)
	((M-J) M-T)
NORMALIZED-RATIONAL-RIGHT-SIGNS
	((PDL-PUSH) M-J)
	(JUMP-XCT-NEXT MAKE-RATIONAL)
       ((MICRO-STACK-DATA-PUSH) (A-CONSTANT (I-MEM-LOC M-T-TO-CPDL)))

;Jump here if GCD is 1.  Numerator on stack, denom in M-A.
NORMALIZED-RATIONAL-ALREADY
	((M-T) PDL-POP)
	((PDL-PUSH) M-A)
	((PDL-PUSH) M-T)
;Stack now has final denominator, final numerator.
	(JUMP NORMALIZED-RATIONAL-FIX-SIGNS)

;Jump here if GCD equals the denominator.	
NORMALIZED-RATIONAL-IS-INTEGER
	((PDL-PUSH) M-1)	;Divide the 1st arg by the gcd
	(JUMP QIDIV)		;and return, leaving that on the stack as the answer.

;Here if the GCD is minus the demoninator.
NORMALIZED-RATIONAL-IS-INTEGER-BUT-NEGATE
	(CALL-XCT-NEXT QIDIV)
       ((PDL-PUSH) M-1)
	(JUMP-XCT-NEXT XMINUS)
       ((MICRO-STACK-DATA-PUSH) (A-CONSTANT (I-MEM-LOC M-T-TO-CPDL)))

;Bignum divided by a fixnum to give an integer quotient on the stack.
;A remainder, in unpacked form, is in M-K.
BFXIDIV
	((MICRO-STACK-DATA-PUSH) (A-CONSTANT (I-MEM-LOC M-T-TO-CPDL)))
BFXDIV1
	(CALL-EQUAL M-2 A-ZERO TRAP)
		(ERROR-TABLE DIVIDE-BY-ZERO)
		(ERROR-TABLE ARG-POPPED M-Q M-T)
	(JUMP-GREATER-THAN M-2 A-ZERO BFXIDIV-1)
	((M-C) XOR M-C (A-CONSTANT (BYTE-VALUE BIGNUM-HEADER-SIGN 1)))	;If fixnum is negative
	((M-2) SUB M-ZERO A-2)	;then change sign of both args.
BFXIDIV-1
	(CALL-XCT-NEXT BNCONS)
       ((M-B) ADD M-I (A-CONSTANT 1))
	((M-R) M-T)
	(CALL-XCT-NEXT DIVIDE-ONCE)	;divide once stores into bignum in M-R,M-J
       ((M-J) M-I)
	((M-D) M-I)		;current length
	((VMA-START-READ) ADD M-T A-D)	;read last word to see if it is zeros
	(CHECK-PAGE-READ)
	((M-3) M-1)		;save remainder.  Can not do this in a typed register.
	(JUMP-NOT-EQUAL-XCT-NEXT MD A-ZERO BCLEANUP)	;not zeros
       ((M-E) M-D)
	(JUMP-XCT-NEXT BCLEANUP)	;zeros so length should be M-D - 1
       ((M-E) SUB M-E (A-CONSTANT 1))

;; DIVIDE-ONCE divides bignum in M-Q,M-I by positive(!) number in M-2.
;; bashes M-1 M-3 M-TEM M-D
;; answer is stored in M-R,M-J
;; remainder is left in M-1
DIVIDE-ONCE
	((M-1) A-ZERO)
	((M-3) (A-CONSTANT 1))
	((M-D) M-I)
DIVIDE-ONCE-L
	((VMA-START-READ) ADD M-Q A-D)
	(CHECK-PAGE-READ)
	((M-TEM) DPB M-3 (BYTE-FIELD 30. 1) A-ZERO)
	((M-TEM1) DPB MD (BYTE-FIELD 31. 1) A-3)
	((Q-R) A-TEM1)
(REPEAT 31. ((M-1) DIVIDE-STEP M-1 A-2))
	(JUMP-GREATER-OR-EQUAL-XCT-NEXT M-D A-J DIVIDE-ONCE-1)
       ((M-3) Q-R)			;Save Q-R which is bashed by page faults
	((MD) (BYTE-FIELD 1 30.) Q-R A-TEM)
	((VMA-START-WRITE) M+A+1 M-R A-D)
	(CHECK-PAGE-WRITE)
DIVIDE-ONCE-1
	(JUMP-GREATER-THAN-XCT-NEXT M-D (A-CONSTANT 1) DIVIDE-ONCE-L)
       ((M-D) SUB M-D (A-CONSTANT 1))
	((Q-R) M-3)
	((M-1) DIVIDE-LAST-STEP M-1 A-2)
	((M-1) DIVIDE-REMAINDER-CORRECTION-STEP M-1 A-2)
	((MD) (BYTE-FIELD 31. 0) Q-R)
	(POPJ-AFTER-NEXT (VMA-START-WRITE) ADD M-R (A-CONSTANT 1))
       (CHECK-PAGE-WRITE)

;Fixnum divided by bignum is 0 except for -setz over +setz which is -1
FXBIDIV
	(POPJ-NOT-EQUAL-XCT-NEXT M-2 (A-CONSTANT NEGATIVE-SETZ))
       ((M-T C-PDL-BUFFER-POINTER-PUSH) (A-CONSTANT (PLUS (BYTE-VALUE Q-CDR-CODE CDR-NEXT)
							  (BYTE-VALUE Q-DATA-TYPE DTP-FIX))))
	(POPJ-IF-BIT-SET BIGNUM-HEADER-SIGN M-C)
	(POPJ-NOT-EQUAL M-I (A-CONSTANT 1))
	((VMA-START-READ) ADD M-Q (A-CONSTANT 1))
	(CHECK-PAGE-READ)
	(POPJ-AFTER-NEXT POPJ-NOT-EQUAL MD (A-CONSTANT POSITIVE-SETZ))
       ((M-T C-PDL-BUFFER-POINTER) DPB M-MINUS-ONE Q-POINTER A-T)

BFXGRP 
FXBLSP
	((M-T) A-V-NIL)
	(POPJ-AFTER-NEXT POPJ-IF-BIT-SET BIGNUM-HEADER-SIGN M-C)
       ((M-T) A-V-TRUE)

BFXLSP 
FXBGRP
	((M-T) A-V-TRUE)
	(POPJ-AFTER-NEXT POPJ-IF-BIT-SET BIGNUM-HEADER-SIGN M-C)
       ((M-T) A-V-NIL)

BFXMIN 
FXBMIN
	((M-T) M-Q)			;neg. bignums are less than fixnums!
	(POPJ-AFTER-NEXT POPJ-IF-BIT-SET BIGNUM-HEADER-SIGN M-C)
       ((M-T) DPB M-2 Q-POINTER (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))
	
BFXMAX 
FXBMAX
	((M-T) M-Q)			;positive bignums are greater than fixnums!
	(POPJ-AFTER-NEXT POPJ-IF-BIT-CLEAR BIGNUM-HEADER-SIGN M-C)
       ((M-T) DPB M-2 Q-POINTER (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))


;; First arg a bignum second a fixnum.  The bignum is expressed in the base of the fixnum
;; and stuffed in to an appropriate art-q array.
(MISC-INST-ENTRY BIGNUM-TO-ARRAY)
BIG-TO-ARY
	((M-A) Q-TYPED-POINTER C-PDL-BUFFER-POINTER-POP)
	((M-Q) Q-TYPED-POINTER C-PDL-BUFFER-POINTER-POP)
    (ERROR-TABLE RESTART BIG-TO-ARY)
	(CALL-DATA-TYPE-NOT-EQUAL M-Q
		(A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-EXTENDED-NUMBER)) TRAP)
    (ERROR-TABLE ARGTYP BIGNUM M-Q 0 BIG-TO-ARY)
    (ERROR-TABLE ARG-POPPED 0 M-Q M-A)
	(DISPATCH Q-DATA-TYPE M-A TRAP-UNLESS-FIXNUM)
    (ERROR-TABLE ARGTYP FIXNUM M-A 1 BIG-TO-ARY)
    (ERROR-TABLE ARG-POPPED 0 M-Q M-A)
	((VMA-START-READ) M-Q)
	(CHECK-PAGE-READ)
	(DISPATCH TRANSPORT-HEADER READ-MEMORY-DATA)
	((M-TEM) HEADER-TYPE-FIELD MD)
	(CALL-NOT-EQUAL M-TEM (A-CONSTANT (EVAL %HEADER-TYPE-BIGNUM)) TRAP)
    (ERROR-TABLE ARGTYP BIGNUM M-Q 0 BIG-TO-ARY)
    (ERROR-TABLE ARG-POPPED 0 M-Q M-A)
	((M-Q) VMA)		;get transported number address 
	((M-I) BIGNUM-HEADER-LENGTH MD)
	((M-1) Q-POINTER M-A)
	(CALL-XCT-NEXT XHAUL1)	;M-T gets number of bits in M-A LESS ONE(!)
       ((M-T) A-MINUS-ONE)
	;; we must allocate an array at least 31*I/T long
	;; 31*I = 32*I - I
	((M-1) DPB M-I (BYTE-FIELD (DIFFERENCE Q-POINTER-WIDTH (PLUS 1 5)) 5) A-ZERO)
	((M-1) SUB M-1 A-I)
	(CALL-XCT-NEXT DIV)
       ((M-2) Q-POINTER M-T)
	(JUMP-EQUAL-XCT-NEXT M-1 A-ZERO BIG-TO-ARY-1)	;If no remainder then we are o.k.
       ((M-C) Q-R)
	((M-C) ADD M-C (A-CONSTANT 1))	;with remainder then allocate 1 more
BIG-TO-ARY-1
;	(CALL-XCT-NEXT SCONS-D)	;Allocate space for art-q array
;      ((M-B) ADD M-C (A-CONSTANT 2))
     ;; Allocate (+ M-C 2) words of boxed structure storage.
        ((pdl-push) m-a)	;Cons routines now clobber M-A.
        ((m-b) add m-c (a-constant 2))
        (call-xct-next allocate-structure-storage-default)
       ((m-a) m-b)
	((m-a) pdl-pop)		;Restore M-A.
	((MD) (A-CONSTANT (PLUS (BYTE-VALUE Q-DATA-TYPE DTP-ARRAY-HEADER)
				(BYTE-VALUE %%ARRAY-NUMBER-DIMENSIONS 1)
				(BYTE-VALUE %%ARRAY-LONG-LENGTH-FLAG 1)
				(EVAL ART-Q))))
	((VMA-START-WRITE M-R) Q-POINTER M-T
			       (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-ARRAY-POINTER)))
	(CHECK-PAGE-WRITE)
	((MD) Q-POINTER M-C (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))
	((VMA-START-WRITE) ADD M-R (A-CONSTANT 1))
	(CHECK-PAGE-WRITE)
	;; now we have the array in M-R with length in M-C
	;; we must now allocate a bignum to divide into.
	(call-xct-next allocate-bignum-storage)
       ((m-b) add m-i (a-constant 1))
	((MD) ADD M-I (A-CONSTANT (PLUS (BYTE-VALUE Q-DATA-TYPE DTP-HEADER)
					(BYTE-VALUE HEADER-TYPE-FIELD %HEADER-TYPE-BIGNUM))))
	((VMA-START-WRITE M-T) Q-POINTER M-T
			       (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-EXTENDED-NUMBER)))
	(CHECK-PAGE-WRITE)
	;; now we have a (temp.) bignum in M-T so we start to divide
	((M-E) M-R)		;move the array into M-E
	((M-B) M-I)		;save length of bignum
	((M-2) Q-POINTER M-A)	;fixnum to divide by
	((M-A) (A-CONSTANT 1))	;index+1 into array
	((M-R) M-T)
	(CALL-XCT-NEXT DIVIDE-ONCE)
       ((M-J) M-I)
	((M-Q) M-R)		;from now on we divide from the temp bignum to itself.
BIG-TO-ARY-L
	((MD) Q-POINTER M-1 (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))
	((VMA-START-WRITE) M+A+1 M-E A-A)	;write remainder.
	(CHECK-PAGE-WRITE)
	((VMA-START-READ) ADD M-R A-J)	;Check to see if last word of quotient was zero.
	(CHECK-PAGE-READ)
	(JUMP-NOT-EQUAL MD A-ZERO BIG-TO-ARY-2)
	(JUMP-EQUAL M-I (A-CONSTANT 1) BIG-TO-ARY-CLEANUP)	;bignum is zero, done
	((M-I) SUB M-I (A-CONSTANT 1))	;pretend bignum is shorter
BIG-TO-ARY-2
	(CALL-XCT-NEXT DIVIDE-ONCE)
       ((M-J) M-I)
	(JUMP-XCT-NEXT BIG-TO-ARY-L)
       ((M-A) ADD M-A (A-CONSTANT 1))

BIG-TO-ARY-CLEANUP
	((M-T) M-E)		;array to return
	((M-1) M-R)
	((M-D) M-A)		;M-A smashed by UN-CONS
	(CALL-XCT-NEXT UN-CONS)	;Give back the bignum
       ((M-2) ADD M-B (A-CONSTANT 1))
	(POPJ-EQUAL M-C A-D)	;all array used so return it!
	;; else give back unused end of array
	((MD) Q-POINTER M-D (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))
	((VMA-START-WRITE M-1) ADD M-T (A-CONSTANT 1))
	(CHECK-PAGE-WRITE)
	((M-1) M+A+1 M-1 A-D)
	(JUMP-XCT-NEXT UN-CONS)	;tail recursive call
       ((M-2) SUB M-C A-D)

;; First arg a art-q array second a fixnum third the sign bit (zero or one).
;; Returns a bignum. Inverse of BIGNUM-TO-ARRAY
(MISC-INST-ENTRY ARRAY-TO-BIGNUM)
(ERROR-TABLE DEFAULT-ARG-LOCATIONS ARRAY-TO-BIGNUM PP M-J M-C)
ARY-TO-BIG
	((M-C) Q-TYPED-POINTER C-PDL-BUFFER-POINTER-POP)	;sign bit.
	((M-J) Q-TYPED-POINTER C-PDL-BUFFER-POINTER-POP)	;fixnum.
    (ERROR-TABLE RESTART ARY-TO-BIG)
	(DISPATCH Q-DATA-TYPE M-C TRAP-UNLESS-FIXNUM)
    (ERROR-TABLE ARGTYP FIXNUM M-C 2 ARY-TO-BIG)
	(DISPATCH Q-DATA-TYPE M-J TRAP-UNLESS-FIXNUM)
    (ERROR-TABLE ARGTYP FIXNUM M-J 1 ARY-TO-BIG)
	((M-C) DPB M-C BIGNUM-HEADER-SIGN A-ZERO)
	((M-J) Q-POINTER M-J)
	(CALL-XCT-NEXT GAHDR)			;array.
       ((m-a) invalidate-array-cache c-pdl-buffer-pointer-pop)
	(call store-array-registers-in-accumulators)
	(CALL-IF-BIT-SET (LISP-BYTE %%ARRAY-DISPLACED-BIT) m-b trap)
    (ERROR-TABLE ARGTYP NON-DISPLACED-ARRAY PP 0)
	((M-B) SELECTIVE-DEPOSIT M-b (LISP-BYTE %%ARRAY-TYPE-FIELD) A-ZERO)
	(CALL-NOT-EQUAL M-B (A-CONSTANT (EVAL ART-Q)) trap)
    (ERROR-TABLE ARGTYP ART-Q-ARRAY PP 0)
	(CALL-NOT-EQUAL M-D (A-CONSTANT 1) trap)
    (ERROR-TABLE ARRAY-NUMBER-DIMENSIONS M-D 1 PP)
	;; now we have the array in M-A (origin in M-E, length in M-S)
	;; sign bit in correct spot in M-C
	;; fixnum in M-J (unboxed)
	((M-T) A-ZERO)
	(CALL-XCT-NEXT XHAUL1)			;Get # bits per array element
       ((M-1) M-J)
	((M-1) M-T)				;Size of bignum in bits
	(CALL-XCT-NEXT MPY)
       ((Q-R) m-s)
	(CALL-NOT-EQUAL M-2 A-ZERO trap)
		(ERROR-TABLE ARGTYP REASONABLE-SIZE-ARRAY M-A)
	((M-1) Q-R)
	(CALL-XCT-NEXT DIV)			;Get size of bignum in words
       ((M-2) (A-CONSTANT 31.))
	((M-I) ADD Q-R (A-CONSTANT 1))
	;; we have now computed the amount of space to allocate for the bignum.
	;; The formula is I := 1+(haulong J)*S/31.
	((M-R) M-E)		;shuffle (origin of array)
	((M-D) M-S)		;suuffle (length of array)
	(CALL-XCT-NEXT BNCONS)
       ((M-B) ADD M-I (A-CONSTANT 1))
	((M-S) M-D)		;unshuffle (length of array)
	((M-2) M-J)		;"radix"
	;; now we have the array in M-A (origin in M-R length in M-S),
	;; we have the fixnum in M-2, we have the bignum in M-T (header in M-C, length in M-I)
	;; first we must zero the bignum.
	((M-D) (A-CONSTANT 1))
	((MD) A-ZERO)
ARY-TO-BIG-2
	((VMA-START-WRITE) ADD M-T A-D)
	(CHECK-PAGE-WRITE)
	(JUMP-LESS-THAN-XCT-NEXT M-D A-I ARY-TO-BIG-2)
       ((M-D) ADD M-D (A-CONSTANT 1))
	((M-Q) M-T)		;copy in M-Q
	;; now we start:
	((M-S) SUB M-S (A-CONSTANT 1))
ARY-TO-BIG-L
	((VMA-START-READ) ADD M-R A-S)
	(CHECK-PAGE-READ)
	(CALL-XCT-NEXT MULTIPLY-ONCE)
       ((M-1) Q-POINTER MD)
	(CALL-NOT-EQUAL M-1 A-ZERO ILLOP)	;overflow (should never happen)
	(JUMP-GREATER-THAN-XCT-NEXT M-S A-ZERO ARY-TO-BIG-L)
       ((M-S) SUB M-S (A-CONSTANT 1))
	;; now we see how many zeros we have at the end
BIGNUM-DPB-CLEANUP	;Enters here with bignum in M-T, header in M-C
			;Use this only for logical operations, not arithmetic
			; ones!  Note the treatment of negative zero!
	((M-E) BIGNUM-HEADER-LENGTH M-C)
	((M-D) BIGNUM-HEADER-LENGTH M-C)
ARY-TO-BIG-CLEANUP
	((VMA-START-READ) ADD M-T A-E)
	(CHECK-PAGE-READ)
	(JUMP-NOT-EQUAL MD A-ZERO BCLEANUP)
	(JUMP-GREATER-THAN-XCT-NEXT M-E (A-CONSTANT 1) ARY-TO-BIG-CLEANUP)
       ((M-E) SUB M-E (A-CONSTANT 1))
	;; Number is nothing but sign bits
#+lambda((OA-REG-HIGH) BIGNUM-HEADER-SIGN M-C)
#+exp	((m-tem3) bignum-header-sign m-c)
#+exp	((oa-reg-high) dpb m-tem3 oah-m-src a-zero)
	((M-TEM) M-ZERO)
	((M-1) Q-POINTER M-T)				;For UN-CONS
	(JUMP-XCT-NEXT BCLEANUP-1)
       ((M-2) ADD M-D (A-CONSTANT 1))

;; Clean up and return a bignum in M-T. Hands back storage and checks for fixnums.
;; Bignum in M-T, header in M-C, length in M-D, actual length in M-E (# of non-zero words).
BCLEANUP	;must not clobber M-3
	(JUMP-GREATER-THAN M-E (A-CONSTANT 1) BCLEANUP-X)  ;Could answer be a fixnum?
	((VMA-START-READ) ADD M-T (A-CONSTANT 1))
	(CHECK-PAGE-READ)
	((M-1) Q-POINTER M-T)				;For UN-CONS
	((M-2) ADD M-D (A-CONSTANT 1))
	((M-A)
	 (BYTE-FIELD (DIFFERENCE 33. Q-POINTER-WIDTH)
		     (DIFFERENCE Q-POINTER-WIDTH 1))
	 MD)			;All but 23 low bits
	(JUMP-NOT-EQUAL-XCT-NEXT M-A A-ZERO BCLEANUP-SETZP)	;no. (unless it is SETZ)
       ((M-TEM) MD)
	(JUMP-IF-BIT-CLEAR BIGNUM-HEADER-SIGN M-C BCLEANUP-1)
	((M-TEM) SUB M-ZERO A-TEM)				;Its negative.
BCLEANUP-1
	(JUMP-XCT-NEXT UN-CONS)
       ((M-T) Q-POINTER M-TEM (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-FIX)))

BCLEANUP-SETZP
	(JUMP-NOT-EQUAL M-TEM (A-CONSTANT POSITIVE-SETZ) BCLEANUP-X)	;Is it setz?
	(JUMP-IF-BIT-SET BIGNUM-HEADER-SIGN M-C BCLEANUP-1)
BCLEANUP-X
	(POPJ-EQUAL M-D A-E)
	((M-2) SUB M-D A-E)			;Number of unused words at end
	((M-C) SUB M-C A-2)			;Fix the header
	((MD) ADD M-C (A-CONSTANT (PLUS (BYTE-VALUE Q-DATA-TYPE DTP-HEADER)
					(BYTE-VALUE HEADER-TYPE-FIELD %HEADER-TYPE-BIGNUM))))
	((VMA-START-WRITE M-1) Q-POINTER M-T)
	(CHECK-PAGE-WRITE)
	((M-1) M+A+1 M-1 A-E)
	(JUMP UN-CONS)
))

