Использование флагов условий в качестве встроенных выходных данных GNU C

Я работаю над кодом, в котором было бы крайне желательно получить выходные данные флагов условий из встроенного asm-блока и использовать их в качестве условия для перехода в вызывающем коде C. Я не хочу хранить флаги (это было бы бесполезно и неэффективно; уже есть более эффективные способы достижения результата), но использую флаги напрямую. Есть ли способ добиться этого с помощью встроенных ограничений GNU C? Мне интересны подходы, которые будут работать для нескольких архитектур наборов команд, с намерением использовать его с флагами условий, создаваемыми атомами стиля LL/SC архитектуры. Конечно, другой очевидный случай использования (отдельно от того, что я делаю) - позволить внешнему коду C перейти на результат флага переноса из операции inline asm.

3 ответа

Решение

Начиная с GCC6 на x86, вы можете использовать "=@ccCOND" как вывод (где COND любой допустимый код условия x86).

Пример изначально отсюда, очищенный предложениями Дэвида:

int variable_test_bit(long n, volatile const unsigned long *addr)
{
    int oldbit;
    asm volatile("bt %[value],%[bit]"
                 : "=@ccc" (oldbit)
                 : [value] "m" (*addr), [bit] "Jr" (n));
    return oldbit;
}

Прежде чем использовать это, вы должны проверить, если __GCC_ASM_FLAG_OUTPUTS__ определено.

Документация на https://gcc.gnu.org.

У меня есть частичное решение, но мне оно не очень нравится, потому что оно требует помещения инструкции перехода в asm, и потому что это требует очень уродливой функции GCC, которую другие "GNU C-совместимые" компиляторы могут не поддерживать: asm goto, Это, однако, позволяет удалить ветку за пределами asm. Идея заключается в следующем:

static inline int foo(...)
{
    __asm__ goto ( " .... ; cond_jmp %l[ret0]" : : "r"(...) ... 
                   : "clobbers" : ret0 );
    return 1;
ret0:
    return 0;
}

Когда указывается в вызывающем if (foo(...)) ... else ...условный переход в блоке asm в конечном итоге указывает на else ветвь, даже если на уровне абстрактной машины присутствуют возвращаемые значения.

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

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

Другие вопросы по тегам