;-*- mode: lisp; base: 8; readtable: ZL -*- ;;; ;;; (c) Copyright 1984 - Lisp Machine, Inc. ;;; (DEFCONST UC-HACKS '( ;;; Sophisticated audio home entertainment center. #-exp(begin-comment) XBEEP (MISC-INST-ENTRY %BEEP) ;;; First argument is half-wavelength, second is duration. Both are in microseconds. ;;; M-1 has 2nd argument (duration) which is added to initial time-check ;;; M-2 contains most recent time check ;;; to compute quitting time ;;; M-C contains 1st argument, the wavelength ;;; M-4 contains the time at which the next click must be done. ;;; Note that the 32-bit clock wraps around once an hour, we have to be careful ;;; to compare clock values in the correct way, namely without overflow checking. (CALL-XCT-NEXT READ-MICROSECOND-CLOCK) ((M-1) Q-POINTER C-PDL-BUFFER-POINTER-POP) ((M-1) M-1 ADD A-2) ((M-C) Q-POINTER C-PDL-BUFFER-POINTER-POP) ((M-4) M-2) (jump-equal m-2 a-zero xfalse) ;forget it if the clock hasn't started yet BEEP-NEXT-CLICK ((M-4) M-4 ADD A-C) BEEP-WAIT ((vma-start-read) setz) (check-page-read) ;let an interrupt happen (CALL READ-MICROSECOND-CLOCK) ((M-TEM) SUB M-2 A-1) (JUMP-GREATER-OR-EQUAL M-TEM A-ZERO XFALSE) ((M-TEM) SUB M-2 A-4) (JUMP-LESS-OR-EQUAL M-TEM A-ZERO BEEP-WAIT) ;do the click here (JUMP BEEP-NEXT-CLICK) #-exp(end-comment) #-cadr (begin-comment) ;CADR version XBEEP (MISC-INST-ENTRY %BEEP) ;;; First argument is half-wavelength, second is duration. Both are in microseconds. ;;; M-1 has 2nd argument (duration) which is added to initial time-check ;;; M-2 contains most recent time check ;;; to compute quitting time ;;; M-C contains 1st argument, the wavelength ;;; M-4 contains the time at which the next click must be done. ;;; Note that the 32-bit clock wraps around once an hour, we have to be careful ;;; to compare clock values in the correct way, namely without overflow checking. (CALL-XCT-NEXT READ-MICROSECOND-CLOCK) ((M-1) Q-POINTER C-PDL-BUFFER-POINTER-POP) ((M-1) M-1 ADD A-2) ((M-C) Q-POINTER C-PDL-BUFFER-POINTER-POP) ((M-4) M-2) BEEP-NEXT-CLICK ((M-4) M-4 ADD A-C) BEEP-WAIT (CALL READ-MICROSECOND-CLOCK) ((M-TEM) SUB M-2 A-1) (JUMP-GREATER-OR-EQUAL M-TEM A-ZERO XFALSE) ((M-TEM) SUB M-2 A-4) (JUMP-LESS-OR-EQUAL M-TEM A-ZERO BEEP-WAIT) ((VMA-START-WRITE) (A-CONSTANT BEEP-HARDWARE-VIRTUAL-ADDRESS)) ;Unibus 764110 (CHECK-PAGE-WRITE) (JUMP BEEP-NEXT-CLICK) #-cadr (end-comment) #-lambda (begin-comment) (begin-pagable-ucode) XBEEP (MISC-INST-ENTRY %BEEP) ;;; First argument is half-wavelength, second is duration. Both are in microseconds. ;;; M-1 has 2nd argument (duration) which is added to initial time-check ;;; M-2 contains most recent time check ;;; to compute quitting time ;;; M-C contains 1st argument, the wavelength ;;; M-3 contains the word to write to the serial chip for the next click ;;; M-4 contains the time at which the next click must be done. ;;; Note that the 32-bit clock wraps around once an hour, we have to be careful ;;; to compare clock values in the correct way, namely without overflow checking. ;;; M-5 gets code for video-board type. (CALL-XCT-NEXT READ-MICROSECOND-CLOCK) ((M-1) Q-POINTER C-PDL-BUFFER-POINTER-POP) ((M-1) M-1 ADD A-2) ((M-C) Q-POINTER C-PDL-BUFFER-POINTER-POP) ((M-4) M-2) ((m-5) a-zero) ;vcmem ((m-tem) a-tv-quad-slot) ((m-tem) ldb (byte-field 8 8) m-tem) (jump-equal m-tem (a-constant 0) xbeep-vcmem) (jump-equal m-tem (a-constant 1) xbeep-vcmem) (jump-equal m-tem (a-constant 2) xbeep-quad) (call illop) xbeep-quad ((m-5) (a-constant 1)) xbeep-vcmem ((m-3) (a-constant #xea)) ; normal mode for vcmem serial chip (doesnt matter for quad) beep-next-click (call reset-watchdog) ;don't let the SDU reset us if this is going to be long ;(also let boot characters come in) ((m-4) m-4 add a-c) beep-wait ((vma-start-read) a-zero) ;allow an interrupt if one is pending (check-page-read) ;this is important for the 60Hz microsec ;clock hack (call read-microsecond-clock) ((m-tem) sub m-2 a-1) (jump-greater-or-equal m-tem a-zero beep-done) ((m-tem) sub m-2 a-4) (jump-less-or-equal m-tem a-zero beep-wait) (jump-equal m-5 (a-constant 1) beep-click-on-quad) beep-click-on-vcmem ((md) (a-constant 5)) ((vma-start-write) (a-constant (plus 177370400 15))) ;vcmem keyboard out control reg (check-page-write-map-reload-only) ((md-start-write m-3) xor m-3 (a-constant 20)) ; toggle "send break" bit (check-page-write) (jump beep-next-click) beep-click-on-quad ((vma) (a-constant (plus 177277400 23))) ((md-start-write m-3) xor m-3 (a-constant 1)) ; toggle bit (check-page-write-map-reload-only) (jump beep-next-click) beep-done (jump-equal m-5 (a-constant 1) beep-quad-done) ((md) (a-constant 5)) ((vma-start-write) (a-constant (plus 177370400 15))) (check-page-write-map-reload-only) ((md-start-write) (a-constant #xea)) (check-page-write) (jump xfalse) beep-quad-done ((vma) (a-constant (plus 177277400 23))) ;leave bit clear, randomly. ((md-start-write) a-zero) (check-page-write-map-reload-only) (jump xfalse) (end-pagable-ucode) #-lambda (end-comment) (begin-pagable-ucode) ;;; %DRAW-TRIANGLE X1 Y1 X2 Y2 X3 Y3 ALU SHEET X-DRAW-TRIANGLE (MISC-INST-ENTRY %DRAW-TRIANGLE) (CALL SELECT-SHEET) ((M-J) DPB C-PDL-BUFFER-POINTER-POP OAL-ALUF) ;M-J ALU function (DISPATCH Q-DATA-TYPE C-PDL-BUFFER-POINTER TRAP-UNLESS-FIXNUM) (ERROR-TABLE ARGTYP FIXNUM PP 5) ;M-1 Y3 sign extended ((M-C) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP) (DISPATCH Q-DATA-TYPE C-PDL-BUFFER-POINTER TRAP-UNLESS-FIXNUM) (ERROR-TABLE ARGTYP FIXNUM PP 4) ;M-1 X3 sign extended ;M-C Y3 ((M-3) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP) (DISPATCH Q-DATA-TYPE C-PDL-BUFFER-POINTER TRAP-UNLESS-FIXNUM) (ERROR-TABLE ARGTYP FIXNUM PP 3) ;M-1 Y2 sign extended ;M-3 X3 ((M-B) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP) (DISPATCH Q-DATA-TYPE C-PDL-BUFFER-POINTER TRAP-UNLESS-FIXNUM) (ERROR-TABLE ARGTYP FIXNUM PP 2) ;M-1 X2 sign extended ;M-B Y2 ((M-2) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP) (DISPATCH Q-DATA-TYPE C-PDL-BUFFER-POINTER TRAP-UNLESS-FIXNUM) (ERROR-TABLE ARGTYP FIXNUM PP 1) ;M-1 Y1 sign extended ;M-2 X2 ((M-A) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP) (DISPATCH Q-DATA-TYPE C-PDL-BUFFER-POINTER TRAP-UNLESS-FIXNUM) (ERROR-TABLE ARGTYP FIXNUM PP 0) ;M-1 X1 sign extended ;M-A Y1 ((M-1) OUTPUT-SELECTOR-EXTEND-25 C-PDL-BUFFER-POINTER-POP) ;;Sort by Y co-ordinate (JUMP-GREATER-OR-EQUAL-XCT-NEXT M-A A-B TV-DRAW-TRI-SORT-1) ((M-TEM) M-1) ((M-1) M-2) ((M-2) M-TEM) ((M-TEM) M-A) ((M-A) M-B) ((M-B) M-TEM) TV-DRAW-TRI-SORT-1 (JUMP-GREATER-OR-EQUAL-XCT-NEXT M-A A-C TV-DRAW-TRI-SORT-2) ((M-TEM) M-1) ((M-1) M-3) ((M-3) M-TEM) ((M-TEM) M-A) ((M-A) M-C) ((M-C) M-TEM) TV-DRAW-TRI-SORT-2 (JUMP-GREATER-OR-EQUAL-XCT-NEXT M-B A-C TV-DRAW-TRI-SORT-3) ((M-TEM) M-2) ((M-2) M-3) ((M-3) M-TEM) ((M-TEM) M-B) ((M-B) M-C) ((M-C) M-TEM) TV-DRAW-TRI-SORT-3 ;;Now sorted, Y1 > Y2 > Y3 ((A-TRI-Y1) M-A) ((A-TRI-X1) M-1) ((A-TRI-Y2) M-B) ((A-TRI-X2) M-2) ((A-TRI-Y3) M-C) ((A-TRI-X3) M-3) ;;Now compute Y co-ordinates as array addresses ((Q-R) A-TV-SCREEN-LOCATIONS-PER-LINE) (CALL-XCT-NEXT MPY12) ((M-1) DPB M-A (BYTE-FIELD 20. 12.) A-ZERO) ((A-TRI-Y1-ADDR) SUB M-2 A-TV-SCREEN-LOCATIONS-PER-LINE) ((Q-R) A-TV-SCREEN-LOCATIONS-PER-LINE) (CALL-XCT-NEXT MPY12) ((M-1) DPB M-B (BYTE-FIELD 20. 12.) A-ZERO) ((A-TRI-Y2-ADDR) M-2) ((Q-R) A-TV-SCREEN-LOCATIONS-PER-LINE) (CALL-XCT-NEXT MPY12) ((M-1) DPB M-C (BYTE-FIELD 20. 12.) A-ZERO) ((A-TRI-Y3-ADDR) M-2) ;;Compute determinant to get handedness ((M-1) SUB M-3 A-TRI-X1) ;X3 - X1 (CALL-XCT-NEXT MPY) ((Q-R) SUB M-B A-A) ;Y2 - Y1 ((M-3) Q-R) ;(X3 - X1) * (Y2 - Y1) ((M-1) A-TRI-X1) ((M-1) SUB M-1 A-TRI-X2) ;X1 - X2 (CALL-XCT-NEXT MPY) ((Q-R) SUB M-A A-C) ;Y1 - Y3 ((A-TRI-DET) SUB Q-R A-3) ;((X1 - X2) * (Y1 - Y3)) - ((Y1 - Y2) * (X1 - X3)) (JUMP-EQUAL-XCT-NEXT M-ZERO A-TRI-DET XFALSE) ;Colinear, draw nothing ((M-1) A-TRI-X1) ((M-B) A-TRI-Y1) ((M-2) A-TRI-X2) (CALL-XCT-NEXT TV-DRAW-TRI-1) ((M-C) A-TRI-Y2) ((M-1) A-TRI-X1) ((M-B) A-TRI-Y1) ((M-2) A-TRI-X3) (CALL-XCT-NEXT TV-DRAW-TRI-1) ((M-C) A-TRI-Y3) ((M-A) A-TRI-Y1-ADDR) ;Initial Y address ((A-TRI-Y-LIM) A-TRI-Y2-ADDR) ;Ending Y address for bottom half TV-DRAW-TRI-LOOP (JUMP-GREATER-OR-EQUAL M-A A-TRI-Y-LIM TV-DRAW-TRI-LOOP-1) TV-DRAW-TRI-HALF-DONE (JUMP-LESS-THAN-XCT-NEXT M-A A-TRI-Y3-ADDR XFALSE) ;Done with second half ((A-TRI-Y-LIM) A-TRI-Y3-ADDR) ((M-1) A-TRI-X2) ((M-B) A-TRI-Y2) ((M-2) A-TRI-X3) (CALL-XCT-NEXT TV-DRAW-TRI-1) ((M-C) A-TRI-Y3) TV-DRAW-TRI-LOOP-1 (JUMP-LESS-THAN-XCT-NEXT M-A A-ZERO TV-DRAW-TRI-SKIP-LINE) ((M-D) M-S) ;Nominal right end (JUMP-GREATER-OR-EQUAL-XCT-NEXT M-R A-ZERO TV-DRAW-TRI-X0-OK) ((M-C) M-R) ;Nominal left end ((M-C) SETZ) ;M-C clipped left end (JUMP-GREATER-OR-EQUAL M-D A-C TV-DRAW-TRI-X0-OK) ((M-D) SETZ) ;Right may be to left of clipped left TV-DRAW-TRI-X0-OK ((C-PDL-BUFFER-POINTER-PUSH) M-C) ;Setup x co-ordinate (CALL-XCT-NEXT TVXYAD0) ((M-2) M-A) ;Setup Y co-ordinate (JUMP-GREATER-OR-EQUAL M-E A-TV-SCREEN-BUFFER-END-ADDRESS TV-DRAW-TRI-SKIP-LINE) (JUMP-LESS-OR-EQUAL M-D A-TV-SCREEN-WIDTH TV-DRAW-TRI-X1-OK) ((M-D) A-TV-SCREEN-WIDTH) ;M-D clipped right end (JUMP-GREATER-OR-EQUAL M-D A-C TV-DRAW-TRI-X1-OK) ((M-C) M-D) ;Left may be to right of clipped right TV-DRAW-TRI-X1-OK ((C-PDL-BUFFER-POINTER-PUSH) SUB M-D A-C) ;Setup width (CALL-XCT-NEXT XTVERS5) ((M-D) (A-CONSTANT 1)) ;Height is 1 TV-DRAW-TRI-SKIP-LINE ((M-A) SUB M-A A-TV-SCREEN-LOCATIONS-PER-LINE) ;Y := Y - 1 ((M-3) SUB M-3 A-TRI-XLIR) ;XLR := XLR - XLIR (JUMP-LESS-THAN-XCT-NEXT M-3 A-ZERO TV-DRAW-TRI-XLR-NEG) ((M-R) SUB M-R A-TRI-XLI) ;XL := XL - XLI (JUMP-GREATER-OR-EQUAL M-3 A-TRI-LY TV-DRAW-TRI-XLR-WRAP) TV-DRAW-TRI-INCR-1 ((M-4) SUB M-4 A-TRI-XRIR) ;XRR := XRR - XRIR (JUMP-LESS-THAN-XCT-NEXT M-4 A-ZERO TV-DRAW-TRI-XRR-NEG) ((M-S) SUB M-S A-TRI-XRI) ;XR := XR - XRI (JUMP-LESS-THAN M-4 A-TRI-RY TV-DRAW-TRI-LOOP) TV-DRAW-TRI-XRR-WRAP ((M-4) SUB M-4 A-TRI-RY) (JUMP-XCT-NEXT TV-DRAW-TRI-LOOP) ((M-S) ADD M-S (A-CONSTANT 1)) TV-DRAW-TRI-XLR-NEG ((M-3) ADD M-3 A-TRI-LY) (JUMP-XCT-NEXT TV-DRAW-TRI-INCR-1) ((M-R) SUB M-R (A-CONSTANT 1)) TV-DRAW-TRI-XLR-WRAP ((M-3) SUB M-3 A-TRI-LY) (JUMP-XCT-NEXT TV-DRAW-TRI-INCR-1) ((M-R) ADD M-R (A-CONSTANT 1)) TV-DRAW-TRI-XRR-NEG ((M-4) ADD M-4 A-TRI-RY) (JUMP-XCT-NEXT TV-DRAW-TRI-LOOP) ((M-S) SUB M-S (A-CONSTANT 1)) ;;;This sets up the starting and incrementing remainders and quotients for the left or right ;;;point depending on the sign of det, which it complements, so as to do the other one next ;;;time. TV-DRAW-TRI-1 ((A-TRI-DET) SUB M-ZERO A-TRI-DET) ((M-C) SUB M-B A-C) ;Y1 - Y2 (JUMP-EQUAL-XCT-NEXT M-C A-ZERO XFALSE) ;Avoid divide by 0 ((M-T) SUB M-1 A-2) ;X1 - X2 ((M-1) DPB M-1 (BYTE-FIELD 31. 1) (A-CONSTANT 1)) ;(2 * X1) + 1 (CALL-XCT-NEXT MPY) ((Q-R) M-C) ((M-1) SUB Q-R A-T) ;L := (((2 * X1) + 1) * (Y1 - Y2)) - (X1 - X2) ((M-C) ADD M-C A-C) ;DY := 2 * (Y1 - Y2) (CALL-XCT-NEXT DIV) ((M-2) M-C) ((M-B) Q-R) ;Save L DIV DY ((M-I) M-1) ;Save L REM DY ((M-1) ADD M-T A-T) (CALL-XCT-NEXT DIV) ((M-2) M-C) (JUMP-LESS-THAN M-ZERO A-TRI-DET TV-DRAW-TRI-1-R) TV-DRAW-TRI-1-L ((A-TRI-LY) M-C) ((M-R) M-B) ((M-3) M-I) (POPJ-AFTER-NEXT (A-TRI-XLI) Q-R) ((A-TRI-XLIR) M-1) TV-DRAW-TRI-1-R ((A-TRI-RY) M-C) ((M-S) M-B) ((M-4) M-I) (POPJ-AFTER-NEXT (A-TRI-XRI) Q-R) ((A-TRI-XRIR) M-1) (end-pagable-ucode) ;;; %AOS-TRIANGLE X1 Y1 X2 Y2 X3 Y3 INCREMENT SHEET ;;; Increment each pixel inside the triangle by the specified amount X-AOS-TRIANGLE (MISC-INST-ENTRY %AOS-TRIANGLE) (call trap) (error-table illegal-instruction) ;;;; Given a rectangle of an ART-4B array, and 16 values which specify new values ;;;; for the pixels (indexed by current pixel value), hacks the ART-4B array appropriately ;;;; ;;;; (%COLOR-TRANSFORM N17 N16 N15 N14 N13 N12 N11 N10 N7 N6 N5 N4 N3 N2 N1 N0 ;;;; WIDTH HEIGHT ARRAY START-X START-Y) XCOLOR-TRANSFORM (MISC-INST-ENTRY %COLOR-TRANSFORM) (call trap) (error-table illegal-instruction) (begin-pagable-ucode) ;;; GCD IS SYMMETRICAL (BIGNUM IN M-B, FIXNUM IN M-2) ;;; THIS DEPENDS ON REMAINDER-BIG-FIX NOT SMASHING M-2 AND LEAVING RESULT IN M-1 ;;; SO THAT WE CAN CALL GCD-FIX-FIX IMMEDIATELY ;;;If you want you can call GCD-BIG-FIX-1 with the length of the bignum in M-C ;;; and the sign bit in the low order bit of M-A. Note that GCD-BIG-FIX-1 doesn't handle ;;; the case with a fixnum 0! GCD-BIG-FIX GCD-FIX-BIG (JUMP-EQUAL M-2 A-ZERO GCD-IS-ABS-M-B) ((M-C) BIGNUM-HEADER-LENGTH MD) ((M-A) BIGNUM-HEADER-SIGN MD) GCD-BIG-FIX-1 GCD-FIX-BIG-1 (JUMP-XCT-NEXT GCD-FIX-FIX) ;DO A FIXNUM FIXNUM GCD, (CALL REMAINDER-BIG-FIX-1) ;BUT FIRST GET (\ BIGNUM FIXNUM) GCD-IS-ABS-M-B ((M-I) BIGNUM-HEADER-LENGTH MD) (JUMP-XCT-NEXT BIGNUM-ABS) ((M-Q) M-B) ;;;We get here with a bignum in M-B and a bignum in M-C with its header in MD ;;; M-T also has the same thing in it as M-B GCD-BIG-BIG ((M-E) HEADER-REST-FIELD MD) ((VMA-START-READ) M-B) (CHECK-PAGE-READ) ((M-J) BIGNUM-HEADER-LENGTH M-E) ((M-I) BIGNUM-HEADER-LENGTH MD) (JUMP-GREATER-OR-EQUAL-XCT-NEXT M-I A-J GCDBB-1) ((M-D) HEADER-REST-FIELD MD) ((M-J) BIGNUM-HEADER-LENGTH M-D) ((M-I) BIGNUM-HEADER-LENGTH M-E) ((M-D) M-E) ((M-B) M-C) ((M-C) M-T) ;Remember M-T and M-B start with the same thing. GCDBB-1 (JUMP-GREATER-THAN M-J (A-CONSTANT 1) GCDBB-LONG) ;; since M-J = 1 we can use Bignum-Fixnum case. ((VMA-START-READ) ADD M-C (A-CONSTANT 1)) (CHECK-PAGE-READ) ((M-2) MD) ((M-C) BIGNUM-HEADER-LENGTH M-D) ((M-A) BIGNUM-HEADER-SIGN M-D) ;;First do (\ bignum fixnum). REMAINDER-BIG-FIX must leave answer in ;;M-1 and not bash M-2. (JUMP-XCT-NEXT GCD-FIX-FIX) (CALL REMAINDER-BIG-FIX-1) ;;;When we get here we have the longer bignum in M-B,M-I shorter in M-C,M-J ;;; So M-I and M-J are both 2 or more. ;;;To make this work BIDIV-REMAINDER-COMMON must not touch the contents of M-C GCDBB-LONG ((M-Q) M-B) ((M-R) M-C) ;saved by BIDIV-REMAINDER-COMMON (CALL-XCT-NEXT BIDIV-REMAINDER-COMMON) ((M-A) A-ZERO) ;indicate quotient is not being saved. ;; Now we have a bignum in M-Q,(M-I + 1) that is the remainder ;;shifted left by an amount determined by M-D. M-C,M-J contains ;;the bignum we were dividing by. ;; We are going to pretend from now on that the bignum in ;;M-Q is only M-J long. ((M-T) M-C) ((M-K) ADD M-I (A-CONSTANT 2)) ;(length of bignum in M-Q) + 1 ;;Now shift down the bignum in M-Q ((M-C) M-Q) (CALL-XCT-NEXT GCDBB-SHIFT) ((M-S) M-Q) (JUMP-NOT-EQUAL-XCT-NEXT M-E A-ZERO GCDBB-NO-LUCK) ((M-C) M-T) ((M-1) M-Q) ((M-Q) A-V-NIL) ;Possible pointer to garbage. ((M-S) A-V-NIL) ;Possible pointer to garbage. (JUMP-XCT-NEXT UN-CONS) ((M-2) M-K) ;saved just for the occasion. GCDBB-NO-LUCK ;;Figure out how much it was shifted: ((M-TEM) DPB M-3 (BYTE-FIELD 27. 5.) A-ZERO) ((M-TEM) SUB M-TEM A-3) ((M-TEM) ADD M-TEM A-4) ((M-TEM) SUB M-TEM (A-CONSTANT 31.)) ((M-D) ADD M-TEM A-D) ;M-D had 31. - (the number of extra zeros that ;BIDIV-REMAINDER-COMMON introduced) . (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-R) Q-POINTER M-T (A-CONSTANT (BYTE-VALUE Q-DATA-TYPE DTP-EXTENDED-NUMBER))) (CHECK-PAGE-WRITE) (CALL-XCT-NEXT GCDBB-SHIFT) ((M-S) M-R) ;Prepare to call GCDBB-SHIFT ;;M-TEM gets the number of factors of two in the bignum in M-R. ((M-TEM) DPB M-3 (BYTE-FIELD 27. 5.) A-ZERO) ((M-TEM) SUB M-TEM A-3) ((M-TEM) ADD M-TEM A-4) ;;M-D gets the power of two in the answer: (JUMP-LESS-THAN M-D A-TEM GCDBB-4) ((M-D) M-TEM) GCDBB-4 ((M-T) M-Q) ;This one will be the answer ((M-K) M-J) ;This is its length ;;;We get here with two odd bignums in M-Q and M-R, their actual length is in M-K, ;;; the one to return as answer is also in M-T, the number of powers of 2 in the ;;; answer is in M-D, M-J contains the length of the bignums that might still be nonzero. GCDBB-LOOP ((M-I) M-J) ;Step down the bignums GCDBB-L1 ((VMA-START-READ) ADD M-Q A-I) (CHECK-PAGE-READ) ((M-2) MD) ((VMA-START-READ) ADD M-R A-I) (CHECK-PAGE-READ) ; (JUMP-EQUAL-XCT-NEXT M-I (A-CONSTANT 1) GCD-FIX-FIX) ;something like this ; ((M-1) MD) ;should be done. (JUMP-NOT-EQUAL-XCT-NEXT M-2 A-ZERO GCDBB-SUB) ((M-I) SUB M-I (A-CONSTANT 1)) (JUMP-NOT-EQUAL MD A-ZERO GCDBB-ORDER) (JUMP-XCT-NEXT GCDBB-L1) ((M-J) M-I) GCDBB-SUB-L ((VMA-START-READ) ADD M-Q A-I) (CHECK-PAGE-READ) ((M-2) MD) ((VMA-START-READ) ADD M-R A-I) (CHECK-PAGE-READ) ((M-I) SUB M-I (A-CONSTANT 1)) GCDBB-SUB (JUMP-GREATER-THAN MD A-2 GCDBB-ORDER) (JUMP-LESS-THAN MD A-2 GCDBB-NORDER) (JUMP-GREATER-THAN M-I A-ZERO GCDBB-SUB-L) ;;;Here we are done, the answer is in M-T, although it might have to be trimmed and shifted. ;;; There is a bignum to give back in M-Q or M-R. (JUMP-EQUAL-XCT-NEXT M-R A-T GCDBB-GIVE-BACK-M-Q) ((M-2) ADD M-K (A-CONSTANT 1)) ;This is how much to give back ((M-Q) M-R) ((M-R) A-V-NIL) ;Possible pointer to garbage. GCDBB-GIVE-BACK-M-Q ((M-1) Q-POINTER M-Q) ((M-S) A-V-NIL) ;Possible pointer to garbage. (CALL-XCT-NEXT UN-CONS) ((M-Q) A-V-NIL) ;Possible pointer to garbage. ((M-1) M-D) (CALL-XCT-NEXT DIV) ((M-2) (A-CONSTANT 31.)) (JUMP-EQUAL-XCT-NEXT M-1 A-ZERO GCDBB-COPY-WORDS) ((M-E) Q-R) ;This is the offset we want ((M-I) M-K) ;Real length (sig. length in M-J) ((M-B) M-T) ;From ((M-D) M-T) ;To ;;Constant for LDB (M-K): ((M-K) ADD M-1 (A-CONSTANT 1)) ;MROT = M-1 + 1 ((M-TEM) SUB M-1 (A-CONSTANT 1)) ;BYTL-1 = M-1 + 1 ((M-K) DPB M-TEM OAL-BYTL-1 A-K) ;;Constant for DPB (M-S): ((M-TEM) (A-CONSTANT 30.)) ((M-TEM) SUB M-TEM A-1) ;BYTL-1 = 30. - M-1 ((M-S) DPB M-TEM OAL-BYTL-1 A-1) ;MROT = M-1 ((M-ZR) SUB M-I A-E) ;Read first word from here. ((VMA-START-READ) ADD M-D A-ZR) (CHECK-PAGE-READ) #+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-ZR (A-CONSTANT 1)) GCDBB-RETURN ;;Cleanup Bignum in M-Q (Have to reread header to get actual length!) ((VMA-START-READ) M-T) (CHECK-PAGE-READ) ((M-D) BIGNUM-HEADER-LENGTH MD) ((M-C) M-D) (JUMP-XCT-NEXT ARY-TO-BIG-CLEANUP) ((M-E) M-D) GCDBB-COPY-WORDS (JUMP-EQUAL M-E A-ZERO GCDBB-RETURN) ((M-A) M-K) ;Move words to here, ((M-B) SUB M-A A-E) ;from here. GCDBB-COPY-WORDS-1 ((VMA-START-READ) ADD M-T A-B) (CHECK-PAGE-READ) ((VMA-START-WRITE) ADD M-T A-A) (CHECK-PAGE-WRITE) ((M-A) SUB M-A (A-CONSTANT 1)) (JUMP-GREATER-THAN-XCT-NEXT M-B (A-CONSTANT 1) GCDBB-COPY-WORDS-1) ((M-B) SUB M-B (A-CONSTANT 1)) ((MD) A-ZERO) GCDBB-COPY-WORDS-2 ((VMA-START-WRITE) ADD M-T A-A) (CHECK-PAGE-WRITE) (JUMP-GREATER-THAN-XCT-NEXT M-A (A-CONSTANT 1) GCDBB-COPY-WORDS-2) ((M-A) SUB M-A (A-CONSTANT 1)) (JUMP GCDBB-RETURN) GCDBB-NORDER ((M-TEM) M-Q) ((M-Q) M-R) ((M-R) M-TEM) GCDBB-ORDER ((M-ZR) (A-CONSTANT 1)) ;steps (up) thru bignums ((M-C) A-ZERO) ;borrow from last round ((M-S) M-R) ;we subtract into this guy ((M-E) A-ZERO) ;For BIGNUM-RIGHT-JUST GCDBB-STUFF ((VMA-START-READ) ADD M-Q A-ZR) (CHECK-PAGE-READ) ((M-2) ADD MD A-C) ;remember to borrow ((VMA-START-READ) ADD M-R A-ZR) (CHECK-PAGE-READ) ((M-2) SUB MD A-2) ((M-C) (BYTE-FIELD 1 31.) M-2 A-ZERO) (CALL-XCT-NEXT BIGNUM-RIGHT-JUST) ((M-2) (BYTE-FIELD 31. 0) M-2 A-ZERO) (JUMP-LESS-THAN-XCT-NEXT M-ZR A-J GCDBB-STUFF) ((M-ZR) ADD M-ZR (A-CONSTANT 1)) (CALL-XCT-NEXT BIGNUM-RIGHT-JUST) ;Flush last bits. ((M-2) A-ZERO) (JUMP-GREATER-THAN M-E A-J GCDBB-LOOP) GCDBB-STUFF-1 ((MD) A-ZERO) ((VMA-START-WRITE) ADD M-S A-E) (CHECK-PAGE-WRITE) (JUMP-LESS-THAN-XCT-NEXT M-E A-J GCDBB-STUFF-1) ((M-E) ADD M-E (A-CONSTANT 1)) (JUMP GCDBB-LOOP) ;;;Right justify a bignum in M-C into a bignum in M-S (M-J contains the length for both.) ;;; M-I steps through M-C and BIGNUM-RIGHT-JUST is used. ;;;In case M-C contains all zeros M-E will contain 0 instead of M-J + 1. GCDBB-SHIFT ((M-E) A-ZERO) ((M-3) A-MINUS-ONE) ((M-I) (A-CONSTANT 1)) ;step thru bignum in M-C GCDBB-2 ((VMA-START-READ) ADD M-C A-I) (CHECK-PAGE-READ) (CALL-XCT-NEXT BIGNUM-RIGHT-JUST) ((M-2) MD) (JUMP-LESS-THAN-XCT-NEXT M-I A-J GCDBB-2) ((M-I) ADD M-I (A-CONSTANT 1)) (CALL-XCT-NEXT BIGNUM-RIGHT-JUST) ;Flush last bits ((M-2) A-ZERO) (POPJ-GREATER-THAN M-E A-J) (POPJ-EQUAL M-E A-ZERO) ;M-C was all zeros! ((MD) A-ZERO) GCDBB-3 ((VMA-START-WRITE) ADD M-S A-E) (CHECK-PAGE-WRITE) (JUMP-LESS-THAN-XCT-NEXT M-E A-J GCDBB-3) ((M-E) ADD M-E (A-CONSTANT 1)) (POPJ) (end-pagable-ucode) ))