У меня возникли проблемы с некоторым встроенным кодом сборки. Я знаю, что нужно сделать, но я скучаю по «как»!
У меня есть эта функция контрольной суммы, которая "почти" работает:
static unsigned long cksum_unroll( unsigned short **w, int *mlen)
{
int len;
unsigned short *w0;
unsigned long sum=0;
len = *mlen;
w0 = *w;
while( len >= 8) {
asm volatile (
"ldmia %[w0]!, {v1, v2}\n\t"
"adds %[sum], %[sum], v1\n\t"
"adcs %[sum], %[sum], v2\n\t"
"adcs %[sum], %[sum], #0"
: [sum] "+r" (sum) : [w0] "r" (w0)
);
len -= 8;
}
*mlen = len;
*w = w0;
return (sum);
}
Моя проблема, я полагаю, заключается в строке ": [sum]" + r "(sum): [w0]" r "(w0) "
На первой сборочной линии w0 корректно обрабатывается с помощью ldmia (когда строка выполняется, данные находятся в r4, r5 и w0 увеличивается). Но увеличенное значение w0 где-то не сохраняется, и когда в цикле кода снова загружается исходное значение w0 (см. Код сборки ниже).
Я предполагаю, что я должен хранить значение w0 в строке ": [sum]" + r "(sum): [w0]" r "(w0)", но я не знаю, как ...
Вот код разборки встроенной части сборки функции:
Обратите внимание, что:
len is stored at r11, #-16
w0 is stored at r11, #-20
sum is stored at r11, #-24
Скомпилирован следующий код:
asm volatile (
"ldmia %[w0]!, {v1, v2}\n\t"
"adds %[sum], %[sum], v1\n\t"
"adcs %[sum], %[sum], v2\n\t"
"adcs %[sum], %[sum], #0"
: [sum] "+r" (sum) : [w0] "r" (w0)
);
len -= 8;
Генерировать:
00031910: ldr r3, [r11, #-20]
00031914: ldr r2, [r11, #-24]
00031918: mov r4, r2
0003191c: ldm r3!, {r4, r5}
00031920: adds r4, r4, r4
00031924: adcs r4, r4, r5
00031928: adcs r4, r4, #0
0003192c: str r4, [r11, #-24]
00031930: ldr r3, [r11, #-16]
00031934: sub r3, r3, #8
00031938: str r3, [r11, #-16]
Как видите, я хотел бы добавить что-то вроде "str r3, [r11, # -20]" между строками 31928 и 3192c, потому что когда цикл программы к строке 31910, r3 загружается с начальным значением r3 ...
Я думаю, что это легко для эксперта по встроенной сборке сообщества переполнения стека!
Кстати, я работаю на процессоре ARM7TDMI (но это может не относиться к этому вопросу ...)
Заранее спасибо!
EDIT:
Чтобы проверить мою идею, я проверил следующее:
asm volatile (
"ldmia %[w0]!, {v1, v2}\n\t"
"adds %[sum], %[sum], v1\n\t"
"adcs %[sum], %[sum], v2\n\t"
"adcs %[sum], %[sum], #0\n\t"
"str %[w0], [r11, #-20]"
: [sum] "+r" (sum) : [w0] "r" (w0)
);
И это работает. Может быть, это решение, но что мне использовать для замены «r11, # 20», которое, вероятно, изменится, если я изменю функцию?