内联汇编中的 sse 约束不起作用
Posted
技术标签:
【中文标题】内联汇编中的 sse 约束不起作用【英文标题】:sse constraint in inline assembly not working 【发布时间】:2013-03-13 13:08:31 【问题描述】:我在编译下面的代码 sn-p 时遇到了一些问题。
#include <iostream>
#include <cstdint>
using namespace std;
union mxcsr
uint32_t v;
struct
uint32_t ie : 1;
uint32_t de : 1;
uint32_t ze : 1;
uint32_t oe : 1;
uint32_t ue : 1;
uint32_t pe : 1;
uint32_t daz : 1;
uint32_t im : 1;
uint32_t dm : 1;
uint32_t zm : 1;
uint32_t om : 1;
uint32_t um : 1;
uint32_t pm : 1;
uint32_t rn : 1;
uint32_t rp : 1;
uint32_t fz : 1;
uint32_t rs0 : 15;
;
;
std::ostream& operator<<(std::ostream& ostr, mxcsr &m)
ostr << std::hex << std::showbase;
ostr << "mxcsr=" << m.v;
ostr << std::dec << std::noshowbase;
ostr << " [ie=" << m.ie << ",de=" << m.de
<< ",ze=" << m.ze << ",oe=" << m.oe << ",ue=" << m.ue
<< ",pe=" << m.pe << ",daz=" << m.daz << ",im=" << m.im
<< ",dm=" << m.dm << ",zm=" << m.zm << ",om=" << m.om
<< ",um=" << m.um << ",pm=" << m.pm << ",r-=" << m.rn
<< ",r+=" << m.rp << ",fz=" << m.fz << "] ";
return ostr;
typedef union __attribute__((aligned(16))) vec_t
double f64[2];
float f32[4];
uint64_t u64[2];
uint32_t u32[4];
uint16_t u16[8];
uint8_t u8[16];
int64_t i64[2];
int32_t i32[4];
int16_t i16[8];
int8_t i8[16];
vec_t;
float add_vec_32f(float ra, float rb, mxcsr &f)
vec_t va, vb;
va.f32[0] = ra; vb.f32[0] = rb;
asm("addps %[vb], %[va];"
"stmxcsr %[f];"
: [va] "+x" (va), [f] "=m" (f)
: [vb] "xm" (vb)
:
);
return va.f32[0];
int main()
mxcsr val;
float b = add_vec_32f(3.4, 5.6, val);
std::cout << "b=" << b << " val=" << val << std::endl;
return 0;
编译器报此错误“'asm' 中的不可能约束”。为了验证这一点,我浏览了 ADDPS 指令的描述。它说的是这样的:-
添加 xmm1, xmm2/m128 将压缩的单精度浮点值从 xmm2/m128 添加到 xmm1。
所以,源可以是内存地址或 xmm 寄存器,但目标必须是 xmm 寄存器。我想我的约束有点同意这一点。 谁能指出我这里可能存在的问题?
谢谢。
【问题讨论】:
“'asm' 中的不可能约束”听起来不像是汇编指令格式错误,而是您的约束格式错误。 请参阅gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html,了解 gcc 如何声明矢量类型(或包括所以我不确定为什么使用union
不起作用,但使用 SIMD 向量指令确实有效,尽管您需要在union
中添加一个。我能够让它像这样工作:
typedef double xmmd __attribute__ ((vector_size (16)));
typedef union __attribute__((aligned(16)))
vec_t
xmmd xmm ;
double f64[2];
float f32[4];
uint64_t u64[2];
uint32_t u32[4];
uint16_t u16[8];
uint8_t u8[16];
int64_t i64[2];
int32_t i32[4];
int16_t i16[8];
int8_t i8[16];
vec_t;
float add_vec_32f(float ra, float rb, mxcsr &f)
vec_t va, vb;
va.f32[0] = ra; vb.f32[0] = rb;
asm("addps %[v2], %[v1];"
"stmxcsr %[f];"
: [v1] "+x" (va.xmm), [f] "=m" (f)
: [v2] "xm" (vb.xmm)
:
);
return va.f32[0];
【讨论】:
谢谢,这样就可以了。看起来 gcc 不允许将联合声明为向量类型,所以这是最明智的做法。 @vikasC 是的,内联汇编通常很难完全理解这篇文章帮助我更好地理解locklessinc.com/articles/gcc_asm 如果你能接受我的回答,我将不胜感激以上是关于内联汇编中的 sse 约束不起作用的主要内容,如果未能解决你的问题,请参考以下文章