PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Compiler-Optimierung bei Register-Variablen



RedBaron
25.10.2013, 14:23
Hallo, ich bin am verzweifeln!

Google und auch die Suche hier im Forum hat mir nicht weiter geholfen. Ich möchte Variablen in einem Register ablegen. Leider optimiert der Compiler die Zugriffe auf die Variable komplett weg.

Hier das auf das Minimum reduzierte Testprogramm (Optimierungseinstellung -Os, wie bei µC-Programme üblich):


register unsigned char Data asm("r6");

int main(void)
{ while(1)
{ Data++;
}
}
führt zu Assembler-Code:

int main(void)
{ while(1)
30: ff cf rjmp .-2 ; 0x30 <main>
Deklariere ich "Data" als

volatile unsigned char Data;
erhalte ich das erwartete Ergebnis (Assembler):

int main(void)
{ while(1)
{ Data++;
40: 80 91 60 00 lds r24, 0x0060
44: 8f 5f subi r24, 0xFF ; 255
46: 80 93 60 00 sts 0x0060, r24
44: fa cf rjmp .-12 ; 0x40 <main>
Wenn man bei der Register-Deklaration ein "volatile" hinzufügt, ändert sich außer einer zusätzlichen Compiler-Warnung nichts.

Benutzen möchte ich solch einen Code in einem Projekt, bei dem eine in Assembler geschriebene ISR einen Wert in einem Register ablegt. Die Speicherzugriffe möchte ich mir deshalb -besonders in der ISR- ersparen.

Ich benutze das Atmel-Studio in der Version 6.1. Das komplette Projekt habe ich als Datei angefügt.

Wie kann ich den Compiler dazu überreden, den Registerinhalt zu ändern?

Viele Grüße RedBaron

Peter(TOO)
25.10.2013, 14:41
Hallo RedBaron,

1. Naja:

register unsigned char Data asm("r6");

int main(void)
{ while(1)
{ Data++;
}
}

Ist für einen optimierenden Compiler auch unsinnig, Data wird nirgends verwendet, also weg damit.
Versuch mal:

register unsigned char Data asm("r6");
unsigned char b;

int main(void)
{ while(Data)
{ Data++;
}
b = Data;
}

2. register ist und war immer nur eine Empfehlung an den Compiler. Der kann das berücksichtigen.
Was er Compiler mit register macht, sollte unter "Implementation Specific" nachzulesen sein.

MfG Peter(TOO)

SprinterSB
27.10.2013, 22:36
> Versuch mal [...]

Das ist dann gleichbeutend mit R6 = 0 :-)

> 2. register ist und war immer nur eine Empfehlung an den Compiler.

Nein, hier ist es keine "Empfehlung". Globale Register sind eine GNU-Erweiterung. Guckst du im GCC-Handbuch bei

Extensions to the C Language Family -> Variables in Specified Registers ->Defining Global Register Variables

Die Frage des OP bezüglich globaler Register wird hier beantwortet: http://www.mikrocontroller.net/topic/312598

RedBaron
26.11.2013, 22:13
ich glaube, ich habe jetzt eine akzeptable Lösung gefunden:

register uint8_t Reg3 asm("r3");

static inline __attribute__((always_inline)) void SetReg3(uint8_t tmp)
{ asm volatile ("mov r3, %0" : : "r" (tmp): "r3");}

static inline __attribute__((always_inline)) uint8_t GetReg3(void)
{ uint8_t tmp; asm volatile ("mov %0, r3": "=r" (tmp)); return tmp;}

wird kompiliert zu "mov r3, r24" und "mov r24, r3". Je nach Konstellation ersetzt der Compiler r24 durch ein anderes Register.

Das Ganze ist (noch) nicht 100%-tig optimal, kommt der Anforderung aber schon sehr nahe. Hier (http://bienonline.magix.net/public/avr-register.html) hab ich noch einmal beschrieben.

vg RdBaron