确定MIPS中数字的位表示形式的奇偶校验

确定MIPS中数字的位表示形式的奇偶校验,mips,parity,Mips,Parity,MIPS中是否有一些指令可以确定某个位表示的奇偶校验?我知道,要确定一个“数”是否具有偶数奇偶校验,需要将二进制表示的各个位异或在一起,但对于一组MIPS指令来说,这似乎需要大量计算。。。我需要尽快做到这一点 另外,我工作的号码用灰色代码表示。。。只是把它扔进去。那么,MIPS中是否有一些伪指令来确定一个“数字”的奇偶校验,或者我必须手动执行 如果没有MIPS指令(这似乎不太可能),有没有关于如何手工操作的建议 谢谢, 赫里斯托 后续:我发现了一个优化,但我的实现不起作用 unsigned in

MIPS中是否有一些指令可以确定某个位表示的奇偶校验?我知道,要确定一个“数”是否具有偶数奇偶校验,需要将二进制表示的各个位异或在一起,但对于一组MIPS指令来说,这似乎需要大量计算。。。我需要尽快做到这一点

另外,我工作的号码用灰色代码表示。。。只是把它扔进去。那么,MIPS中是否有一些伪指令来确定一个“数字”的奇偶校验,或者我必须手动执行

如果没有MIPS指令(这似乎不太可能),有没有关于如何手工操作的建议

谢谢, 赫里斯托

后续:我发现了一个优化,但我的实现不起作用

unsigned int v; // 32-bit word
v ^= v >> 1;
v ^= v >> 2;
v = (v & 0x11111111U) * 0x11111111U;
return (v >> 28) & 1;

我不知道有哪种MIPS变体使用奇偶校验指令,但有一种比特旋转技巧可以比明显的依次遍历32位的方法更快地计算奇偶校验。在C中:

result = in ^ (in >> 16);
result ^= (result >> 8);
result ^= (result >> 4);
result ^= (result >> 2);
result ^= (result >> 1);
result &= 1;
  • 在第一步之后,结果的底部16位包含输入的位N和N+16的奇偶校验-基本上,奇偶校验计算的16个步骤已经一次性执行。将
    结果{N}
    写入表示“结果的
    位N
    ”:

    (现在可以忽略
    结果
    的剩余前16位;它们在剩余的计算中没有任何用处)

  • 第二步后,
    结果的底部8位包含原始输入的位N、N+8、N+16、N+24的奇偶校验:

    result{0} = result{0} ^ result{8}  =  in{0} ^  in{8} ^ in{16} ^ in{24}
    result{1} = result{1} ^ result{9}  =  in{1} ^  in{9} ^ in{17} ^ in{25}
    ...
    result{7} = result{7} ^ result{15} =  in{7} ^ in{15} ^ in{23} ^ in{31}
    
    (同样,从这里开始,可以忽略剩余的位)

  • …依此类推,直到原始输入的所有位的奇偶校验在
    结果的底部位结束:

    result{0}  =  in{0} ^ in{16}
    result{1}  =  in{1} ^ in{17}
    result{2}  =  in{2} ^ in{18}
    ...
    result{7}  =  in{7} ^ in{23}
    result{8}  =  in{8} ^ in{24}
    ...
    result{15} = in{15} ^ in{31}
    
    result{0} = in{0} ^ in{1} ^ in{2} ^ ... ^ in{30} ^ in{31}
    
这很容易直接转换到MIPS组件;这是11条说明:

# input in $a0, output in $v0, $t0 corrupted
srl $t0, $a0, 16
xor $v0, $a0, $t0
srl $t0, $v0, 8
xor $v0, $v0, $t0
srl $t0, $v0, 4
xor $v0, $v0, $t0
srl $t0, $v0, 2
xor $v0, $v0, $t0
srl $t0, $v0, 1
xor $v0, $v0, $t0
and $v0, $v0, 1

一个可能的改进可能是使用查找表。例如,在前两个步骤之后,我们有:

    result{0} =  in{0} ^  in{8} ^ in{16} ^ in{24}
    result{1} =  in{1} ^  in{9} ^ in{17} ^ in{25}
    ...
    result{7} =  in{7} ^ in{15} ^ in{23} ^ in{31}
所以我们可以在这里使用一个256字节的查找表。在C中:

result = in ^ (in >> 16);
result ^= (result >> 8);
result = lookup_table[result & 0xff];
其中,
查找表[n]
已预先计算,例如:

for (i = 0; i < 256; i++) {
    n = i ^ (i >> 4);
    n ^= (n >> 2);
    n ^= (n >> 1);
    lookup_table[i] = n & 1;
}

然而,这是7条指令,其中包括内存访问,而11条指令纯粹是寄存器操作;它可能更快,也可能不会更快。(这种微观优化总是需要分析!)

感谢您的回复。这就是我现在拥有的。。。但我正试图将代码优化为更少的指令,因为这组指令将被多次调用,这会降低性能。有什么优化想法吗?在第二次异或之后,所有有用的信息都在底部8位;最后的答案是这些位的函数,因此您可以将它们用作256字节查找表的索引。这是否会更快,取决于内存访问、缓存等的速度-你必须尝试并分析它…你所说的“所有有用的信息都在底部8位”是什么意思?所以你建议移位16,xor,移位8,xor,然后最右边的8位是重要的?好的。谢谢!我已经实现了它,但它不起作用,但我确信我有一些看不到的错误。@Hristo:哦,不,这是我的错,因为我搞砸了查找表的初始化。我现在已经改正了。很抱歉。
# input in $a0, lookup table address in $a1, output in $v0, $t0 corrupted
srl  $t0, $a0, 16
xor  $v0, $a0, $t0
srl  $t0, $v0, 8
xor  $v0, $v0, $t0
andi $v0, $v0, 0xff
addu $t0, $a1, $v0
lbu  $v0, 0($t0)