При портировании AVR-USB драйвера с GCC на IAR вылезла небольшая проблема с точки зрения эффективности кода. Автор оригинала использует следующие конструкции, которые нормально проходят в GCC:
Код
#define USB_CFG_IOPORT PORTD
...
#define USBIN (*(&USB_CFG_IOPORT - 2)) /* input port for USB bits */
#define USBDDR (*(&USB_CFG_IOPORT - 1)) /* data direction for USB bits */
Под IAR это все транслируется, но превращается вот в такой вот кошмар:
Код
// USBDDR |= 0x10;
// USB_CFG_IOPORT |= 0x10;
IN R16, 0x11
ORI R16, 0x10
OUT 0x11, R16
SBI 0x12, 0x04
То есть, непосредственное обращение к регистру использует SBI, а обращение к указанной конструкции - последовательность команд, не считая определение константным выражением.
Перепробовал несколько идей - не помогло. Изменить определение самого порта с PORTx на просто x с последующей конкатенацией префиксов с именем порта не подходит, так как автор ориентируется в первую очередь на GCC и едва ли согласится радикально менять код, конфигурируемый пользователем.
Для себя-то я могу выйти из положения. Но работая совместно с Кристианом над официальным портом для IAR, хотелось предложить что-то более-менее портабельное без ухода от выбранного им способа определения портов.
Нет у кого идей? Подходит вариант с условной компиляцией (то есть, для именно IAR можно использовать тут __io и тому подобные специфические конструкции). Важно лишь, чтобы раскрывались они в конечном итоге в SBI, а не чтение-модификацию-запись покомандно.