Если у меня есть следующий код C++ для сравнения двух 128-разрядных целых чисел без знака, с инлайн АМД-64 ассемблере:В расширенном встроенном asm в стиле GCC можно вывести «виртуализированное» логическое значение, например. флаг переноса?
struct uint128_t {
uint64_t lo, hi;
};
inline bool operator< (const uint128_t &a, const uint128_t &b)
{
uint64_t temp;
bool result;
__asm__(
"cmpq %3, %2;"
"sbbq %4, %1;"
"setc %0;"
: // outputs:
/*0*/"=r,1,2"(result),
/*1*/"=r,r,r"(temp)
: // inputs:
/*2*/"r,r,r"(a.lo),
/*3*/"emr,emr,emr"(b.lo),
/*4*/"emr,emr,emr"(b.hi),
"1"(a.hi));
return result;
}
Тогда будет встраиваемыми достаточно эффективно, но с одним недостатком. Возвращаемое значение выполняется через «интерфейс» общего регистра со значением 0 или 1. Это добавляет две или три лишние дополнительные инструкции и отвлекает от операции сравнения, которая в противном случае была бы полностью оптимизирована. Сгенерированный код будет выглядеть примерно так:
mov r10, [r14]
mov r11, [r14+8]
cmp r10, [r15]
sbb r11, [r15+8]
setc al
movzx eax, al
test eax, eax
jnz is_lessthan
Если я использую «SBB% 0,% 0» с «ИНТ» возвращаемого значения вместо «SETC% 0» с «BOOL» возвращаемого значения, есть еще две дополнительные инструкции:
mov r10, [r14]
mov r11, [r14+8]
cmp r10, [r15]
sbb r11, [r15+8]
sbb eax, eax
test eax, eax
jnz is_lessthan
То, что я хочу это:
mov r10, [r14]
mov r11, [r14+8]
cmp r10, [r15]
sbb r11, [r15+8]
jc is_lessthan
GCC расширенный рядный асмовый замечательно, в противном случае. Но я хочу, чтобы это было так же хорошо, как и внутренняя функция. Я хочу иметь возможность напрямую возвращать логическое значение в виде состояния флага или флагов ЦП без необходимости «рендерить» его в общий регистр.
Возможно ли это, или же GCC (и компилятор Intel C++, который также позволяет использовать эту форму встроенного asm), необходимо изменить или даже реорганизовать, чтобы сделать возможным?
Кроме того, пока я нахожусь в нем - есть ли другой способ, который может улучшить моя формулировка оператора сравнения?
Начиная с 2013 года, по-видимому, это невозможно сделать напрямую. Но вот отчет об ошибке 2011 года, в котором обсуждается желательность такой функции: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49611. Он ссылается на поток ядра Linux 2001 года, который также хочет этого: http: //lkml.indiana.Edu/hypermail/Linux/ядро / 0111,2/0256.html. –