***************************************** * * * UMult_SMult_060.s * * $VER: UMult_SMult_060.s 1.3 (26.9.98) * * * ***************************************** *=================================================================== * The timings are given without any warranty. It's hard to figure * out all possible situations... * * The difference between minimum and maximum timings is due to the * branch cache and superscalar capabilities. * Maximum timing assumes no superscalar dispatches and wrong branch * predictions. * Minimum timing assumes superscalar dispatches and correctly * predicted branches. *=================================================================== CNOP 0,8 Patch_Start * a (32) × b (32) = c (64) unsigned) * d0 d1 d0:d1 * * timings : * a×b=0 : 13 (min) -> 29 (max) cycles. * a×b<>0 : 36 (min) -> 55 (max) cycles. * * NOTE: Shift/rotate instructions may be dispatched, while * swap will only execute in pOEP. UMult64 ; movem.l d5/d6,-(sp) ; 2 move.l d6,-(sp) move.l d5,-(sp) move.l d1,d6 ; 1 beq.s return0 ; Result = 0 move.l d0,d5 ; 1/8 beq.s return0 ; Result = 0 ; movem.l d2/d3,-(sp) ; 3/10 move.l d3,-(sp) move.l d2,-(sp) moveq #16,d2 ; 1 move.l d0,d3 ; 0/1 ror.l d2,d6 ; 1 (=swap) ror.l d2,d3 ; 0/1 (=swap) ; 9 (min) => 25 (max) ; d0.w = Factor1_l = d5.w * [(a<<16)+b] × [(c<<16)+d] = ; d3.w = Factor1_h * ac<<32 + (ad+bc)<<16 + bd ; d1.w = Factor2_l ; d6.w = Factor2_h mulu.w d1,d0 ; 2 Factor2_l × Factor1_l = bd mulu.w d3,d1 ; 2 Factor1_h × Factor2_l = ad mulu.w d6,d5 ; 2 Factor2_h × Factor1_l = bc mulu.w d6,d3 ; 2 Factor2_h × Factor1_h = ac ror.l d2,d0 ; 1 (=swap) clr.l d6 ; 0/1 add.w d1,d0 ; 1 Add ad to bd's most significant word addx.l d6,d3 ; 1 Add the potential carry to ac add.w d5,d0 ; 1 Add bc to bd's most significant word addx.l d6,d3 ; 1 Add the potential carry to ac lsr.l d2,d1 ; 1 (~swap) lsr.l d2,d5 ; 0/1 (~swap) add.l d3,d1 ; 1 ror.l d2,d0 ; 0/1 (=swap) Reorder bd add.l d5,d1 ; 1 = Most significant longword. ; movem.l (sp)+,d2/d3/d5/d6 ; 4 move.l (sp)+,d2 move.l (sp)+,d3 move.l (sp)+,d5 move.l (sp)+,d6 rts ; 7 ; 27 (min) => 30 (max) ; ----- ; TOTAL : 36 => 55 cycles. CNOP 0,8 return0 clr.l d0 ; 1/8 clr.l d1 ; 0/1 movem.l (sp)+,d5/d6 ; 2 ; move.l (sp)+,d5 ; move.l (sp)+,d6 rts ; 7 ; 10 -> 18 *============================================================================== * a (32) × b (32) = c (64) unsigned) * d0 d1 d0:d1 * * timings : * a×b=0 : 13 (min) -> 29 (max) * a>0, b>0 : 41 (min) -> 82 (max) * a>0, b<0 : 45 (min) -> 88 (max) * a<0, b>0 : 45 (min) -> 88 (max) * a<0, b<0 : 46 (min) -> 90 (max) CNOP 0,8 SMult64 ; movem.l d5/d6,-(sp) ; 2 move.l d6,-(sp) move.l d5,-(sp) move.l d0,d6 ; 1 beq.s return0 tst.l d1 ; 1/8 beq.s return0 ; movem.l d2-d4,-(sp) ; 4/11 move.l d4,-(sp) move.l d3,-(sp) move.l d2,-(sp) eor.l d1,d6 ; 1 Get result's sign move.l d0,d2 ; 0/1 bpl.s .pos0 ; --- ; 9 (min) => 24 (max) neg.l d2 ; 1/8 neg.l d0 ; 1 .pos0 move.l d1,d4 ; 0/1 (or 1/8 when branch was taken) bpl.s .pos1 ; --- ; b>0 : 1 (min) => 8 (max) ; b<0 : 2 (min) => 10 (max) neg.l d4 ; 1/8 neg.l d1 ; 1 .pos1 moveq #16,d5 ; 0/1 (or 1/8 when branch was taken) move.l d0,d3 ; 1 ror.l d5,d4 ; 0/1 ror.l d5,d3 ; 1 ; --- ; a>0 : 3 (min) => 11 (max) ; a<0 : 4 (min) => 13 (max) ; d0.w = Factor1_l = d2.w * [(a<<16)+b] × [(c<<16)+d] = ; d3.w = Factor1_h * ac<<32 + (ad+bc)<<16 + bd ; d1.w = Factor2_l ; d4.w = Factor2_h mulu.w d1,d0 ; 2 Factor2_l × Factor1_l = bd mulu.w d3,d1 ; 2 Factor1_h × Factor2_l = ad mulu.w d4,d2 ; 2 Factor2_h × Factor1_l = bc mulu.w d4,d3 ; 2 Factor2_h × Factor1_h = ac ror.l d5,d0 ; 1 clr.l d4 ; 0/1 add.w d1,d0 ; 1 Add ad to bd's most significant word addx.l d4,d3 ; 1 Add the potential carry to ac add.w d2,d0 ; 1 Add bc to bd's most significant word addx.l d4,d3 ; 1 Add the potential carry to ac lsr.l d5,d1 ; 1 (~swap) lsr.l d5,d2 ; 0/1 (~swap) add.l d3,d1 ; 1 ror.l d5,d0 ; 0/1 (=swap) Reorder bd add.l d2,d1 ; 1 = Most significant longword. ; ---- ; 16 (min) => 19 (max) tst.l d6 ; 0/1 bpl.s .exit ; ---- ; 0 (min) => 1 (max) neg.l d0 negx.l d1 ; not.l d0 ; 1/8 ; not.l d1 ; 1 ; addq.l #1,d0 ; 0/1 ; addx.l d4,d1 ; 1 ; ---- ; 3 (min) => 11 (max) .exit ; movem.l (sp)+,d2-d6 ; 5 (or 5/12 if bpl was taken) move.l (sp)+,d2 move.l (sp)+,d3 move.l (sp)+,d4 move.l (sp)+,d5 move.l (sp)+,d6 rts ; 7 ; ---- ; a×b<0 : 12 (min) => 12 (max) ; a×b>0 : 12 (min) => 19 (max) ; CNOP 0,8 ; ;.return0 clr.l d0 ; 1/8 ; clr.l d1 ; 0/1 ; movem.l (sp)+,d5/d6 ; 2 ; move.l (sp)+,d5 ; move.l (sp)+,d6 ; rts ; 7 ; ---- ; 10 (min) => 18 (max) ; Name of the MsgPort we check to see if we have ; already patched these functions. PortName: dc.b "PatchMult64_checkport",0 CNOP 0,4 ; Ensure that the code's length is an Patch_End: ; even multiple of 4.