2013-04-03 14 views
9

Wie kann ich gcc anweisen, für arm application processorsidiv (Integer-Division, udiv und sdiv) Anweisungen zu emittieren?GCC emittieren ARM idiv Anweisungen

Bisher kann ich nur -mcpu=cortex-a15 mit gcc 4.7 verwenden.

$cat idiv.c 
int test_idiv(int a, int b) { 
    return a/b; 
} 

auf gcc 4.7 (gebündelt mit Android NDK r8e)

$gcc -O2 -mcpu=cortex-a15 -c idiv.c 
$objdump -S idiv.o 

00000000 <test_idiv>: 
    0: e710f110 sdiv r0, r0, r1 
    4: e12fff1e bx lr 

Auch dies gibt idiv.c:1:0: warning: switch -mcpu=cortex-a15 conflicts with -march=armv7-a switch [enabled by default] wenn Sie -march=armv7-a neben -mcpu=cortex-a15 hinzufügen und emittieren nicht idiv Anweisung.

$gcc -O2 -mcpu=cortex-a15 -march=armv7-a -c idiv.c 

idiv.c:1:0: warning: switch -mcpu=cortex-a15 conflicts with -march=armv7-a switch [enabled by default] 

$objdump -S idiv.o 
00000000 <test_idiv>: 
    0: e92d4008 push {r3, lr} 
    4: ebfffffe bl 0 <__aeabi_idiv> 
    8: e8bd8008 pop {r3, pc} 

auf gcc 4.6 (gebündelt mit Android NDK R8e) es nicht emittieren idiv Anweisungen überhaupt, sondern erkennt -mcpu=cortex-a15 auch -mcpu=cortex-a15 -march=armv7-a Kombination nicht beschweren.

Afaik idiv ist optional auf armv7, so sollte es eine sauberere Art und Weise gcc geben, sie zu emittieren, aber wie?

+0

Sind Sie sicher, dass es eine tatsächliche Anweisung namens 'idiv'? Ich kann nur 'sdiv' (unterschriebene Division) und' udiv' (vorzeichenlose Division) finden ... – unwind

+0

@unwind Ich nehme an, idiv = sdiv | udiv – auselen

+0

Welche CPU ist speziell Ihr Ziel? AFAIK der Cortex-A15 unterstützt sdiv/udiv, aber der Cortex-A5 nicht. Beide sind ARMv7-A-kompatibel. –

Antwort

5

Wenn die Anweisung nicht in den Maschinenbeschreibungen ist, bezweifle ich, dass gcc Code ausgibt. Note1

Sie können immer Inline-Assembler verwenden, um die Anweisung zu erhalten, wenn der Compiler nicht unterstützt wird. Hinweis2 Da Ihre op-code ziemlich selten/maschinenspezifisch ist, gibt es wahrscheinlich nicht so viel Aufwand, um es in der gcc Quelle zu bekommen. Vor allem gibt es Bogen und tune/cpu Flags. Die tune/CPU ist für eine spezifischere Maschine, aber die Bogen soll alle Maschinen in dieser Architektur erlauben. Diese op-code scheint diese Regel zu brechen, wenn ich verstehe.

Für gcc 4.6.2, sieht es aus wie thumb2 und Cortex-R4 Hinweise sind diese Anweisungen zu verwenden und wie Sie mit gcc 4.7.2 erwähnt, ist die Cortex-A15 hinzugefügt zu werden scheint Verwenden Sie diese Anweisungen. Mit gcc 4.7.2 hat die thumb2.md Datei nicht mehr udiv/sdiv. Es könnte jedoch irgendwo anders enthalten sein; Ich bin nicht 100% vertraut mit der Maschinenbeschreibung Sprache. Es scheint auch, dass Cortex-a7, Cortex-A15 und Cortex-r5 diese Anweisungen mit 4.7.2 ermöglichen können. Note3

Dies beantwortet die Frage nicht direkt, aber es gibt einige Informationen/Pfad, um die Antwort zu erhalten. Sie können das Modul mit -mcpu=cortex-r4 kompilieren, obwohl das Linkerprobleme verursachen kann.Außerdem gibt es int my_idiv(int a, int b) __attribute__ ((__target__ ("arch=cortexe-r4")));, in dem Sie für jede Funktion die vom Codegenerator verwendete Maschinenbeschreibung angeben können. Ich habe selbst nichts davon benutzt, aber es sind nur Möglichkeiten, es zu versuchen. Im Allgemeinen möchten Sie nicht die falsche Maschine behalten, da sie suboptimale (und möglicherweise illegale) Op-Codes generieren könnte. Sie müssen experimentieren und dann vielleicht die echte Antwort bereitstellen.

Hinweis 1: Diese ist für ein Lagergcc 4.6.2 und 4.7.2. Ich weiß nicht, ob dein Android-Compiler Patches enthält.

gcc-4.6.2/gcc/config/arm$ grep [ius]div *.md 
arm.md: "...,sdiv,udiv,other" 
cortex-r4.md:;; We guess that division of A/B using sdiv or udiv, on average, 
cortex-r4.md:;; This gives a latency of nine for udiv and ten for sdiv. 
cortex-r4.md:(define_insn_reservation "cortex_r4_udiv" 9 
cortex-r4.md:  (eq_attr "insn" "udiv")) 
cortex-r4.md:(define_insn_reservation "cortex_r4_sdiv" 10 
cortex-r4.md:  (eq_attr "insn" "sdiv")) 
thumb2.md: "sdiv%?\t%0, %1, %2" 
thumb2.md: (set_attr "insn" "sdiv")] 
thumb2.md:(define_insn "udivsi3" 
thumb2.md:  (udiv:SI (match_operand:SI 1 "s_register_operand" "r") 
thumb2.md: "udiv%?\t%0, %1, %2" 
thumb2.md: (set_attr "insn" "udiv")] 
gcc-4.7.2/gcc/config/arm$ grep -i [ius]div *.md 
arm.md: "...,sdiv,udiv,other" 
arm.md: "TARGET_IDIV" 
arm.md: "sdiv%?\t%0, %1, %2" 
arm.md: (set_attr "insn" "sdiv")] 
arm.md:(define_insn "udivsi3" 
arm.md: (udiv:SI (match_operand:SI 1 "s_register_operand" "r") 
arm.md: "TARGET_IDIV" 
arm.md: "udiv%?\t%0, %1, %2" 
arm.md: (set_attr "insn" "udiv")] 
cortex-a15.md:(define_insn_reservation "cortex_a15_udiv" 9 
cortex-a15.md:  (eq_attr "insn" "udiv")) 
cortex-a15.md:(define_insn_reservation "cortex_a15_sdiv" 10 
cortex-a15.md:  (eq_attr "insn" "sdiv")) 
cortex-r4.md:;; We guess that division of A/B using sdiv or udiv, on average, 
cortex-r4.md:;; This gives a latency of nine for udiv and ten for sdiv. 
cortex-r4.md:(define_insn_reservation "cortex_r4_udiv" 9 
cortex-r4.md:  (eq_attr "insn" "udiv")) 
cortex-r4.md:(define_insn_reservation "cortex_r4_sdiv" 10 
cortex-r4.md:  (eq_attr "insn" "sdiv")) 

Hinweis 2: Siehe pre-processor as Assembler wenn gcc wird Optionen gas vorbei, die Verwendung der udiv/sdiv Anweisungen verhindern. Zum Beispiel können Sie asm(" .long <opcode>\n"); verwenden, wobei Opcode ist einige Token eingefügt Stringed Register-Encode-Makro-Ausgabe. Außerdem können Sie Ihren Assembler mit Anmerkungen versehen, um Änderungen in machine anzugeben. So können Sie vorübergehend liegen und sagen, Sie haben ein Cortex-R4 usw.

Note3:

gcc-4.7.2/gcc/config/arm$ grep -E 'TARGET_IDIV|arm_arch_arm_hwdiv|FL_ARM_DIV' * 
arm.c:#define FL_ARM_DIV (1 << 23)   /* Hardware divide (ARM mode). */ 
arm.c:int arm_arch_arm_hwdiv; 
arm.c: arm_arch_arm_hwdiv = (insn_flags & FL_ARM_DIV) != 0; 
arm-cores.def:ARM_CORE("cortex-a7", cortexa7, 7A, ... FL_ARM_DIV 
arm-cores.def:ARM_CORE("cortex-a15", cortexa15, 7A, ... FL_ARM_DIV 
arm-cores.def:ARM_CORE("cortex-r5", cortexr5, 7R, ... FL_ARM_DIV 
arm.h: if (TARGET_IDIV)        \ 
arm.h:#define TARGET_IDIV    ((TARGET_ARM && arm_arch_arm_hwdiv) \ 
arm.h:extern int arm_arch_arm_hwdiv; 
arm.md: "TARGET_IDIV" 
arm.md: "TARGET_IDIV" 
+0

(+1) Danke, dass Sie etwas Mut für Maschinendefinitionen haben, ich denke, dass ich einen neuen Maschinentyp wie * armv7-ad * von armv7-a kopieren kann. Ich denke nicht, dass Sie Inline-Assembler verwenden können, der Compiler wird immer noch über Mismatch-Anweisungen weinen. Über mach, mcpu, mtune ... Also ganzzahlig div ist optional, es ist optional mach ... dann würde ich erwarten, entweder eine Mach-Variante oder einige zusätzliche Flagge wie FPU. Ich erwarte, dass mcpu/mtune dem Optimierer Informationen zur Befehlsplanung gibt - deshalb zögere ich, cortex-a15 zu verwenden. – auselen

+0

@auselen Haben Sie '-mcpu = cortex-a7' versucht? Oder ist das nicht für Ihre Maschine? Es sieht so aus, als gäbe es die gleichen * FL_ARM_DIV * -Berechtigungen wie die '-mcpu = cortex-a15'. –

+1

Nein. Nehmen wir an, ich verwende einen Cortex-a9 mit idiv Unterstützung. Vielleicht kann ich "-mcpu = cortex-a15-mtune = cortex-a9" verwenden, ich werde das später testen. – auselen

Verwandte Themen