/* * _ldiv - Division u / v * * Bestimme q und r mit u = q * v + r und 0 <= |r| < |v|. */ long _ldiv (v,u) long u,v; { asm { movem.l D4-D7,-(A7) clr D7 ; kennzeichnet das Vorzeichen clr.l D0 ; Quotient q move.l u(A6),D5 ; u := (u1,u2) move.l v(A6),D3 ; v := (v1,v2) bne v_ok divs D3,D5 ; Division durch 0 bra ret v_ok: bge v_ge neg.l D3 addq #1,D7 ; negativer Quotient v_ge: tst.l D5 bge u_ge neg.l D5 addq #3,D7 ; negativer Dividend u_ge: cmp.l D5,D3 bgt ready ; v > u ? bne not_eq ; v != u ? move.l #1,D0 ; q = 1 clr.l D5 ; r = 0 bra ready not_eq: move.l D3,D4 swap D4 tst D4 beq v_word ; v < 2**16 ? moveq #15,D2 ; bestimme Normierungsfaktor move #0xFF00,D1 and D4,D1 beq len_8 lsr #8,D4 subq #8,D2 len_8: moveq #0xF0,D1 and.b D4,D1 beq len_4 lsr #4,D4 subq #4,D2 len_4: moveq #0xC,D1 and.b D4,D1 beq len_2 lsr #2,D4 subq #2,D2 len_2: moveq #0x2,D1 and.b D4,D1 beq len_1 subq #1,D2 len_1: asl.l D2,D3 ; normalisiere v clr.l D4 move D3,D4 ; D4 = v2 clr D3 swap D3 ; D3 = v1 move.l D5,D6 ; normalisiere u clr D5 swap D5 asl.l D2,D5 asl.l D2,D6 ; D6 = (u1,u2) move.l D6,D1 swap D1 move D1,D5 ; D5 = (u0,u1) divu D3,D5 ; (u0,u1) / v1 move D5,D0 ; Quotient q move D6,D5 ; r * 2**16 + u2 move D4,D1 ; v2 mulu D0,D1 ; v2 * q q_test: cmp.l D1,D5 bcc q_ok ; D5 >= D1 ? (32 Bit) subq #1,D0 ; q-- sub.l D4,D1 ; unsigned add.l D3,D5 ; unsigned bcc q_test q_ok: sub.l D1,D5 ; Rest r lsr.l D2,D5 bra ready v_word: ; Divisor hat nur 2 Byte move.l D5,D6 clr D6 swap D6 ; D6 = u1 cmp D3,D6 blt low_div divu D3,D6 move D6,D0 ; Quotient : High-Word swap D0 move D5,D6 move.l D6,D5 low_div: divu D3,D5 move D5,D0 ; Quotient : Low-Word clr D5 swap D5 ; Rest ready: cmp #3,D7 blt r_pos neg.l D5 ; negiere Rest r_pos: lsr #1,D7 bcc q_pos neg.l D0 ; negiere Quotient q_pos: move.l D0,v(A6) move.l D5,u(A6) ret: movem.l (A7)+,D4-D7 } }