Forum: Compiler & IDEs undefined combination of operands


von Benedikt K. (benedikt)


Lesenswert?

Ich erhalte beim Compilieren eines größeren Programms folgede Warnung:

-------- begin --------
avr-gcc (GCC) 4.1.1 (WinAVR 20070122)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is 
NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR 
PURPOSE.


Compiling: main.c
avr-gcc -c -mmcu=atmega8515 -I. -g -O2 -funsigned-char 
-funsigned-bitfields -fpack-struct -fshort-enums -Wall 
-Wstrict-prototypes -Wa,-adhlns=main.lst  -std=gnu99 main.c -o main.o
C:\DOKUME~1\ich\LOKALE~1\Temp/ccy6aaaa.s: Assembler messages:
C:\DOKUME~1\ich\LOKALE~1\Temp/ccy6aaaa.s:231: Warning: undefined 
combination of operands
C:\DOKUME~1\ich\LOKALE~1\Temp/ccy6aaaa.s:232: Warning: undefined 
combination of operands

Was bedeuted das, und wie bekomme ich das weg ? Die Datei wird 
anscheinend nach dem Compilieren sofort wieder gelöscht, daher kann ich 
nicht nachschauen was an Zeile 231 und 232 steht.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Benedikt K. wrote:

> Compiling: main.c
> avr-gcc -c -mmcu=atmega8515 -I. -g -O2 -funsigned-char
> -funsigned-bitfields -fpack-struct -fshort-enums -Wall
> -Wstrict-prototypes -Wa,-adhlns=main.lst  -std=gnu99 main.c -o main.o
> C:\DOKUME~1\ich\LOKALE~1\Temp/ccy6aaaa.s: Assembler messages:
> C:\DOKUME~1\ich\LOKALE~1\Temp/ccy6aaaa.s:231: Warning: undefined
> combination of operands
> C:\DOKUME~1\ich\LOKALE~1\Temp/ccy6aaaa.s:232: Warning: undefined
> combination of operands

> Was bedeuted das,

Dass dem Assembler die Operanden in einem Befehl oder Ausdruck nicht
passen.

Sollte bei Compiler-generiertem Code nicht passieren, kann aber
natürlich gut und gern bei inline asm passieren.

> und wie bekomme ich das weg?

Indem du den Fehler beseitigst. ;-)

> Die Datei wird anscheinend nach dem Compilieren sofort wieder
> gelöscht, daher kann ich nicht nachschauen was an Zeile 231 und 232
> steht.

Ja, das ist eine temporäre Datei.  Du kannst mit
1
avr-gcc -S -mmcu=atmega8515 -I. -g -O2 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes  -std=gnu99 main.c

den Compiler dazu bringen, den Code lediglich in die Datei main.s zu
compilieren und danach seine Tätigkeit zu beenden.  (Sonst würde er an
dieser Stelle den Assembler rufen.)  Diese Datei sollte bis auf den
Namen äquivalent zu der genannten Datei sein, sodass du darin an Hand
der Zeilennummer den Fehler suchen kannst.

Falls dein Makefile eine Regel dafür hat, genügt auch »make main.s«.

von Benedikt K. (benedikt)


Lesenswert?

Jörg Wunsch wrote:
> Sollte bei Compiler-generiertem Code nicht passieren, kann aber
> natürlich gut und gern bei inline asm passieren.

Es gibt nur kein inline asm, deshalb ja auch die ganze Frage...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Es gibt nur kein inline asm, ...

Muss dir nicht immer gleich bewusst sein.  Die avr-libc erledigt auch
einiges mit inline asm.

von Peter D. (peda)


Lesenswert?

Von AVR-GCC 3.4.6 zu 4.1.1 wurden sehr viele Änderungen vorgenommen, die 
wohl ne Menge Seiteneffekte haben.
Insbesondere bei der Optimierung gibts einige Überraschungen 
(Reordering, manchmal größerer Code).

In ner Beta des 4.1.1 hatte bei mir sogar ne harmlose switch Anweisung 
Assembler-Warnungen erzeugt.

Der 4.1.1 muß quasi erst noch reifen, während der 3.4.6 bei mir 
keinerlei Probleme machte.


Mit dem Schalter -save-temps kannst Du Dir die temporären Dateien 
ansehen.


Peter

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter Dannegger wrote:

> Von AVR-GCC 3.4.6 zu 4.1.1 wurden sehr viele Änderungen vorgenommen,
> die wohl ne Menge Seiteneffekte haben.

Du weißt es ja so genau: welche denn?

> Insbesondere bei der Optimierung gibts einige Überraschungen
> (Reordering, manchmal größerer Code).

Ja, die Optimierung ist komplett neu gefasst worden.  Einige deiner
früheren Lieblingsbeschwerden scheinen sich in Luft aufgelöst zu
haben.  Es wird sehr viel mehr 8-bit-Code erzeugt, wo GCC 3.x noch
16-bit-Code erzeugt hat.  Darüber magst du aber offenbar nicht mehr
sprechen, man kann so wenig jammern drüber.  Sorry, langsam geht mir
deine Polemik aber auf den Senkel.  Die hast du nicht nötig.

> In ner Beta des 4.1.1 hatte bei mir sogar ne harmlose switch
> Anweisung Assembler-Warnungen erzeugt.

Das war ein Problem des (nach wie vor inoffiziellen) ATmega256x-
Patches, bei dem wir uns mit dem Autor des Patches mittlerweile einig
geworden sind, dass die Warnung einerseits sowieso unzureichend war
(da sie nicht alle möglichen Fälle abdecken konnte, in denen sie
gerechtfertigt gewesen wäre) und andererseits zu Verwirrung geführt
hat an Stellen, wo dies nicht notwendig war.

Das heißt nicht, dass Björn sich nicht was dabei gedacht hätte, als er
damals diese Warnung in den Assembler gebaut hat: die Sprungtabellen
zwischen den beiden 128-KiB-Blöcken sind nicht ganz ohne.  Wenn deine
jump table aus dem switch aus Versehen doch eine 128-KiB-Grenze
schneidet, dann kracht's.  Dafür gibt es auch keine Abhilfe, es sei
denn, du würdest den Übergang von 16-bit- auf 32-bit-Zeiger (für
alles, auch RAM-Adressen) für den ATmega256x bevorzugen.

> Der 4.1.1 muß quasi erst noch reifen, während der 3.4.6 bei mir
> keinerlei Probleme machte.

Unfug, der auch von wiederholter Behauptung deinerseits nicht wirklich
richtiger wird.  Das mag für GCC 4.0.x noch halbwegs richtig gewesen
sein, seither sind aber auch schon Jahre ins Land gegangen.
Gegenbehauptung: der GCC 4.1.x optimiert nicht nur deutlich besser,
sondern hat auch einige Bugs gefixt, die der 3.x noch hatte.  Das
Risiko, mit GCC 3.x also Schiffbruch zu erleiden, ist mittlerweile
schon größer, als mit den aktuellen Versionen.

Keine von beiden Aussagen wirst du weder stichhaltig beweisen noch
widerlegen können.  Also hör bitte auf, hier FUD zu verbreiten.

Zum Thema dieses Threads trägt es sowieso Nullkommanichts bei.  Das
dürfte einfach was komplett anderes sein.  Leider mag uns der OP
seinen Quellcode nicht antun, also können wir nur mutmaßen.

> Mit dem Schalter -save-temps kannst Du Dir die temporären Dateien
> ansehen.

Genau wie mit der von mir vorgeschlagenen -S Option.

von Peter D. (peda)


Lesenswert?

Jörg Wunsch wrote:

> Du weißt es ja so genau: welche denn?

Sorry, ist natürlich nur mein ganz persönlicher Eindruck.
Es waren halt mehr Anpassungen nötig, wenn ich älteren Code übernommen 
habe, als bei früheren Versionswechseln (Ich weiß natürlich, es liegt 
nur an meinen nicht C-Standard konformen Annahmen).

> Einige deiner
> früheren Lieblingsbeschwerden scheinen sich in Luft aufgelöst zu
> haben.

Nö, das unerwünschte inlining bei -Os macht er immer noch (ja ich weiß, 
man kann inlining global verbieten, aber an anderen Stellen möchte man 
es doch).

>  Es wird sehr viel mehr 8-bit-Code erzeugt, wo GCC 3.x noch
> 16-bit-Code erzeugt hat.  Darüber magst du aber offenbar nicht mehr
> sprechen, man kann so wenig jammern drüber.

Ja, switch geht manchmal sogar 8-bittig. Man darf bloß nicht maskieren, 
z.B. switch(i&0xF0), dann ists wieder 16-bittig.
Ich hatte ja auch einige if-Ausdrücke, die beim 3.4.6 grundlos 16-bittig 
erweitert wurden, muß die mal überprüfen.


Peter

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter Dannegger wrote:

>> Du weißt es ja so genau: welche denn?

> Sorry, ist natürlich nur mein ganz persönlicher Eindruck.

Es ist offenbar massiv am Optimierer gearbeitet worden.  Mein erster
persönlicher Eindruck war übrigens völlig gegenteilig zu deinem: knapp
10 % Codeeinsparung.  Allerdings arbeite ich (zumindest im Job) in
einer komplett anderen Kategorie als du, der du mal irgendwo
schriebst, dass du nicht wüsstest, womit du einen ATmega128 auch nur
annähernd füllen könntest.  Wir lasten einen ATmega1281 gut aus,
RAM-mäßig auf jeden Fall, ROM-mäßig so bei 30...50 % zurzeit.

> Nö, das unerwünschte inlining bei -Os macht er immer noch ...

Inlining ist ja nicht generell unerwünscht.  Es kann schließlich zu
kleinerem Code führen und damit der Prämisse von -Os entsprechen.  Ich
habe auch einen Bugreport offen, wo er sich verrechnet hat damit.  Was
mir bei der Diskussion um diesen Report nur wie ein Seifensieder
aufgegangen ist: wenn du Funktionen hast wie diese:
1
void dosomeasm(uint16_t i)
2
{
3
   inline asm("do this" "\n\t"
4
              "and that" "\n\t"
5
              "and" "\n\t"
6
              "way" "\n\t"
7
              "more"
8
              :
9
              : r(i));
10
}

...dann ist das für GCCs Kostenberechnung erst einmal nur eine einzige
CPU-Anweisung.  Mehr kann er davon nicht sehen.  Entsprechend kann er
davon einige Kopien inline unterbringen, bevor seiner Meinung nach der
Preis für die CALL/RET erreicht ist.  So'ne Funktion muss man daher
also schlicht
1
static void dosomeasm(uint16_t) __attribute__((noinline));
2
3
void dosomeasm(uint16_t i)
4
{
5
  ...
6
}

deklarieren.  Das "static" ist besonders wichtig, wenn die Funktion
ein Kandidat fürs inlining sein sollte (und man es nicht verhindern
möchte/muss), andernfalls wird trotz inlining noch eine separate Kopie
(für die Benutzung als externes Symbol) bereitgestellt.  Aber static
gehört sowieso zum guten Programmierstil.

Der Unterschied zum GCC 3.x hier ist, dass letzterer bei -Os eben nie
versucht hat, Funktionen inline zu erweitern, auch dann nicht, wenn es
wirklich kürzeren Code ergeben hätte.


Aber wie schon gesagt, wir bewegen uns jetzt vom ursprünglichen Punkt
dieses Threads mächtig weit weg.

von Benedikt K. (benedikt)


Lesenswert?

Was mir bezüglich des neuen Compilers aufgefallen ist:
-o2 erzeugt meist einen schnelleren und kleineren Code als -os.

Ich weiß nicht was ich gemacht habe, auf jedenfall ist diese Warning 
jetzt weg. Aktiv wurde auf jedenfall kein inline asm von mir verwendet. 
Falls doch, dann irgendwo in einem mitgelieferten Makro.
Sobald ich diese wieder hinbekomme (ich hatte sowas schon öfters), dann 
suche ich mal was genau schief läuft.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.