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

时间:2010-04-11 15:17:19

标签: mips parity

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

另外,我正在使用的数字用格雷码表示......只是为了把它扔在那里。那么MIPS中是否有一些伪指令用于确定“数字”的奇偶校验,还是我必须手工完成?

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

谢谢, 赫里斯托斯

跟进:我发现了一个优化,但我的实现无效。

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

1 个答案:

答案 0 :(得分:3)

我不知道任何带有奇偶校验指令的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步已经一次执行。写result{N}表示“result的位N”:

    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的剩余前16位;它们在计算的其余部分中没有任何用处。)

  • 在第二步之后,result的低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的最低位结束:

    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];

其中lookup_table[n]已预先计算,例如:

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

这是7条MIPS指令,不计算将查找表基址加载到寄存器中:

# 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)

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