19-Jan-05 08:40 Maxim Polyanskiy wrote to Anton Abrosimov:
AA>> Я пpивел эту стpуктуpу только на твое утвеpждение, что в сях плохо AA>> pеализована pабота с битами. Так вот, switch pаботает с несколькими AA>> значениями одной пеpеменной, здесь же несколько пеpеменных. В таблицу AA>> набоp флагов никак не скомпилиpуется, вне зависимости, битовые они или AA>> байтовые. А скомпилиться пpовеpка этих флогов может, напpимеp, в AA>> подобную последовательность: AA>> lds r16,... AA>> sbrc r16,0 AA>> rcall ... AA>> sbrc r16,1 AA>> rcall ... AA>> ... MP> Hе пойдет: 1) в это никогда не откомпилируется (ну во всяком случае при MP> текущем интелекте компиллеров). "что я делаю не так?" (С) коллективный разум эхи. Конечно, код немножечко не такой, как приведено, но об этом ниже.
struct { unsigned char a:1; unsigned char b:1; } flags;
void fa(void); void fb(void);
void f(void) { if(flags.a) fa(); if(flags.b) fb(); }
avr-gcc -Os -S дал такое
.text .global f .type f, @function f: lds r24,flags sbrc r24,0 rcall fa lds r24,flags sbrc r24,1 rcall fb ret
MP> 2) кто сказал, что не срется R16 в задаче? А дело тут не в том, "срётся или не срётся R16", а в том, что компилятор понятия не имеет - "срётся или не срётся" сама структура flags. Любая вызванная функция может изменить любую глобальную переменную. Поэтому компилятор просто обязан перезагрузить flags в регистр. gcc позволяет сказать, что функция не имеет побочных эффектов, т.е. не меняет ничего "на стороне". Тогда имеем:
struct { unsigned char a:1; unsigned char b:1; } flags;
int fa(void) __attribute__((pure)); int fb(void) __attribute__((pure));
int f(void) { int temp=0; if(flags.a) temp=fa(); if(flags.b) temp=fb(); return temp; }
avr-gcc -Os -S
.text .global f .type f, @function f: push r28 ldi r24,lo8(0) ldi r25,hi8(0) lds r28,flags sbrc r28,0 rcall fa sbrc r28,1 rcall fb pop r28 ret
И это при том, что в общем и целом я уровнем оптимизации avr-gcc недоволен :-)
wbr,