; INTARITH.ASM ; ------------ ; ; See FALCONER.WS4 for doc. ; ; (Retyped by Emmanuel ROCHE.) ; ;-------------------------------- ; Allowable entry points ; entry imul,idiv,mul.div ; ;-------------------------------- ; Entry points for utility routines ; entry stadr.ldes,lbcs.las ; Stack addressing entry bclz,bclc,bcra,bcrc ; Shifts and complements entry dhlz,dera,derc ; entry c2bc.c1bc,c2de,c1de,c2dhl entry mul10,dten,dquik ; Fast arithmetic ; ;-------------------------------- ; Macro definition ; ; "Return" and check stack level zero ; rtn macro if .lvl error "0"+.lvl .lvl set 0 endif ret endm ; ;-------------------------------- ; Utility routines ;-------------------------------- ; ; Stack addressing routines operate on an input stack level, ; supplied via the A-register. This specifies the stack level ; with respect to the calling routine, derived by counting ; "pushes" since the item was pushed. If the item was stored ; by the last "push", its address is zero. The address may ; not exceed 252. ; ; Generate stack absolute address for stack addressing routines ; A,F,H,L ; stadr: lxi h,3 ; Allow for push H and 2 RETs add l ; Max stack level is 252 mov l,a ; dad h ; Convert to byte address dad sp ; Memory address formed rtn ; ; ; Load (DE) from stack level (A) ; A,F,D,E ; ldes: push h ; call stadr ; Get absolute address mov e,m ; inx h ; mov d,m ; pop h ; rtn ; ; ; Load (BC) from stack level (A) ; (A) is stack level W.R.T. calling routine ; A,F,B,C ; lbcs: push h ; call stadr ; Form absolute address mov c,m ; inx h ; mov b,m ; pop h ; rtn ; ; ; Load (A) from stack level (A) ; Value was stored by push psw ; A,F ; las: push h ; call stadr ; Form absolut address inx h ; mov a,m ; pop h ; rtn ; ; ; Shift (DEHL) register left, insert 0 ; Original high order bit to Carry ; A,F,D,E,H,L (A=D on exit) ; dhlz: dad h ; mov a,e ; ral ; mov e,a ; mov a,d ; ral ; mov d,a ; rtn ; ; ; (BC) left shift, zero insert, leave (B) in (A) ; A,F,B,C ; bclz: ora a ; Clear Carry ; ; (BC) left shift, Carry insert, leave (B) in (A) ; A,F,B,C ; bclc: mov a,c ; ral ; mov c,a ; mov a,b ; ral ; mov b,a ; rtn ; ; ; Arith shift right (BC), leave (C) in (A) ; A,F,B,C ; bcra: mov a,b ; ral ; ; ; (BC) right shift, Carry in, leave (C) in (A) ; A,F,B,C ; bcrc: mov a,b ; rar ; mov b,a ; mov a,c ; rar ; mov c,a ; rtn ; ; ; Arithmetic right shift (DE), leave (E) in (A) ; A,F,D,E ; dera: mov a,d ; ral ; ; ; (DE) right shift, Carry insert, leave (E) in (A) ; A,F,D,E ; derc: mov a,d ; rar ; mov d,a ; mov a,e ; rar ; mov e,a ; rtn ; ; ; 2's complement (BC), leave (B) in (A) ; A,B,C ; c2bc: dcx b ; ; ; 1's complement (DE), leave (B) in (A) ; A,D,E ; c1bc: mov a,c ; cma ; mov c,a ; mov a,b ; cma ; mov b,a ; rtn ; ; ; 2's complement (DE), leave (D) in (A) ; A,D,E ; c2de: dcx d ; ; ; 1's complement (DE), leave (D) in (A) ; A,D,E ; c1de: mov a,e ; cma ; mov e,a ; mov a,d ; cma ; mov d,a ; rtn ; ; ; 2's complement (DEHL) ; A,F,D,E,H,L ; c2dhl: xchg ; call c2de ; xchg ; call c1de ; mov a,h ; ora l ; rnz ; inx d ; Propagate Carry rtn ; ; ; Multiply (HL) by 10 (modulo 65536) ; No overflow signal ; F,H,L ; mul10: push d ; mov d,h ; mov e,l ; Copy HL to DE dad d ; 2* dad h ; 4* dad d ; 5* dad h ; 10* pop d ; Restore DE rtn ; ; ; Divide integer (HL) by 10 ; Remainder appears in (A) with flags set ; A,F,H,L ; dten: push b ; Save BC mvi c,10 ; Divisor dten1: xra a ; Clear mvi b,-16 ; Iteration count dten2: dad h ; ral ; Shift off into (A) jc dten3 ; Allow for DQUIK cmp c ; Test jc dten4 ; No bit dten3: sub c ; Bit = 1 inx h ; dten4: inr b ; Done? jm dten2 ; No ora a ; Set flags for RDR., clear Carry pop b ; Restore rtn ; ; ; *** This routine is not used in the FLTARITH system *** ; Integer divide 16 by 0 bit quantities ; (HL)/(A) => (HL); remainder => (A) ; Set Carry for division by zero. Preserve HL ; A,F,H,L ; dquik: ora a ; stc ; rz ; Division by zero push b ; .lvl set .lvl-1 ; mov c,a ; jmp dten1 ; ; ; *** End utility routines *** ; ---------------------------- ; ; Integer (pos.) multiply DE*BC -> DEHL ; Operand range 0 to 65535 ; D,E,H,L ; imul: push psw ; lxi h,0 ; Clear Accumulator mvi a,-16 ; Iteration count imul1: push psw ; Save iteration count dad h ; Left shift, Carry out mov a,e ; Left sh m'plier, insert o'flow ral ; mov e,a ; mov a,d ; ral ; mov d,a ; jnc imul2 ; No bit dad b ; Add in multiplicand jnc imul2 ; No overflow imul2: pop psw ; Iteration count inr a ; jm imul1 ; Do again pop psw ; Restore rtn ; ; ; Integer (pos.) divide (DEHL)/(BC)=>(DE) ; Remainder appears in (HL) ; Carry for overflow, when registers unchanged ; Divisor, remainder and quotient range 0 to 65535 ; Dividend range 0 to 4295*10^6 (approx.) ; F,D,E,H,L ; idiv: push psw ; mov a,e ; Check for overflow sub c ; mov a,d ; sbb b ; jc idiv1 ; No overflow pop psw ; Restore (A) stc ; Mark overflow rtn ; .lvl set .lvl+1 ; idiv1: push b ; call c2bc ; Change (BC) sign xchg ; Do arithmetic in (HL) mvi a,-16 ; Iteration count idiv2: push psw ; Save iteration count dad h ; Left shift (HLDE) rar ; Save Carry out xchg ; dad h ; xchg ; jnc idiv3 ; No Carry into L inx h ; idiv3: ral ; Regain Carry from H jc idiv4 ; Yes, generate quotient bit mov a,l ; add c ; Test for quotient bit mov a,h ; adc b ; jnc idiv5 ; No bit idiv4: dad b ; Subtract inx d ; Insert quotient bit idiv5: pop psw ; Get iteration count inr a ; jm idiv2 ; Not done pop b ; Restore BC pop psw ; Restore A ora a ; Clear any Carry, no overflow rtn ; ; ; *** This routine is not used in the FLTARITH system *** ; Signed multiply (DE)*(BC)->(DEHL) ; F,D,E,H,L ; mul: push psw ; push b ; mov a,d ; ora a ; jm mul3 ; (DE) -ve (negative) mov a,b ; ora a ; jp mul4 ; Both +ve (positive) mul1: call c2bc ; 2's complement BC mul2: call imul ; Result -ve call c2dhl ; 2's complement DEHL jmp mul5 ; mul3: call c2de ; (DE) -ve mov a,e ; ora a ; jp mul2 ; (DE) -ve, (BC) +ve call c2bc ; (DE) -ve, (BC) -ve mul4: call imul ; Result +ve mul5: pop b ; pop psw ; ora a ; Reset Carry, no overflow rtn ; ; ; *** This routine is not used in the FLTARITH system *** ; Do IDIV on signed + ho's & check overflow ; Expecting +ve result ; A,F,D,E,H,L ; idivq: call idiv ; rc ; mov a,d ; ral ; rtn ; Result should be +ve ; ; *** This routine is not used in the FLTARITH system *** ; Do IDIV on signed + ho's & check overflow ; Inputs may include 8000H ; Expecting -ve result, allow 8000H ; A,F,D,E,H,L ; idivn: call idiv ; rc ; Overflow call c2de ; Complement quotient ral ; Result should be -ve cmc ; rtn ; ; ; *** This routine is not used in the FLTARITH system *** ; Signed divide (DEHL)/(BC)->(DE) ; Remainder appears in (HL) ; Carry indicates overflow when ; inputs are preserved, except flags ; F,D,E,H,L (9) ; div: push psw ; push b ; push d ; push h ; Save in case of overflow mov a,d ; ora d ; jm div4 ; Dividend negative ora b ; @01 set .lvl ; jm div2 ; +/- call idivq ; +/+ jc div3 ; Overflow div1: pop b ; Purge stack, no overflow pop b ; pop b ; pop psw ; ora a ; Reset Carry, no overflow rtn ; .lvl set @01 ; div2: call c2bc ; +/-, complement BC call idivn ; jnc div1 ; No overflow div3: pop h ; Restore entry, overflow pop d ; pop b ; pop psw ; stc ; Mark overflow wit Carry rtn ; div4: call c2dhl ; -/?, complement DEHL mov a,b ; ora a ; jm div7 ; -/- call idivn ; div5: jc div3 ; Overflow div6: xchg ; call c2de ; xchg ; Complement remainder jmp div1 ; div7: call c2bc ; -/-, complement BC call idivq ; jmp div5 ; ; ;-------------------------------- ; END ; of INTARITH.ASM