Google
 

Trailing-Edge - PDP-10 Archives - BB-AS80B-SM_1985 - sources/arith.mic
There are 5 other files named arith.mic in the archive. Click here to see a list.
.TOC	"ADD, SUB"

	.DCODE
270:	R-PF,	AC,	J/ADD
	I-PF,	AC,	J/ADD
	RPW,	M,	J/ADD
	RPW,	B,	J/ADD
	.UCODE

=0****00****
ADD:	AR_AR*AC0,AD/A+B,AD FLAGS,EXIT
=


	.DCODE
274:	R-PF,	AC,	J/SUB
	I-PF,	AC,	J/SUB
	RPW,	M,	J/SUB
	RPW,	B,	J/SUB
	.UCODE

=0****00****
SUB:	AR_AC0,BR/AR
=	AR_AR-BR,AD FLAGS,EXIT
.TOC	"MUL, IMUL"

	.DCODE
220:	R,	AC,	J/IMUL
	I,	AC,	J/IMULI
	RW,	M,	J/IMUL
	RW,	B,	J/IMUL
	.UCODE

.IFNOT/IMULI.OPT
=0****00*01*
IMULI:
.IF/IMULI.OPT
=0****00*000
IMULI:	SKP AR18,GEN AC0,SIGNS DISP,	;OPTIMIZE SPECIAL CASE
		TIME/3T,SC_#,#/17.
=010	MQ_AR,AR_AC0,			;HERE FOR IMULI OF + BY +
		CLR ARX,FE_#,#/-9.,	; 9 STEPS WILL DO
		CALL,J/MULSUB
.ENDIF/IMULI.OPT
IMUL:	MQ_AR,AR_AC0,			;M'IER TO MQ, M'CAND TO AR
		CLR ARX,FE_#,#/-18.,
		CALL,J/MULSUB		;CALL MULTIPLY SUBROUTINE
.IF/IMULI.OPT
=110	AR_SHIFT,SKP AR NE,INH CRY18,	;HERE FROM IMULI
		I FETCH,J/MUL1		; AFTER SHORT MULTIPLY
.ENDIF/IMULI.OPT
	SC_#,#/35.,SKP AR SIG		;CHECK OVERFLOW AND STORE
=
=0
IMUL2:	AR_SHIFT,B WRITE,J/ST6		;STORE LOW WORD OF PRODUCT
	SET AROV,AR_SIGN,J/IMUL2	;NOTE OVERFLOW...


	.DCODE
224:	R,	DBL AC,	J/MUL
	I,	DBL AC,	J/MUL
	RW,	M,	J/MUL
	RW,	DBL B,	J/MUL
	.UCODE

=0****00*000
MUL:	MQ_AR,CLR ARX,			;MULTIPLIER TO MQ
		AR_AC0,FE_#,#/-18.,	;SETUP MULTIPLICAND AND STEP CNT
		CALL,J/MULSUB		;AND GO TO SUBROUTINE
=100	GEN AR*BR,AD/AND,SKP AD0	;M'IER NEG, CHECK M'CAND & PROD TOO
=110
MUL1:	SC_#,#/35.,EXIT			;STORE DOUBLE RESULT
	SET AROV,J/MUL1			;MUST HAVE SQUARED 400000,,0
=
.TOC	"MULTIPLY SUBROUTINE"
; ENTER WITH MULTIPLIER IN MQ,
; MULTIPLICAND IN AR!ARX, MINUS STEP COUNT IN FE
; RETURNS PRODUCT IN AR!ARX!MQ.
; RETURN 4, 6 TELLS SIGN OF MULTIPLIER
; 4 AND 6 ARE USED SO CALLER CAN IGNORE
; DIFFERENCE BY ALIGNMENT OF CALL LOC'N
;[TIME=4+2(-FE)+(# OF ARITH STEPS)] ... IF FE=-18, 40-58.
;
;Recall:
; MUL		"FE_FE+1,DISP/MUL,MQ/MQ*.25"
;

MULSUB:	BR_AR LONG,AR_0S,ARX_0S,	;M'CAND TO BR LONG, CLEAR PROD
		MUL,J/MULP		;START THE MULTIPLICATION
=000					;GRAB AN 8-WORD BLOCK
MULP:
.IF/MODEL.B
	(AR+ARX+MQ)*2,FE_SC,RETURN6	;XADDR MACHINE HAS
	(AR+ARX+MQ)*2,FE_SC,RETURN6	; NO "CRA MUL DONE"
	(AR+ARX+MQ)*2,FE_SC,RETURN6
.ENDIF/MODEL.B
=011	(AR+ARX+MQ)*2,FE_SC,RETURN6	;DISCARD REDUNDANT SIGN BIT

=100	AR_AR*.25 LONG,MUL,J/MULP	;M'IER BITS 00 AFTER POS STEP
	AR_(AR+BR)*.25,ARX/ADX*.25,	;01 AFTER +
		MUL,J/MULP
	AR_(AR-2BR)*.25,ARX/ADX*.25,	;10 AFTER +
		MUL,J/MULM
	AR_(AR-BR)*.25,ARX/ADX*.25,
		MUL,J/MULM		;11 AFTER +

=000					;ANOTHER 8-WORD BLOCK FOR
MULM:					; AFTER SUBTRACTION STEPS
.IF/MODEL.B
	(AR+ARX+MQ)*2,FE_SC,RETURN4
	(AR+ARX+MQ)*2,FE_SC,RETURN4
	(AR+ARX+MQ)*2,FE_SC,RETURN4
.ENDIF/MODEL.B
=011	(AR+ARX+MQ)*2,FE_SC,RETURN4	;M'IER WAS NEGATIVE

=100	AR_(AR+BR)*.25,ARX/ADX*.25,	;M'IER BITS 00 AFTER NEG STEP
		MUL,J/MULP
	AR_(AR+2BR)*.25,ARX/ADX*.25,	;01 AFTER -
		MUL,J/MULP
	AR_(AR-BR)*.25,ARX/ADX*.25,	;10 AFTER -
		MUL,J/MULM
	AR_AR*.25 LONG,MUL,J/MULM	;11 AFTER -

;HERE TO CONTINUE A LONG MULTIPLICATION
; WITH PARTIAL PRODUCT IN AR LONG

MULREE:	AD/0S,MUL,J/MULP		;DIVE IN WITHOUT CLOBBERING AR
.TOC	"DIV, IDIV"

	.DCODE
230:	R,	DBL AC,	J/IDIV
	I,	DBL AC,	J/IDIV
	RW,	M,	J/IDIV
	RW,	DBL B,	J/IDIV

234:	R,	DBL AC,	J/DIV
	I,	DBL AC,	J/DIV
	RW,	M,	J/DIV
	RW,	DBL B,	J/DIV
	.UCODE

=0****00*000
DIV:	BR/AR,ARX+MQ_0.M,		;DIVISOR TO BR
		AR_AC1*2,ARL/AD*2,	;LOW DIVIDEND TO AR
		CALL.M,J/DIV1		;GET HIGH DIVIDEND
.IF/MODEL.B
IDIV:	BR/AR, AR_1, J/IDIV2		;[236]
IDIV1:	BR/AR,ARX+MQ_0.M,SC_1,		;DIVISOR TO BR
		AR_AC0,ARL/AD,CALL.M,	;DIVIDEND TO AR
		SKP AR0,J/DIV2		;TEST DIVISOR SIGN
.IFNOT/MODEL.B
=10
IDIV:	BR/AR,ARX+MQ_0.M,SC_1,		;DIVISOR TO BR
		AR_AC0,ARL/AD,CALL.M,	;DIVIDEND TO AR
		SKP AR0,J/DIV2		;TEST DIVISOR SIGN
.ENDIF/MODEL.B
=011
NODIVD:	SET NO DIVIDE,J/NOP		;HERE IF DIVIDE IMPOSSIBLE

=110	ARX_AR,AR_-BRX,			;REMAIN TO ARX, GET CORRECT QUOTIENT
		SC_#,#/36.,EXIT
	ARX_AR,AR_BRX,			;HERE FOR POS QUOTIENT
		SC_#,#/36.,EXIT
=
.IF/MODEL.B
IDIV2:	GEN AR-BR, SKP AD NE		;[236] IS DIVISOR = 1?
=0	AR_AC0, CLR ARX, SC_#, #/36.,	;[236] YES, ANSWER IS AC0.
		EXIT			;[236]
	AR_BR, J/IDIV1			;
.ENDIF/MODEL.B
;HERE ON DIVIDE TO SET UP DIVIDEND

DIV1:	BRX/ARX,ARX_AR,AR_AC0,		;CLR BRX, DIVIDEND IN AR LONG
		FE_#,#/33.,TIME/3T,	;SETUP ITERATION COUNT
		SIGNS DISP,J/DIVS1	;ENTER SUBR

;HERE ON IDIV TO SET UP DIVIDEND.  SKIP IF DIVISOR NEG
; ALSO CALLED BY ADJBP
=0
DIV2:	BRX/ARX,ARX_SHIFT,AR_SIGN,	;CLR BRX, DIVIDEND TO AR LONG
		FE_#,#/33.,		;SETUP LOOP COUNT
		SKP AR0,J/DIVS1		;ENTER SUBR ACCORDING TO SIGNS
	BRX/ARX,ARX_SHIFT,AR_SIGN,	;CLR BRX, DIVIDEND TO AR LONG
		FE_#,#/33.,		;SETUP LOOP COUNT
		SKP AR0,J/DIVS2		;ENTER SUBR ACCORDING TO SIGNS
.TOC	"INTEGER DIVIDE SUBROUTINE"
; ENTER WITH SIGNS DISPATCH OF DIVISOR AND DIVIDEND,
; DIVISOR IN BR, BRX CLR; DIVIDEND IN AR!ARX
; STEP COUNT IN FE (# OF QUOTIENT BITS -2)
; IF NO DIVIDE, RETURN 3 WITH IFETCH STARTED
; OTHERWISE, RETURN WITH SIGNED REMAINDER IN AR,
; POSITIVE QUOTIENT IN BRX AND MQ.
; RETURN 6 IF QUOTIENT SHOULD BE NEGATIVE,
; RETURN 7 IF QUOTIENT SHOULD BE POSITIVE.
;[TIME=14+3(FE)+3(D'END NEG)+3(RESTORE REQ'D)+1(REMAINDER NEG)]
; ... IF FE=33, 113-120
;
;Recall:
; DIVIDE	"FE_FE-1,DISP/DIV,MQ/MQ*2"
;
=1100
DIVS1:	DIVIDE,AR_2(AR-BR),
		ARX/ADX*2,J/DIVS3	;BOTH D'END AND D'SOR POS
	AR_-AR LONG,J/DIVS1		;MAKE POS DIVIDEND, THEN CHK
DIVS2:	DIVIDE,AR_2(AR+BR),
		ARX/ADX*2,J/DIVS4	;D'END POS, D'SOR NEG
	AR_-AR LONG,J/DIVS2

=010
DIVS3:	DIVIDE,AR_2(AR+BR),ARX/ADX*2,
		ARL/AD*2,CALL.M,J/DIVLP	;START DIVIDING
	I FETCH,RETURN3			;RETURN TO CALLER WITH NO DIVIDE

	AR_-BR,BRX/ARX,RETURN6		;D'END NEG, SO NEGATE QUO & REM
	BRX/ARX,RETURN7			;EVERYTHING POSITIVE


=010
DIVS4:	DIVIDE,AR_2(AR-BR),ARX/ADX*2,
		ARL/AD*2,CALL.M,J/DIVLP	;BEGIN DIVISION FOR REAL BITS
	I FETCH,RETURN3			;ABORT FOR IMPOSSIBLE DIVISION

	BRX/ARX,RETURN6			;NEGATE QUO
	AR_-BR,BRX/ARX,RETURN7		;NEGATE REM
.TOC	"BASIC DIVIDE LOOP"
; THE LOOP ITSELF IS AN INNER SUBROUTINE, TO MAKE IT SUITABLE
; FOR USE IN DOUBLE-LENGTH DIVISION.
; THE DOUBLE LENGTH REMAINDER IS RETURNED IN BR!BRX (RESTORED)
; THE SINGLE LENGTH QUOTIENT (LOW PART IF DBL-LEN DIVISION) IN ARX
; RETURN 6 IF QUOTIENT (REALLY AC0.XOR.BR) NEGATIVE, OR 7 IF POSITIVE
;[TIME=12+3(FE)+3(RESTORE REQ'D)] ... IF FE=33, 111-114.

=000
DIVLP:	DIVIDE,AR_2(AR+BR),ARX/ADX*2,J/DIVLP
	DIVIDE,AR_2(AR-BR),ARX/ADX*2,J/DIVLP
DIV-:	DIVIDE,AR_2(AR-BR),ARX/ADX*2,J/DIVLP
DIV+:	DIVIDE,AR_2(AR+BR),ARX/ADX*2,J/DIVLP
	DIVIDE,AR_AR+BR,ARX/ADX,J/DIVX
	DIVIDE,AR_AR-BR,ARX/ADX,J/DIVX
	DIVIDE,AR_AR-BR,ARX/ADX,J/DIVX		;NO SHIFT ON FINAL STEP
	DIVIDE,AR_AR+BR,ARX/ADX,J/DIVX

;HERE AFTER FINAL DIVIDE STEP
; MQ HAS POSITIVE FORM QUOTIENT
; AR!ARX HAS REMAINDER, EXCEPT THAT IT MUST BE RESTORED IF IT IS
; NEGATIVE (IT'S NEGATIVE IF THERE WAS NO CARRY ON FINAL STEP)
; THE ORIGINAL DIVIDEND IS STILL IN AC0, SO WE CHECK ITS SIGN
; TO DETERMINE WHETHER TO NEGATE THE (RESTORED) REMAINDER.

=100
DIVX:	AR_AR+BR LONG			;RESTORE REMAIN WITH POS D'SOR
	BR_AR LONG,ARX/MQ,FE_SC,	;LONG REMAIN TO BR, QUO TO ARX
		SKP AC0+,RETURN6	;RETURN TESTING D'END SIGN
	AR_AR-BR LONG			;RESTORE REMAIN WITH NEG D'SOR
	BR_AR LONG,ARX/MQ,FE_SC,
		SKP AC0-,RETURN6


;SUBROUTINE FOR FIRST PART OF LONG DIVISIONS
; ENTER AT DDVSUB WITH SKP BR0
; RETURN3 IF SHOULD RESUME WITH ADD STEP
; RETURN5 IF SHOULD RESUME WITH SUBTRACT

=000
DDVLP:	AR_2(AR+BR),ARX/ADX*2,DIVIDE,J/DDVLP
	AR_2(AR-BR),ARX/ADX*2,DIVIDE,J/DDVLP
DDVSUB:	AR_2(AR-BR),ARX/ADX*2,DIVIDE,J/DDVLP
	AR_2(AR+BR),ARX/ADX*2,DIVIDE,J/DDVLP
	AR_MQ,MQ_AR,FE_#,#/32.,RETURN3
	AR_MQ,MQ_AR,FE_#,#/32.,RETURN5
	AR_MQ,MQ_AR,FE_#,#/32.,RETURN5
	AR_MQ,MQ_AR,FE_#,#/32.,RETURN3
.TOC	"DOUBLE INTEGER ARITHMETIC -- DADD, DSUB, DMUL, DDIV"

	.DCODE
.IFNOT/DBL.INT
114:	EA,	J/UUO
	EA,	J/UUO
	EA,	J/UUO
	EA,	J/UUO
.IF/DBL.INT
114:	R,	B/0,	J/DASMD		;DADD
	R,	B/2,	J/DASMD		;DSUB
	R,	B/4,	J/DASMD		;DMUL
	R,		J/DDIV
	.UCODE

;HERE FOR DOUBLE WORD ADD, SUBTRACT, MULTIPLY, OR DIVIDE
;ENTER WITH (E) IN AR, E IN VMA

=0****00**00
DDIV:	ARX_AC3,CLR MQ,J/DDIV0		;GET LOWEST PART OF D'END

DASMD:	BR/AR,AR_AC1*2,ARL/AD*2,	;HIGH MEM WORD TO BR
		VMA_VMA+1,LOAD ARX,	;ASK FOR LOW WORD
		MQ_0.S,CALL.S,J/XFERW	;AND WAIT FOR IT
=11	ARX_ARX*2			;SHIFT LOW MEM WORD LEFT
=	BRX/ARX,ARX_AR,AR_AC0,		;ALL DATA IN PLACE
		SC_#,#/35.,B DISP	;DO THE OPERATION

;HERE WITH (E) IN BR, (E+1)*2 IN BRX
; (AC) IN AR, (AC+1)*2 IN ARX

=00*	AR_AR+BR LONG,AD FLAGS,EXIT DBL	;DADD

	AR_AR-BR LONG,AD FLAGS,EXIT DBL	;DSUB

	MQ_SHIFT,AR_0S,ARX_0S,		;DMUL, USE AC1 AS INITIAL M'IER
		FE_#,#/-18.,J/DMULT	;SETUP STEP COUNT
=
;HERE FOR DOUBLE WORD MULTIPLY

=00*
DMULT:	AD/0S,MUL,CALL.M,J/MULP		;BEGIN MULTIPLY
=10*	AR_AR+BR LONG			;CANCEL EFFECTS OF LOW BIT 0
	MQ_AR,AR_MQ			;EXCH HI AND LOW PRODUCT WORDS

;HERE AFTER 1ST CALL ON MPY SUBR.  SAVE LOW WORD OF PROD, GET HIGH M'IER

	AC3_AR				;LOW WORD OF PRODUCT
	AR_AC0				;GET HIGH M'IER WORD
=000	MQ_AR,AR_MQ,CALL,		;DIVE IN AGAIN
		FE_#,#/-18.,J/MULREE	;CONTINUE THE MULTIPLY
=100	GEN AR*BR,AD/AND,SKP AD0	;SKP IF M'IER, M'CAND, & PROD NEG
=110
DMUL1:	AC0_AR,AR_SIGN,
		SC_#,#/35.,J/DMUL2	;STORE HIGH WORD OF PRODUCT
	SET AROV,J/DMUL1

;MULTIPLY NOW COMPLETE, STORE RESULTS WITH PROPER SIGN IN BIT 0

DMUL2:	BR/AR,AR_SHIFT			;GET 2ND WITH SIGN, SAVE SIGN
	AC1_AR,AR_ARX,ARX/MQ		;READY TO BUILD 3RD WORD
	ARX_SHIFT,AR_BR,MQ_MQ*2		;SIGNIFICANT BITS TO ARX, SIGN TO AR
	AR_SHIFT,ARX_AC3,		;3RD WORD IN AR, GET LOW
		MQ_MQ*.25		;EXTRA PROD BIT TO MQ 35
	AC2_AR,AR_MQ			;,I FETCH WHEN TIMING FIXED
=0*	ARX_SHIFT,AR_BR,I FETCH,	;LOW WORD AND SIGN READY
		CALL,J/SHIFT		; GET LOW WORD TO AR
STRAC3:	AC3_AR,FINISH			;GANZ GETAN
;HERE FOR DOUBLE INTEGER DIVISION
;AR HAS (E), ARX HAS (AC3), AND MQ IS CLEAR

DDIV0:	T0_AR,AR_ARX,ARX_ARX*8,SC_1	;SAVE (E) IN T0
	BRX/ARX,ARX_SHIFT,		;AC3 3-35 TO BRX, 1-2 TO ARX
		AR_AC2,SC_#,#/2		;GET AC2 READY
	AR_SHIFT,BR/AR,			;AC2 BITS 2-35 WITH AC3 1-2
		ARX_AC1,VMA_VMA+1	;READY TO GET (E+1)
	BR/AR,AR_ARX,ARX_BR*2,		;LOW DOUBLE WORD NOW IN BR LONG
		SC_1,FE_1
	ARX_SHIFT,AR_AC0,SKP AD0	;HIGH DOUBLEWORD IN AR LONG
=0
DDIV1:	BR_AR LONG,AR_BRX,ARX_BR,	;HI POS D'END TO BR
		LOAD AR,J/DDIV2		;GET LOW D'SOR READY
	BR_AR LONG,AR_-BR LONG,		;NEGATE LOW D'END
		FE_-1,SKP CRY0		;TEST FOR CARRY PROPAGATION
=0	BR_AR LONG,AR_BR COMP LONG,J/DDIV1
	BR_AR LONG,AR_-BR LONG,J/DDIV1	;FINISH NEGATION OF D'END
=0*
DDIV2:	T1_AR,MQ_ARX,ARX_0S,		;LOWEST D'END TO T1, NEXT TO MQ
		CALL,J/XFERW		; WAIT FOR (E+1)
	ARX_SHIFT,AR_T0,SKP FE0		;DIVISOR NOW IN AR LONG
=0	AR_BR LONG,BR_AR LONG,		;PUT OPERANDS IN PLACE FOR DIV
		SIGNS DISP,J/DDIV3	;TEST D'SOR SIGN
	AR_BR LONG,BR_AR LONG,SET SR2,	;NOTE D'END NEGATIVE
		SIGNS DISP,J/DDIV3

;HERE WITH THE DIVISOR IN BR LONG,
; THE HIGH PART OF THE MAGNITUDE OF THE DIVIDEND IN AR LONG,
; AND THE LOW PART OF THE MAGNITUDE OF THE DIVIDEND IN MQ AND T1
; SKIP IF DIVISOR NEGATIVE, & CHECK FOR NO-DIVIDE.
=1011
DDIV3:	AR_2(AR-BR),ARX/ADX*2,MQ_MQ*2,	;SEE IF FIRST DIVIDE STEP
		SKP CRY0,J/DDIV4	; GENERATES A 1
	AR_2(AR+BR),ARX/ADX*2,MQ_MQ*2,SKP CRY0
=000
DDIV4:	FE_#,#/33.,SKP BR0,CALL,J/DDVLP	;GO DO FIRST HALF OF DIVIDE
	I FETCH,J/NODIVD		;TOO MANY QUOTIENT BITS
=011	AC1_AR,CLR SC,J/DDIV6		;SAVE HI QUOTIENT IN AC1
=101	AC1_AR,SC_1S			;SET FLAG FOR RESUMPTION
=
DDIV6:	AR_T1				;GET LOWEST DIVIDEND BITS
=100	MQ_AR,AR_MQ,CALL,		;FINISH DIVISION, GENERATING
		SKP SC0,J/DIVLP		; 35 MORE QUOTIENT BITS
=110	AR_AC1,SR DISP,SET SR3,J/DDVX1	;QUOTIENT NEGATIVE.  NOTE
	AR_AC1,SR DISP			;HERE'S HIGH PART OF QUOTIENT
=1101
DDVX1:	BR_AR LONG,AR_BR LONG,J/DDVX2	;POS REMAINDER.  GO STORE
	BR_AR LONG,AR_-BR LONG,J/DDVX2	;NEGATE REMAINDER
DDVX2:	AC2_AR,AR_SIGN,SC_#,#/35.
	AR_SHIFT,SR DISP		;GET LOW WORD OF REM.  TEST QUO SIGN
=1110	AC3_AR,AR_BR,ARX/ADX*2,EXIT DBL	;GET QUOTIENT, SQUEEZE OUT HOLE
	AC3_AR,AR_-BR,ARX/ADX*2,AD LONG,;GET NEGATIVE QUOTIENT
		EXIT DBL
.ENDIF/DBL.INT