Google
 

Trailing-Edge - PDP-10 Archives - klu2_442 - shift.mic
There are 5 other files named shift.mic in the archive. Click here to see a list.
.TOC	"Rotate and Logical Shift -- LSH, ROT"

	.DCODE
240:	I,		J/ASH		;ASH [423]
	I,		J/ROT		;ROT
	I,		J/LSH		;LSH
	I,		J/JFFO		;JFFO
	I,		J/ASHC		;ASHC [423]
	I,		J/ROTC		;ROTC
	I,		J/LSHC		;LSHC--Adjoins UUO (247)
	.UCODE
;
;	Single word Logical SHift.  If |count| > 36, we just zero AC0.
;
1412:					;[413] Must adjoin JFFO
LSH:	AR_AC0,SC_EA,SKP AR18,I FETCH	;Get count, data, shift direction
=0	ARX_0S,J/SHFLOD			;Left. Zeros come in from right
	ARX_AR,AR_0S,SC_#+SC,#/36.,	;Right. Swap data to right, adjust
	    SKP SCAD0,J/SHFLOD		; count, and shift if needed
;
;	Single word ROTate.  We must always do the shift (even if the count
;	is ridiculously huge), so we cannot have an I FETCH pending if we
;	must normalize the count.  Still, we can optimize if -37 < count
;	< 36. [413]
;
1415:					;Must adjoin ASH
ROT:	AR_AC0,ARX/AD,SC_EA,SKP AR18,	;Get data and count. Left or right
	    I FETCH			; rotation?
=0	AR_SHIFT,SC_#+SC,#/-36.,	;Left rotation. Try to do it, and
	    SKP SCAD0,J/ROTL		; test range
	SC_#+SC,#/36.,SKP SCAD0		;Right rotation. In range?
=0	AR_SHIFT,J/STAC			;[417] Yes. Shift and store
	FETCH WAIT,SC_#+SC,#/36.,	;No. Force next instruction into
	    SKP SCAD0			; ARX and try to normalize count
=0
RTRLUP:	MQ_ARX,ARX_AR (AD),J/ROTDUN	;[417] OK. Save inst, restore data
	SC_#+SC,#/36.,SKP SCAD0,J/RTRLUP;Loop until count in range
;
=0					;Left rotation
ROTL:	FETCH WAIT,SC_#+SC,#/-36.,	;Count too big. Wait for I FETCH
	    SKP SCAD0,J/RTLLUP		; and normalize count
	AC0_AR,NXT INSTR		;Count OK. Done!
=0
RTLLUP:	SC_#+SC,#/-36.,SKP SCAD0,J/RTLLUP;Keep normalizing until in range
	MQ_ARX,ARX_AR (AD),SC_#+SC,#/36.;Keep inst, restore data and count
ROTDUN:	AR_SHIFT,ARX/MQ,J/STAC		;[417] Shift, snarf inst, and store
.TOC	"Rotate and Logical Shift Combined (ROTC, LSHC)"

;
;	ROTate Combined--Normalize the count first, then do rotation.
;
1417:					;Next to ASHC
ROTC:	ARX_AC1,SC_EA,FE_#,#/-36.,	;Get low word
	    SKP AR18			; Which way do we rotate?
=0	AR_AC0,MQ_AC0,FE_FE+SC,		;Left. Put high word in both low
	    BYTE DISP,TIME/3T,J/ROTCL	; and high words. Test count range
	AR_ARX,MQ_ARX,ARX_AC0,SC_#+SC,	;Right. Put low word in both places,
	    #/36.,SKP SCAD0		; force count into range
=0
ROTCR:	MQ_SHIFT,AR_ARX (AD),ARX/MQ,	;Count all set. Generate left word,
	    I FETCH,J/DSHIFT		; set up for right word
	AR_ARX,MQ_ARX,ARX/MQ,SC_#+SC,	;Not yet in range. Swap shift words
	    #/36.,SKP SCAD0,J/ROTCR	; and keep forcing count up
;
=110
ROTCL:	AR_ARX,MQ_ARX,ARX_AR (AD),SC_FE,;Long left. Swap shift words, keep
	    FE_FE-#,#/36.,SKP SCAD0,J/ROTCL; adjusted count, and test again
	MQ_SHIFT,AR_ARX (AD),ARX/MQ,	;Count now in range. Shift left
	    I FETCH,J/DSHIFT		; half and set for right half
;
;	Logical SHift Combined.  Normalize the count before we do
;	any shifting.  This is very similar to ROTC.
;
1004:					;Must adjoin UUO (247)
LSHC:	ARX_AC1,AR+MQ_0.M,SC_EA,SKP AR18;Get low word. Left or right?
=0	AR_AC0,FE_#+SC,#/-36.,		;Left. Get high word; test count
	    SKP SCAD0,J/CLEFT		; range
	MQ_ARX,ARX_AC0,SC_#+SC,#/36.,	;Right. Shuffle data; try to force
	    SKP SCAD0			; shift count into 0-35 range
=0
CRIGHT:	MQ_SHIFT,AR_ARX (AD),ARX/MQ,	;Count OK. Generate left word
	    I FETCH,J/DSHIFT		; and set up for right word
	MQ_ARX,ARX_AR (AD),SC_#+SC,	;Long shift. Adjust one word to
	    #/36.,SKP SCAD0,J/CRIGHT	; right and loop again
;
=0
CLEFT:	AR_ARX,ARX_0S,SC_FE,FE_FE-#,	;Long left shift. Adjust one word
	    #/36.,SKP SCAD0,J/CLEFT	; left, force count into range
	MQ_SHIFT,AR_ARX (AD),ARX/MQ,	;Count set. Shift left word and set
	    I FETCH			; for right half shift
DSHIFT:	AR_SHIFT,ARX/MQ,J/DLOAD		;Shift right word, store, and exit
.TOC	"Arithmetic Shifts (ASH, ASHC) and JFFO"

;
;	[423] ASH completely rewritten for speed.
;
1414:					;[413] Must adjoin ROT
ASH:	AR_AC0,ARL/AD,MQ_0.M,SC_EA,	;ASH. Fetch count and data, test
	    VMA/PC+1,SKP AR18		; left/right, set VMA for NICOND
=0	ARX_AR,AR_SIGN,SC_#+SC,#/1,	;Left. Set up to examine bits
	    J/ASHL			; shifted out
	ARX_AR,AR_SIGN,SC_#+SC,#/36.,	;Right. Adjust count and set up
	    SKP SCAD0,FETCH,J/SHFLOD	; to shift in sign bits
;
ASHL:	BR/AR,MQ_SHIFT,AR_ARX (AD),	;MQ_bits shifted out, BR_sign bits
	    ARX/MQ,GEN #+SC,#/-37.,SKP SCAD0; Set for shift. Is count huge?
=0	MQ_AR XOR BR			;Yes. Force overflow unless 0 data
	ARX_SHIFT,SC_#,#/35.,		;Shift all but sign bit. Was
	    SKP MQ NE BR,I FETCH	; significant data shifted out?
=0	AR_BR,J/SHFLOD			;No. Set to shift in sign and store
	SET AROV,AR_BR,J/SHFLOD		;Yes. Set overflow and sign shift
;
;	Arithmetic SHift Combined.  This has been left alone due to its
;	low execution frequency.
;
1416:					;[415] Must adjoin ROTC
ASHC:	SC_EA,SKP AR18,AR_AC1*2		;Set up shift count, get low word
=0	ARX_AR,AR_AC0,SKP SC NE,J/ASHL1	;[423] Left shift. Check for null
	ARX_AR,AR_AC0,SC_#+SC,#/36.,	;HERE IF RIGHT SHIFT
	    SKP SCAD0			;CHECK FOR LONG ONE
=0
ASHR1:	BR/AR,ARX_SHIFT,AR_SIGN,J/ASHR2	;LOW OUTPUT TO ARX
	ARX_AR,AR_SIGN,SC_#+SC,#/36.,	;HERE IF SHIFT COUNT .GT. 36
	    SKP SCAD0,J/ASHR1		; Count it down to reasonable

ASHR2:	BRX/ARX,ARX_BR,J/ASHX		;[423] HIGH INPUT TO ARX
;
;	[423] Here for left double arithmetic shift.
;
=0
ASHL1:	I FETCH,J/NOP			;SHIFT 0 IS A NOP
	BR_AR LONG,AR_SIGN		;SAVE INPUT, GEN SIGN WORD
	BR/AR,AR_BR*2 LONG		;SAVE SIGN, GET MAGNITUDE BITS
=0*
ASHL2:	BRX/ARX,ARX_AR,AR_BR,		;HI IN TO ARX, LOW TO BRX
	    CALL,J/SHIFT		;CALL SHIFTER TO GET BITS LOST
	SKP AR NE BR			;ANY BITS DIFFERENT FROM SIGN?
=0
ASHL3:	AR_ARX,ARX_BRX,GEN #+SC,#/-36.,	;RESTORE HI TO AR, LOW TO ARX
	    SKP SCAD0,J/ASHL4
	SET AROV,J/ASHL3		;BITS SHIFTED OUT NE SIGN
=0
ASHL4:	AR_ARX,ARX_0S,SC_#+SC,#/-36.,	;HERE IF E .GT. 36
	    J/ASHL2			;SHIFT 36 PLACES, TRY AGAIN
	MQ_SHIFT,AR_BRX,CLR ARX,	;HIGH OUTPUT TO MQ,
	    SC_#+SC,#/-1		;COMPENSATE FOR EXTRA SHIFT
	ARX_SHIFT			;LOW OUTPUT TO ARX
	AR_BR,BRX/ARX,ARX/MQ,SC_#,#/35.	;SIGN TO AR, HIGH OUT TO ARX
ASHX:	AR_SHIFT,ARX_BRX,SC_#,#/35.,	;[423] Generate high word and
	    J/ST2AC			; set up low for finish
;
;	Jump if Find First One (!)--This is implemented by first finding
;	the group of six bits which contains the first one, and then
;	isolating the actual bit.  The bit isolation has been rewritten
;	to speed up the slower cases (actually, the faster cases were
;	helped a bit, too).  [432]
;
1413:					;Must be near LSH
JFFO:	SC_#,#/6,AR_AC0,SKP AD NZ	;JFFO! Any bits set at all?
=0	AC1_AR,I FETCH,J/NOP		;AC was zero, no jump
	ARX+MQ_0.M,FE_P,SKP SCAD NZ,	;Test first 6 bits
		AR_SHIFT,ARL/SH		; and discard them
=0
JFGRUP:	AR_SHIFT,FE_P,SKP SCAD NZ,	;[432] Loop through six bit groups
	    ARX_ARX-1,J/JFGRUP		; until we find a one bit
;
;	We now have the negative of the group number in ARX.  Convert this
;	to a bit number, and test the FE in two bit groups to find which
;	bit we hit on.
;
	ARX_ARX*-6,GEN FE AND #,#/60,	;Convert group to bit number
	    SKP SCAD NZ			; Is one in first two bits?
=0	BRX/ARX,ARX_2+MQ0,GEN FE AND #,	;No. Must add at least 2 to group
	    #/14,SKP SCAD NZ,J/JFBITS	; count. Is one in second two bits?
	BRX/ARX,ARX_0S,GEN FE AND #,#/40,;Yes. Set up 0 and test bit 0 in
	    SKP SCAD NZ,FETCH,J/LOWBIT	; group
;
=0
JFBITS:	ARX_ARX*2,GEN FE AND #,#/2,	;Must be in third two bits. Set up
	    SKP SCAD NZ,FETCH,J/LOWBIT	; 4 and test bit 4 in group
	GEN FE AND #,#/10,SKP SCAD NZ,	;In second two bits; leave bit
	    FETCH			; number at 2. Is bit 2 set?
=0
LOWBIT:	AR_ARX+BRX+1,TIME/2T,J/STAC1	;No, so low bit is. Add 1 to bit #
	AR_ARX+BRX,TIME/2T,J/STAC1	;Yes. Add group+bit number in group