Как написать инструкцию btr с помощью 'asm volatile' - PullRequest
0 голосов
/ 29 августа 2018

Что такое правильная реализация, которая использует btr для сброса бита в целое число в C ++ с синтаксисом расширенной сборки (asm volatile)? Мне нужно вернуть значение в бите до сброса.

Это реализация, которая у меня есть, это правильно для 16-битного целого числа?

std::uint16_t reset(std::uint16_t& integer, std::uint32_t bit) {
  auto success = false;
  asm volatile("lock btrw %1, (%2); setnc %0"
               : "=r"(success)
               : "i"(bit), "r"(&integer)
               : "memory", "flags");
  return !success;
}

Правильна ли эта реализация? Я что-то упустил? Я не очень знаком с синтаксисом asm() или сборкой x86.

1 Ответ

0 голосов
/ 29 августа 2018

Вот версия, которая заменяет memory clobber на правильный операнд чтения-записи вместо передачи адреса в регистре, а также избавляется от setnc (требуется gcc 6+). Добавлен r, чтобы охватить случай, когда bit не известен во время компиляции. Изменено success на более читаемое was_set с типом bool. Обратите внимание: если вы хотите, чтобы это было атомарно, вам также нужно добавить префикс lock. Для барьера памяти компилятора вам может потребоваться вернуть ограничение memory.

bool reset(std::uint16_t& integer, std::uint32_t bit) {
  bool was_set;
  asm volatile("btrw %w2, %1"
               : "=@ccc"(was_set), "+mr"(integer)
               : "ri"(bit)
               : "cc");
  return was_set;
}

Атомная версия может выглядеть так:

bool reset(std::uint16_t& integer, std::uint32_t bit) {
  bool was_set;
  asm volatile("lock btrw %w2, %1"
               : "=@ccc"(was_set), "+m"(integer)
               : "ri"(bit)
               : "cc", "memory");
  return was_set;
}
...