Я работаю над пользовательской ОС для процессора ARM Cortex -M3. Чтобы взаимодействовать с моим ядром, пользовательские потоки должны генерировать команду SuperVisor Call (SVC )(, ранее известную как SWI, для прерывания SoftWare ). Определение этой инструкции в ARM ARM::
Это означает, что инструкции требуется непосредственный аргумент, а не значение регистра.
Это усложняет мне разработку моего интерфейса в удобочитаемой форме. Требуется такой код, как:
asm volatile( "svc #0");
когда я бы предпочел что-то вроде
svc(SVC_YIELD);
Однако я затрудняюсь построить эту функцию, потому что инструкция SVC требует немедленного аргумента, а я не могу предоставить его, когда значение передается через регистр.
Для фона инструкция svc декодируется в ядре следующим образом
#define SVC_YIELD 0
// Other SVC codes
// Called by the SVC interrupt handler (not shown)
void handleSVC(char code)
{
switch (code) {
case SVC_YIELD:
svc_yield();
break;
// Other cases follow
Этот оператор case быстро выходит из-под контроля, но я не вижу пути решения этой проблемы. Любые предложения приветствуются.
Сначала я считал
__attribute__((naked)) svc(char code)
{
asm volatile ("scv r0");
}
но это, конечно, не работает, так как SVC требует регистрового аргумента.
Попытка грубой -решить проблему выглядит так:
void svc(char code)
switch (code) {
case 0:
asm volatile("svc #0");
break;
case 1:
asm volatile("svc #1");
break;
/* 253 cases omitted */
case 255:
asm volatile("svc #255");
break;
}
}
но это имеет неприятный запах кода. Наверняка это можно сделать лучше.
Последней попыткой было сгенерировать инструкцию в ОЗУ (, остальная часть кода выполняется только для чтения -во флэш-памяти ), а затем запустить ее :
void svc(char code)
{
asm volatile (
"orr r0, 0xDF00 \n\t" // Bitwise-OR the code with the SVC encoding
"push {r1, r0} \n\t" // Store the instruction to RAM (on the stack)
"mov r0, sp \n\t" // Copy the stack pointer to an ordinary register
"add r0, #1 \n\t" // Add 1 to the address to specify THUMB mode
"bx r0 \n\t" // Branch to newly created instruction
"pop {r1, r0} \n\t" // Restore the stack
"bx lr \n\t" // Return to caller
);
}
. но это тоже не кажется правильным. Кроме того, это не работает -Здесь я что-то делаю не так;возможно, моя инструкция не выровнена должным образом, или я не настроил процессор для запуска кода из ОЗУ в этом месте.
Я должен работать над этим последним вариантом. Но все же мне кажется, что я должен уметь делать что-то вроде:
__attribute__((naked)) svc(char code)
{
asm volatile ("scv %1"
: /* No outputs */
: "i" (code) // Imaginary directive specifying an immediate argument
// as opposed to conventional "r"
);
}
но я не нахожу такой опции в документации и затрудняюсь объяснить, как такая функция будет реализована, поэтому, вероятно, ее не существует. Как мне это сделать?