无心人 发表于 2008-3-27 13:39:04

想到一个节约指令的拆解方法
假设数据在mm0
mm7=0
movq mm1, mm0
punpckhdq mm1, mm7
punpckldq mm0, mm7
则分解mm0=mm1:mm0

无心人 发表于 2008-3-27 14:46:54

void UInt128x128To256_SSE2_92F( UINT32 * const result,
                              const UINT32 * const left,
                              const UINT32 * const right )
{
      __asm
    {
      mov eax,
                mov edx,
      mov ecx,
                movd mm0,
                pmuludq mm0, //mm0 = 0:0
                pxor mm7, mm7 //mm7 = 0
      movd , mm0
                punpckhdq mm0, mm7

                movd mm1,
                pmuludq mm1, //mm1=0:1
                movd mm2,
                pmuludq mm2, //mm2=1:0
                movq mm3, mm1
                punpckhdq mm3, mm7
      punpckldq mm1, mm7
                movq mm4, mm2
                punpckhdq mm4, mm7
                punpckldq mm2, mm7
                paddq mm0, mm1
                paddq mm0, mm2
                paddq mm3, mm4
      movd , mm0
      punpckhdq mm0, mm7
                paddq mm0, mm3

                movd mm1,
                pmuludq mm1, //mm1=1:1
      movd mm2,
                pmuludq mm2, //mm2=0:2
                movd mm3,
                pmuludq mm3, //mm3=2:0
      movq mm4, mm1
                punpckhdq mm4, mm7
                punpckldq mm1, mm7
                movq mm5, mm2
                punpckhdq mm5, mm7
                punpckldq mm2, mm7
                movq mm6, mm3
                punpckhdq mm6, mm7
                punpckldq mm3, mm7
                paddq mm0, mm1
                paddq mm4, mm5
                paddq mm0, mm2
                paddq mm4, mm6
                paddq mm0, mm3
                movd , mm0
                punpckhdq mm0, mm7
                paddq mm0, mm4
      
                movd mm1,
                pmuludq mm1, //mm1=0:3
                movd mm2,
                pmuludq mm2, //mm2=3:0
                movq mm4, mm1
                punpckhdq mm4, mm7
                punpckldq mm1, mm7
                movq mm5, mm2
                punpckhdq mm5, mm7
                punpckldq mm2, mm7
      paddq mm0, mm1
                paddq mm4, mm5
                paddq mm0, mm2
      
                movd mm1,
                pmuludq mm1, //mm1=1:2
                movd mm2,
                pmuludq mm2, //mm2=2:1
      movq mm5, mm1
                punpckhdq mm5, mm7
                punpckldq mm1, mm7
                movq mm6, mm2
                punpckhdq mm6, mm7
                punpckldq mm2, mm7
                paddq mm0, mm1
                paddq mm4, mm5
                paddq mm0, mm2
                paddq mm4, mm6
                movd , mm0
                punpckhdq mm0, mm7
                paddq mm0, mm4

               
                movd mm1,
                pmuludq mm1, //mm1=2:2
      movd mm2,
                pmuludq mm2, //mm2=1:3
                movd mm3,
                pmuludq mm3, //mm3=3:1
      movq mm4, mm1
                punpckhdq mm4, mm7
                punpckldq mm1, mm7
                movq mm5, mm2
                punpckhdq mm5, mm7
                punpckldq mm2, mm7
                movq mm6, mm3
                punpckhdq mm6, mm7
                punpckldq mm3, mm7
                paddq mm0, mm1
                paddq mm4, mm5
                paddq mm0, mm2
                paddq mm4, mm6
                paddq mm0, mm3
                movd , mm0
                punpckhdq mm0, mm7
                paddq mm0, mm4

                movd mm1,
                pmuludq mm1, //mm1=2:3
                movd mm2,
                pmuludq mm2, //mm2=3:2
                movq mm3, mm1
                punpckhdq mm3, mm7
      punpckldq mm1, mm7
                movq mm4, mm2
                punpckhdq mm4, mm7
                punpckldq mm2, mm7
                paddq mm0, mm1
                paddq mm0, mm2
                paddq mm3, mm4
      movd , mm0
      punpckhdq mm0, mm7
                paddq mm0, mm3

                movd mm1,
                pmuludq mm1,
                paddq mm0, mm1
                movq , mm0

                emms
    }
}
时间不理想

无心人 发表于 2008-3-27 21:32:25

76有问题
      movq         , mm5
                psrlq         mm5, 32                        //carry
               
                //------保存最高DWORD
                movq         , mm5                        //mm3,中间结果
   =================================
                就是movq,mm5
                不知道后面两条啥意思?
                   另外最后一条应该是movd 如果写movq 存在内存溢出危险

liangbch 发表于 2008-3-27 22:30:59

完全采用SSE2指令的一个版本,指令数110条,比预期的指令少要多,仅仅比76楼少一条指令。这个版本全部使用XMM寄存器。解包主要采用pshufd指令来实现。尽管指令数不多,但却比采用我的另一个使用MMX寄存器的版本慢上好多(在PIV 2.6G上测试的结果).
   个人感觉,一次计算2组 32bit * 32bit 的SSE2指令并没有带来多大收益,就这个题目而言,使用MMX寄存器可能是一个好的选择。下面是完整的源代码。_declspec(naked)
void UInt128x128To256_SSE2_94F( UINT32 * const result,
                              const UINT32 * const left,
                              const UINT32 * const right )
// 使用XMM寄存器
// 16次乘法,分4趟,
// 操作数一律在xmm 寄存器中进行,每次乘法 计算2 组 32bit * 32 bit 乘法,每次加法 仅仅使用低64bit
// 第1趟计算 left[] * right
// 第2趟计算 left[] * right
// 第3趟计算 left[] * right
// 第4趟计算 left[] * right

// 每趟的计算结果为 5 DWORD,最低位DWORD 直接存储到result, 前3趟的计算结果的高4个DWORD(中间结果)存储到一组寄存器

// 寄存器的使用
// 1. 中间结果 放入 xmm0,xmm1,xmm2,xmm3
// 2。乘数使用 xmm4
// 2. 乘积1 使用 xmm5
// 3. 乘积2 使用 xmm6
// 4. 进位使用 xmm7
// 5. 掩码依然使用xmm5, 和 乘积1 分时复用
// 可以看到8个mmx寄存器全部派上用场

{
#define LEFT_REG        eax
#define RIGHT_REG        edx       
#define RESULT_REG        ecx

#define T0_REG        xmm0
#define T1_REG        xmm1
#define T2_REG        xmm2
#define T3_REG        xmm3

#undefMUL_REG
#define MUL_REG                xmm4

#undefMASK_REG
#define MASK_REG        xmm5

#define PROD_1_REG        xmm5
#define PROD_2_REG        xmm6
#define CARRY_REG        xmm7

//记号 XX00, 表示当前 128bit 寄存器的 值状态,每个字符表示32bit, X表示有数,0表示这部分为0
//        第1个字符bit0-bit31,第2个表示bit32-bit63,
//        第3个字符bit64-bit95, 最后1个字符表示bit96-bit127
//D0: 表示寄存器的 bit0-bit31
//D1: 表示寄存器的 bit32-bit63,        
//D2: 表示寄存器的 bit64-bit95,       
//D3: 表示寄存器的 bit96-bit127
// -〉表示传送

        __asm
    {
        mov                 RIGHT_REG, dword ptr   ;right
        mov                 LEFT_REG,dword ptr    ; left
        mov                 RESULT_REG, dword ptr   ; result
        push                ebx
        mov                ebx,0xffffffff                                        //置掩码,用来清除高位,仅仅保留低32bit
   
        //第1趟乘开始---
        movq                MUL_REG,qword ptr
        pshufd                MUL_REG,MUL_REG, 01000100b       // R -> 0:3, R -> 2:4

        movdqu                PROD_1_REG,                                 // 将4个DWORD一次载入
        pshufd                PROD_2_REG,        PROD_1_REG, 00110010b        // L -> PROD_2_REG
        pshufd                PROD_1_REG,        PROD_1_REG, 11011100b        // L -> PROD_1_REG
               
        //-------- 第1,2次乘
        pmuludq                PROD_1_REG, MUL_REG                // L * R,XXXX
        movd                ,PROD_1_REG        // store low32 bit of L0 * R
        psrldq              PROD_1_REG, 4                        // PROD_1_REG >>= 32, high 32 bit is full zero,shape XXX0
        pshufd                CARRY_REG,         PROD_1_REG, 11111100b        // 将carry分解出来, X0000
        psrldq              PROD_1_REG, 4                        // PROD_1_REG:= L1*R,RROD_1_REG: XX00
        paddq                PROD_1_REG, CARRY_REG        // PROD_1_REG:= L1 * R + carry, RROD_1_REG: XX00

        //----插入第3,4次乘指令
        pmuludq                PROD_2_REG, MUL_REG                //PROD_2_REG:= L * R,PROD_2_REG:XXXX

        pshufd                T0_REG,         PROD_1_REG, 11111100b        // T0= L1 * R,   T0_REG: X0000
        pshufd                CARRY_REG,         PROD_1_REG, 11111101b        // high 32bit ofL1 * R -->carry, carry,X0000
               
        movd                MASK_REG,        ebx
        paddq                PROD_2_REG, CARRY_REG       // PROD_2_REG +=carry, PROD_2_REG:XXXX
        movdqa                T1_REG,                PROD_2_REG       // T1= L2 * RO,T1_REG: XXXX

        psrldq              PROD_2_REG, 4                        //         PROD_2_REG:XXX0
        pand                T1_REG,                MASK_REG        //T1_REG: X0000
               
        pshufd                CARRY_REG,         PROD_2_REG, 11111100b        // 将carry分解出来, CARRY_REG:X0000
        psrldq              PROD_2_REG, 4                        // PROD_2_REG = L3 *R,        PROD_2_REG:XX00
        paddq                PROD_2_REG, CARRY_REG        // PROD_2_REG = L3 *R + carry,        PROD_2_REG:XX00

        pshufd                T2_REG,                PROD_2_REG, 11111100b        // PROD_2_REG:D0 -> T2, T2:X0000
        pshufd                T3_REG,                PROD_2_REG, 11111101b        // PROD_2_REG:D0 -> T3, T3 :X0000


        //----第二趟乘开始
        psrldq              MUL_REG, 4                               
       
        movdqu                PROD_1_REG,                                 // 将4个DWORD一次载入
        pshufd                PROD_2_REG,        PROD_1_REG, 00110010b        // L -> PROD_2_REG
        pshufd                PROD_1_REG,        PROD_1_REG, 11011100b        // L -> PROD_1_REG
               
        //   第5,6次乘
        pmuludq                PROD_1_REG, MUL_REG                //L * R,PROD_1_REG:XXXX
        paddq                PROD_1_REG, T0_REG                //L * R +t0,   PROD_1_REG:XXXX
        movd                ,PROD_1_REG        // PROD_1_REG:D0 -> result
        psrldq              PROD_1_REG, 4                // PROD_1_REG >>= 32, PROD_1_REG: XXX0
        pshufd                CARRY_REG,         PROD_1_REG, 11111100b        // 将carry分解出来,PROD_1_REG:D0-> carry
        psrldq              PROD_1_REG, 4                // PROD_1_REG>>32, PROD_1_REG: XX00
        paddq                PROD_1_REG, CARRY_REG        // PROD_1_REG += carry, PROD_1_REG:XX00
        paddq                PROD_1_REG, T1_REG                // PROD_1_REG += T1, PROD_1_REG:XX00

        //- 插入第7,8次乘指令
        pmuludq                PROD_2_REG, MUL_REG                // L * R, PROD_2_REG:XXXX

        pshufd                T0_REG,         PROD_1_REG, 11111100b        // PROD_1_REG:D0 -> T0, T0:X000
        pshufd                CARRY_REG,         PROD_1_REG, 11111101b        // PROD_1_REG:D1 -> carry, carry:X000

        movd                MASK_REG,        ebx
        paddq                PROD_2_REG, CARRY_REG       // PROD_2_REG +=carry
        paddq                PROD_2_REG, T2_REG               // PROD_2_REG += T2, PROD_2_REG:XX00
        movdqa                T1_REG,                PROD_2_REG       // PROD_2_REG -> T1, T1:XXXX

        psrldq              PROD_2_REG, 4        //PROD_2_REG: XXX0
        pand                T1_REG,                MASK_REG        //T1:X000
               
        pshufd                CARRY_REG,         PROD_2_REG, 11111100b        // 将carry分解出来, carry:X0000
        psrldq              PROD_2_REG, 4                // PROD_2_REG>>32, PROD_2_REG: XX00
        paddq                PROD_2_REG, CARRY_REG        // PROD_2_REG += carry, PROD_2_REG:XX00
        paddq                PROD_2_REG, T3_REG                // PROD_2_REG += T3, PROD_2_REG:XX00

        pshufd                T2_REG,                PROD_2_REG, 11111100b        //PROD_2_REG:D0 -> T2, T2:X000
        pshufd                T3_REG,                PROD_2_REG, 11111101b        //PROD_2_REG:D1 -> T3, T3:X000


        //第3趟乘开始 -
        movq                MUL_REG,qword ptr
        pshufd                MUL_REG,MUL_REG, 01000100b       // R -> 0:3, R -> 2:4

        movdqu                PROD_1_REG,                                 // 将4个DWORD一次载入
        pshufd                PROD_2_REG,        PROD_1_REG, 00110010b        // L -> PROD_2_REG
        pshufd                PROD_1_REG,        PROD_1_REG, 11011100b        // L -> PROD_1_REG
               

        //   第9,10 次乘
        pmuludq                PROD_1_REG, MUL_REG                // L * R,PROD_1_REG:XXXX
        paddq                PROD_1_REG, T0_REG                // L * R + t0,   PROD_1_REG:XXXX
        movd                ,PROD_1_REG        // PROD_1_REG:D0 -> result
        psrldq              PROD_1_REG, 4                // PROD_1_REG >>= 32, PROD_1_REG: XXX0
        pshufd                CARRY_REG,         PROD_1_REG, 11111100b        // 将carry分解出来,PROD_1_REG:D0-> carry
        psrldq              PROD_1_REG, 4                 // PROD_1_REG: XX00
        paddq                PROD_1_REG, CARRY_REG        // PROD_1_REG += carry, PROD_1_REG:XX00
        paddq                PROD_1_REG, T1_REG                // PROD_1_REG += T1, PROD_1_REG:XX00

        //- 插入第11,12次乘指令
        pmuludq                PROD_2_REG, MUL_REG                // L * R, PROD_2_REG:XXXX

        pshufd                T0_REG,         PROD_1_REG, 11111100b        // PROD_1_REG:D0 -> T0, T0:X000
        pshufd                CARRY_REG,         PROD_1_REG, 11111101b        // PROD_1_REG:D1 -> carry, carry:X000
               
        movd                MASK_REG,        ebx
        paddq                PROD_2_REG, CARRY_REG       // PROD_2_REG += carry
        paddq                PROD_2_REG, T2_REG                // PROD_1_REG += T2, PROD_1_REG:XX00
        movdqa                T1_REG,                PROD_2_REG       // PROD_2_REG -> T1, T1:XXXX

        psrldq              PROD_2_REG, 4                // PROD_2_REG>>32,PROD_2_REG: XXX0
        pand                T1_REG,                MASK_REG        // T1:X000
               
        pshufd                CARRY_REG,         PROD_2_REG, 11111100b        // 将carry分解出来, carry:X0000
        psrldq              PROD_2_REG, 4                // PROD_2_REG>>32, PROD_2_REG: XX00
        paddq                PROD_2_REG, CARRY_REG        // PROD_2_REG += carry, PROD_2_REG:XX00
        paddq                PROD_2_REG, T3_REG                // PROD_2_REG += T3, PROD_2_REG:XX00

        pshufd                T2_REG,                PROD_2_REG, 11111100b        //PROD_2_REG:D0 -> T2, T2:X000
        pshufd                T3_REG,                PROD_2_REG, 11111101b        //PROD_2_REG:D1 -> T3, T3:X000

               
        //   第4 趟乘开始 -
        psrldq              MUL_REG, 4        //
               
        movdqu                PROD_1_REG,                                 // 将4个DWORD一次载入
        pshufd                PROD_2_REG,        PROD_1_REG, 00110010b        // L -> PROD_2_REG
        pshufd                PROD_1_REG,        PROD_1_REG, 11011100b        // L -> PROD_1_REG
               
        //   第13,14 次乘
        pmuludq                PROD_1_REG, MUL_REG                //L * R,PROD_1_REG:XXXX
        paddq                PROD_1_REG, T0_REG                //L * R+t0,   PROD_1_REG:XXXX
        movd                ,PROD_1_REG        // PROD_1_REG:D0 -> result
        psrldq              PROD_1_REG, 4                // PROD_1_REG >>= 32, PROD_1_REG: XXX0
        pshufd                CARRY_REG, PROD_1_REG, 11111100b        // 将carry分解出来,PROD_1_REG:D0-> carry
        psrldq              PROD_1_REG, 4                // PROD_1_REG>>32, PROD_1_REG: XX00
        paddq                PROD_1_REG, CARRY_REG        // PROD_1_REG += carry, PROD_1_REG:XX00
        paddq                PROD_1_REG, T1_REG

        //- 插入第15,16次乘指令
        pmuludq                PROD_2_REG, MUL_REG                // L * R, PROD_2_REG:XXXX

        movd                , PROD_1_REG                                // PROD_1_REG:D0
        pshufd                CARRY_REG,         PROD_1_REG, 11111101b                // PROD_1_REG:D1 -> carry, carry:X000
               
        paddq                PROD_2_REG, CARRY_REG       // PROD_2_REG +=carry
        paddq                PROD_2_REG, T2_REG               // PROD_2_REG +=carry
        movd                ,        PROD_2_REG       // PROD_2_REG -> T1, T1:XXXX

        psrldq              PROD_2_REG, 4                //PROD_2_REG>>32, PROD_2_REG: XXX0
               
        pshufd                CARRY_REG,         PROD_2_REG, 11111100b        // 将carry分解出来, carry:X0000
        psrldq              PROD_2_REG, 4                        // PROD_2_REG>>32, PROD_2_REG: XX00
        paddq                PROD_2_REG, CARRY_REG        // PROD_2_REG += carry, PROD_2_REG:XX00
        paddq                PROD_2_REG, T3_REG
        movq                qword ptr ,PROD_2_REG
               
        // 恢复寄存器
        pop                ebx
        ret
    }
}

liangbch 发表于 2008-3-27 22:37:41

原帖由 无心人 于 2008-3-27 21:32 发表 http://images.5d6d.net/dz60/common/back.gif
76有问题
      movq         , mm5
                psrlq         mm5, 32                        //carry
               
                //------保存最高DWORD
               ...

    movq 表示一次写2个DWORD(8个byte)和movdqa不同,并不需要16字节对齐。如果不是特别处理,right,left,result应为DWORD数组,一定是4字节对齐的,所以使用这条指令不会出错。

关于最后的指令,我仔细看了下,确实有问题,下面的2条指令应该删除。
    “psrlq   mm5, 32” 和 “movq      , mm5”,如此速度更快些。

liangbch 发表于 2008-3-27 22:50:57

正如无心人所言,第76#程序有个bug,就是对result缓冲区多写了4个byte,不过结果却是正确的。修复后的版本见下,减少了2条指令,加上Emms指令,指令条数和94楼,56楼持平(110 条)。不知有谁会破了这个记录。_declspec(naked)
void UInt128x128To256_SSE2_96F( UINT32 * const result,
                              const UINT32 * const left,
                              const UINT32 * const right )
// 使用MMX寄存器, 但用SSE2指令
// 指令的使用,乘法 使用 32bit * 32bit 的MMX指令,加法使用 64 bit + 64 bit 的SSE2指令

// 16次乘法,分4趟, 操作数一律在mmx 寄存器中进行
// 第1趟计算 left[] * right
// 第2趟计算 left[] * right
// 第3趟计算 left[] * right
// 第4趟计算 left[] * right

// 每趟的计算结果为 5 DWORD,最低位DWORD 直接存储到result, 前3趟的计算结果的高4个DWORD(中间结果)存储到一组寄存器

// 寄存器的使用

// 中间结果 放入 mm0,mm1,mm2,mm3

// 掩码寄存器 mm7,用来请64位寄存器的高32bit
// 进位 寄存器 和 当前乘积寄存器 为 mm4 和 mm5,轮换使用
// 乘数 寄存器 mm6
// 可以看到8个mmx寄存器全部派上用场

{
#define LEFT_REG        eax
#define RIGHT_REG        edx       
#define RESULT_REG        ecx
#define MASK_REG        mm7
#define MUL_REG                mm6
       
        __asm
    {
        mov                  eax, 0xffffffff
        mov         RESULT_REG, dword ptr   ; result
        movd                MASK_REG, eax

        mov         RIGHT_REG, dword ptr   ; right
        movq        MUL_REG,   
        mov         LEFT_REG,dword ptr    ; left
      
               
        //--------第1次乘
        movd          mm4,       
        pmuludq          mm4, MUL_REG
        movd          , mm4
        psrlq          mm4, 32                //carry

        //------第2次乘
        movd           mm5,       
        pmuludq           mm5, MUL_REG
        paddq           mm5, mm4                //64bit + 32 bit carry
        movq           mm0, mm5
        psrlq           mm5, 32                        //carry
        pand           mm0, MASK_REG        //mm0,中间结果
               
        //------第3次乘
        movd           mm4,       
        pmuludq           mm4, MUL_REG
        paddq           mm4, mm5                        //64bit + 32 bit carry
        movq           mm1, mm4
        psrlq           mm4, 32                        //carry
        pand           mm1, MASK_REG        //mm1,中间结果
               
        //------第4次乘
        movd           mm5,       
        pmuludq           mm5, MUL_REG
        paddq           mm5, mm4                //64bit + 32 bit carry
        movq           mm2, mm5
        psrlq           mm5, 32                        //carry
        pand           mm2, MASK_REG        //mm2,中间结果
        movq           mm3, mm5                        //mm3,中间结果

        //----得到乘数
        psrlq          MUL_REG, 32                //得到right

               
        //---第二趟乘---------
               
        //--------第5次乘
        movd          mm4,       
        pmuludq          mm4, MUL_REG
        paddq          mm4, mm0                // 64bit + 32 bit 中间结果
        movd          , mm4
        psrlq          mm4, 32                //carry

        //------第6次乘
        movd           mm5,       
        pmuludq           mm5, MUL_REG
        paddq           mm5, mm4                //64bit + 32 bit carry
        paddq           mm5, mm1                //64bit + 32 bit 中间结果
        movq           mm0, mm5
        psrlq           mm5, 32                        //carry
        pand           mm0, MASK_REG        //mm0,中间结果
               
        //------第7次乘
        movd           mm4,       
        pmuludq           mm4, MUL_REG
        paddq           mm4, mm5                        //64bit + 32 bit carry
        paddq           mm4, mm2                        //64bit + 32 bit 中间结果
        movq           mm1, mm4
        psrlq           mm4, 32                        //carry
        pand           mm1, MASK_REG        //mm1,中间结果
               
        //------第8次乘
        movd           mm5,       
        pmuludq           mm5, MUL_REG
        paddq           mm5, mm4                //64bit + 32 bit carry
        paddq           mm5, mm3                //64bit + 32 bit 中间结果
        movq           mm2, mm5
        psrlq           mm5, 32                        //carry
        pand           mm2, MASK_REG        //mm2,中间结果
        movq           mm3, mm5                        //mm3,中间结果

        //----得到乘数
        movq                MUL_REG,   
               
        //--------第9次乘
        movd          mm4,       
        pmuludq          mm4, MUL_REG
        paddq          mm4, mm0                // 64bit + 32 bit 中间结果
        movd          , mm4
        psrlq          mm4, 32                //carry

        //------第10次乘
        movd           mm5,       
        pmuludq           mm5, MUL_REG
        paddq           mm5, mm4                //64bit + 32 bit carry
        paddq           mm5, mm1                //64bit + 32 bit 中间结果
        movq           mm0, mm5
        psrlq           mm5, 32                        //carry
        pand           mm0, MASK_REG        //mm0,中间结果
               
        //------第11次乘
        movd           mm4,       
        pmuludq           mm4, MUL_REG
        paddq           mm4, mm5                        //64bit + 32 bit carry
        paddq           mm4, mm2                        //64bit + 32 bit 中间结果
        movq           mm1, mm4
        psrlq           mm4, 32                        //carry
        pand           mm1, MASK_REG        //mm1,中间结果
               
        //------第12次乘
        movd           mm5,       
        pmuludq           mm5, MUL_REG
        paddq           mm5, mm4                //64bit + 32 bit carry
        paddq           mm5, mm3                //64bit + 32 bit 中间结果
        movq           mm2, mm5
        psrlq           mm5, 32                        //carry
        pand           mm2, MASK_REG        //mm2,中间结果
        movq           mm3, mm5                        //mm3,中间结果

               
        //----得到乘数
        psrlq          MUL_REG, 32                //得到right
               
        //--------第13次乘
        movd          mm4,       
        pmuludq          mm4, MUL_REG
        paddq          mm4, mm0                // 64bit + 32 bit 中间结果
        movd          , mm4
        psrlq          mm4, 32                //carry

        //------第14次乘
        movd           mm5,       
        pmuludq           mm5, MUL_REG
        paddq           mm5, mm4                //64bit + 32 bit carry
        paddq           mm5, mm1                //64bit + 32 bit 中间结果
        movd           , mm5
        psrlq           mm5, 32                        //carry
       
               
        //------第15次乘
        movd           mm4,       
        pmuludq           mm4, MUL_REG
        paddq           mm4, mm5                        //64bit + 32 bit carry
        paddq           mm4, mm2                        //64bit + 32 bit 中间结果
        movd           , mm4
        psrlq           mm4, 32                        //carry
               
               
        //------第16次乘
        movd           mm5,       
        pmuludq           mm5, MUL_REG
        paddq           mm5, mm4                //64bit + 32 bit carry
        paddq           mm5, mm3                //64bit + 32 bit
        movq           , mm5

        emms
      ret
    }
}

无心人 发表于 2008-3-28 07:58:00

我说的并不是他指令错误
而是最后还4个字节位置
用8字节写,至少在我的VC2008肯定是抛出异常的
:)
========================================
另外,我觉得
双乘并不弱于MMX,关键在我们的指令安排可能存在问题
现在想起来,16个乘,如果每条用6个指令加结果,就至少100条了
而我想,减少每次乘法后结果的指令数是很困难的

如果仔细比较,你们会发现,这次时间已逼近你们96bit的算法的时间了
而按照比率,这次最佳时间是上次的1.5倍以上
现在是否突破了上次的1.5倍呢?

无心人 发表于 2008-3-31 11:09:15

怎么停顿了
不想讨论了么?

liangbch 发表于 2008-3-31 11:31:24

原帖由 无心人 于 2008-3-31 11:09 发表 http://images.5d6d.net/dz60/common/back.gif
怎么停顿了
不想讨论了么?
好吧, 我将编写一个完全使用X86指令(不使用任何MMX,SSE,SSE2指令的版本)的版本,再对比现在的SSE2,MMX版本,看看使用 SIMD 指令的 最高加速比是多少。

无心人 发表于 2008-3-31 11:36:15

SSE2代码似乎还存在优化可能
页: 1 2 3 4 5 6 7 8 9 [10] 11 12 13 14 15
查看完整版本: x86上128位二进制乘法最快速算法征解