原子指令¶
原子指令,也称为原子操作或者是原子性指令,是指在多处理器系统或多线程环境中执行时不会被中断的操作,即操作要么完全执行,要么完全不执行。因为这些环境中可能有多个处理器或线程同时访问共享资源。原子指令可以确保这些操作不会被打断或部分执行,从而避免数据不一致和出现不可预测的结果。一条原子指令往往包含一组操作,这样可以提高指令集的效率、简化编程模型、减少指令流水线的开销、以及提高处理器的吞吐量。
系统块中原子指令目前主要包含以下几种:
LOAD.OP类指令¶
LOAD.OP类指令从左源寄存器SrcL指定的内存位置读出32或64位的值,将其写入目的寄存器。然后将这个读出的值与右源寄存器SrcR的值执行相应的操作(例如相加,按位与等),计算结果存入SrcL寄存器指定的内存中,并且保证这些步骤都是原子的。
| 微指令 | 汇编格式 | 描述 |
|---|---|---|
| LW.ADD | lw.add<{.aq,.rl,.aqrl}> [SrcL], SrcR, ->{t, u, Rd} | 加内存字写回,输出原内存字 |
| LW.AND | lw.and<{.aq,.rl,.aqrl}> [SrcL], SrcR, ->{t, u, Rd} | 与内存字写回,输出原内存字 |
| LW.OR | lw.or<{.aq,.rl,.aqrl}> [SrcL], SrcR, ->{t, u, Rd} | 或内存字写回,输出原内存字 |
| LW.XOR | lw.xor<{.aq,.rl,.aqrl}> [SrcL], SrcR, ->{t, u, Rd} | 异或内存字写回,输出原内存字 |
| LW.SMAX | lw.smax<{.aq,.rl,.aqrl}> [SrcL], SrcR, ->{t, u, Rd} | 内存字比较有符号最大值写回,输出原内存字 |
| LW.UMAX | lw.umax<{.aq,.rl,.aqrl}> [SrcL], SrcR, ->{t, u, Rd} | 内存字比较无符号最大值写回,输出原内存字 |
| LW.SMIN | lw.smin<{.aq,.rl,.aqrl}> [SrcL], SrcR, ->{t, u, Rd} | 内存字比较有符号最小值写回,输出原内存字 |
| LW.UMIN | lw.umin<{.aq,.rl,.aqrl}> [SrcL], SrcR, ->{t, u, Rd} | 内存字比较无符号最小值写回,输出原内存字 |
| LD.ADD | ld.add<{.aq,.rl,.aqrl}> [SrcL], SrcR, ->{t, u, Rd} | 加内存双字写回,输出原内存双字 |
| LD.AND | ld.and<{.aq,.rl,.aqrl}> [SrcL], SrcR, ->{t, u, Rd} | 与内存双字写回,输出原内存双字 |
| LD.OR | ld.or<{.aq,.rl,.aqrl}> [SrcL], SrcR, ->{t, u, Rd} | 或内存双字写回,输出原内存双字 |
| LD.XOR | ld.xor<{.aq,.rl,.aqrl}> [SrcL], SrcR, ->{t, u, Rd} | 异或内存双字写回,输出原内存双字 |
| LD.SMAX | ld.smax<{.aq,.rl,.aqrl}> [SrcL], SrcR, ->{t, u, Rd} | 内存双字比较有符号最大值写回,输出原内存双字 |
| LD.UMAX | ld.umax<{.aq,.rl,.aqrl}> [SrcL], SrcR, ->{t, u, Rd} | 内存双字比较无符号最大值写回,输出原内存双字 |
| LD.SMIN | ld.smin<{.aq,.rl,.aqrl}> [SrcL], SrcR, ->{t, u, Rd} | 内存双字比较有符号最小值写回,输出原内存双字 |
| LD.UMIN | ld.umin<{.aq,.rl,.aqrl}> [SrcL], SrcR, ->{t, u, Rd} | 内存双字比较无符号最小值写回,输出原内存双字 |
LOAD.OP类原子指令可以通过"aq"和"rl"两个后缀来添加额外的内存访问顺序限制,以保证内存访问的一致性。具体定义请见“内存访问限制参数表”。
STORE.OP类指令¶
STORE.OP类指令与LOAD.OP类指令基本功能相同,只不过没有目的寄存器,不会返回指定内存位置上没有修改之前的值。
| 微指令 | 汇编格式 | 描述 |
|---|---|---|
| SW.ADD | sw.add<{.rl}> [SrcL], SrcR | 加内存字写回 |
| SW.AND | sw.and<{.rl}> [SrcL], SrcR | 与内存字写回 |
| SW.OR | sw.or<{.rl}> [SrcL], SrcR | 或内存字写回 |
| SW.XOR | sw.xor<{.rl}> [SrcL], SrcR | 异或内存字写回 |
| SW.SMAX | sw.smax<{.rl}> [SrcL], SrcR | 内存字比较有符号最大值写回 |
| SW.UMAX | sw.umax<{.rl}> [SrcL], SrcR | 内存字比较无符号最大值写回 |
| SW.SMIN | sw.smin<{.rl}> [SrcL], SrcR | 内存字比较有符号最小值写回 |
| SW.UMIN | sw.umin<{.rl}> [SrcL], SrcR | 内存字比较无符号最小值写回 |
| SD.ADD | sd.add<{.rl}> [SrcL], SrcR | 加内存双字写回 |
| SD.AND | sd.and<{.rl}> [SrcL], SrcR | 与内存双字写回 |
| SD.OR | sd.or<{.rl}> [SrcL], SrcR | 或内存双字写回 |
| SD.XOR | sd.xor<{.rl}> [SrcL], SrcR | 异或内存双字写回 |
| SD.SMAX | sd.smax<{.rl}> [SrcL], SrcR | 内存双字比较有符号最大值写回 |
| SD.UMAX | sd.umax<{.rl}> [SrcL], SrcR | 内存双字比较无符号最大值写回 |
| SD.SMIN | sd.smin<{.rl}> [SrcL], SrcR | 内存双字比较有符号最小值写回 |
| SD.UMIN | sd.umin<{.rl}> [SrcL], SrcR | 内存双字比较无符号最小值写回 |
| SW.SUB | sw.sub<{.rl}> [SrcL], SrcR | 减内存字写回(v0.58 新增) |
| SD.SUB | sd.sub<{.rl}> [SrcL], SrcR | 减内存双字写回(v0.58 新增) |
STORE.OP类原子指令需要通过"rl"后缀来添加额外的内存访问顺序限制,以保证内存访问的一致性。详细定义请见“内存访问限制参数表”。
SX 尺寸覆盖扩展(v0.58)¶
v0.58 起,atomic 主类(6..4=000)的最高 5 位(31..27)统一为 op5 字段:
- b30..27 为操作码/尺寸码(b27 原为 far,现并入操作码作最低位):操作码
0000=ADD、0001=AND、0010=OR、0011=XOR、0100=SMAX、0101=SMIN、0110=UMAX、0111=UMIN、1000=SUB(新增);LR/SC/SWAP 的尺寸码0000=B、0001=H、0010=W、0011=D; - b31 为标志位:store-op(SW/SD 槽)为尺寸覆盖位(0=字/双字原宽度,1=缩小一档:SW 槽
14..12=011覆盖为字节 SB,SD 槽14..12=101覆盖为半字 SH);LR/SC/SWAP 及 load-op(LW.*/LD.*)为far远端访问标志(自 b27 迁至 b31,语义不变); - 因此 store-op 类指令不再支持
.f后缀(b31 已被覆盖位占用);其余家族.f后缀保留。
由此新增 4 条尺寸覆盖的原子存储指令:
| 微指令 | 汇编格式 | 描述 |
|---|---|---|
| SB.ADD | sb.add<{.rl}> [SrcL], SrcR | 加内存字节写回(SW 槽覆盖) |
| SB.SUB | sb.sub<{.rl}> [SrcL], SrcR | 减内存字节写回(SW 槽覆盖) |
| SH.ADD | sh.add<{.rl}> [SrcL], SrcR | 加内存半字写回(SD 槽覆盖) |
| SH.SUB | sh.sub<{.rl}> [SrcL], SrcR | 减内存半字写回(SD 槽覆盖) |
原子交换指令¶
原子交换指令从寄存器SrcL指定的内存位置读取8,16,32或64位的值,将其写入目的寄存器。然后再将寄存器SrcR中8,16,32或64位的值存入寄存器SrcL指定的内存中,并且保证这些步骤都是原子的。
| 微指令 | 汇编格式 | 描述 |
|---|---|---|
| SWAPB | swapb<{.aq,.rl,.aqrl}> [SrcL], SrcR, ->{t, u, Rd} | 内存与寄存器交换字节 |
| SWAPH | swaph<{.aq,.rl,.aqrl}> [SrcL], SrcR, ->{t, u, Rd} | 内存与寄存器交换半字 |
| SWAPW | swapw<{.aq,.rl,.aqrl}> [SrcL], SrcR, ->{t, u, Rd} | 内存与寄存器交换字 |
| SWAPD | swapd<{.aq,.rl,.aqrl}> [SrcL], SrcR, ->{t, u, Rd} | 内存与寄存器交换双字 |
原子交换操作指令可以通过"aq"和"rl"两个后缀来添加额外的内存访问顺序限制,以保证内存访问的一致性。具体定义请见“内存访问限制参数表”。
原子比较交换指令¶
原子比较交换指令从寄存器SrcL指定的内存位置读取8,16,32或64位的值,然后再用这个读出的值和寄存器SrcR比较,如果它们相同的话,就把寄存器SrcD中8,16,32或64位的值存入寄存器SrcL指定的内存中。最后不管前面比较的结果相不相同,都把从内存读取的原始值写入目的寄存器中,并且保证这些步骤都是原子的。
32 位编码的 CAS 指令支持 .aq/.rl 排序限制,不支持 .f 远端访问后缀;如需远端访问请使用 48 位的 HL.CAS* 系列指令。
| 微指令 | 汇编格式 | 描述 |
|---|---|---|
| CASB | casb<{.aq,.rl,.aqrl}> [SrcL], SrcR, SrcD, ->{t, u, Rd} | 内存与寄存器比较交换字节 |
| CASH | cash<{.aq,.rl,.aqrl}> [SrcL], SrcR, SrcD, ->{t, u, Rd} | 内存与寄存器比较交换半字 |
| CASW | casw<{.aq,.rl,.aqrl}> [SrcL], SrcR, SrcD, ->{t, u, Rd} | 内存与寄存器比较交换字 |
| CASD | casd<{.aq,.rl,.aqrl}> [SrcL], SrcR, SrcD, ->{t, u, Rd} | 内存与寄存器比较交换双字 |
原子比较交换指令可以通过"aq"和"rl"两个后缀来添加额外的内存访问顺序限制,以保证内存访问的一致性。具体定义请见“内存访问限制参数表”。
内存访问限制参数表¶
| aq | rl | 含义 |
|---|---|---|
| 0 | 0 | 没有顺序限制 |
| 0 | 1 | 表示该指令的前序所有访问内存的指令的结果必须在该指令执行之前被观察到 |
| 1 | 0 | 表示该指令的后序所有访问内存的指令必须等该指令执行完成后才开始执行 |
| 1 | 1 | 表示该指令的前序所有访问内存的指令的结果必须在该指令执行之前被观察到,该指令的后序所有访问内存的指令必须等该指令执行完成后才开始执行 |