Как использовать определенный регистр во встроенном ассемблере ARM

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

asm("" :: "r0" (value));
asm("" :: "a1" (value));

Обе строки сработают:

Error: matching constraint references invalid operand number

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

Почему я спрашиваю В настоящее время я работаю над некоторыми системными вызовами. Я хочу использовать макрос системного вызова следующим образом:

#define SYSCALL0(NUMBER) asm("swi #" STRINGIFY(NUMBER));
#define SYSCALL1(NUMBER, A) asm("swi #" STRINGIFY(NUMBER) :: "r0"(A));
#define SYSCALL2(NUMBER, A, B) asm("swi #" STRINGIFY(NUMBER) :: "r0"(A), "r1"(B));
...

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

#define SYSCALL1(NUMBER, A) register type R0 asm("r0") = A;
                            SYSCALL0(NUMBER)

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


person Nobody moving away from SE    schedule 31.05.2012    source источник
comment
Возможный дубликат Как указать отдельный регистр как ограничение во встроенной сборке ARM GCC?   -  person Ciro Santilli    schedule 23.02.2019


Ответы (1)


С GCC есть ярлык:

register long r0 asm ("r0");

Затем r0 "псевдонимы", которые прописываются.

Объедините это с выражением оператора, и вы даже можете получить r0 как «возвращаемое значение».

#define SYSCALL1(NUMBER,A) ({\
  register long r0 asm("r0") = (long) (A); \
  asm("swi #" STRINGIFY(NUMBER) : "=r"(r0) : "r"(r0) : "memory"); \
  r0; })

(Я понятия не имею, является ли клоббер законным или нет, хотя реализация системного вызова uClibc имеет это.)

См. расширенную сборку и локальные регистрационные переменные.

person Mat    schedule 31.05.2012
comment
Да, это я знал, но мне не нравится длинный синтаксис. Я обновлю свой вопрос, чтобы показать свою мотивацию. - person Nobody moving away from SE; 31.05.2012
comment
Разве все регистры, с которыми вы имеете дело, не относятся к одному и тому же типу C (long)? - person Mat; 31.05.2012
comment
Регистры относятся к этому типу, но входящие переменные могут иметь произвольные типы (например, int, char*, void(fn*)(void),...), поэтому мне придется каждый раз выполнять приведение типов. Это не то чтобы невозможно, но это действительно уродливо. - person Nobody moving away from SE; 31.05.2012
comment
Сделайте приведение в макросе, если вы действительно этого хотите. Обновлено. - person Mat; 31.05.2012
comment
Ну я имел в виду актерский состав в макросе, но вижу, что без него никуда. Спасибо за ваши советы, я не знал об этих выражениях утверждений, поэтому я посмотрю на них. - person Nobody moving away from SE; 31.05.2012
comment
Вы также можете просто использовать статическую встроенную функцию, чтобы получить аргументы в нужные регистры. - person R.. GitHub STOP HELPING ICE; 31.05.2012
comment
@R.. В этом случае преимущество встроенной функции над макросом (безопасность типа) является излишним. Мне нужно отбрасывать типы, поэтому использование встроенной функции привело бы к большему количеству приведений, которые мне пришлось бы писать. - person Nobody moving away from SE; 31.05.2012
comment
Вы можете обернуть встроенную функцию в макрос, который отбрасывает типы. Я упоминаю об этом, потому что так (примерно) работают мои макросы системных вызовов на musl. Существует внешний вариативный макрос __syscall, который вызывает правильную функцию __syscallN (статическую встроенную) со всеми аргументами, приведенными к long, а затем статическая встроенная функция отвечает за размещение аргументов в правильных регистрах и выполнение системного вызова. - person R.. GitHub STOP HELPING ICE; 01.06.2012
comment
См. git .etalabs.net/cgi-bin/gitweb.cgi?p=musl;a=blob;f=src/internal/ и git.etalabs.net/cgi-bin/gitweb.cgi?p=musl; a=blob;f=arch/x86_64/ для примера того, о чем я говорю. - person R.. GitHub STOP HELPING ICE; 01.06.2012