Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Сдвиг 64битного беззнакового целого
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
coolibin
Есть код:

CODE

#define UINT unsigned int
#define UINT64 unsigned long long
....
UINT64 iValue;
UINT iOffset;

iOffset = rand()&63;
iValue = (UINT64)(1) << iOffset;


компилятор генерит такой асм:

CODE

_BLF rand,??rand??rT
LSLS R2,R0,#+26
LSRS R2,R2,#+26
MOVS R0,#+1
MOVS R1,#+0
_BLF ??lllsl_t,??rT??lllsl_t


т. е. он юзает функцию lllsl_t для сдвига. Как заставить его обойтись без этой функции, т. е. через простые операции, если это конечно, возможно?
DpInRock
iOffset тогда должна быть константой.
coolibin
да, я это знаю, но увы по замыслу она не может быть константой

Cделать циклом что ли?
Код
iOffset = rand()&63;
iValue = 1;
while(iOffset){
    iValue = iValue << 1;
    iOffset--;
}
aaarrr
Цитата(coolibin @ Jul 1 2009, 14:58) *
Cделать циклом что ли?

Зачем? Вы же единицу сдвигаете, сделайте так:
Код
    UINT vl = 0, vh = 0;

    iOffset = rand()&63;
    if(iOffset < 32) vl = 1UL << iOffset;
    else vh = 1UL << (iOffset - 32);
    iValue = ((UINT64)vh << 32) | vl;
Rst7
А рукопашную проверку нельзя?
Код
UINT64 f1(void)
{
  UINT iOffset = rand()&63;
  if (iOffset>31) return (UINT64)(1UL<<(iOffset-32))<<32;
  return (UINT64)(1UL<<iOffset);
}


CODE

// 123 UINT64 f1(void)
// 124 {
f1:
PUSH {LR}
SUB SP,SP,#+4
// 125 UINT iOffset = rand()&63;
BL rand
AND R0,R0,#0x3F
// 126 if (iOffset>31) return (UINT64)(1UL<<(iOffset-32))<<32;
MOV R1,#+1
CMP R0,#+32
BCC ??f1_0
SUB R0,R0,#+32
LSL R0,R1,R0
MOV R1,R0
MOV R0,#+0
B ??f1_1
// 127 return (UINT64)(1UL<<iOffset);
??f1_0:
LSL R0,R1,R0
MOV R1,#+0
??f1_1:
ADD SP,SP,#+4 ;; stack cleaning
POP {LR}
BX LR ;; return
// 128 }


Я вам всем больше скажу. Стреляет такой код (щас курнул мануал, при сдвиге больше чем 31 результат равен 0). Но будьте аккуратны. В других ядрах (не ARM) поведение сдвига другое (например AVR32).

Код
UINT64 f1(void)
{
  UINT vl, vh;
  UINT iOffset = rand()&63;
  vl = 1UL << iOffset;
  vh = 1UL << (iOffset - 32);
  return ((UINT64)vh << 32) | vl;
}


CODE

// 123 UINT64 f1(void)
// 124 {
f1:
PUSH {LR}
SUB SP,SP,#+4
// 125 UINT vl, vh;
// 126 UINT iOffset = rand()&63;
BL rand
AND R0,R0,#0x3F
// 127 vl = 1UL << iOffset;
// 128 vh = 1UL << (iOffset - 32);
// 129 return ((UINT64)vh << 32) | vl;
MOV R2,#+1
SUB R1,R0,#+32
LSL R1,R2,R1
LSL R0,R2,R0
ADD SP,SP,#+4 ;; stack cleaning
POP {LR}
BX LR ;; return
// 130 }
DpInRock
В библиотеке JPEG люди сдвигают вообще по таблице. Т.е. ищут результат сдвига по таблице.
Сергей Борщ
Цитата(DpInRock @ Jul 1 2009, 14:17) *
В библиотеке JPEG люди сдвигают вообще по таблице. Т.е. ищут результат сдвига по таблице.
Это актуально для AVR, но не для ARM. ARM имеет аппаратный сдвигатель, позволяющий сдвигать не затрачивая времени - в той же операции, где используется результат сдвига. Или сдвигать отдельной командой за такт, что явно быстрее, чем чтение таблицы.
Rst7
Цитата
В библиотеке JPEG люди сдвигают вообще по таблице.


В какой библиотеке? wink.gif

Цитата
Это актуально для AVR


Для AVR в качестве barrel-shift'ера надо использовать аппаратный умножитель
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.