c - 从UINT16到UINT8提取和组合位的更快方法

标签 c algorithm assembly optimization dspic

我正在寻找所需的特殊提取和合并操作的更快方法,如下所述:

+-------+-------+-------+-------+-------+-------+-------+-------+
| BIT 7 | BIT 6 | BIT 5 | BIT 4 | BIT 3 | BIT 2 | BIT 1 | BIT 0 |
+-------+-------+-------+-------+-------+-------+-------+-------+
|   D1  |  D0   |  C1   |  C0   |  B1   |  B0   |  A1   |   A0  |
+-------+-------+-------+-------+-------+-------+-------+-------+

A = A0 OR A1
B = B0 OR B1
C = C0 OR C1
D = D0 OR D1

+-------+-------+-------+-------+-------+-------+-------+-------+
| BIT 7 | BIT 6 | BIT 5 | BIT 4 | BIT 3 | BIT 2 | BIT 1 | BIT 0 |
+-------+-------+-------+-------+-------+-------+-------+-------+
|       |       |       |       |   D   |   C   |   B   |   A   |
+-------+-------+-------+-------+-------+-------+-------+-------+
为了简单起见,上面仅是一个8位示例,这同样适用于16位值。它应该在dsPIC33F单片机上尽快实现。
C语言中的简单方法是:
PairFlags |= (ChannelFlags & 0x0003) ? 0x0001 : 0;
PairFlags |= (ChannelFlags & 0x000C) ? 0x0002 : 0;
PairFlags |= (ChannelFlags & 0x0030) ? 0x0004 : 0;
PairFlags |= (ChannelFlags & 0x00C0) ? 0x0008 : 0;
PairFlags |= (ChannelFlags & 0x0300) ? 0x0010 : 0;
PairFlags |= (ChannelFlags & 0x0C00) ? 0x0020 : 0;
PairFlags |= (ChannelFlags & 0x3000) ? 0x0040 : 0;
PairFlags |= (ChannelFlags & 0xC000) ? 0x0080 : 0;
这将产生约。在我的情况下,40条指令(带有O3)对应于1µs。
如果可能,应减少指令周期的数量。在C或内联汇编中是否有更快的方法?

最佳答案

以下应该将16位的值减小为8位(输出的每一位通过对一对输入的位进行“或”运算):

// Set even bits to bits in pair ORed together, and odd bits to 0...
PairFlags = (ChannelFlags | (ChannelFlags >> 1)) & 0x5555; // '0h0g0f0e0d0c0b0a'
// Compress the '00' or '01' bit pairs down to single '0' or '1' bits...
PairFlags = (PairFlags ^ (PairFlags >> 1)) & 0x3333; // '00hg00fe00dc00ba'
PairFlags = (PairFlags ^ (PairFlags >> 2)) & 0x0F0F; // '0000hgfe0000dcba'
PairFlags = (PairFlags ^ (PairFlags >> 4)) & 0x00FF; // '00000000hgfedcba'
注意:上面的^可以替换为|以获得相同的结果。

关于c - 从UINT16到UINT8提取和组合位的更快方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64749088/

相关文章:

c - 拦截 stat()

c - C linux 中的信号量与客户端/服务器

c - 弹出 x86 堆栈以访问函数 arg 时出现段错误

assembly - 让调用堆栈向上增长会使缓冲区溢出更安全吗?

assembly - = 和 := 之间的区别

c - 简单的C scanf 不起作用?

c - 已经释放内存

algorithm - 多项式回归 - 两种算法之间的结果准确性

algorithm - 不使用 BigInt 计算

algorithm - 完全加权图和哈密顿之旅