Created sm2_z256_loong64.S 代码分析 (markdown)

Sun Yimin 2025-10-08 16:35:16 +08:00
parent bf553ba56f
commit c2497b2f36

@ -0,0 +1,69 @@
# 代码来源
代码来自`GmSSL`的一个未合并的PRhttps://github.com/DengJianbo-loongson/GmSSL/blob/2497946ac6458ae1fb6931b66804dbc62cfffe44/src/sm2_z256_loong64.S
# 函数说明
## __sm2_z256_modp_add
实现`(t0, t1, t2, t3) = (t0, t1, t2, t3) + (a4, a5, a6, a7)`每个代表64位整数从低到高排列也就是说`t0``a4`是最低64位数也就是多字(Multi-Word)加法。
**总体实现思路**
1. 在RISC(如龙芯/LoongArch、MIPS)架构中没有x86那样的进位标识寄存器所以进位都要用`sltu` (无符号小于)等指令手动计算。
1. 使用加`1`来实现`mod P`,这里的`1`为 $2^{256} - P$ 。
1. 使用`or`合并进位(carry)。
1. 使用`masknez``maskeqz`来选择最终结果。
## __sm2_z256_modp_dbl
实现`(t0, t1, t2, t3) = (t0, t1, t2, t3)*2`double运算。
**总体实现思路**
1. 使用移位操作:`srli.d``srli.d`和算术运算`alsl.d`实现double运算。`alsl.d $t3, $t3, $t5, 1`表示`t3 = t3<<1 + t5`
1. 其它和`__sm2_z256_modp_add`实现一致。
https://github.com/DengJianbo-loongson/GmSSL/blob/2497946ac6458ae1fb6931b66804dbc62cfffe44/src/sm2_z256_loong64.S#L94
```asm
add.d $t5, $t1, $t8 //no carry
add.d $t5, $t5, $a1
```
改为
```asm
add.d $t5, $a1, $t8 //no carry
add.d $t5, $t5, $t1
```
虽然不影响最终结果,但改完后的 `//no carry` 注释才成立 (这里`t8`的值为`0x00000000ffffffff`,`a1`为上一个字加法进位)。
https://github.com/DengJianbo-loongson/GmSSL/blob/2497946ac6458ae1fb6931b66804dbc62cfffe44/src/sm2_z256_loong64.S#L104
```asm
add.d $a2, $a2, $a1
```
改为
```asm
or $a2, $a2, $a1
```
也可以,其实我们只关注`a2`的值是0还是非0。
## __sm2_z256_modp_sub
计算 `(t0, t1, t2, t3) = (t0, t1, t2, t3) - (a4, a5, a6, a7)`
**总体实现思路**
1. 和加法一样在RISC(如龙芯/LoongArch、MIPS)架构中没有x86那样的借位标识寄存器所以借位都要用`sltu` (无符号小于)等指令手动计算。
1. 如果最后一个字的减法有借位,则再减`1`来实现`mod P`,这里的`1`为 $2^{256} - P$ 否则再减的就是0。
1. 使用`maskeqz`来选择减数是0还是`1`
## __sm2_z256_modp_neg_sub
计算`(t0, t1, t2, t3) = (t0, t1, t2, t3) - (a4, a5, a6, a7)`
和上面方法类似。
## __sm2_z256_modp_haf
计算 `(t0, t1, t2, t3) = (t0, t1, t2, t3) / 2`
**总体实现思路**
1. 如果该数是奇数,则先减`1`,这里的`1`为 $2^{256} - P$ 相当于先加P否则先减的就是0。
1. 通过`andi $a2, $t0, 1`取最低位值。
1. 使用`maskeqz`来选择减数是0还是`1`
1. 通过`srli.d``bstrins.d`进行除2操作。`bstrins.d $t0, $t1, 63, 63`表示`t0[63] = t1[0]``t0`的其它位值保持不变。
## __sm2_z256_modp_mont_mul
按字蒙哥马利模约减乘法WW-MM计算 `(t0,t1,t2,t3) = (a4,a5,a6,a7) * (t0,t1,t2,t3)`