;+ ; Program: Quadword arithmetic routines ; ------- .title quadword ; Author: M. Erik Husby, September 1982 ; ------ .ident /1-1/ ; Modifications: MEH, 8-DEC-1982, Added check in KDIV for divide by ; ------------- zero. Also to use temporary in KDIV for storage of ; numerator not the potential quotient. ; ; General notes: ; 1. All routines leave r0 set with a value indicating sign of the ; result. ; 1, result >0 ; 0, result =0 ; -1, result <0 ; -2, overflow occurred. ; .sbttl Macro definitions ; ; Test a quadword value, Leaves r0 set to 1,0,-1 depending on sign of ; the quadword value. .macro tstq a,?l1,?l2 movaq a,r1 bsbw tstq_internal .endm .sbttl tstq ; Function: Internal routine to test a quadword value. ; --------- ; Calling Sequence: tstq a ; ---------------- ; Inputs: type usage ; ------ ; R1 address of the quadword ; Completion code: See General notes ; --------------- ; Side effects: None ; ------------ ; ; Program logic: ; ------------- .psect code,con,exe,lcl,pic,rel,shr,nowrt tstq_internal: clrl r0 ; Assume 0 result movq (r1),-(sp) ; Test quadword by moving it. blss 10$ ; Is it <0? beql 20$ ; Is it 0? incl r0 ; Is >0, return 1 brb 20$ ;... 10$: decl r0 ; Is <0, return -1 20$: addl2 #8,sp ; Clean up the stack rsb .sbttl kadd ; Function: C=A+B ; --------- ; Calling Sequence: i*2=kadd(a,b,c) ; ---------------- ; Inputs: type usage ; ------ ; A Quad Read-only ; B Quad Read-only ; Outputs: type usage ; ------- ; C Quad Written. ; Completion code: See general notes ; --------------- ; Side effects: None ; ------------ ; ; Program logic: ; ------------- .psect code,con,exe,lcl,pic,rel,shr,nowrt .entry kadd,0 movq @8(ap),-(sp) ; Copy B to a temporary movq @4(ap),@12(ap) ; Copy A to C movl 12(ap),r1 ; Get address of C addl (sp),(r1) ; Add low part of B to C adwc 4(sp),4(r1) ; Add high part of B to C tstq (r1) ; Check out the result ret .sbttl ksub ; Function: C=A-B ; --------- ; Calling Sequence: i*2=ksub(a,b,c) ; ---------------- ; Inputs: type usage ; ------ ; A quad Read-only ; B quad Read-only ; Outputs: type usage ; ------- ; C quad Written ; Completion code: See General notes ; --------------- ; Side effects: None ; ------------ ; ; Program logic: ; ------------- .psect code,con,exe,lcl,pic,rel,shr,nowrt .entry ksub,0 movq @8(ap),-(sp) ; Copy B to a temporary movq @4(ap),@12(ap) ; Move A to C movl 12(ap),r1 ; Get address of C subl (sp),(r1) ; Subtract low part of B from C sbwc 4(sp),4(r1) ; Subtract high part of B from C tstq (r1) ; Check out the result ret .sbttl kmul ; Function: C=A*B ; --------- ; Calling Sequence: i*2=kmul(a,b,c) ; ---------------- ; Inputs: type usage ; ------ ; A quad Read-only ; B quad Read-only ; Outputs: type usage ; ------- ; C quad Written ; Completion code: See General notes ; --------------- ; Side effects: None ; ------------ ; ; Program logic: ; ------------- .psect code,con,exe,lcl,pic,rel,shr,nowrt MULTIPLIER=4 MULITPLICAND=8 PRODUCT=12 .ENTRY kmul,^M MOVL MULTIPLIER(AP),R3 ;ADDRESS OF MULTIPLIER MOVL MULITPLICAND(AP),R4 ;ADDRESS OF MULTIPLICAND EMUL (R3),(R4),#0,R0 ;LOW PRODUCT EMUL (R3),4(R4),R1,R1 ;FIRST CROSS TERM PRODUCT EMUL 4(R3),(R4),R1,R1 ;SECOND CROSS TERM PRODUCT TSTL (R3) ;CHECK SIGN BGEQ 1$ ;NO SIGN PROBLEMS ADDL (R4),R1 ;SIGN COMPENSATION 1$: TSTL (R4) ;CHECK OTHER SIGN BGEQ 2$ ;NO SIGN PROBLEMS ADDL (R3),R1 ;SIGN COMPENSATION 2$: MOVQ R0,@PRODUCT(AP) ;GIVE THE ANSWER tstq @product(ap) ; Check out the result RET ;RETURN TO CALLER .sbttl kdiv ; Function: C=A/B, remainder=D ; --------- ; Calling Sequence: i*2=kdiv(a,b,c,d) ; ---------------- ; Inputs: type usage ; ------ ; A quad read-only ; B quad read-only ; Outputs: type usage ; ------- ; C quad written, The quotient ; D quad written, The remainder, is optional ; Completion code: See General notes ; --------------- ; Side effects: None ; ------------ ; ; Program logic: ; ------------- .psect code,con,exe,lcl,pic,rel,shr,nowrt NUMERATOR=4 DENOMINATOR=8 QUOTIENT=12 REMAINDER=16 .ENTRY kdiv,^M CLRB R6 ;PRESUME POS NUM AND DEN movq @NUMERATOR(AP),-(sp) ;GET THE NUMERATOR on stack BGEQ 1$ ;XFER IF POSITIVE MCOML (sp),(sp) ;MAKE TWO'S COMPLEMENT MCOML 4(sp),4(sp) ; INCL (sp) ; ADWC #0,4(sp) ; MOVB #3,R6 ;FLAG THE SIGN SWITCH 1$: MOVQ @DENOMINATOR(AP),R0 ;GET THE DENOMINATOR bneq 11$ ; Ok if not zero mnegl #2,r0 ; Indicate error ret ; and go home 11$: bgtr 2$ ;XFER IF POSITIVE MCOML R0,R0 ;MAKE TWO'S COMPLEMENT MCOML R1,R1 ; INCL R0 ; ADWC #0,R1 ; XORB #1,R6 ;FLAG THE SIGN SWITCH 2$: CLRQ R2 ;CLEAR QUOTIENT CLRQ R4 ;CLEAR REMAINDER MOVZBL #63,R7 ;SET COUNT AND BIT POINTER 3$: ASHQ #1,R2,R2 ;ROOM FOR NEXT QUOTIENT BIT ASHQ #1,R4,R4 ;ROOM FOR NEXT NUMERATOR BIT BBC R7,(sp),4$ ;CHECK NEXT NUMERATOR BIT INCB R4 ;MOVE IT TO THE REMAINDER 4$: CMPL R5,R1 ;COMPARE REMAINDER AND DENOM BLSS 6$ ;NO SUBTRACT IF REMAINDER LESS BGTR 5$ ;CERTAIN SUBTRACT IF LARGER CMPL R4,R0 ;HIGH PARTS EQUAL SO COMPARE LOW BLSSU 6$ ;NO SUBTRACT IF REMAINDER LESS 5$: SUBL R0,R4 ;SUBTRACT DENOM FROM REMAINDER SBWC R1,R5 ; INCB R2 ;INCREMENT THE QUOTIENT 6$: SOBGEQ R7,3$ ;LOOP FOR EACH BIT BLBC R6,7$ ;CHECK QUOTIENT SIGN SWITCH MCOML R2,R2 ;MAKE QUOTIENT NEGATIVE MCOML R3,R3 ; INCL R2 ; ADWC #0,R3 ; 7$: MOVQ R2,@quotient(ap) ;RETURN THE QUOTIENT BBC #2,0(AP),9$ ;CHECK FOR FOUR ARGS BBC #1,R6,8$ ;CHECK REMAINDER SIGN SWITCH MCOML R4,R4 ;MAKE REMAINDER NEGATIVE MCOML R5,R5 ; INCL R4 ; ADWC #0,R5 ; 8$: MOVQ R4,@REMAINDER(AP) ;RETURN THE REMAINDER 9$: tstq @quotient(ap) ; Check out the result RET ;RETURN TO CALLER .sbttl ikcvt ; Function: Convert I*8 to i*2 ; --------- ; Calling Sequence: i*2=ikcvt(a,i) ; ---------------- ; Inputs: type usage ; ------ ; A quad Read-only ; Outputs: type usage ; ------- ; I word Written ; Completion code: See General notes ; --------------- ; Side effects: None ; ------------ ; ; Program logic: ; ------------- .psect code,con,exe,lcl,pic,rel,shr,nowrt .entry ikcvt,0 clrl r0 ; Assume a non-negative result movl 4(ap),r1 ; Get address of A cvtlw (r1)+,@8(ap) ; Convert low half bvs 20$ ; Error if overflow during convert bgeq 10$ ; Highword must be either 0 or -1 decl r0 ; Low half negative, high must be -1 10$: cmpl r0,(r1) ; Check out high half bneq 20$ ; Not correct, overflow during convert tstq @4(ap) ; Check out the result ret 20$: mnegl #2,r0 ; Indicate overflow ret .sbttl jkcvt ; Function: Convert I*8 to I*4 ; --------- ; Calling Sequence: i*2=jkcvt(a,i) ; ---------------- ; Inputs: type usage ; ------ ; A quad Read-only ; Outputs: type usage ; ------- ; I long Written ; Completion code: See General notes ; --------------- ; Side effects: None ; ------------ ; ; Program logic: ; ------------- .psect code,con,exe,lcl,pic,rel,shr,nowrt .entry jkcvt,0 clrl r0 ; Assume a non-negative quadword movl 4(ap),r1 ; Get address of the quadword movl (r1)+,@8(ap) ; Move low half to the longword I bgeq 10$ ; High half must be either 0 or -1 decl r0 ; High half must be -1 10$: cmpl r0,(r1) ; Check out the high half bneq 20$ ; Overflow, high half not 0 or -1 tstq @4(ap) ; Check out the result ret 20$: mnegl #2,r0 ; Indicate overflow ret .sbttl kicvt ; Function: Convert I*2 to I*8 ; --------- ; Calling Sequence: i*2=kicvt(i,a) ; ---------------- ; Inputs: type usage ; ------ ; I word Read-only ; Outputs: type usage ; ------- ; A quad Written. ; Completion code: See General notes ; --------------- ; Side effects: None ; ------------ ; ; Program logic: ; ------------- .psect code,con,exe,lcl,pic,rel,shr,nowrt .entry kicvt,0 movl 8(ap),r1 ; Address of Quadword cvtwl @4(ap),(r1) ; Convert word to lowhalf extv #31,#1,(r1),4(r1) ; Extend sign to high half tstq (r1) ; Check out the result ret .sbttl kjcvt ; Function: Convert I*4 to I*8 ; --------- ; Calling Sequence: i*2=kjcvt(i,a) ; ---------------- ; Inputs: type usage ; ------ ; I long read-only ; Outputs: type usage ; ------- ; A quad written ; Completion code: See General notes ; --------------- ; Side effects: None ; ------------ ; ; Program logic: ; ------------- .psect code,con,exe,lcl,pic,rel,shr,nowrt .entry kjcvt,0 movl 8(ap),r1 ; Get address of the quadword movl @4(ap),(r1) ; Get lowhalf of the quadword extv #31,#1,(r1),4(r1) ; Extend sign to highhalf tstq (r1) ; Check out the result. ret .sbttl kmov ; Function: Move a quadword ; --------- ; Calling Sequence: i*2=kmov(a,b) ; ---------------- ; Inputs: type usage ; ------ ; A quad Read-only ; Outputs: type usage ; ------- ; B quad written ; Completion code: See General notes ; --------------- ; Side effects: None ; ------------ ; ; Program logic: ; ------------- .psect code,con,exe,lcl,pic,rel,shr,nowrt .entry kmov,0 clrl r0 ; Assume 0 result movq @4(ap),@8(ap) ; Move A to B blss minus ; Is result <0? beql zero ; Is result =0? incl r0 ; Must be positive zero: ret minus: decl r0 ret .sbttl ktst ; Function: Test a quad word value ; --------- ; Calling Sequence: i*2=ktst(a) ; ---------------- ; Inputs: type usage ; ------ ; A quad read-only ; Completion code: See General notes ; --------------- ; Side effects: None ; ------------ ; ; Program logic: ; ------------- .psect code,con,exe,lcl,pic,rel,shr,nowrt .entry ktst,0 tstq @4(ap) ; Test the value ret .sbttl kcmp ; Function: Compare two quadwords ; --------- ; Calling Sequence: i*2=kcmp(a,b) ; ---------------- ; Inputs: type usage ; ------ ; A quad read-only ; B quad read-only ; Completion code: See General notes ; --------------- ; Side effects: None ; ------------ ; ; Program logic: ; ------------- .psect code,con,exe,lcl,pic,rel,shr,nowrt .entry kcmp,^M clrl r0 ; Assume equal movl 4(ap),r1 ; Get address of A movl 8(ap),r2 ; Get address of B cmpl 4(r1),4(r2) ; Compare high parts first blss 10$ ; AB? cmpl (r1),(r2) ; Compare low parts since high parts same blssu 10$ ; AB? ret ; They are the same, return 0 10$: decl r0 ; AB, return 1 ret ;- .end