我记得在集会课上,我们学习了m68k处理器,你可以做3种班次。线性移位,循环移位和带延伸的圆周移位。
最后一个,带有extend的循环移位,基本上是向左或向右旋转所有位,但它会将最外面的位置放到一个延伸位,然后再将它移动到开头(如果你再次移动了1)。
我画了一张小照片:
基本上,第33位用于循环移位,但当然不会出现在32位字中。第33位是处理器的X标志,代表扩展。你可以很容易地使用任何状态标志,例如进位标志,但我想摩托罗拉人想要保留那个标志,这样它就不会被覆盖,以防万一你需要进行正常职责的进位标志。一些算法也需要用extend进行旋转。
无论如何,使用extend 旋转的目的是什么?它是干什么用的?需要什么?看起来很奇怪。为什么世界上你需要第33位?
我已阅读this和this两个相关问题,但他们没有谈到循环移位有扩展。
我知道正常轮班的一些用途。基本上除以2,或测试可分性,并置换随机性位。类似的东西。但是我想不出为什么你需要在旋转中插入一些扩展位而不会在结果中出现。
编辑:我对它的任何使用感兴趣,无论是现代的还是旧的,如果它在m68k上都无关紧要。 m68k只是我遇到它的第一个位置(我从来没有在那里使用它)。
答案 0 :(得分:2)
假设您要将32位字向右移位,但您拥有的只是16位寄存器。为此,您必须将32位字的两个16位部分向右移位,并将从高位字移出的位转换为低位字。
如果您只是有逻辑转换,这很麻烦,因为您必须手动修复该位。 rotate-through-carry指令允许您将需要传输的位保留在进位标志中并一次性将其移入。旋转进位指令将位移出进位标志,这样您就可以轻松地将它们链接在一起以右移任意大小的数据。
答案 1 :(得分:2)
在x86(以及大多数具有此指令的体系结构)上,额外的位是进位标志,很多东西都可以设置该标志。向左或向右旋转可让您将进位位移回其他寄存器。有趣的是,m68k使用不同的标志进行扩展旋转。
我不再熟悉m68k,所以我主要谈论其他拱门。 (但是apparently that's what you want:)
这样的指令通常可用于微控制器,其功能远低于x86或m68k。或者由于操作码空间有限(以及解码复杂度),某些CPU 仅具有1的旋转进位而不是常规的移位指令。如果你想要移入零,请确保首先清除标志。
8051是这样的:只向左/向右旋转1,并且左/右旋转1,而不是移位。请参阅ISA参考手册中的rlc
。如果可能的话,当你希望通过将clr
放在保留Carry清除的其他内容后将rlc
移位时,避免使用rcl reg, 1
指令。
我认为扩展循环移位通常使用进位标志,而不是像m68k那样使用自己的X位。
无论如何,扩展精度旋转对于CPU来说是传统的/预期的,但在更有限的CPU上有更多用途。
对于寄存器,adc reg,reg
与shld
的操作相同:将旧内容移位1,并将低位设置为CF.旋转或adc移出的位成为CF的新值。因此,RCL只是指令集的非冗余部分,如果它可用于内存操作数,或者(对于奇怪的情况)计数大于1.(旋转右侧版本不是多余的。)
IDK为什么要使用计数> 1.在现代x86上,循环进位相当快,count = 1,但在变量计数或固定计数> 1时肯定会很慢。 IDK鸡/蛋问题走了哪条道路:CPU设计师并没有把它变得快,因为无论如何没有人使用它,或者人们停止使用它因为它很慢。但可能是前者,因为我不记得曾经看到旋转通过提到超过1位的用途。
对于扩展精度移位,x86有一个双移指令(shrd dst, src, count
/ dst
),移位src
,从rcr dword [edi], 1
移位而不是零或符号位的副本。它不适用于2个存储器操作数,因此扩展精度移位循环必须使用单独的指令加载和存储寄存器。这比使用sub edi, 4
/ shrd
的循环更多的代码大小,但代码大小在现代x86上很少出现问题,并且使用单独的指令执行加载/存储并不慢。)更重要的是,{{ 1}}一次移位多个位,因此您可以循环一次数组,以实现2位或更多位的多精度移位。
扩展旋转只能在寄存器之间一次移位一位,因为它使用1位存储空间(在标志中)。我想m68k如果你想在寄存器之间移位多个位,你可能会复制一个寄存器并使用常规移位+ OR来组合。 (或旋转和AND / OR分割位。)
在AMD CPU上,shld
/ shrd
比rcl
/ rcr
慢1,但在英特尔CPU上则相反。 (http://agner.org/optimize/)。
除了在寄存器之间移位之外,我无法想到任何用例。也许如果你移出一点,然后分支可能设置或清除X位的东西,然后将位移回,你可以使用扩展旋转对低位或高位执行某些操作?但是你通常可以使用AND,OR或XOR与常量更容易地做同样的事情。
答案 2 :(得分:2)
想象一下,你想重复分支单词中的位。简单的rcl reg, 1
或rcr reg, 1
循环允许您只需设置标志可用于分支或其他条件指令(它位于x86上)即可。根据移出的位设置标志的移位提供相同的功能(尽管最终会破坏被移位的字)。
在相反的情况下,假设您想基于一系列真/假测试构建位图。在测试中设置的标志中移动的旋转允许您有效地执行此操作(不清楚是否可以以这种方式设置68k X标志,但x86上的进位标志当然可以)。
答案 3 :(得分:2)
ROXL对于非破坏性测试位非常有用,与BTST.x指令相比可以节省相当多的指令(仅适用于8位和32位大小)。一旦你这样做,旋转多个地方也可以使跳过比特成为可能。
ROXL.W #4,D0 ; shift bit 12 into carry and X
BCC.S isNotSet ; branch if bit is not set
BSR isSet ; do whatever you want
isNotSet:
ROXL.W #11,D0 ; rotate around to reset to previous value