.TITLE NGET ;EXTRACT NUMBER FROM BIT STRING GIVEN LOC, SIZE .GLOBL NGET ;FORTRAN CALLABLE. ; CALL NGET(ADDR,BSTART,NBITS,TYPE,OUT) ; ADDR=WORD (16 BITS) OF START ADDRESS ; BSTART=BIT FROM LEFT TO SKIP TO GET TO DATA ; NBITS=NUMBER BITS LONG OF DATA FIELD ; TYPE= 0 2'S COMPLEMENT SIGNED ; = 1 UNSIGNED ; = 2 1 COMPLEMENT SIGNED ; = 3 SIGN/MAGNITUDE ; >3 UNDEFINED ; OUT=DOUBLE PRECISION FLOATING POINT RESULT ; ;FLOATING ACCUMULATORS: AC0=%0 AC1=%1 AC2=%2 AC3=%3 AC4=%4 AC5=%5 SCR: .WORD 0,0,0,0 ;FLOATING 4 WORD SCRATCH WRDMAG: .FLT4 65536. ;MAGNITUDE OF A WORD AS 16-BIT INTEGER (+1) SIGNF: .WORD 0 ;NEGATIVE FLAG IF NONZERO DATA: .WORD 0 .WORD 0 .WORD 0 .WORD 0 ;SAVE AREA FOR DATA .WORD 0,0,0,0 ;ALLOW PRECAUTIONARY CLEAR OF TRAILING WORDS NGET: LDFPS #40300 ;DBL PRECISION, NO INTERRUPTS, 32 BIT INT. CLRF SCR ;ENSURE THAT SCR IS 0 INITIALLY CLR SIGNF ;SAY POSITIVE MOV 2(R5),R0 ;DATA ADDRESS (1ST WORD OF UP TO 4) MOV (R0)+,DATA ;COPY DATA MOV (R0)+,DATA+2 MOV (R0)+,DATA+4 MOV (R0)+,DATA+6 ;SO WE LEAVE CALLER'S BUFFER INTACT MOV #DATA,R0 ;POINT R0 AT COPY OF DATA MOV #100000,R3 CLR R2 MOV @4(R5),-(SP) ;GET SHIFT COUNT NEG @SP ;NEGATE IT FOR RIGHT SHIFT ASHC (SP)+,R2 ;AND RIGHT SHIFT INTO R3 FOR SIGN MASK CMP @10(R5),#1 ;SEE IF 2 COMP OR UNSIGNED BHIS 4$ ;FALL THRU ON TYPE=0 (2 COMPL. SIGNED) BIT R3,DATA ;SIGN BIT SET? BEQ 1$ ;NO, DON'T HAVE TO DO ANYTHING COM DATA COM DATA+2 COM DATA+4 COM DATA+6 ADD #1,DATA+6 ADC DATA+4 ADC DATA+2 ADC DATA ;2 COMPL NEGATE BR 3$ 4$: CMP @10(R5),#1 BLOS 1$ ;IF SO, DON'T MODIFY DATA HERE CMP @10(R5),#3 ;SIGN/MAGNITUDE? BNE 2$ ;NO, BRANCH BIT R3,DATA ;NEGATIVE? BEQ 1$ ;NO, LEAVE NOW BIC R3,DATA ;ZAP OUT SIGN BIT 3$: INC SIGNF ;AND FLAG NEGATIVE BR 1$ ;SKIP OTHER TESTS IF HERE. 2$: CMP @10(R5),#2 ;1 COMPLEMENT SIGNED? BNE 1$ ;IF NOT, FALL THRU TO UNSIGNED. BIT R3,DATA ;IS IT NEGATIVE? BEQ 1$ ;NO, OK NOW COM DATA ;YES, SO COMPLEMENT, THEN FLAG COM DATA+2 COM DATA+4 COM DATA+6 ;COMPLEMENT=1'S COMPL. NEGATE BR 3$ ;GO FLAG NEGATIVE NUMBER. 1$: ; DATA NOW HAS POSITIVE NUMBER AND SIGNF FLAGS WHAT IS NEGATIVE ; SO WE CAN NOW PROCEED TO GET THE NUMBER ITSELF. MOV @6(R5),R4 ;LENGTH, BITS ADD @4(R5),R4 ;POINT TO LAST BIT MOV R4,-(SP) ;COPY BIC #-20,(SP) ;POINT TO BIT IN WORD (0-15) ASH #-4,R4 ;GET WORD DISPLACEMENT IN DATA OF END BIT #17,(SP) ;TEST FOR NEXT BIT=HIGH BIT IN WORD BNE 18$ ;IF SO, THEN WORD DISPLACEMENT IS 1 LESS DEC R4 ;SO COUNT IT DOWN 18$: MOV R4,DATA+10 ;SAVE ASL R4 ;MAKE IT BYTE ADDRESS ADD R0,R4 ;POINT TO DATA ADDR MOV @R4,R3 ;MAKE DATA LOW 16 BITS OF 32 CLR R2 ;AND SHIFT OFF LOW BITS NEG @SP ;MAKE SHIFT COUNT 16-(SP) TO REMOVE LOW BITS ADD #20,(SP) ;RIGHT SHIFT AMOUNT BIC #177760,@SP ;ENSURE IN WORD RANGE NEG @SP ;SO MAKE SHIFT NEGATIVE ASHC (SP),R2 ;SHIFT LOW BITS OFF NEG (SP) ;THEN CHANGE SIGN OF SHIFT ASHC (SP)+,R2 ;AND SHIFT ZEROES IN THERE MOV R3,@R4 ;REPLACE LAST WORD WITH 0-FILLED ONE ;NOW FIGURE OUT NUMBER TO DIVIDE BY AND SAVE IN AC3 MOV R0,-(SP) MOV R1,-(SP) MOV #100000,R1 ;GET NUMBER TO SHIFT RIGHT BY... CLR R0 ;32 BITS SO NO SIGN EXTENDING... MOV R2,-(SP) MOV @6(R5),R2 ;GET LAST BIT USED ADD @4(R5),R2 ;BY SUMMING LENGTH, SKIP BITS DEC R2 ;BACK UP 1 SO IF 0 SKIP BITS, LAST BIT IS 1, ; IF 1 SKIP BIT, LAST BIT IS 100000, ETC. BIC #-20,R2 ;MAKE 0-15 NEG R2 ;MAKE A RIGHT SHIFT ASHC R2,R0 ;MAKE IT A POWER OF 2 AS REQUIRED MOV R1,SCR+2 LDCIF SCR,AC3 ;GET DIVISOR TO AC3 MOV (SP)+,R2 MOV (SP)+,R1 MOV (SP)+,R0 ;GET BACK REGS ;NOW LAST BITS OF DATA ARE SHIFTED OFF. GET RID OF FIRST ONES NEXT. ;WE KNOW THE NUMBER IS POSITIVE-- MAKE SURE RESULT WINDS UP THAT WAY. CLR R3 ;BE SURE LOW BITS CLEAR NOW MOV @R0,R2 ;SET HIGH BITS FOR RIGHT SHIFT MOV @4(R5),R4 ;GET BITS TO SKIP CLC ASHC R4,R2 ;SHIFT NUMBER LEFT, REMOVE EXTRA JUNK NEG R4 ;SET FOR RIGHT SHIFT CLC ROR R2 ;ROTATE DOWN FIRST TIME ROR R3 ;BY 1 BIT ZERO FILLED INC R4 ;SHIFT RIGHT 1 LESS THAN NORMAL ASHC R4,R2 ;NOW DO REST OF SHIFTS MOV R2,@R0 ;SAVE DATA ;NOW TOP OF WORD HAS ZEROES IN HIGHEST PLACES. WE CAN NOW LOAD AS ;FLOATING POINT AND COMBINE. MOV DATA+10,R4 ;NO. WORDS-1 IN DATA INC R4 ;NO. WORDS (1 TO 4) CLR DATA+10 ;(CLEANUP) CLRF AC0 ;AC0 GETS RESULT. INITIALLY ZERO IT. CMP R4,#4 BHI 11$ ;CHECK WORD COUNT TST R4 BEQ 11$ ;PROTECT VS. INFINITE SOB LOOPS 10$: MULF WRDMAG,AC0 ;MULTIPLY RESULT BY 65536 MOV (R0)+,SCR+2 ;SAVE DATA LDCIF SCR,AC1 ;AND CONVERT AS LOW 16 OF UNSIGNED # ADDF AC1,AC0 ;AND SUM IN AC0 SOB R4,10$ ;CONTINUE UNTIL DONE 11$: ;DIVIDE RESULT IN AC0 BY AC3 TO ACCOUNT FOR SCALING OF LOWEST NUMBER BIT TSTF AC3 ;CHECK FOR 0 CFCC BEQ 17$ ;IF 0.0, NO DIVIDE DIVF AC3,AC0 ;RESULT IN AC0. TST SIGNF ;NEGATIVE RESULT? BEQ 17$ ;NO, LEAVE IT ALONE NEGF AC0 ;YES, NEGATE NUMBER 17$: STF AC0,@12(R5) ;SAVE RESULT AS DBL PREC. .IF DF,XXXXXX STCFI AC0,ODATA ;DEBUG--SAVE AS INTEGER RTS PC ODATA:: .WORD 0,0 ;DATA (32 BIT INTEGER AS CONVERTED) .IFF RTS PC .ENDC .END