Hallo! Ich habe mal ne Frage zur Optimierung von AVR-GCC 3.3 20021209: Es geht dabei um eine Funktion zur Ansteuerung eines LCDs. Dabei wurde immer nur ein Befehl umgeschrieben, die Funktion blieb aber gleich und trotzdem gab's große Codeunterschiede. Der Code der Funktion(am besten optimiert): #define DB_SHIFT=2 void lcd_send(unsigned char data, unsigned char ormask) { unsigned char tmp; //////////////////// tmp=data&0xF0; // Um diese vier // tmp>>=4-DB_SHIFT; // Zeilen geht es // LCD_PORT=tmp | ormask; //////////////////// lcd_enable(); LCD_PORT=((data & 0x0F)<<DB_SHIFT) | ormask; lcd_enable(); lcd_wait_20us(10); } und das zugehörige Assemblerlisting: 216 0050 0F93 push r16 217 0052 1F93 push r17 219 0054 082F mov r16,r24 220 0056 162F mov r17,r22 41:lcd.c **** unsigned char tmp; 42:lcd.c **** tmp=data&0xF0; 224 0058 807F andi r24,lo8(-16) 43:lcd.c **** tmp>>=4-DB_SHIFT; 227 005a 8695 lsr r24 228 005c 8695 lsr r24 44:lcd.c **** LCD_PORT=tmp | ormask; 231 005e 862B or r24,r22 232 0060 85BB out 53-0x20,r24 Besser hätte ich es auch nicht machen gekonnt. Aber wenn ich den Befehl verkürze: tmp=(data&0xF0)>>(4-DB_SHIFT); Bekomm ich aber einen um 8Byte großeren Code: 216 0050 FF92 push r15 217 0052 0F93 push r16 218 0054 1F93 push r17 220 0056 F62E mov r15,r22 41:lcd.c **** unsigned char tmp; 42:lcd.c **** tmp=(data&0xF0)>>(4-DB_SHIFT); 224 0058 082F mov r16,r24 225 005a 1127 clr r17 226 005c C801 movw r24,r16 227 005e 9695 lsr r25 228 0060 8795 ror r24 229 0062 9695 lsr r25 230 0064 8795 ror r24 231 0066 8C73 andi r24,lo8(60) 43:lcd.c **** LCD_PORT=tmp | ormask; 234 0068 862B or r24,r22 235 006a 85BB out 53-0x20,r24 Genausoschlimm ist folgender Befehl: LCD_PORT=((data>>4)<<DB_SHIFT) | ormask; 216 0050 0F93 push r16 217 0052 1F93 push r17 219 0054 082F mov r16,r24 220 0056 162F mov r17,r22 46:lcd.c **** LCD_PORT=((data>>4)<<DB_SHIFT) | ormask; 223 0058 8295 swap r24 224 005a 8F70 andi r24,0x0f 225 005c 9927 clr r25 226 005e 880F lsl r24 227 0060 991F rol r25 228 0062 880F lsl r24 229 0064 991F rol r25 230 0066 862B or r24,r22 231 0068 85BB out 53-0x20,r24 47:lcd.c **** lcd_enable(); 234 006a 0E94 0000 call lcd_enable 48:lcd.c **** LCD_PORT=((data & 0x0F)<<DB_SHIFT) | ormask; 237 006e 802F mov r24,r16 238 0070 9927 clr r25 Was mir hier besonders negativ auffällt ist die Tatsache das immer wieder(225,227,229) mir r25 gearbeitet wird, dieses Register aber in 238 gelöscht wird ohne das der darin stehende Wert jemals benutzt worden wäre. Kann mir vielleicht mal jemand erklären an welche Regeln ich mich halten muss, damit der Compiler effektiven Code produziert.
Die Antwort steht in der FAQ: http://savannah.nongnu.org/download/avr-libc/doc/avr-libc-user-manual/FAQ.html#faq_intpromote
OK, nicht exakt, aber den Weg hast Du ja schon gefunden. Alternativ müßte es auch mit passenden typecasts gehen.
Das in der FAQ hatte ich schon gelesen. Aber das kann ja wohl kaum der Grund sein. Wenn ich den Befehl auf mehrere Zeilen aufteile bekomme ich ja einen kleinen Code. Nur wenn ich alles in eine Zeile schreibe ist das Problem da. Herman
Du bekommst den Code mit entsprechenden Casts auch in einer Zeile gebacken. Die Zwischenvariable (die vom Typ unsigned char ist) spart Dir allerdings den Cast. Da sie ansonsten sowieso wegoptimiert wird und der Code durch diese übersichtlicher wird als mit all der andernfalls notwendigen Casterei, warum läßt Du es dann nicht einfach so? Du kannst den Compiler ja mal spaßeshalber mit -mint8 aufrufen, dann sollte er das auch alles nicht brauchen. Allerdings ist die Library damit nicht kompatibel.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.