Hallo Forum,
zur Zeit beschäftige ich mich gezwungenermaßen mit dem LPC824. Die
gesamte Serie von NXP besitzt sogenannte ROM-APIs. Hauptsächlich dienen
diese zur Hardware-Ansteuerung.
Speziell dieses Modell hat aber auch "Performance-optimized
signed/unsigned integer division" Funktionen. Folgende Funktionen sind
im ROM implementiert: 1 | int32_t sdiv(int32_t num, int32_t denom);
| 2 | uint32_t udiv(uint32_t num, uint32_t denom);
| 3 | sdiv_t sdivmod(int32_t num, int32_t denom);
| 4 | udiv_t udivmod(uint32_t num, uint32_t denom);
|
Diese liegen an der Adresse 0x1FFF_1FF8 + 0x10 und den darauffolgenden
Adressen.
Aus der ARM EBAI Beschreibung*) entnehme ich, dass (da es keine
Divisions-Instruktionen gibt) die folgenden Funktionen aus der libgcc
aufgerufen werden: 1 | int32_t __aeabi_idiv(int32_t numerator, int32_t denominator);
| 2 | uint32_t __aeabi_uidiv(uint32_t numerator, uint32_t denominator);
| 3 | typedef struct { int32_t quot; int32_t rem; } idiv_return;
| 4 | typedef struct { uint32_t quot; uint32_t rem; } uidiv_return;
| 5 | idiv_return __aeabi_idivmod(int32_t numerator, int32_t denominator);
| 6 | uidiv_return __aeabi_uidivmod(uint32_t numerator, uint32_t denominator);
|
Soweit zu den Gegebenheiten:
Meine Frage ist jetzt, wie ich den GCC dazu bewegen kann, statt den
Funktionen der libgcc die ROMAPI aufzurufen.
Mein naiver Ansatz wäre so: 1 | int32_t __aeabi_idiv(int32_t numerator, int32_t denominator) {
| 2 | int32_t (*sdiv)(int32_t, int32_t) = 0x1FFF1FF8 + 0x10 + 0x0;
| 3 | return sdiv(numerator, denominator);
| 4 | }
| 5 | /* usw. */
|
Allerdings werden so ja extra Funktionen, samt extra push/pop-Sequenz,
generiert, die dann weitere Funktionen anspringen. Diesen extra Sprung
und das push/pop**) würde ich gerne, wenn es geht, abstellen.
Kann ich dem GCC mitteilen, dass die __aeabi_[ui]div(mod) an speziellen
Adressen liegen und nicht nochmal dazugelinkt werden müssen? (mglw. mit
-Wl,--defsym=name=...?)
Mit freundlichen Grüßen,
N.G.
PS:
1. ich weiß nicht, ob die Performance der ROM-API besser ist, ich will
es aber einfach mal ausprobieren.
2. Ich habe weder ein Performance-, noch ein Speicher-Problem,
allerdings will ich die Funktion schon mal nutzen, wenn sie angeboten
wird.
*)
http://infocenter.arm.com/help/topic/com.arm.doc.ihi0043d/IHI0043D_rtabi.pdf
**) https://godbolt.org/g/zskz1x
Vielleicht so? Hier mit avr-gcc: 1 | int a, b;
| 2 |
| 3 | int main()
| 4 | {
| 5 | return a / b;
| 6 | }
|
Wird zu: 1 | 0000008a <main>:
| 2 | ...
| 3 | 9a: 02 d0 rcall .+4 ; 0xa0 <__divmodhi4>
| 4 | 9c: cb 01 movw r24, r22
| 5 | 9e: 08 95 ret
| 6 |
| 7 | 000000a0 <__divmodhi4>:
| 8 | a0: 97 fb bst r25, 7
| 9 | ...
|
Also ähnlich wie bei arm: gcc erzeugt einen lib-Aufruf, hier __divmodhi4
aus libgcc. Um stattdessen nach 0x1234 zu springen (wo hier kein
sinnvoller Code steht) bein Linken: 1 | -Wl,--defsym,__divmodhi4=0x1234
|
Was dann wird zu: 1 | 0000008a <main>:
| 2 | ...
| 3 | 9a: 0e 94 1a 09 call 0x1234 ; 0x1234 <__divmodhi4>
| 4 | 9e: cb 01 movw r24, r22
| 5 | a0: 08 95 ret
| 6 |
| 7 | 000000a2 <_exit>:
| 8 | ...
|
D.h. ld löst das Symbol nicht durch Linken gegen libgcc.a auf, sonder
gemäß der Definition des Symbols von der Kommandozeile.
Symbole können auch im Linker-Skript festgelegt werden, falls das besser
in den Build-Prozess passt.
Ob das gut mit Symbolreferenzen funktioniert, die sich in anderen
Bibliotheken oder der libgcc selbst befinden, weiß ich nicht konkret.
Evtl. hilft es dann, ein anderes Symbol zu verwenden, das nicht in der
Bibliothek auftaucht: 1 | -Wl,--wrap,__divmodhi4 -Wl,--defsym,__wrap___divmodhi4=0x1234
|
1 | 0000008a <main>:
| 2 | ...
| 3 | 9a: 0e 94 1a 09 call 0x1234 ; 0x1234 <__wrap___divmodhi4>
| 4 | ...
|
Hallo Johann,
danke für deine Antwort.
Dann lag ich ja mit meiner defsym-Idee gar nicht so falsch :-)
Das werde ich probieren, sobald ich die Hardware wieder habe. Dann teste
ich auch mal die Performance.
Johann L. schrieb:
> Symbole können auch im Linker-Skript festgelegt werden, falls das besser
> in den Build-Prozess passt.
Ja, das wäre mir lieb, da ich (ARM-typisch) sowieso ein eigenes
ld-Skript nutze. Wie müsste ich so etwas machen (ich tippe auf
PROVIDE())?
Johann L. schrieb:
> Ob das gut mit Symbolreferenzen funktioniert, die sich in anderen
> Bibliotheken oder der libgcc selbst befinden, weiß ich nicht konkret.
> Evtl. hilft es dann, ein anderes Symbol zu verwenden, das nicht in der
> Bibliothek auftaucht
Inwiefern könnte es da Probleme geben, und wie würden die sich äußern?
Link-time-errors oder ein nicht-funktionierendes Programm?
Mit freundlichen Grüßen,
N.G.
N. G. schrieb:
> Johann L. schrieb:
>> Ob das gut mit Symbolreferenzen funktioniert, die sich in anderen
>> Bibliotheken oder der libgcc selbst befinden, weiß ich nicht konkret.
>> Evtl. hilft es dann, ein anderes Symbol zu verwenden, das nicht in der
>> Bibliothek auftaucht
>
> Inwiefern könnte es da Probleme geben, und wie würden die sich äußern?
> Link-time-errors oder ein nicht-funktionierendes Programm?
Okay, scheinbar geht es sowohl mit (war zu erwarten), als auch ohne
--wrap. 1 | $ cat arm-div.c
| 2 | int main() {
| 3 | volatile unsigned int a = 5, b = 2;
| 4 | return a / b;
| 5 | }
|
1 | $ arm-none-eabi-gcc -Wall -Os -mthumb -mcpu=cortex-m0 arm-div.c -nostartfiles -Wl,--defsym,__aeabi_uidiv=0x1234
| 2 | .../ld: warning: cannot find entry symbol _start; defaulting to 0000000000008000
|
(Warning, weil ich kein eigenes ld-skript angegeben habe. Kann hier
ignoriert werden) 1 | $ arm-none-eabi-objdump -d -S a.out
| 2 |
| 3 | a.out: file format elf32-littlearm
| 4 |
| 5 |
| 6 | Disassembly of section .text:
| 7 |
| 8 | 00008000 <main>:
| 9 | 8000: 2305 movs r3, #5
| 10 | 8002: b507 push {r0, r1, r2, lr}
| 11 | 8004: 9300 str r3, [sp, #0]
| 12 | 8006: 3b03 subs r3, #3
| 13 | 8008: 9301 str r3, [sp, #4]
| 14 | 800a: 9800 ldr r0, [sp, #0]
| 15 | 800c: 9901 ldr r1, [sp, #4]
| 16 | 800e: f7f9 f911 bl 1234 <__aeabi_uidiv>
| 17 | 8012: bd0e pop {r1, r2, r3, pc}
|
Funktioniert also.
Die Performance habe ich mangels Hardware noch nicht testen können.
Die Frage nach der Angabe im Linker-Skript bleibt aber noch bestehen ;-)
Mit freundlichen Grüßen,
N.G.
N. G. schrieb:
> Die Frage nach der Angabe im Linker-Skript bleibt aber noch bestehen ;-)
Für die genaue Syntax müsste ich auch erst die Doku konsultieren:
https://sourceware.org/binutils/docs-2.29/ld/Scripts.html
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|