首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用C语言实现SHLD/SHRD指令

用C语言实现SHLD/SHRD指令
EN

Stack Overflow用户
提问于 2022-01-10 19:16:31
回答 1查看 307关注 0票数 5

我试图在不使用内联程序集的情况下有效地实现SHLDSHRDx86指令。

代码语言:javascript
运行
复制
uint32_t shld_UB_on_0(uint32_t a, uint32_t b, uint32_t c) {
    return a << c | b >> 32 - c;
}

似乎工作,但调用未定义的行为时,c == 0,因为第二班的操作数变成32。第三个操作数为0的实际0指令被很好地定义为什么也不做。(https://www.felixcloutier.com/x86/shld)

代码语言:javascript
运行
复制
uint32_t shld_broken_on_0(uint32_t a, uint32_t b, uint32_t c) {
    return a << c | b >> (-c & 31);
}

不会调用未定义的行为,但是当c == 0时,结果是a | b而不是a

代码语言:javascript
运行
复制
uint32_t shld_safe(uint32_t a, uint32_t b, uint32_t c) {
    if (c == 0) return a;
    return a << c | b >> 32 - c;
}

实现了预期的目标,但是gcc现在提供了一个je。另一方面,clang足够聪明地将其转换为单个shld指令。

是否有任何方法可以在不进行内联装配的情况下正确有效地实现它?

为什么gcc这么不想把shld放进去?shld_safe尝试由gcc 11.2 -O3 as (哥德波特)翻译:

代码语言:javascript
运行
复制
shld_safe:
        mov     eax, edi
        test    edx, edx
        je      .L1
        mov     ecx, 32
        sub     ecx, edx
        shr     esi, cl
        mov     ecx, edx
        sal     eax, cl
        or      eax, esi
.L1:
        ret

当嘎嘎作响的时候,

代码语言:javascript
运行
复制
shld_safe:
        mov     ecx, edx
        mov     eax, edi
        shld    eax, esi, cl
        ret
EN

回答 1

Stack Overflow用户

发布于 2022-04-09 03:33:10

就我使用gcc 9.3 (x86-64)进行的测试而言,它将下面的代码转换为shldqshrdq

代码语言:javascript
运行
复制
uint64_t shldq_x64(uint64_t low, uint64_t high, uint64_t count) {
  return (uint64_t)(((((unsigned __int128)high << 64) | (unsigned __int128)low) << (count & 63)) >> 64);
}

uint64_t shrdq_x64(uint64_t low, uint64_t high, uint64_t count) {
  return (uint64_t)((((unsigned __int128)high << 64) | (unsigned __int128)low) >> (count & 63));
}

另外,gcc -m32 -O3将以下代码转换为shldshrd。(不过,我还没有和gcc (i386)做过测试。)

代码语言:javascript
运行
复制
uint32_t shld_x86(uint32_t low, uint32_t high, uint32_t count) {
  return (uint32_t)(((((uint64_t)high << 32) | (uint64_t)low) << (count & 31)) >> 32);
}

uint32_t shrd_x86(uint32_t low, uint32_t high, uint32_t count) {
  return (uint32_t)((((uint64_t)high << 32) | (uint64_t)low) >> (count & 31));
}

(我刚读过gcc的代码,写了上面的函数,即我不确定它们是否是你所期望的。)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70657806

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档