Вот некоторые результаты моего компилятора на ассемблере.Это компилятор MPLAB C30 C, основанный на GCC v3.23, для dsPIC33FJ128GP802, 16-битного умеренно высокоскоростного DSP / MCU.
212: inline uint16_t ror_16(uint16_t word, int num)
213: {
078C4 608270 and.w w1,#16,w4
078C6 DE0204 lsr w0,w4,w4
078C8 780101 mov.w w1,w2
078CA EA8102 com.w w2,w2
078CC EA8183 com.w w3,w3
078CE 610170 and.w w2,#16,w2
078D0 DD0002 sl w0,w2,w0
078D2 700004 ior.w w0,w4,w0
214: num &= 16; // limit to 16 shifts
215: return (word >> num) | (word << (16 - num));
216: }
078D4 060000 return
В частности меня интересует следующее:
and.w w1,#16,w4 AND W1 with 16, storing result in W4
lsr w0,w4,w4 Logical shift right W0 by W4 times storing result in W4
mov.w w1,w2 Move W1 to W2
com.w w2,w2 Logical complement of W2 stored in W2
com.w w3,w3 Logical complement of W3 stored in W3 <-- This line is confusing me
and.w w2,#16,w2 AND W2 with 16, storing result in W2
sl w0,w2,w0 (Logical) shift left W0 left by W2 times storing result in W0
ior.w w0,w4,w0 Inclusive OR of W0 and W4 stored in W0
return Return from function
W0..W15 - массив из шестнадцати 16-разрядных регистров на кристалле.
Фактически это упрощает до (в примитивном RTL):
W4 := W1 & 16
W4 := W0 LSR W4
W1 := W2
W2 := COM W2
W3 := COM W3
W2 := W2 & 16
W0 := W0 SL W2
W0 := W0 | W4
return
СейчасМеня смущает, почему он вычисляет дополнение к W3, когда передается только два переданных аргумента (W0 и W1 - он использует массив W для передачи аргументов в функции для функций с меньшими аргументами.) W3 никогда не используется в вычислениях,и никогда не возвращается.На самом деле, он даже не содержит данных: в нем ничего не хранится, и только вызываемый будет иметь некоторые данные (хотя функции не обязаны сохранять W0..W7, поэтому вызываемый не долженполагаться на это.) Почему это включено в код?Это просто ошибка компилятора или ошибка, или я что-то упустил?
И это не просто этот код - я вижу ту же странность в других частях кода.Даже код, предназначенный для вычисления таких вещей, как дополнения 16-битной переменной, всегда использует два регистра.Это меня потеряло!