Как правильно повернуть 64-битное значение в ассемблере ARM7?

Набор команд ARM7 предлагает эффективные способы правого поворота 32-битных значений на произвольную величину в ассемблере. Для второго операнда операции это даже "бесплатно", указав ror #n в качестве операнда сдвига, но для 64-битных целых чисел прямая поддержка набором инструкций не предоставляется. Помимо особых случаев поворота на 1, 31, 33 или 63 битные позиции (не говоря уже о 0 или 32), я знаю только, как повернуть 64-битное значение, используя четыре инструкции (это довольно легко, поэтому я не пишу это здесь). В четырех особых случаях я могу сократить это до трех инструкций, но я не знаю, как это сделать вообще. Вот мой вопрос:

Учитывая 64-битное значение в двух регистрах, скажем, R0 и R1, возможно ли повернуть это значение вправо на n позиций (для произвольного n) всего тремя инструкциями ARM7?

2 ответа

Решение

Если регистр (например, r4) содержит правильную магическую константу (1 сдвинут влево на желаемую величину левого поворота), я думаю, что это можно сделать двумя инструкциями:

  ум r3,r2,r1,r4
  умл r2,r3,r0,r4

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

Если есть решение для этого, gcc также не распознает это:

unsigned long long int reg64 = random_value;
unsigned int n = shift_value;
reg64 = (reg64 >> (n%64)) | (reg64 << ((64-n)%64));

результаты в следующем:

п =1:

MOVS R2, R0, LSR #1
MOV R3, R1, RRX
ORR R2, R2, R1, ASL #31

п =2-31:

MOV R2, R0, LSR #n
ORR R2, R2, R1, ASL #32-n
MOV R3, R0, ASL #32-n
ORR R3, R3, R1, LSR #n

п =33-62:

MOV R3, R0, ASL #64-n
ORR R3, R3, R1, LSR #n-32
MOV R2, R0, LSR, #n-32
ORR R2, R2, R1, ASL #64-n

п =63:

ADDS R2, R0, R0
ADC R3, R1, R1
ORR R2, R2, R1, LSR #31
Другие вопросы по тегам