Old1 0 16 декабря, 2005 Опубликовано 16 декабря, 2005 · Жалоба Просматривал хидер pgmspace.h и обратил внимание на модификаторы __x_z и __z, в мануале на компилятор про их назаначение ничего не нашел (или плохо искал?...), в апликашках они тоже вроде бы не встречаются. Решил попробовать использовать их наугад, написал простенький код на С++ (описал две одинаковых функции одна с __x_z, другая без, исходный код и результат компиляции см. в присоединенных файлах), скомпилировал, оказалось что код функции с модификатором компактнее (за счет ИМХО более рационального использования регистров-указателей) и выполняется быстрей (на 30% в данном примере). Вопросы: кто, что о них (модификаторах) знает (особенности их использования)? Какие мысли есть о том, почему ИАР ничего не пишет о них ( ведь ИМХО вещ вроде бы полезная)? modifikaori.rar Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 65 16 декабря, 2005 Опубликовано 16 декабря, 2005 · Жалоба Просматривал хидер pgmspace.h и обратил внимание на модификаторы __x_z и __z, в мануале на компилятор про их назаначение ничего не нашел (или плохо искал?...), в апликашках они тоже вроде бы не встречаются. Решил попробовать использовать их наугад, написал простенький код на С++ (описал две одинаковых функции одна с __x_z, другая без, исходный код и результат компиляции см. в присоединенных файлах), скомпилировал, оказалось что код функции с модификатором компактнее (за счет ИМХО более рационального использования регистров-указателей) и выполняется быстрей (на 30% в данном примере). Вопросы: кто, что о них (модификаторах) знает (особенности их использования)? Какие мысли есть о том, почему ИАР ничего не пишет о них ( ведь ИМХО вещ вроде бы полезная)? Если в объявлении функции присутствует модификатор __z, или, __x или комбинированный, то передача параметров в такую функцию будет производиться не через пару r16:17, через пару, образующую соответсвующий указатель (z или x). Особенно это рулит для функций-членов классов, в которых первым параметром всегда скрыто передается указатель this. Но есть случаи, когда так делать не выгодно, несколько лет назад спрашивал у саппорта, но уже не помню, чем они обосновали отказ от повсеместного использования такой схемы передачи параметров. Что-то типа того, что в большинстве случаев при передаче первым параметром не указателя потребуется дополнительное копирование для освобождения Z-указателя. Конечно, можно было бы сделать более гибкую схему, чтобы компилятор соображал, если указатель, то передавать его через Z, если не указатель, то через 16:17. Но до этого они не дошли, делать не стали. Считают, что и так неплохо. Т.ч. никто не мешает использовать обсуждаемые квалификаторы. Есть только два минуса - 1) переносимость; 2) нет гарантий, что в очередной версии эти вещи не уберут или не изменят их функциональность. Хотя вероятность этого, имхо, стремится к нулю. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IgorKossak 0 16 декабря, 2005 Опубликовано 16 декабря, 2005 · Жалоба Для улучшения скорости и компактности некоторых функций, особенно static, применяю эти квалификаторы. О ни действительно в руководствах ничего нет. Некоторые замеченные особенности: - квалификаторы действуют только на указатели, в остальных случаях игнорируются; - не существует квалификатора __z_x ;) ; - ... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 16 декабря, 2005 Опубликовано 16 декабря, 2005 · Жалоба Для улучшения скорости и компактности некоторых функций, особенно static, применяю эти квалификаторы. О ни действительно в руководствах ничего нет. Некоторые замеченные особенности: - квалификаторы действуют только на указатели, в остальных случаях игнорируются; - не существует квалификатора __z_x ;) ; - ... Cуществует и __z_x и __x_z - соответственно, как передавать первый и второй указатель. По поводу только указателей - если очень надо, преобразуй например int в void * и передай, а потом наоборот. На форуме "Точка опоры" я писал про недокумментированные фичи иара, всякие "__raw", "__no_return" и прочее. Поищи там, давненько дело было. Также есть еще SBRA и CBRA - это коммады какие-то AVR, иар их может использовать. Что за хрень - не знаю. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IgorKossak 0 16 декабря, 2005 Опубликовано 16 декабря, 2005 · Жалоба ...По поводу только указателей - если очень надо, преобразуй например int в void * и передай, а потом наоборот. В том то и дело, что кроме головной боли такие преобразования не принесут, а выигрыша никакого. На форуме "Точка опоры" я писал про недокумментированные фичи иара, всякие "__raw", "__no_return" и прочее. Поищи там, давненько дело было. Хорошие фичи, применяю. __raw - в прерываниях, обслуживаемых ОСРВ (там свои функции сохранения/восстановления контекста); __no_return - в бутлоадере (немного сокращает размер). Также есть еще SBRA и CBRA - это коммады какие-то AVR, иар их может использовать. Что за хрень - не знаю. Ни в стандартном, ни в расширенном наборе (по крайней мере для ATmega) таких инструкций нет. Что имели в виду ИАРовцы - не понятно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 65 16 декабря, 2005 Опубликовано 16 декабря, 2005 · Жалоба Хорошие фичи, применяю. __raw - в прерываниях, обслуживаемых ОСРВ (там свои функции сохранения/восстановления контекста); А что в EWAVR тоже __raw включили? В 4.10А я специально смотрел, не было там (не нашел ни в доке, ни в перечне ключей компилятора). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Old1 0 16 декабря, 2005 Опубликовано 16 декабря, 2005 · Жалоба А что в EWAVR тоже __raw включили? В 4.10А я специально смотрел, не было там (не нашел ни в доке, ни в перечне ключей компилятора). В 4.11А точно есть, и (как выяснилось :( ) даже документирован, правда в самом мануале на компилятор про этот квалификатор ничего нет, а вот в файлах ...\avr\doc\iccavr.htm и ...\avr\doc\manuals.htm он описан... Смутно вспоминаю, что ранее кто-то здесь задавал вопрос: как отключить сохранение регистров в функции обслуживания прерывания если в ней вызывается функция... теперь появилась возможность сделать это корректно... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ig_z 0 17 декабря, 2005 Опубликовано 17 декабря, 2005 · Жалоба Как то пытался переписывать порты под вытесняющие ОСи на чистом С в иар для мсп430. __no_return не оказывает никакого эффекта. Т.е. компилятор не ругается, но и рет не подавляет. Плюс __interrupt разрешают применять только для обработчиков прерываний, так что красота не получается пока :glare: __no_return - в бутлоадере (немного сокращает размер). Подавляет ret, тем самым позволяет на С создавать конструкции типа "несколько точек входа на одну точку выхода", я правильно понимаю? И почему в бутлоадере? Это как-то связанно с АВР или больше нигде не возникает необходимость в подобном механизме? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 17 декабря, 2005 Опубликовано 17 декабря, 2005 · Жалоба ..... Подавляет ret, тем самым позволяет на С создавать конструкции типа "несколько точек входа на одну точку выхода", я правильно понимаю? И почему в бутлоадере? Это как-то связанно с АВР или больше нигде не возникает необходимость в подобном механизме? Подавляет не ret. Подавляет сохранение регистров. Но как-то отличается от __root. Особо не разбирался. По поводу гемороя с передачей значений как указатели. Используя такой метод (с __x_z) можно за раз передать в функцию не 8 (R16-R23), а 12 (R16,R23,X,Z) байт БЕЗ ИСПОЛЬЗОВАНИЯ СТЕКА. В некоторых случаях очень удобно и позволяет повысить производительность. Единственное, нельзя сделать функцию с _z в любой комбинации, если используется вызов данной функции по указателю. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Old1 0 19 декабря, 2005 Опубликовано 19 декабря, 2005 · Жалоба Подавляет не ret. Подавляет сохранение регистров. Но как-то отличается от __root. Особо не разбирался. Непонятно (по поводу __noreturn), если я правильно перевел, этот квалификатор указывает компилятору, что программа после выполнения функции не возвращается к точке ее вызова (если я не прав поправьте), в этом случае ИМХО функция уже вроде как не функция (заметил, что после добавления __noreturn переход на функцию осуществляется при помощи RJMP) и как следствие регистры уже не сохраняются (но это вторично)... И какое отношение __root имеет к сохранению регистров? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IgorKossak 0 19 декабря, 2005 Опубликовано 19 декабря, 2005 · Жалоба Подавляет ret, тем самым позволяет на С создавать конструкции типа "несколько точек входа на одну точку выхода", я правильно понимаю? Не правильно. Это лишь означает, что функция не будет иметь возврата, а значит, что не нужно сохранять контекст в начале и восстанавливать его в конце (т. к. конца функции нет). Это обычно функция main(). И почему в бутлоадере? Это как-то связанно с АВР или больше нигде не возникает необходимость в подобном механизме? Бутлоадер желательно впихнуть в как можно меньшую область из 8, 4, 2, 1 кБайт. Поэтому экономия на сохранении\восстановлении контекста может в этом помочь. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 19 декабря, 2005 Опубликовано 19 декабря, 2005 (изменено) · Жалоба а значит, что не нужно сохранять контекст в начале и восстанавливать его в конце (т. к. конца функции нет). Это обычно функция main(). Заманчиво было :-(, кроме main() это еще все 'задачи'. Попробовал __noreturn и __root на IAR ARM ANSI C/C++ Compiler V4.30A-P050906/W32 Слова худого не сказал в ответ, но и не сделал абсолютно ничего - сохранение контекста осталось :-(. Похоже было, но похерено. Изменено 19 декабря, 2005 пользователем zltigo Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IgorKossak 0 19 декабря, 2005 Опубликовано 19 декабря, 2005 · Жалоба Для задач я обычно применяю __task. Помогает однозначно. Что касается __root, то он скорее предназначен для переменных, оптимизация которых нежелательна. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ig_z 0 19 декабря, 2005 Опубликовано 19 декабря, 2005 · Жалоба Подавляет не ret. Подавляет сохранение регистров. Но как-то отличается от __root. Особо не разбирался. Непонятно (по поводу __noreturn), если я правильно перевел, этот квалификатор указывает компилятору, что программа после выполнения функции не возвращается к точке ее вызова (если я не прав поправьте), в этом случае ИМХО функция уже вроде как не функция (заметил, что после добавления __noreturn переход на функцию осуществляется при помощи RJMP) и как следствие регистры уже не сохраняются (но это вторично)... И какое отношение __root имеет к сохранению регистров? Очень странно. Какой у вас компилер и версия? У меня мсп430 3.30 итак: __raw и __task подавляют сохранение/восстановление регистров в для "прерывательных" и "обычных" функций __interrupt -заменяет рет на ирет __root обязывает компилятор/линкер включать функцию в объектный/бинарный файл, даже если на нее нет ни одной ссылки __noreturn keyword can be used on a function to inform the compiler that the function will not return. Т.е. не будет возврата из функции - будет выполняться следующий по порядку оператор. О подавлении/сохранении регистров ни слова. Точно так же очень сомнительно выглядит вызов функции по jmp. По крайней мере мсп430 3.30 вызывает __noreturn функцию через call. Чесно предупреждает, что больше не сможет вернуться в точку вызова :cranky: . Но т.к. не подавляет ret в вызываемой функции, благополучно возвращается в точку вызова :tongue: На мсп430 3.30 __noreturn не делает ничего. Т.е. ret не подавляется, а регистры сохраняются. Все остальные extended keywords работают корректно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 19 декабря, 2005 Опубликовано 19 декабря, 2005 · Жалоба Очень странно. Какой у вас компилер и версия? У меня мсп430 3.30 итак: __raw и __task подавляют сохранение/восстановление регистров в для "прерывательных" и "обычных" функций __interrupt -заменяет рет на ирет __root обязывает компилятор/линкер включать функцию в объектный/бинарный файл, даже если на нее нет ни одной ссылки __noreturn keyword can be used on a function to inform the compiler that the function will not return. Т.е. не Эксперимент: IAR ARM ANSI C/C++ Compiler V4.30A-P050906/W32 __raw и __task - знать не знает, ведать не ведает таких :-(. Ругается долго и мучительно (вообще с локализацией ошибки IAR далеко не в первых рядах). __interrupt - тоже не знает, но не беда, ибо __irq имеет место быть... __root - не ругается, ну может и работает, как описано __noreturn - не делает ничего. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться