LINUX.ORG.RU

ARM ассемблер - не пойму, заинлайнилась ли функция?

 , , ,


1

2

Пишу под STM32 (BluePill).

Есть вот такая функция:

__attribute__((always_inline, section(".ramfunc")))
uint16_t readAddressBus()
{
    // Для ускорения адрес вначале считается 32-х битным чтобы проще работать
    // с 32-х битным регистром PA, и только в конце он один раз преобразуется в 16 бит
    uint32_t addr = 0;

    // Установка на мультиплексоре сегмента адреса 00
    GPIOB->BSRR = 0 | (GPIO_BSRR_BR3_Msk | GPIO_BSRR_BR4_Msk );

    // Считывается и запоминается значение ножек сегмента 0
    addr = ((GPIOA->IDR & 0x0F00) >> 8);


    // Установка на мультиплексоре сегмента адреса 01
    GPIOB->BSRR = 0 | (GPIO_BSRR_BS3_Msk | GPIO_BSRR_BR4_Msk );

    // Считывается и запоминается значение ножек сегмента 1
    addr = addr | ((GPIOA->IDR & 0x0F00) >> 4);


    // Установка на мультиплексоре сегмента адреса 10
    GPIOB->BSRR = 0 | (GPIO_BSRR_BR3_Msk | GPIO_BSRR_BS4_Msk );

    // Считывается и запоминается значение ножек сегмента 2
    addr = addr | (GPIOA->IDR & 0x0F00);


    // Установка на мультиплексоре сегмента адреса 11
    GPIOB->BSRR = 0 | (GPIO_BSRR_BS3_Msk | GPIO_BSRR_BS4_Msk );

    // Считывается и запоминается значение ножек сегмента 3
    addr = addr | ((GPIOA->IDR & 0x0F00) << 4);

    return (uint16_t) addr;
}

Она вызывается из main loop:
__attribute__((noinline, section(".ramfunc")))
void mainLoop()
{
    ...
            // Нужно получить текущий адрес с ША
            uint16_t addr=readAddressBus();
    ...
}

В дизассемблере ARM это дело представлено таким образом:
Disassembly of section .ramfunc:

080004d0 <readAddressBus>:
 80004d0:	f44f 13c0 	mov.w	r3, #1572864	; 0x180000
 80004d4:	490d      	ldr	r1, [pc, #52]	; (800050c <readAddressBus+0x3c>)
 80004d6:	4a0e      	ldr	r2, [pc, #56]	; (8000510 <readAddressBus+0x40>)
 80004d8:	480e      	ldr	r0, [pc, #56]	; (8000514 <readAddressBus+0x44>)
 80004da:	610b      	str	r3, [r1, #16]
 80004dc:	6893      	ldr	r3, [r2, #8]
 80004de:	6108      	str	r0, [r1, #16]
 80004e0:	6890      	ldr	r0, [r2, #8]
 80004e2:	f3c3 2303 	ubfx	r3, r3, #8, #4
 80004e6:	0900      	lsrs	r0, r0, #4
 80004e8:	f000 00f0 	and.w	r0, r0, #240	; 0xf0
 80004ec:	4318      	orrs	r0, r3
 80004ee:	4b0a      	ldr	r3, [pc, #40]	; (8000518 <readAddressBus+0x48>)
 80004f0:	610b      	str	r3, [r1, #16]
 80004f2:	6893      	ldr	r3, [r2, #8]
 80004f4:	f403 6370 	and.w	r3, r3, #3840	; 0xf00
 80004f8:	4318      	orrs	r0, r3
 80004fa:	2318      	movs	r3, #24
 80004fc:	610b      	str	r3, [r1, #16]
 80004fe:	6893      	ldr	r3, [r2, #8]
 8000500:	011b      	lsls	r3, r3, #4
 8000502:	f403 4370 	and.w	r3, r3, #61440	; 0xf000
 8000506:	4318      	orrs	r0, r3
 8000508:	4770      	bx	lr
 800050a:	bf00      	nop
 800050c:	40010c00 	andmi	r0, r1, r0, lsl #24
 8000510:	40010800 	andmi	r0, r1, r0, lsl #16
 8000514:	00100008 	andseq	r0, r0, r8
 8000518:	00080010 	andeq	r0, r8, r0, lsl r0

0800051c <mainLoop>:
 800051c:	e92d 47f0 	stmdb	sp!, {r4, r5, r6, r7, r8, r9, sl, lr}
 8000520:	2100      	movs	r1, #0
 8000522:	f44f 15c0 	mov.w	r5, #1572864	; 0x180000
 8000526:	f04f 0c18 	mov.w	ip, #24
 800052a:	f44f 3480 	mov.w	r4, #65536	; 0x10000
 800052e:	f04f 0e01 	mov.w	lr, #1
 8000532:	4a20      	ldr	r2, [pc, #128]	; (80005b4 <mainLoop+0x98>)
 8000534:	4820      	ldr	r0, [pc, #128]	; (80005b8 <mainLoop+0x9c>)
 8000536:	4e21      	ldr	r6, [pc, #132]	; (80005bc <mainLoop+0xa0>)
 8000538:	4f21      	ldr	r7, [pc, #132]	; (80005c0 <mainLoop+0xa4>)
 800053a:	f8df 8088 	ldr.w	r8, [pc, #136]	; 80005c4 <mainLoop+0xa8>
 800053e:	6893      	ldr	r3, [r2, #8]
 8000540:	f013 0fc0 	tst.w	r3, #192	; 0xc0
 8000544:	d005      	beq.n	8000552 <mainLoop+0x36>
 8000546:	2900      	cmp	r1, #0
 8000548:	d0f9      	beq.n	800053e <mainLoop+0x22>
 800054a:	f8c2 e010 	str.w	lr, [r2, #16]
 800054e:	2100      	movs	r1, #0
 8000550:	e7f5      	b.n	800053e <mainLoop+0x22>
 8000552:	6115      	str	r5, [r2, #16]
 8000554:	6883      	ldr	r3, [r0, #8]
 8000556:	6116      	str	r6, [r2, #16]
 8000558:	f3c3 2a03 	ubfx	sl, r3, #8, #4
 800055c:	6883      	ldr	r3, [r0, #8]
 800055e:	6117      	str	r7, [r2, #16]
 8000560:	ea4f 1913 	mov.w	r9, r3, lsr #4
 8000564:	6883      	ldr	r3, [r0, #8]
 8000566:	f009 09f0 	and.w	r9, r9, #240	; 0xf0
 800056a:	f8c2 c010 	str.w	ip, [r2, #16]
 800056e:	f403 6370 	and.w	r3, r3, #3840	; 0xf00
 8000572:	ea49 090a 	orr.w	r9, r9, sl
 8000576:	ea43 0909 	orr.w	r9, r3, r9
 800057a:	6883      	ldr	r3, [r0, #8]
 800057c:	011b      	lsls	r3, r3, #4
 800057e:	f403 4370 	and.w	r3, r3, #61440	; 0xf000
 8000582:	ea43 0309 	orr.w	r3, r3, r9
 8000586:	f483 4900 	eor.w	r9, r3, #32768	; 0x8000
 800058a:	f1b9 0f04 	cmp.w	r9, #4
 800058e:	bf8f      	iteee	hi
 8000590:	f04f 0988 	movhi.w	r9, #136	; 0x88
 8000594:	4443      	addls	r3, r8
 8000596:	f5a3 4300 	subls.w	r3, r3, #32768	; 0x8000
 800059a:	f893 9000 	ldrbls.w	r9, [r3]
 800059e:	6893      	ldr	r3, [r2, #8]
 80005a0:	b29b      	uxth	r3, r3
 80005a2:	ea43 2309 	orr.w	r3, r3, r9, lsl #8
 80005a6:	60d3      	str	r3, [r2, #12]
 80005a8:	2900      	cmp	r1, #0
 80005aa:	d1c8      	bne.n	800053e <mainLoop+0x22>
 80005ac:	6114      	str	r4, [r2, #16]
 80005ae:	2101      	movs	r1, #1
 80005b0:	e7c5      	b.n	800053e <mainLoop+0x22>
 80005b2:	bf00      	nop
 80005b4:	40010c00 	andmi	r0, r1, r0, lsl #24
 80005b8:	40010800 	andmi	r0, r1, r0, lsl #16
 80005bc:	00100008 	andseq	r0, r0, r8
 80005c0:	00080010 	andeq	r0, r8, r0, lsl r0
 80005c4:	20000000 	andcs	r0, r0, r0

И я вижу, что код функции readAddressBus() оттранслировался в отдельные адреса. Но я нигде не вижу вызова этой функции. При этом я вижу искаженный код данной функции внутри mainLoop(), значит readAddressBus() вроде как заинлайнилась.

Но тогда зачем сделана реализация этой функции в отдельных адресах, если эта реализация вообще не используется?

Исходник на Си: https://github.com/xintrea/mikroshamem/blob/c00c10606dca71d3531c45f70b1169732...
Ассемблер: https://pastebin.com/gpc4tA03

★★★★★

Последнее исправление: Xintrea (всего исправлений: 1)

Компилятор не знает, вызываете ли Вы нестатическую функцию из других единиц трансляции или не вызываете. Поэтому на всякий случай пишет реализацию функции в объектный модуль.

Если повезёт, то при компоновке ненужный код отдельной реализации может быть выброшен.

vM ★★
()
Ответ на: комментарий от vM

Компилятор не знает, вызываете ли Вы нестатическую функцию из других единиц трансляции или не вызываете. Поэтому на всякий случай пишет реализацию функции в объектный модуль.


Хорошее объяснение, благодарю.

Xintrea ★★★★★
() автор топика
Последнее исправление: Xintrea (всего исправлений: 1)
Ответ на: комментарий от fluorite

Тут gcc сделал ровно то, что просили - поместил определение функции readAddressBus в секцию .ramfunc и в то же время заинлайнил её в mainLoop.

Непонятно только, сделает ли он то же самое в bin-файле. Я то взял asm-информацию из elf.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

Непонятно только, сделает ли он то же самое в bin-файле.

Естественно сделает. BIN получается из ELF без изменений.

Сделай «static uint16_t readAddressBus()» и отдельная версия продает.

SRAM начинается c 0x20000000. 0x08000000 - это flash. Так что нужно смотреть в линкер как собирается .ramfunc.

alexru ★★★★
()
Последнее исправление: alexru (всего исправлений: 2)