А рукопашную проверку нельзя?
Код
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 }