SM 0 27 августа, 2014 Опубликовано 27 августа, 2014 · Жалоба Я что-то запутался... Как мне объявить внешнюю thumb функцию, расположенную по заданному статическому адресу? Я сделал вот так: 1) arm-rom.h int rom_func (void* dev_descr, int data); 2) скрипт для линкера .... SECTIONS { .... rom_func = 0x123456; } Все тут хорошо, но линкер думает, что rom_func следует исполнять как ARM, а не как THUMB, и генерирует соотв. BLX инстукцию (при вызове из THUMB кода). А как мне указать, что он THUMB? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SM 0 27 августа, 2014 Опубликовано 27 августа, 2014 · Жалоба Проблему сам решил, через ж. автогеном. Сделал ассемблерный файл rom_funcs.S, внутри которого написал: .globl rom_func .thumb_set rom_func, 0x123456 Ну и прилинковал получившийся объектный модуль в общую кучу. А из скрипта линкера убрал указание адреса. В результате вызов из THUMB-кода по BL, что и требовалось. ----- Но вопрос остался - а не через зад, можно? Прямо линкеру указать, что этот символ thumb и имеет такое-то значение? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
den_po 0 27 августа, 2014 Опубликовано 27 августа, 2014 · Жалоба можно без линкера сделать указатель на функцию, а в качестве адреса указывать адрес функции +1 void (*fn)() = (void(*)())(0x123456+1); fn(); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 28 августа, 2014 Опубликовано 28 августа, 2014 · Жалоба Проблему сам решил, через ж. автогеном. Сделал ассемблерный файл rom_funcs.S, внутри которого написал: Выключайте автоген: typedef void (__thumb *iap_entry_typ)(u32 *, u32 *); #define iap_entry ((iap_entry_typ)0x7FFFFFF1) iap_entry(buf, buf); for IAR Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SM 0 28 августа, 2014 Опубликовано 28 августа, 2014 · Жалоба for IAR Спасибо, конечно, но в теме было про gcc. Никаких IAR там быть не может. Это около-линуксовая тема. Обхожу баг ROM-загрузчика AM3517, который не может загрузить из NAND больше 2К кода, если NAND имеет размер страницы больше, чем 2К. а в качестве адреса указывать адрес функции +1 Проверено, при этом линкер при оптимизации накладывает маску на адрес 0xFFFFFFF8, чем убивает и +1, и если код находится на смещениях +2 (если gcc понимает, что указатель можно соптимизировать в прямой вызов). И генерирует команды перехода BLX... В общем, мимо. Можно, конечно, volatile указатель объявить, но не хочется указатели, хочется прямой вызов сделать корректно (без asm). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 28 августа, 2014 Опубликовано 28 августа, 2014 · Жалоба ИМХО корректнее честный АСМ вызов, чем игры со смещением... может есть какая дирректива аля pragma, для тхумб вызовов? Кстати вроде есть регистр режима работы, если вы работаете в дном режиме, вызовы в другом режиме разрешены? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
den_po 0 28 августа, 2014 Опубликовано 28 августа, 2014 (изменено) · Жалоба Проверено, при этом линкер при оптимизации накладывает маску на адрес 0xFFFFFFF8, чем убивает и +1 И с какой, интересно, стати? Или речь о непосредственном операнде? Тут такое дело, если из арм кода вызывается BLX 0x123456 (обратите внимание - чётно), то оно переключает в тумбу. Может лажанул с кратностью 2, но сути не меняет, чётный адрес в непосредственном операнде BLX переключит режим. Изменено 28 августа, 2014 пользователем den_po Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 28 августа, 2014 Опубликовано 28 августа, 2014 · Жалоба Я сделал вот так: 1) arm-rom.h int rom_func (void* dev_descr, int data); А если так: int __attribute__((interfacethumb)) rom_func (void* dev_descr, int data); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SM 0 28 августа, 2014 Опубликовано 28 августа, 2014 · Жалоба И с какой, интересно, стати? Или речь о непосредственном операнде? О непосредственном. То есть, когда gcc понимает, что указатель можно заоптимизировать до его смерти. При этом линкер, не видя какого-то атрибута, что адрес, куда перейти, относится к thumb режиму, обнуляет ему младшие два бита принудительно, причем без всяких варнингов. Да и ручное прибавление единицы к адресу в указателе, это еще более мощный автоген в ж., чем ассемблерный .thumb_set А если так: То так: warning: 'interfacethumb' attribute directive ignored [-Wattributes] gcc 4.7.2 PS И, все наоборот - в тумбу переключает нечетный адрес, и при этом в тумбе адресация кратна двум. А четный адрес переключает в ARM, и там кратность уже равна четырем. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 28 августа, 2014 Опубликовано 28 августа, 2014 · Жалоба Там есть еще одна фигня - линкер может вставлять BLX просто потому, что для BL не хватает дальности "прыжка". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SM 0 28 августа, 2014 Опубликовано 28 августа, 2014 · Жалоба Там есть еще одна фигня - линкер может вставлять BLX просто потому, что для BL не хватает дальности "прыжка". Хватает, хватает... Только .thumb_set-ом все объявишь, сразу BL. Да и BL вроде не отличается от BLX по "дальности". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
den_po 0 28 августа, 2014 Опубликовано 28 августа, 2014 (изменено) · Жалоба О непосредственном. То есть, когда gcc понимает, что указатель можно заоптимизировать до его смерти. При этом линкер, не видя какого-то атрибута, что адрес, куда перейти, относится к thumb режиму, обнуляет ему младшие два бита принудительно, причем без всяких варнингов. Кто-то из нас что-то недопонимает. Если адрес thumb функции N*4, на выходе из предложенного мной кода получается обычно один из двух вариантов: 1) BLX (N*4) 2) LDR Rx, =N*4+1 BLX Rx Если адрес thumb функции N*4+2, на выходе получается один вариант: LRD Rx, =N*4+2+1 BLX Rx У вас какой-то другой результат получается? Да и ручное прибавление единицы к адресу в указателе, это еще более мощный автоген в ж., чем ассемблерный .thumb_set Чем это хуже использования заданного статического адреса? Изменено 28 августа, 2014 пользователем den_po Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SM 0 28 августа, 2014 Опубликовано 28 августа, 2014 · Жалоба У вас какой-то другой результат получается? Естественно, другой. - Если я делаю вызов ф-ции, описанной по .thumb_set из THUMB-кода, то я получаю BL N*2 ; thumb -> thumb - Если я делаю вызов ф-ции, описанной по .set из THUMB-кода, то я получаю BLX N*4 ; thumb -> arm - Если я делаю вызов ф-ции, описанной по .thumb_set из ARM-кода, то я получаю (должен получить, не пробовал, не надо) BLX N*2+1 ; arm -> thumb - Если я делаю вызов ф-ции, описанной по .set из ARM-кода, то я получаю BL N*4 ; arm -> arm ну, естественно, линкеру дана опция ком. строки --use-blx, иначе она всякий там гемор с регистрами генерирует Чем это хуже использования заданного статического адреса? Тем, что линкер/компилятор разбираются сами, где там +1 сделать, где не сделать, где BL поставить, где BLX. (тем более, докучи, откуда компилятор узнает, что при переходе по указателю нужен будет BLX, а не BL). Собственно, вопрос то не в этом. Вопрос - как уйти от .thumb_set и ассемблера, по аналогии с IAR-овским __thumb Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
den_po 0 28 августа, 2014 Опубликовано 28 августа, 2014 · Жалоба В общем, говорим мы о разных вещах. Если в исходнике указывать адрес указанным мной способом, всё будет работать нормально, никакой линкер никакие биты самовольно не сбросит. Задачу из первой строки первого поста это решает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 29 августа, 2014 Опубликовано 29 августа, 2014 · Жалоба Хватает, хватает... Только .thumb_set-ом все объявишь, сразу BL. Да и BL вроде не отличается от BLX по "дальности". Как оно может не отличаться? если BX - косвенная адресация, соотв. -32битное смещение, а B - с адресом в команде (т.е. - явно меньше 32 бит). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться