跳转至

SC.D

说明

条件存入双字(Store-Conditional Doubleword)
本指令执行如下的原子操作:如果以右源寄存器值为地址的内存上存在加载保留,那么将左源寄存器中8个字节的数据存入该地址。如果存入成功,将0写入目的寄存器;否则写入一个非0的错误码。

汇编语法

    sc.d<.{aq, rl, f, aqrl, aqf, rlf, aqrlf}> SrcL, [SrcR], ->{t, u, Rd}

汇编符号

  • SrcL:左源寄存器,可以索引全局寄存器R0-R23和前序1-4条输出至T队列或U队列的指令结果。
  • SrcR:右源寄存器,可以索引全局寄存器R0-R23和前序1-4条输出至T队列或U队列的指令结果。
  • .aq,.rl:内存访问限制,详见原子指令介绍。
  • .f:指令可选后缀,表示内存访问发生在远端Cache中。
  • ->:用于指示目的寄存器。
  • {t,u,Rd}:表示三种可选的目的寄存器,编码于RegDst域。其中:
    • t,u:分别表示块内的T和U寄存器队列。
    • Rd:可以索引全局寄存器R1-R23。

编码格式

SC.D

执行方式

  • 转换为十进制数:UInt()
  • 通用寄存器读写:R[]
  • 条件存储:StoreConditonal()-把值写到目标地址之前,会先判断目标内存地址是否有设置保留标记,如果设置了,则把值正常写入到目标内存地址里,并把目的寄存器设置成 0,表示保存成功。如果目的内存地址没有设置保留标记,则不保存,并把目的寄存器设置成非 0 表示保存失败。不管成功还是失败,sc指令都会把当前保留的所有标记清除。
    integer d = UInt(RegDst);
    integer m = UInt(SrcL);
    integer n = UInt(SrcR);
    integer datawidth = 64;

    bits(datawidth) operand = R[m, datawidth];
    bits(datawidth) address = R[n, datawidth];

    bits(datawidth) result = StoreConditonal(Mem[address], operand);

    R[d, datawidth] = result;

汇编示例

用 lr/sc 实现内存双字 Mem[a0]的比较-交换操作:预期的旧值在a1中;所需的新值在a2中。

0 :  lr.d [a0], ->t        /* 加载旧的值 */
4 :  b.ne t#1, a1, 60      /* 比较旧的值与a1是否相等 */
8 :  sc.d a2, [a0], ->t    /* 相等则存入新的值 */
c :  b.ne t#1, zero, 0     /* 如果存入失败,重新尝试 */
    ...                    /* 比较交换成功之后执行的指令 */
    ...
60:                        /* 比较交换不成功 */

汇编索引模式

  • 指令输出到块内t寄存器
sc.d a1, [a2],          ->t      /* 双寄存器绝对索引 */
sc.d a1, [t#2],         ->t      /* 双寄存器混合索引 */
sc.d a1, [u#2],         ->t      /* 双寄存器混合索引 */
sc.d t#1, [a2],         ->t      /* 双寄存器混合索引 */
sc.d t#1, [t#2],        ->t      /* 双寄存器相对索引 */
sc.d t#1, [u#2],        ->t      /* 双寄存器相对索引 */
sc.d u#1, [a2],         ->t      /* 双寄存器混合索引 */
sc.d u#1, [t#2],        ->t      /* 双寄存器相对索引 */
sc.d u#1, [u#2],        ->t      /* 双寄存器相对索引 */
sc.d.aq a1, [a2],       ->t      /* 后序访存指令限制 */
sc.d.rl a1, [t#2],      ->t      /* 前序访存指令限制 */
sc.d.aqrl a1, [u#2],    ->t      /* 前序和后序访存指令限制 */
  • 指令输出到块内u寄存器
sc.d a1, [a2],          ->u      /* 双寄存器绝对索引 */
sc.d a1, [t#2],         ->u      /* 双寄存器混合索引 */
sc.d a1, [u#2],         ->u      /* 双寄存器混合索引 */
sc.d t#1, [a2],         ->u      /* 双寄存器混合索引 */
sc.d t#1, [t#2],        ->u      /* 双寄存器相对索引 */
sc.d t#1, [u#2],        ->u      /* 双寄存器相对索引 */
sc.d u#1, [a2],         ->u      /* 双寄存器混合索引 */
sc.d u#1, [t#2],        ->u      /* 双寄存器相对索引 */
sc.d u#1, [u#2],        ->u      /* 双寄存器相对索引 */
sc.d.aq a1, [a2],       ->u      /* 后序访存指令限制 */
sc.d.rl a1, [t#2],      ->u      /* 前序访存指令限制 */
sc.d.aqrl a1, [u#2],    ->u      /* 前序和后序访存指令限制 */
  • 指令输出到全局寄存器R1-R23
sc.d a1, [a2],          ->a3      /* 双寄存器绝对索引 */
sc.d a1, [t#2],         ->a3      /* 双寄存器混合索引 */
sc.d a1, [u#2],         ->a3      /* 双寄存器混合索引 */
sc.d t#1, [a2],         ->a3      /* 双寄存器混合索引 */
sc.d t#1, [t#2],        ->a3      /* 双寄存器相对索引 */
sc.d t#1, [u#2],        ->a3      /* 双寄存器相对索引 */
sc.d u#1, [a2],         ->a3      /* 双寄存器混合索引 */
sc.d u#1, [t#2],        ->a3      /* 双寄存器相对索引 */
sc.d u#1, [u#2],        ->a3      /* 双寄存器相对索引 */
sc.d.aq a1, [a2],       ->a3      /* 后序访存指令限制 */
sc.d.rl a1, [t#2],      ->a3      /* 前序访存指令限制 */
sc.d.aqrl a1, [u#2],    ->a3      /* 前序和后序访存指令限制 */

约束

  • 本指令属于系统块指令集,仅允许在系统块内使用。
  • 本指令要求内存访问地址必须8字节对齐,否则触发地址不对齐异常。
  • LR.D与SC.D指令成对出现性能会比较好,单独出现会导致监视器阻塞。