реклама на сайте
подробности

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> ARM gcc, вызвать THUMB функцию из ROM
SM
сообщение Aug 27 2014, 17:02
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881



Я что-то запутался... Как мне объявить внешнюю 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?
Go to the top of the page
 
+Quote Post
SM
сообщение Aug 27 2014, 18:23
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881



Проблему сам решил, через ж. автогеном. Сделал ассемблерный файл rom_funcs.S, внутри которого написал:

Код
      .globl rom_func
      .thumb_set rom_func, 0x123456


Ну и прилинковал получившийся объектный модуль в общую кучу. А из скрипта линкера убрал указание адреса. В результате вызов из THUMB-кода по BL, что и требовалось.

-----
Но вопрос остался - а не через зад, можно? Прямо линкеру указать, что этот символ thumb и имеет такое-то значение?
Go to the top of the page
 
+Quote Post
den_po
сообщение Aug 27 2014, 22:17
Сообщение #3


Частый гость
**

Группа: Участник
Сообщений: 139
Регистрация: 9-11-12
Из: Санкт-Петербург
Пользователь №: 74 315



можно без линкера сделать указатель на функцию, а в качестве адреса указывать адрес функции +1

void (*fn)() = (void(*)())(0x123456+1);

fn();
Go to the top of the page
 
+Quote Post
jcxz
сообщение Aug 28 2014, 02:02
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(SM @ Aug 28 2014, 00:23) *
Проблему сам решил, через ж. автогеном. Сделал ассемблерный файл rom_funcs.S, внутри которого написал:

Выключайте автоген:
typedef void (__thumb *iap_entry_typ)(u32 *, u32 *);
#define iap_entry ((iap_entry_typ)0x7FFFFFF1)
iap_entry(buf, buf);

for IAR
Go to the top of the page
 
+Quote Post
SM
сообщение Aug 28 2014, 05:58
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881



Цитата(jcxz @ Aug 28 2014, 06:02) *
for IAR

Спасибо, конечно, но в теме было про gcc. Никаких IAR там быть не может. Это около-линуксовая тема. Обхожу баг ROM-загрузчика AM3517, который не может загрузить из NAND больше 2К кода, если NAND имеет размер страницы больше, чем 2К.

Цитата(den_po @ Aug 28 2014, 02:17) *
а в качестве адреса указывать адрес функции +1

Проверено, при этом линкер при оптимизации накладывает маску на адрес 0xFFFFFFF8, чем убивает и +1, и если код находится на смещениях +2 (если gcc понимает, что указатель можно соптимизировать в прямой вызов). И генерирует команды перехода BLX... В общем, мимо. Можно, конечно, volatile указатель объявить, но не хочется указатели, хочется прямой вызов сделать корректно (без asm).
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Aug 28 2014, 10:05
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



ИМХО корректнее честный АСМ вызов, чем игры со смещением... может есть какая дирректива аля pragma, для тхумб вызовов? Кстати вроде есть регистр режима работы, если вы работаете в дном режиме, вызовы в другом режиме разрешены?
Go to the top of the page
 
+Quote Post
den_po
сообщение Aug 28 2014, 10:20
Сообщение #7


Частый гость
**

Группа: Участник
Сообщений: 139
Регистрация: 9-11-12
Из: Санкт-Петербург
Пользователь №: 74 315



Цитата(SM @ Aug 28 2014, 09:58) *
Проверено, при этом линкер при оптимизации накладывает маску на адрес 0xFFFFFFF8, чем убивает и +1

И с какой, интересно, стати?
Или речь о непосредственном операнде?
Тут такое дело, если из арм кода вызывается BLX 0x123456 (обратите внимание - чётно), то оно переключает в тумбу. Может лажанул с кратностью 2, но сути не меняет, чётный адрес в непосредственном операнде BLX переключит режим.

Сообщение отредактировал den_po - Aug 28 2014, 10:32
Go to the top of the page
 
+Quote Post
scifi
сообщение Aug 28 2014, 10:36
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(SM @ Aug 27 2014, 21:02) *
Я сделал вот так:

1) arm-rom.h
Код
int rom_func (void* dev_descr, int data);

А если так:
Код
int __attribute__((interfacethumb)) rom_func (void* dev_descr, int data);
Go to the top of the page
 
+Quote Post
SM
сообщение Aug 28 2014, 10:41
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881



Цитата(den_po @ Aug 28 2014, 14:20) *
И с какой, интересно, стати?
Или речь о непосредственном операнде?

О непосредственном. То есть, когда gcc понимает, что указатель можно заоптимизировать до его смерти. При этом линкер, не видя какого-то атрибута, что адрес, куда перейти, относится к thumb режиму, обнуляет ему младшие два бита принудительно, причем без всяких варнингов.

Да и ручное прибавление единицы к адресу в указателе, это еще более мощный автоген в ж., чем ассемблерный .thumb_set

Цитата(scifi @ Aug 28 2014, 14:36) *
А если так:

То так:
warning: 'interfacethumb' attribute directive ignored [-Wattributes]

gcc 4.7.2

PS
И, все наоборот - в тумбу переключает нечетный адрес, и при этом в тумбе адресация кратна двум. А четный адрес переключает в ARM, и там кратность уже равна четырем.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 28 2014, 12:02
Сообщение #10


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Там есть еще одна фигня - линкер может вставлять BLX просто потому, что для BL не хватает дальности "прыжка".


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
SM
сообщение Aug 28 2014, 12:09
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881



Цитата(Сергей Борщ @ Aug 28 2014, 16:02) *
Там есть еще одна фигня - линкер может вставлять BLX просто потому, что для BL не хватает дальности "прыжка".

Хватает, хватает... Только .thumb_set-ом все объявишь, сразу BL. Да и BL вроде не отличается от BLX по "дальности".
Go to the top of the page
 
+Quote Post
den_po
сообщение Aug 28 2014, 12:44
Сообщение #12


Частый гость
**

Группа: Участник
Сообщений: 139
Регистрация: 9-11-12
Из: Санкт-Петербург
Пользователь №: 74 315



Цитата(SM @ Aug 28 2014, 14:41) *
О непосредственном. То есть, когда 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

У вас какой-то другой результат получается?

Цитата(SM @ Aug 28 2014, 14:41) *
Да и ручное прибавление единицы к адресу в указателе, это еще более мощный автоген в ж., чем ассемблерный .thumb_set

Чем это хуже использования заданного статического адреса?

Сообщение отредактировал den_po - Aug 28 2014, 12:47
Go to the top of the page
 
+Quote Post
SM
сообщение Aug 28 2014, 13:09
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881



Цитата(den_po @ Aug 28 2014, 16:44) *
У вас какой-то другой результат получается?

Естественно, другой.

- Если я делаю вызов ф-ции, описанной по .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, иначе она всякий там гемор с регистрами генерирует

Цитата(den_po @ Aug 28 2014, 16:44) *
Чем это хуже использования заданного статического адреса?

Тем, что линкер/компилятор разбираются сами, где там +1 сделать, где не сделать, где BL поставить, где BLX. (тем более, докучи, откуда компилятор узнает, что при переходе по указателю нужен будет BLX, а не BL).

Собственно, вопрос то не в этом. Вопрос - как уйти от .thumb_set и ассемблера, по аналогии с IAR-овским __thumb
Go to the top of the page
 
+Quote Post
den_po
сообщение Aug 28 2014, 20:44
Сообщение #14


Частый гость
**

Группа: Участник
Сообщений: 139
Регистрация: 9-11-12
Из: Санкт-Петербург
Пользователь №: 74 315



В общем, говорим мы о разных вещах.
Если в исходнике указывать адрес указанным мной способом, всё будет работать нормально, никакой линкер никакие биты самовольно не сбросит. Задачу из первой строки первого поста это решает.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Aug 29 2014, 02:41
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(SM @ Aug 28 2014, 18:09) *
Хватает, хватает... Только .thumb_set-ом все объявишь, сразу BL. Да и BL вроде не отличается от BLX по "дальности".

Как оно может не отличаться? если BX - косвенная адресация, соотв. -32битное смещение, а B - с адресом в команде (т.е. - явно меньше 32 бит).
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 13:38
Рейтинг@Mail.ru


Страница сгенерированна за 0.01493 секунд с 7
ELECTRONIX ©2004-2016