Я хочу создать функции, которые сохраняют / восстанавливают состояние регистров ЦП с помощью компилятора GCC.
Register- asm
локальные переменные для этой цели бесполезны.
Они гарантированно находятся в указанном регистре, только если он используется в качестве операнда для оператора расширенного asm ( gcc manual ).Это позволяет компилятору разливать / перезагружать регистр через вызовы функций, если это необходимо.
Что более важно для вашего случая, присвоение нового значения локальной переменной register-asm внутри функции приведет к сохранению / восстановлению компиляторомзначение вызывающего абонента в функции пролог / эпилог.См. этот пример в проводнике компилятора Godbolt :
int call_clobbered(int x) {
register int a asm("r2") = 123;
asm("" :: "r"(a)); // force the compiler to have the value in the register
return a;
}
# gcc4.8.5 -O3 -mregnames
li %r2,123
li %r3,123 # return-value register
blr
int call_preserved(int x) {
register int a asm("r22") = 123;
asm("" :: "r"(a)); // force the compiler to have the value in the register
return a;
}
# gcc4.8.5 -O3 -mregnames
stwu %r1,-48(%r1)
stw %r22,8(%r1) # save caller's r22
li %r22,123
li %r3,123
lwz %r22,8(%r1) # restore caller's r22
addi %r1,%r1,48 # deallocate stack space
blr
Так что вы можете создать код, который будет работать для сохранения регистров вашего вызывающего, но безвстроенный asm вы не сможете писать код, который восстанавливает регистры как часть переключения контекста.
Кроме того, вы все равно не хотите сохранять / восстанавливать все 8 полубайтов CR
отдельно!Сохраните весь 32-битный регистр как обычный человек.Или, что еще лучше, сделайте вашу функцию переключения контекста реальной функцией, вызываемой сгенерированным компилятором кодом, чтобы вам не приходилось сохранять / восстанавливать регистры с закрытыми вызовами.(Поскольку компилятор ожидает, что ваша функция затрет все эти регистры, прежде чем он вернется.)
Я не знаю соглашений о вызовах PowerPC, но я предполагаю, что весь CR - это вызовзатерт.На ISA с одним регистром FLAGS / код состояния он всегда перекрывается при вызове.
Если вам нужно сохранить / восстановить CR, вам, вероятно, придется написать всю вашу функцию в чистом asm,потому что любой код, сгенерированный компилятором, мог бы заморозить CR после восстановления.
Чтобы сохранить / восстановить весь CR, см. этот краткий справочник ISA PPC .
Использование mfcr r1
( перейти от CR ), чтобы скопировать все 32 бита в целочисленный регистр (который затем можно сохранить в памяти).Используйте mtcr r1
до и переходите к CR при восстановлении.Работает с любым регистром;r1
это просто пример.