Какой код встроенной сборки подходит для rdtscp?

Отказ от ответственности: слова не могут описать, насколько я ненавижу синтаксис стиля AT & T

У меня есть проблема, которая, я надеюсь, вызвана регистрацией клонирования. Если нет, у меня есть гораздо большая проблема.

Первая версия, которую я использовал, была

static unsigned long long rdtscp(void)
{
    unsigned int hi, lo;
    __asm__ __volatile__("rdtscp" : "=a"(lo), "=d"(hi));
    return (unsigned long long)lo | ((unsigned long long)hi << 32);
}

Я замечаю, что в этой версии нет "clobbering". Является ли это проблемой, я не знаю... Я полагаю, это зависит от того, компилятор строит функцию или нет. Использование этой версии вызывает проблемы, которые не всегда воспроизводятся.

Следующая версия, которую я нашел, -

static unsigned long long rdtscp(void)
{
    unsigned long long tsc;
    __asm__ __volatile__(
        "rdtscp;"
        "shl $32, %%rdx;"
        "or %%rdx, %%rax"
        : "=a"(tsc)
        :
        : "%rcx", "%rdx");

    return tsc;
}

Это неуверенно нечитаемо и официально выглядит, но, как я уже сказал, моя проблема не всегда воспроизводима, поэтому я просто пытаюсь исключить одну из возможных причин моей проблемы.

Причина, по которой я считаю, что первая версия является проблемой, заключается в том, что она перезаписывает регистр, ранее содержащий параметр функции.

Какая правильная... версия 1 или версия 2 или оба?

Ответ 1

Здесь код С++, который вернет TSC и сохранит вспомогательные 32-биты в эталонный параметр

static inline uint64_t rdtscp( uint32_t & aux )
{
    uint64_t rax,rdx;
    asm volatile ( "rdtscp\n" : "=a" (rax), "=d" (rdx), "=c" (aux) : : );
    return (rdx << 32) + rax;
}

Лучше сделать shift и add, чтобы объединить обе 32-разрядные половинки в С++-выражении, а не в строку, это позволяет компилятору планировать эти инструкции по своему усмотрению.

Ответ 2

Я думаю, вы можете с уверенностью относиться к к этому документу, а не только для проверки, но и для получения более подробного углубленного анализа точность RDTSC и RDTSCP.

Надеюсь, это поможет.

Ответ 3

В соответствии с этим эта операция clobbers EDX и ECX. Вам нужно отметить те регистры, которые были сбиты, что и делает второй. Кстати, это ссылка, в которой вы получили вышеуказанный код, или вы нашли его в другом месте? Он также показывает несколько других вариаций для таймингов, а это довольно аккуратно.