Rev 635 | Blame | Compare with Previous | Last modification | View Log | Download
;; LONG function for long integer package:;;INCLUDE "bds.lib"FUNCTION "LONG"FUNCHEAD longsz; temporary storage is allocated in the; "args" area of the run-time environmentu equ args ;temporary quad storage (4 bytes)uh equ u ;high word of uul equ u+2 ;low word of umq equ u+4 ;temporary quad storage used by;multiplication and division routinestemp equ mq+4 ;temporary storage byte used by div'n routine; long is main routine which dispatches to the various functions; of the package according to the value of its first argument;long:push bc ;save for benefit of callercall ma2toh ;get 1st arg (function code) into HL and Ald d,hld e,ladd hl,hladd hl,de ;HL now has triple the function code_1=$+1ld de,jtab ;base of jump tableadd hl,dejp (hl) ;dispatch to appropriate functionjtab:_2=$+1jp lmake ;jump table for quad functions_3=$+1jp lcomp_4=$+1jp ladd_5=$+1jp lsub_6=$+1jp lmul_7=$+1jp ldiv_8=$+1jp lmod; lmake converts integer (arg3) to a long (arg2)lmake: call ma4toh ;get arg3 into HLld a,h ;look at sign firstor apush af ;save itcall m,cmh ;take abs valueex de,hl ;into (DE)ld bc,0 ;zero out high wordpop af_9=$+1call m,qneg ;complement if necessary_10=$+1jp putarg ;copy result into arg2 and return;all other routines copy their arguments into the quad register (BCDE);and the temporary quad storage location u (note that temporary storage;must be used to keep the routines from clobbering the user's arguments);lcomp compares arg2 with arg3, returns -1, 0, 1 for <, =, >, resplcomp: call ma3toh ;get pointer to arg2_11=$+1call qldld hl,u_12=$+1call qst ;arg2 now in ucall ma4toh ;get pointer to arg3_13=$+1call qld ;arg3 now in (BCDE)ld hl,-1 ;presume <_14=$+1call qsub_15=$+1call qtstpop bc ;restore bc for callerret minc hlret zinc hlret; long additionladd:_16=$+1call getargs ;get args into (BCDE) and u_17=$+1call qadd ;do the addition_18=$+1jp putarg ;copy result into arg2 and returnlsub:_19=$+1call getargs_20=$+1call qsub_21=$+1jp putarglmul:_22=$+1call getargs_23=$+1call qmul_24=$+1jp putargldiv:_25=$+1call getargs_26=$+1call qdiv_27=$+1jp putarglmod:_28=$+1call getargs_29=$+1call qmod_30=$+1jp putarg;getargs gets arg3 into u, arg4 into (BCDE)getargs:call ma5toh ;get ptr to arg3 (note use ma5 cause of;return addr on stack)_31=$+1call qld ;arg3 now in (BCDE)ld hl,u_32=$+1call qst ;now in ucall ma6toh ;get ptr to arg4_33=$+1jp qld ;arg4 now in (BCDE); putarg copies (BCDE) into result arg (arg2) and cleans upputarg: call ma3toh ;get pointer to arg2_34=$+1call qst ;copy (BCDE) into itpop bc ;restore BC for callerret; quad subtraction u - (BCDE) -> (BCDE)qsub:_35=$+1call qneg ;complement (BCDE) and fall thru to add; quad addition u + (BCDE) -> (BCDE)qadd: push hlld hl,u+3 ;tenSHUNld a,(hl) ;hupadd e ;twold e,a ;threedec hl ;fourld a,(hl) ;hupadc d ;twold d,a ;threedec hl ;fourld a,(hl) ;hupadc c ;twold c,a ;threedec hl ;fourld a,(hl) ;hupadc b ;twold b,a ;threepop hl ;fourret ;at ease; two's complement (BCDE)qneg: push hlxor ald l,asbc eld e,ald a,lsbc dld d,ald a,lsbc cld c,ald a,lsbc bld b,apop hlretqneghl: push bcpush de_36=$+1call qld_37=$+1call qneg_38=$+1call qstpop depop bcret; signed quad multiplication; u * (BCDE) --> (BCDE)qmul:_39=$+1call csign ;take abs values and compute signspush af ;save result sign_40=$+1call uqmul ;compute productqmul1: pop af_41=$+1jp m,qneg ;complement product if neededret; csign takes abs vals of u, (BCDE), and computes product of their signscsign: ld a,b ;look at (BCDE) firstor apush af ;save flags_42=$+1call m,qneg ;complement if neededld hl,u ;now look at uld a,(hl)or a_43=$+1jp p,csign1_44=$+1call qneghlpop afxor 80h ;flip signretcsign1: pop afret; unsigned quad multiplication; u * (BCDE) --> (BCDE) (expects ptr. to u in (HL)uqmul: ld hl,upush hl ;put pointer to u on stackld hl,mq_45=$+1call qst ;(BCDE) -> mqld bc,0 ;init product to 0ld de,0uqmul1:_46=$+1call qtsthl ;test if mq is 0_47=$+1jp z,uqmul2 ;if so, donexor a ;clear carry_48=$+1call qrarhl ;shift mq over_49=$+1call c,qadd ;add u to (BCDE) if lsb=1ex (sp),hl ;get pointer to uxor a ;clear carry_50=$+1call qralhl ;double uex (sp),hl ;get back pointer to mq_51=$+1jp uqmul1uqmul2: pop hl ;restore stackret; signed division u / (BCDE) --> (BCDE)qdiv:_52=$+1call qtst ;first test for zero divisorret z_53=$+1call csign ;take care of signspush af ;save quotient sign_54=$+1call uqdiv_55=$+1call qld ;get quotient in (BCDE)_56=$+1jp qmul1 ;adjust sign of result; signed remainder u mod (BCDE) --> (BCDE)qmod:_57=$+1call qtst ;test for zero modulusret zlda u ;sign of u is that of resultor apush af ;save flags_58=$+1call csign ;get abs val of args_59=$+1call uqdiv ;remainder in (BCDE)_60=$+1jp qmul1; unsigned division u / (BCDE) --> mq, remainder in (BCDE)uqdiv: ld hl,mq ;mq will contain quotient_61=$+1call qclrhl ;clear itpush hl ;save it on the stackld l,1 ;now normalize divisoruqdiv1: ld a,b ;look at most signif non-sign bitand 40h_62=$+1jp nz,uqdiv2_63=$+1call qral ;if not 1, shift leftinc l_64=$+1jp uqdiv1uqdiv2: ld a,lsta temp ;save normalization countld hl,u_65=$+1call qxchg ;want divid in (BCDE), divisor in uex (sp),hl ;pointer to mq in (HL), u on stack;main loopuqdiv3:_66=$+1call trial ;trial subtraction of divisor_67=$+1call qralhl ;shift in the carrylda temp ;get the countdec a_68=$+1jp z,uqdiv4 ;donesta temp ;save count againex (sp),hl ;divisor in (HL)xor a_69=$+1call qrarhl ;shift it right oneex (sp),hl ;quotient in (HL)_70=$+1jp uqdiv3uqdiv4: inc spinc sp ;clean off top of stackrettrial:_71=$+1call qsub ;subtract divid from divisor_72=$+1call qneg ;actually want divisor from dividscf ;assume was positiveret p_73=$+1call qadd ;else must restore dividendxor a ;clear carryret;; routines to manipulate quads;; qld loads the quad pointed to by (HL) into (BCDE)qld: push hlld b,(hl)inc hlld c,(hl)inc hlld d,(hl)inc hlld e,(hl)pop hlret; qst is inverse of qldqst: push hlld (hl),binc hlld (hl),cinc hlld (hl),dinc hlld (hl),epop hlret; rotate (BCDE) right thru carryqrar: ld a,brrald b,ald a,crrald c,ald a,drrald d,ald a,errald e,aret; same for quad pointed to by (HL)qrarhl: push hlld a,(hl)rrald (hl),ainc hlld a,(hl)rrald (hl),ainc hlld a,(hl)rrald (hl),ainc hlld a,(hl)rrald (hl),apop hlret; rotate (BCDE) left thru carryqral: ld a,erlald e,ald a,drlald d,ald a,crlald c,ald a,brlald b,aret; qralhl does it for quad pointed to by (HL)qralhl: inc hlinc hlinc hl ;get to rightmost byteld a,(hl)rlald (hl),adec hlld a,(hl)rlald (hl),adec hlld a,(hl)rlald (hl),adec hlld a,(hl)rlald (hl),aret;qclrhl clears quad pointed to by (HL)qclrhl: push hlxor ald (hl),ainc hlld (hl),ainc hlld (hl),ainc hlld (hl),apop hlret; qtst tests sign of (BCDE), setting the usual flagsqtst: ld a,b ;look at most signif byteor aret nzor c ;test for zeroor dor eqtst1: ret pld a,1or aretqtsthl: ld a,(hl)or aret nzpush hlinc hlor (hl)inc hlor (hl)inc hlor (hl)pop hl_74=$+1jp qtst1; swap (BCDE) with thing pointed to by HLqxchg: push hlld a,(hl)ld (hl),bld b,ainc hlld a,(hl)ld (hl),cld c,ainc hlld a,(hl)ld (hl),dld d,ainc hlld a,(hl)ld (hl),eld e,apop hlretENDFUNC longsz,74