Моделирование LDREX / STREX (исключительная загрузка / сохранение) в Cortex-M0

В наборе инструкций Cortex-M3 существует семейство инструкций LDREX / STREX, такое что, если местоположение считывается с помощью инструкции LDREX, следующая инструкция STREX может писать по этому адресу, только если известно, что адрес не был изменен. Как правило, результат состоит в том, что STREX завершится успешно, если с момента LDREX не возникло никаких прерываний («исключения» на языке ARM), но в противном случае произойдет сбой.

Что? Самый практичный способ имитировать такое поведение в Cortex M0? Я хотел бы написать код C для M3 и перенести его на M0. На M3 можно сказать что-то вроде:

__inline void do_inc(unsigned int *dat)
{
  while(__strex(__ldrex(dat)+1,dat)) {}
}

для выполнения атомарного приращения. Единственные способы, которые я могу придумать для достижения аналогичной функциональности на Cortex-M0, это либо:

  1. Отключить исключения "ldrex" и повторно включить их "strex" и "clrex" с требованием, чтобы каждый " ldrex »вскоре после этого должен сопровождаться либо« strex », либо« clrex ».
  2. Сделайте «ldrex», «strex» и «clrex» очень маленькими подпрограммами в ОЗУ, при этом одна инструкция «ldrex» исправляется либо на «str r1, [r2]», либо на «mov r0, # 1» ". Пусть процедура "ldrex" вставляет инструкцию "str" ​​в подпрограмму "strex", а подпрограмму "clrex" вставляет "mov r0, # 1" там. Имеются все исключения, которые могут сделать недействительным вызов последовательности «ldrex» «clrex».

В зависимости от того, как используются функции ldrex / strex, отключение прерываний может работать разумно, но кажется неприятным изменять семантику «load-excluded», чтобы вызвать плохие побочные эффекты, если от него отказаться. Идея исправления кода кажется, что она достигнет желаемой семантики, но она кажется неуклюжей.

(Кстати, побочный вопрос: мне интересно, почему STREX на M3 сохраняет индикацию успеха / неудачи в регистре, а не просто устанавливает флаг Для его фактической работы требуется четыре дополнительных бита в коде операции, требуется, чтобы регистр был доступен для хранения индикации успеха / неудачи, и требуется, чтобы для определения успешности операции использовалось выражение «cmp r0, # 0». Ожидалось ли, что компиляторы не смогли бы разумно обращаться с внутренним STREX, если бы они не получить результат в реестре? Для переноса в регистр требуется две короткие инструкции.)

11
задан starblue 16 March 2015 в 15:43
поделиться