1

我在编译下面的代码片段时遇到了一些问题。

#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;
}

编译器抱怨这个错误"impossible constraint in 'asm'"。为了验证这一点,我浏览了 ADDPS 指令的描述。它说的是这样的:-

ADDPS xmm1, xmm2/m128 将压缩的单精度浮点值从 xmm2/m128 添加到 xmm1。

因此,源可以是内存地址或 xmm 寄存器,但目标必须是 xmm 寄存器。我想我的约束有点同意这一点。谁能指出我这里可能存在的问题?

谢谢。

4

1 回答 1

1

所以我不确定为什么使用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];
}
于 2013-03-13T14:53:35.940 回答