Assembler cracks anwesend?

Ich habe mal eine kleine Aufgabe fuer diejenigen die noch Bits persoenlich atmen. :)

Ich habe hier auf meinem SH7262, also SH2A die libmad installiert um damit mp3s abzuspielen. Mittlerweile funktioniert das auch ganz gut, koennte aber noch etwas schneller sein. Dafuer kennt die Libarie fuer verschiedene Prozessoren spezielle Assembleroptimierungen, aber leider nicht fuer meinen sh2a.

Defaultmaessig macht die Libary soetwas:

#define mad_f_mul(x, y) (((x) >> 12) * ((y) >> 16))

Das funktioniert, ist langsam und hat einen gewissen Verlust an Genauigkeit zur Folge. Alle Variablen sind 32Bit signed longs.

Besser waer natuerlich soetwas: (x*y)>>28. Das ist aber natuerlich wegen den notwendigen Registerbreiten auf den meisten Prozessoren inakzeptabel. Ein ARM oder auch mein SH2A sollten das aber koennen.

Jetzt mal zu meinen Loesungsansaetzen:

#define mad_f_mul(x, y) ({ signed long __dummy; signed long __result;\ asm ( \ "dmuls.l %2, %3\n\t" \ "sts mach, %1\n\t" \ "sts macl, %0\n\t" \ \ "shlr16 %0\n\t" 28Bit logisch nach rechts \ "shlr8 %0\n\t" \ "shlr2 %0\n\t" \ "shlr2 %0\n\t" \ \ "shll2 %1\n\t" \ "shll2 %1\n\t" \ \ "add %0,%1\n\t" \ \ : "=&r" (__dummy), "=r" (__result) \ : "%r" (x), "r" (y) \ : "cc" \ ); \ __result; \ })

Obiger Code funktioniert. Allerdings ueberrascht es mich das er funktioniert. Und zwar wegen den shlr Befehlen. Da die Libmad mit signed longs arbeitet sollten das IMHO shar, also arithmetisches Shift sein. Das kann die CPU aber leider nur Bitweise und nicht fuer mehrere Bits in einem einzigen Befehl. BTW: Jeder der obigen Befehle benotigt

1Takt, nur die 32x32=64Bit Multiplikation benoetigt 2Takte.

Mein naechstes Versuch sah so aus:

#define mad_f_mul(x, y) ({ signed long __dummy; signed long __result;\ asm ( \ "dmuls.l %2, %3\n\t" 32x32=64Bit \ "sts macl, %0\n\t" Low32Bit \ "sts mach, %1\n\t" High32Bit \ \ "shad %4,%0\n\t" 28Bit arith nach rechts\ \ "shll2 %1\n\t" 2Bit nach links \ "shll2 %1\n\t" nochmal \ "add %0,%1\n\t" alles zusammenbastln\ \ : "=&r" (__dummy), "=r" (__result) \ : "%r" (x), "r" (y), "r" (0xffffffe4L) \ : "cc" \ ); \ __result; \ })

Hier benutze ich den Barrelshifter in dem Microcontroller. Er kann damit in einem Takt 28Bits arithmetisch nach rechts shiften. Allerdings wird das reinladen der Konstante (0xffffffe4L =

-28) einen Extratakt kosten. Problem ist nur das dieser Code nicht funktioniert. Genauer gesagt verwurstet er mir jedes MP3 zu weissem Rauschen. Und ich verstehe leider nicht warum. Wenn ich die Funktion mit ein paar Testdaten aufrufe und mit meinem Taschenrechner gegenrechne sieht alles gut aus!

Das shiften um genau 28Bits ist notwendig weil die gesamte Libarie darauf aufbaut. Hat vielleicht jemand eine bessere Idee wie man soetwas loesen kann? Tricks welchen den Divisionsbefehl verwenden sind leider nichts zielfuehrend weil der lahme 34Takte braucht.

Das Problem ist das mir die Multiplikation ihr 64Bit Ergebniss in zwei getrennten Registern liefert. Ich benoetige davon zwar nur 32Bit aber muss die Bits muehsam zusammenbasteln.

Jeder einzelne Takt der eingespart werden kann ist wichtig. Diese Funktion wird bei der MP3 Decodierung wirklich reichlich verwendet und ich kann sofort sehen wie die Ausfuehrungszeiten nach oben gehen wenn diese Funktion laenger wird. Allerdings koennte eine Loesung die

1-2Befehle laenger ist eventuelle akzeptabel sein wenn ich die Befehle geschickt verschachteln kann weil der Controller ja zwei Befehle gleichzeitig ausfuehren kann, auch wenn ich noch nicht begriffen habe nach welchen Kriterien das ablaeuft.

Olaf

Reply to
Olaf Kaluza
Loading thread data ...

Olaf Kaluza schrieb:

Prüfe mal mit einem Disassembler, was er tatsächlich assembliert. Evtl. ist einfach der Zugriff auf %4 problematisch.

Mit freundlichem Gruß

Jan

Reply to
Jan Kandziora

Ich kenne die libmad Library nicht, aber dein Prozessor hat doch Floating Point Operationen, warum also Fixpoint verwenden? Laut dem Software Manual sind die meist auch 1 Takt schnell, wenn die von Registern arbeiten. Das sollte dann einiges bringen. Und ich vermute mal, daß man auch sehr gut die multiply-add Befehle brauchen kann, wenn man es denn in Assembler programmieren will, falls der C-Compiler die nicht automatisch verwendet.

Übrigens: für Ogg Vorbis brauchst du keine Lizenzkosten zu zahlen, wie du es für MP3 musst, wenn mal ein Produkt aus deinem Teil werden sollte. Ein weiterer Vorteil von Ogg Vorbis ist, daß man damit z.B. 5.1 Surround Musik speichern kann, was mit MP3 nicht möglich ist.
--
Frank Buss, http://www.frank-buss.de
piano and more: http://www.youtube.com/user/frankbuss
Reply to
Frank Buss

Du solltets dir aber auch einmal erst klarmachen, in welchem Format deine Daten sind! D. h. werden wirklich alle 32 bit verwendet?

Warum das (bei deiner Anwendung?) funktioniert: Ich kenne zwar die SH2A Assemblerbefehle nicht, dafür aber die vom 68000 sehr gut (ist auch ein 32-bitter). Mache dir aber bitte den Unterschied zwischen logischen und arithmetischen shifts einmal klar. Die shlr16, 8, 2, 2 schieben die 4 höchstwertigen bits vom low-teil des Ergebnisses ganz nach rechts und setzen die oberen bits auf null. Da der low-teil des Ergebnisses kein Vorzeichen enthält ist natürlich dafür ein logische shift notwendig. Die beiden shll2 schieben das high Ergebnis um 4 bits nach links und setzen die 4 niedrigsten bits auf 0 damit das nachfolgende add richtig funktioniert. Das ganze funktioniert aber nur richtig, solange der Absolutwert deiner Eingangsdaten nicht zu gross werden und die (Vorzeiche-)bits die du mit den shll2 rausschiebst immer gleich sind. Also das funktioniert nur wenn die obersten 5 bits des Ergebnisses alle 0 oder 1 sind.

Sollte aus obigem klar sein warum das nicht geht: mit dem shad ... hast du entweder lauter 0 oder lauter 1 in den höherwertigen bits, du brauchst aber 0 für das darauffolgende add.

Also erst einmal nachforschen welchen Wertebereich deine Eingangsdaten wirklich haben, dann ans optimieren gehen. Man könnte nämlich die Eingangsdaten auch vor der Multiplikation jeweils um 2 bit nach links verschieben und vom Ergebnis der Multiplikation nur den high-Wert verwenden (der hat dann das richtige Format).

Zum optimieren in Assembler: Ich glaube nicht, dass es sehr viel Sinn macht eine einzelne Routine optimieren zu wollen (das kann der Compiler normalerweise schon ganz gut). Ich habe bei meinen Problemen einen grösseren Programmteil inklusive der meist benutzten Schleifen optimiert. Besonders geholfen hat mir dabei, wenn ich die internen Register der CPU ausgiebig genutzt habe und den Zugriff auf den Speicher minimiert habe.

--
Freundliche Grüsse -- Regards
F. Seuhs
Reply to
Friedrich Seuhs

"Olaf Kaluza" schrieb im Newsbeitrag news: snipped-for-privacy@criseis.ruhr.de...

Vergiss Assembler. Der SH2A C-Compiler kennt long long

#define mad_f_mul(x, y) ((long)(((long long)(x)*(long long)(y) >> 28 ))

und lass den Compiler die besten Instruktionen raussuchen

--
Manfred Winterhoff, reply-to invalid, use mawin at gmx dot net
homepage: http://freenet-homepage.de/mawin/
de.sci.electronics FAQ: http://dse-faq.elektronik-kompendium.de/
Read 'Art of Electronics' Horowitz/Hill before you ask.
Lese 'Hohe Schule der Elektronik 1+2' bevor du fragst.
Reply to
MaWin

[...]

So wie ich MP3-Decoder kenne, werfen die die oberen 32 Bit weg, in denen ein arithmetischer Shift die 28 Vorzeichenbits produzieren würde. Damit ist egal, wie die belegt sind.

Wenn ich das richtig sehe (ich spreche kein ARM) schiebst du den Low-Teil arithmetisch. Der Low-Teil wird immer logisch geschoben.

Zur Illustration: du hast hhhhhhhhhhhhhhhh llllllllllllllll Du willst hhhhhhhhhhhhhhll Also schiebst du den einen nach links hhhhhhhhhhhhhh00 und den anderen nach rechts 00000000000000ll und addierst das. Schiebst du hier arithmetisch, bekommst du statt der Nullen ggf. Einsen, und das ist falsch.

Probier's auf jeden Fall mal in C. Falls der Compiler das nicht packt, wäre auf jeden Fall sinnvoll, nur den dmuls.l/sts/sts-Teil in den asm-Block zu packen und das Geshifte dem Compiler zu überlassen. Wenn er mixed-Operationen nicht packt, shiften und addieren kann er typischer- weise.

Stefan

Reply to
Stefan Reuther

Weil ich nicht alles neu schreiben wollte. Natuerlich waer das so viel besser, aber libmad installieren ist halt viel einfacher. :-)

Ich bin mir ziemlich sicher das man es locker zehnmal so schnell hinbekommt wenn man alles neu schreibt und alles ausnutzt was der Prozessor so kann. Aber ich wollte in diesem Leben nochmal was anderes machen....

Ich hab nicht vor etwas zu verkaufen und MP3 ist nunmal bereits Standard. Das ganze ist ja mehr ein Spassproject (Autoradio) das ich fast alleine nur mit einer anderen Person durchziehe.

Mir schwebt allerdings noch ein Kopfhoererverstaerker mit Roehren vor der auch den SH7262 enthaelt und so gleich einen SD-Slot und SPDIF in/out hat. Aber das wird wohl noch bis naechstes Jahr Weihnachten dauern.

Mir reicht 2.0. Die Vorstellung das ich sechs T&A TML160 im Wohnzimmer stehen haette finde ich etwas bizarr und es wuerde nur wenig Platz fuer Musikhoerer uebrig bleiben. Ich habe auch noch nichts von dem 5.1 Abfall gehoert was mich musikalisch ueberzeugen konnte. Ausserdem sind auch meine Nachbarn der Meinung das nur zwei solche Boxen fuer mich ausreichend sind. :-D

Olaf

Reply to
Olaf Kaluza

Das klarzumachen ist nicht so ganz einfach wenn man nicht vor hat vertieft in die MP3 Dekodierung einzusteigen. Wenn ich sage das die Standardausfuehrung nicht so genau ist dann habe ich da den Autor der Libary aus seinen Kommentaren zitiert.

Ich dachte das waer mir klar...hm...

Aber es koennte doch ein Vorzeichen haben und dann waere doch arithmetisches shiften richtig damit dieses Vorzeichen erhalten bleibt? Ich habe aber schon ueberlegt, aber nicht geprueft, ob es vielleicht so ist das garkeine negativen Zahlen vorkommen und es deshalb funktioniert.

Hm..das klingt wie soll ich es sagen....aeh...richtig! Da koennte ich was uebersehen haben....

Das geht nicht. Das habe ich so ziemlich als erstes probiert da dies ja nahe liegt. Es ist aber wohl so das die Werte alle stark nach oben skaliert sind.

Das scheint in dem Fall nicht so zu sein. Wenn du Interesse hast dann schau dir mal die Datei fixed.h in libmad-0.15.1b an. Da wird gerade diese Multiplikation fuer jeden Prozessor mit viel Liebe und Hingabe optimiert. Ausserdem ist diese Datei ein echt abschreckendes Beispiel fuer C-Hasser weil es da vor defines nur so wimmelt. :) Ich selbst werfe mir hier beim abspielen eines MP3 Statusinformationen auf ein VT100 Terminal womit ich meinen Bufferfuellstand und die Ausfuehrungszeit der Dekodierroutine sehen kann. Da faellt mir sofort auf wenn die Multiplikation 1-2Takte mehr braucht.

Olaf

Reply to
Olaf Kaluza

Hehe..ich glaub das probier ich gleich mal. Aber irgendwie denke ich werden da interessante Unterschiede zwischen gcc und Renesas Compiler bei rumkommen. Ich werde berichten...

Olaf

Reply to
Olaf Kaluza

Nein. Denke weniger an signed unsigned mathematik und ersetze den letzten Befehl durch ein bitweises or statt dem add (wo die beiden Teilbitfolgen zusammengefasst werden), vielleicht verstehst du es dann besser. Funktional ist diser add Befehl nämlich kein addieren von 2 32-bit Teilergebnissen, sondern ein Zusammensetzen der niederwertigen 4 bits die aus der 28-bit shiftoperation herkommen mit den 28 bits des höherwertigen Teils. Das add funktioniert in diesem Fall nur richtig weil immer in einem rigister 28 bits 0 und im anderen 4 bits 0 sind.

Wenn das wirklich so ist, dann müsste aber die neue Routine mit den 2 shll2 am ende versagen, da dadurch die obersten 4 signifikanten bits weggeworfen werden. Nur bei werten die nur VZ + 27 signifikante bits haben geht das OK. Mit probieren ist das so eine Sache, darum meinte ich auch ja du solltest genau wissen wie deine Daten skaliert sind.

Bin nicht gerade der Linux Spezilist und zum suchen zu faul. :-)

--
Freundliche Grüsse -- Regards
F. Seuhs
Reply to
Friedrich Seuhs

Aber erst nach der Multiplikation. Dein Vorschlag will aber vorher bereits shiften und verliert dann Aufloesung bei den 32Bit werten. Ich schnibble aber am 64Bit Wert nach der Multipliaktion rum damit der Wert wieder in 32Bit reinpasst.

Ich wuerde es ja hier posten, aber das uebersteigt definitiv die Grenzen des guten Usenetgeschmacks.

Vielleicht klappt das ja hier:

formatting link

Oder bei google codesearch nach "fixed.h lang:c" suchen.

BTW: Weiss einer warum der Autor bei den ganzen Praprozessoranweisungen zwischen dem '#' und dem Kommando immer Leerstellen laesst? Dient das der Optimierung der Unleserlichkeit? (hebelt die farblichen hervorhebungen in Emacs aus)

Ich habe gerade ein bisschen die Compiler verglichen und schreibe da gleich noch was zu..... Olaf

Reply to
Olaf Kaluza

Hallo Leute,

Ich habe mal ein paar Messungen gemacht. Einmal mit der Originalloesung aus der Libary, dann mit longlong Loesung von Mawin, und mit meinem Ansatz. Letzteres leider nur mit dem gcc weil ich erst noch rausfinden muss wie ich beim Compiler von Renesas Assembler verwenden kann und dem Variablen uebergebe. Ich benutze halt Assembler nur noch sehr selten.

Auserdem gibt es am Ende einen Compilervergleich zwischen gcc und Renesas.

Noch was zu meinem Programm. Ich habe eine Fifo welche Zeiger verwaltet die jeweils einen Audio-Frame enthalten. Ein im Hintergrund laufender DMA holt alle 26ms einen Zeiger aus der Fifo und spielt den ab. Im Hauptprogramm muss ich also im Mittel alle 26ms oder schneller einen neuen Sampleblock bereitstellen. Bei den gemessenen Zeiten handelt es sich um die Zeit die notwendig ist die MP3-Daten von einer SD-Karte zu lesen und zu dekodieren. Also ein ganzer Rundlauf bis ein neuer Block in die Fifo geworfen wird. Diese Zeiten unterliegen Schwankungen. Zum einen braucht der MP3-Decoder unterschiedlich lange, zum anderen geht auch schonmal etwas mehr Zeit fuer die Datenverwaltung der SD-Karte verloren. Daher gebe ich immer maximal und Minimalwerte an. Einmalige grobe Ausreiser habe ich ignoriert.

| gcc | Renesas | Datenrate/MP3 +------------+-------------+---------------- libmad | 27-36ms | 20-27ms | 192kbit | 26-29ms | 18-26ms | 128kbit

-------+------------+-------------+---------------- Mawin | 30-37ms | 39-75ms | 192kbit | 28-30ms | 30-60ms | 128kbit

-------+------------+-------------+---------------- Olaf | 24-30ms | | 192kbit | 20-28ms | | 128kbit

Wie man sieht ist der Ansatz von Mawin glatt durchgefallen. Ich finde es aber interessant das der so erhebliche Schwankungen aufweisst. Allerdings nur beim Compiler von Renesas.

Die Standardloesung der libmad reicht beim Compiler von Renesas fuer

128kbit und 192kbit aus. Ich glaube auch 256kbit hab ich schon erfolgreich getestet.

Meine Loesung reicht unter dem gcc fuer 128kbit aus, ist aber fuer

192kbit gerade so eben zu langsam. So alle 15-20s laeuft mein Buffer leer und mein MP3 hat einen Sprung in der Rille beim abspielen. Der Test meiner Loesung unter dem Compiler von Renesas steht leider noch aus. Aber ich denke man sieht ganz deutlich wieviel die Optimierung gerade dieser einen Funktion so bringt.

Jetzt zum Compilervergleich. Ich habe dabei mit beiden Compilern dasselbe Codestueck uebersetzt:

#define mad_f_multest(x, y) (((x) >> 12) * ((y) >> 16))

volatile signed long a,b,c;

a=555555; b=666666;

c=mad_f_multest(a,b);

a=0; b=0; c=0;

Ich setze die Variablen am Ende wieder auf null weil der Compiler von Renesas sonst den erzeugten Code stark mit meinem normalen Programm verschachtelt. Es ist dann kaum zu verstehen was er so treibt.

a=555555; ; = 0x87a23

1C001524 0101087A MOVI20S #H'0087A00,R1 ;Das ist 23h zu wenig!

b=666666;

1C00152A 04010A2C MOVI20S #H'00A2C00,R4 ; 2ah zuwenig!

c=mad_f_multest(a,b);

1C001528 E5F4 MOV #H'F4,R5 ;F4 = -12 fuer Bitshifter 1C00152A 04010A2C MOVI20S #H'00A2C00,R4 ;Nochmal dasselbe?

a=0;

1C00152E E600 MOV #H'00,R6 ;Fuer spaeter

1C001530 7123 ADD #H'23,R1 ;jetzt ist R1=a=555555

1C001532 0EF1E800 MOVI20S #H'FE80000,R14 1C001536 742A ADD #H'2A,R4 ;jetzt ist R4=b=666666

1C001538 2F12 MOV.L R1,@R15 ;Was das hier soll???

1C00153A 1F41 MOV.L R4,@(H'04:4,R15) 1C00153C 7EFF ADD #H'FF,R14 1C00153E 64F2 MOV.L @R15,R4 1C001540 51F1 MOV.L @(H'04:4,R15),R1 ;y holen?

1C001542 445C SHAD R5,R4 ; x>>12

1C001544 4129 SHLR16 R1 ; y>>16 1C001546 601F EXTS.W R1,R0 1C001548 4480 MULR R0,R4 ; *

b=0;

1C001552 1F61 MOV.L R6,@(H'04:4,R15) ;R6 in b kopieren c=0;

Folgendes ist interessant:

  1. Der Compiler teilt Zuweisungen auf. Er benutzt einmal 20Bit Move-Befehle und die fehlenden Bits addiert er spaeter hinzu. Vermutlich machts das Sinn weil der Controller ja zwei Befehle gleichzeitig ausfuehren kann.

  1. Er weisst dem Shift-counter des Barrelshifter nur einen 8Bit wert zu. In der Doku von Renesas steht zwar das nur die unteren 5Bit genutzt werden, in ihren Beispielen wurden aber immer 32Bit gesetzt. Das werde ich bei mir noch aendern. Ich dachte 32Bit waeren notwendig weil die Zahl im 2er Komplement gebraucht wird.

  2. Der Debugger von Renesas zeigt den Befehl an der Adresse 1C00152A zweimal an. Vermutlich weil er an dieser Stelle noch parallel laeuft.

  1. Es gibt einen Codeblock ab Adresse 1C001538 der mir nicht so ganz klar ist. Vielleicht gehoert das schon zu anderen Programmteilen und der Compiler hat das nur vorgezogen.

  2. Der eigentliche Shift und Multiplikationsvorgang ist ziemlich genauso wie ich das von Hand auch gemacht haette. Es gibt lediglich den neuen Befehl EXTS.W. Den kenn ich noch nicht. Muss ich noch nachschlagen. Aber ich glaube irgendwie der ist fuer meine Vorzeichenbits wichtig. :)

Und jetzt dasselbe wie es vom gcc erzeugt wird:

102:pcmtest.c **** volatile signed long a,b,c; 103:pcmtest.c **** 104:pcmtest.c **** a=555555; 35 .loc 1 105 0 36 0008 D20C mov.l .L2,r2 37 000a 61E3 mov r14,r1 38 000c 71CC add #-52,r1 39 000e 112F mov.l r2,@(60,r1) 40 .LVL0: 105:pcmtest.c **** b=666666; 41 .loc 1 106 0 42 0010 D20B mov.l .L3,r2 106:pcmtest.c **** 107:pcmtest.c **** c=mad_f_multest(a,b); 43 .loc 1 108 0 44 0012 D30C mov.l .L4,r3 106:pcmtest.c **** 45 .loc 1 106 0 46 0014 112E mov.l r2,@(56,r1) 47 .LVL1: 48 .loc 1 108 0 49 0016 541F mov.l @(60,r1),r4 50 0018 430B jsr @r3 51 001a 0009 nop 52 001c 521E mov.l @(56,r1),r2 53 001e 6229 swap.w r2,r2 54 0020 622F exts.w r2,r2 55 0022 0247 mul.l r4,r2 56 0024 021A sts macl,r2 57 0026 112D mov.l r2,@(52,r1) 58 .LVL2: 108:pcmtest.c **** 109:pcmtest.c **** 110:pcmtest.c **** a=0; 59 .loc 1 111 0 60 0028 E200 mov #0,r2 61 002a 112F mov.l r2,@(60,r1) 111:pcmtest.c **** b=0; 62 .loc 1 112 0 63 002c 112E mov.l r2,@(56,r1) 112:pcmtest.c **** c=0; 64 .loc 1 113 0 65 002e 112D mov.l r2,@(52,r1)

  1. Der Code ist besser lesbar weil geordneter. Aber das wird natuerlich auf die Geschwindigkeit gehen.

  2. Es wird irgendein Unterprogramm aufgerufen. (Zeile50) Keine Ahnung warum, aber allein das er das tut ist ja schon die Hoelle.

  1. Es wird ein anderer Multiplikationsbefehl genutzt der das Ergebniss umstaendlich im MAC Register liefert.

  2. Vom Barrelshifter oder dem SHLR16 Befehl hat der gcc wohl noch nichts gehoert.

  1. Auch der gcc benutzt exts.w. Muss wohl wichtig sein. :-)

Insgesamt erklaert das schon ganz gut warum der Code des GCCs so lahm ist oder?

Olaf

Reply to
Olaf Kaluza

Olaf Kaluza schrieb:

Ganz nett, aber für einen aussagekräftigen Benchmark fehlen u.a. die gesetzten Compileroptionen sowie die Versionsnummern der Compiler.

Christian

--
Christian Zietz  -  CHZ-Soft  -  czietz (at) gmx.net
WWW: http://www.chzsoft.de/
PGP/GnuPG-Key-ID: 0x6DA025CA
Reply to
Christian Zietz

Gcc: CFLAGS = -O2 -m2a -Wfloat-equal -Wunused-variable -g

-Wa,-alhcn=$@.asm,-L LDFLAGS = -nostartfiles -s -o start.elf start.o -Wl,-Map=mapfile.txt -T sh2a.ld -l mad -L ./

[olaf] /home/olaf/sources/SH2A/pcm3060: sh2a-gcc --version sh2a-gcc (GCC) 4.5.1

Renesas: TOOLCHAIN VERSION : 9.3.2.0 Optimize for Speed

Das ist die aktuelle Version die ich gerade hier laufen habe:

/* 9Takte (x*y)>>28 */ #define mad_f_mul(x, y) ({ signed long __dummy; signed long __result;\ asm ( \ "dmuls.l %2, %3\n\t" /* 64Bit mult */ \ "mov #228,%1\n\t" /* 28bit shift */ \ "sts macl, %0\n\t" /* low 32bit */ \ \ "shad %1,%0\n\t" /* shiften */ \ "sts mach, %1\n\t" /* high 32bit */ \ \ "shll2 %1\n\t" /* 4bit shift */ \ "shll2 %1\n\t" \ "add %0,%1\n\t" /* 32bit basteln*/ \ \ : "=&r" (__dummy), "=r" (__result) \ : "%r" (x), "r" (y) \ : "cc" \ ); \ __result; \ })

Braucht maximal 9Takte, vielleicht sogar 1-2weniger wenn der Controller was parallel ausfuehrt. Leider reicht es beim gcc immer noch nicht fuer 192kbit. Ich denke aber da muss ich wohl an anderer Stelle optimieren. Dafuer glaube ich mir einzubilden das es besser klingt. Irgendwie kommen s-Laute sauberer rueber. Liegt vielleicht an der hoeheren Rechengenauigkeit.

Olaf

Reply to
Olaf Kaluza

Klingt ziemlich nach sign extension.

Gru=C3=9F, Enrik

Reply to
Enrik Berkhan

Du machst einen multi-precision-shift. Dabei wird grundsätzlich nur beim obersten ("linken") Wort das Vorzeichen beachtet. Alle anderen Worte werden vorzeichenlos geschoben.

Eselsbrücke: wenn du eine Dezimalzahl wie diese -224466 "shiftest" (z.B. multiplizierst oder dividierst), berücksichtigst du das Vorzeichen auch nur, wenn du links außen angekommen bist.

Stefan

Reply to
Stefan Reuther

IIRC *muss* das "#" streng nach Standard in der ersten Spalte stehen, Einrücken geht also nur dahinter (ja, die meisten Präprozessoren akzeptieren das auch anders).

Warum er auf der obersten Ebene allerdings bereits mit einem Space einrückt, erschliesst sich mir nicht.

cu Michael

Reply to
Michael Schwingen

Hast Du das mal ohne volatile probiert, und die Multiplikation wirklich in eine eigene Funktion verschoben?

ich überblicke den Assemblercode jetzt nicht 100%, aber volatile verhindert u.U. einige Optimierungen.

cu Michael

Reply to
Michael Schwingen

Nein, weil ohne volatile alles wegoptimiert wird und in einer eigenen Funktion macht das ganze wenig Sinn weil allein der Aufruf schon laenger dauern wird. Okay, zu testzwecken koennte man es probieren, hab ich aber nicht dran gedacht.

Ich werde meine Optimierungsbemuehungen erst mal auf andere Stellen konzentrieren weil ich nicht glaube das man unter 9Takte kommen kann. Es gibt in dem Programm derzeit noch eine unnoetige

24->16bit downscalierung fuer die PCM-Daten welche 2ms kostet.

Das glaube ich hier nicht weil der Compiler ja in der Wahl seiner Register nicht beschraenkt wird. Nebenbei gesagt das C/ASM Interface des GCCs ist um einiges flexibler als das von Renesas. Ausserdem ist das ganze drumherum, also das ablegen der Testdaten fuer den Vergleich sowieso irrelevant.

Olaf

Reply to
Olaf Kaluza

Das dient im Normalfall der Übersicht, genauso wie man normale "if" auch einrückt. Zumindest mein Emacs färbt das auch weiter korrekt ein, andere Editoren jedoch in der Tat nicht (die halt nur nach "#include" suchen und nicht nach "#include").

Das "#" darf eingerückt sein, es darf sogar ein Kommentar davorstehen (ISO 9989:1999 §6.10(2)). Typischerweise setzt man das "#" aber eben doch in die erste Spalte, eben damit die Editoren es korrekt einfärben...

Stefan

Reply to
Stefan Reuther

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.