- 注册时间
- 2007-12-28
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 12785
- 在线时间
- 小时
|
发表于 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[0]
- // 第2趟计算 left[] * right[1]
- // 第3趟计算 left[] * right[2]
- // 第4趟计算 left[] * right[3]
-
- // 每趟的计算结果为 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
-
- #undef MUL_REG
- #define MUL_REG xmm4
-
- #undef MASK_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[esp + 0Ch] ; right
- mov LEFT_REG, dword ptr [esp + 08h] ; left
- mov RESULT_REG, dword ptr[esp + 04h] ; result
- push ebx
- mov ebx,0xffffffff //置掩码,用来清除高位,仅仅保留低32bit
-
- //第1趟乘开始---
- movq MUL_REG, qword ptr [RIGHT_REG]
- pshufd MUL_REG, MUL_REG, 01000100b // R[0] -> 0:3, R[1] -> 2:4
-
- movdqu PROD_1_REG, [LEFT_REG] // 将4个DWORD一次载入
- pshufd PROD_2_REG, PROD_1_REG, 00110010b // L[2:3] -> PROD_2_REG
- pshufd PROD_1_REG, PROD_1_REG, 11011100b // L[0:1] -> PROD_1_REG
-
- //-------- 第1,2次乘
- pmuludq PROD_1_REG, MUL_REG // L[0:1] * R[0], XXXX
- movd [RESULT_REG],PROD_1_REG // store low32 bit of L0 * R[0]
- 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:[D0,D1]= L1*R[0],RROD_1_REG: XX00
- paddq PROD_1_REG, CARRY_REG // PROD_1_REG:[D0,D1]= L1 * R[0] + carry, RROD_1_REG: XX00
-
- //----插入第3,4次乘指令
- pmuludq PROD_2_REG, MUL_REG //PROD_2_REG:[D0-D4]= L[2:3] * R[0], PROD_2_REG:XXXX
-
- pshufd T0_REG, PROD_1_REG, 11111100b // T0= L1 * R[0], T0_REG: X0000
- pshufd CARRY_REG, PROD_1_REG, 11111101b // high 32bit of L1 * R[0] -->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[0], PROD_2_REG:XX00
- paddq PROD_2_REG, CARRY_REG // PROD_2_REG = L3 *R[0] + 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, [LEFT_REG] // 将4个DWORD一次载入
- pshufd PROD_2_REG, PROD_1_REG, 00110010b // L[2:3] -> PROD_2_REG
- pshufd PROD_1_REG, PROD_1_REG, 11011100b // L[0:1] -> PROD_1_REG
-
- // 第5,6次乘
- pmuludq PROD_1_REG, MUL_REG // L[0:1] * R[1], PROD_1_REG:XXXX
- paddq PROD_1_REG, T0_REG // L[0:1] * R[1] + t0, PROD_1_REG:XXXX
- movd [RESULT_REG+4],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[2:3] * R[1], 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 [RIGHT_REG+8]
- pshufd MUL_REG, MUL_REG, 01000100b // R[0] -> 0:3, R[1] -> 2:4
-
- movdqu PROD_1_REG, [LEFT_REG] // 将4个DWORD一次载入
- pshufd PROD_2_REG, PROD_1_REG, 00110010b // L[2:3] -> PROD_2_REG
- pshufd PROD_1_REG, PROD_1_REG, 11011100b // L[0:1] -> PROD_1_REG
-
-
- // 第9,10 次乘
- pmuludq PROD_1_REG, MUL_REG // L[0:1] * R[2], PROD_1_REG:XXXX
- paddq PROD_1_REG, T0_REG // L[0:1] * R[2] + t0, PROD_1_REG:XXXX
- movd [RESULT_REG+8],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[2:3] * R[2], 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, [LEFT_REG] // 将4个DWORD一次载入
- pshufd PROD_2_REG, PROD_1_REG, 00110010b // L[2:3] -> PROD_2_REG
- pshufd PROD_1_REG, PROD_1_REG, 11011100b // L[0:1] -> PROD_1_REG
-
- // 第13,14 次乘
- pmuludq PROD_1_REG, MUL_REG // L[0:1] * R[3], PROD_1_REG:XXXX
- paddq PROD_1_REG, T0_REG // L[0:1] * R[3]+ t0, PROD_1_REG:XXXX
- movd [RESULT_REG+12],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[2:3] * R[3], PROD_2_REG:XXXX
-
- movd [RESULT_REG+16], 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 [RESULT_REG+20], 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 [RESULT_REG+24],PROD_2_REG
-
- // 恢复寄存器
- pop ebx
- ret
- }
- }
复制代码 |
|