2009-08-26 6 views
4

Ceci est un extrait de code AVR démonté d'un projet C sur lequel je travaille. J'ai remarqué que ce curieux code était généré, et je ne peux pas comprendre comment cela fonctionne. Je suppose que c'est une sorte d'optimisation ridicule ...Pourquoi ce code est-il généré par avr-gcc et comment ça marche?

Quelle est l'explication?

92:   ticks++;   // unsigned char ticks; 
+0000009F: 91900104 LDS  R25,0x0104  Load direct from data space 
+000000A1: 5F9F  SUBI  R25,0xFF  Subtract immediate 
+000000A2: 93900104 STS  0x0104,R25  Store direct to data space 
95:   if (ticks == 0) { 
+000000A4: 2399  TST  R25   Test for Zero or Minus 
+000000A5: F009  BREQ  PC+0x02  Branch if equal 
+000000A6: C067  RJMP  PC+0x0068  Relative jump 

Plus précisément, pourquoi la deuxième Soustraire d'instruction de 0xFF R25 au lieu de simplement INC R25?

+2

Dans le cas où ce n'est pas évident, je fais référence à la deuxième ligne: Soustraire 0xFF de R25 ... pourquoi ne pas simplement "INC R25"? –

+1

Quel est le type de données C? – Inshallah

+0

char non signée (8 bits) –

Répondre

4

L'instruction SUBI peut être utilisé pour ajouter/soustraire une constante quelconque vers/à partir d'une valeur de 8 bits 8 bits. Il a le même coût que INC, c'est-à-dire la taille de l'instruction et le temps d'exécution. SUBI est donc préféré par le compilateur car il est plus général. Il n'y a pas d'instruction ADDI correspondante, probablement parce que ce serait redondant.

+1

vous avez raison que les deux ont la même taille/CPU horloges - encore dire "SUBI" est préféré (...) parce que c'est plus général "est juste agiter sans décrire les détails; 'SUBI' n'est pas" plus général ", car il nécessite les registres r16-31 au lieu de la gamme r0-31 du' INC'. Le compilateur avr-gcc a été * hand-tuned * pour faire 'SUBI' au lieu de' INC', pour la raison même donnée par Greg ci-dessous - 'SUBI' définit correctement le drapeau de report, tandis que' INC' l'ignore. Cela rend les compteurs 16/32 bits beaucoup plus simples avec 'SUBI', parce que vous n'avez pas à vérifier les octets inférieurs pour le débordement du tout! – vaxquis

3

tl; dr le compilateur a été conçu pour utiliser la solution générale & plus portable et plus efficace ici.

L'instruction SUBI définit C (carry) et H (demi-carry) drapeaux CPU pour une utilisation avec les instructions suivantes (il n'y a pas ADDI à 8 bits AVR BTW, afin d'ajouter une valeur immédiate de x nous soustrayons -x de il), alors que INC ne fait pas. SUBI & INC ont 2 octets de longueur et s'exécutent pendant 1 cycle d'horloge, vous ne perdez rien en utilisant SUBI - OTOH, si vous utilisez un compteur de taille 8 bits, vous pouvez alors facilement détecter s'il a basculé (par BRCC/BRCS), et si vous aviez un compteur de taille 16 ou 32 bits, il vous permet de l'incrémenter de manière très simple - avec seulement INC, 0x00FF serait augmenté à 0x0000, donc vous devriez vérifier si l'octet le plus bas est 0xFF avant INC ing. OTOH, avec SUBI vous juste SUBI -1 l'octet le plus bas, puis ADC 0 pour les octets suivants, assurant que tous les bits de retenue potentiels ont été pris en compte.

en savoir plus:

https://lists.gnu.org/archive/html/avr-gcc-list/2008-11/msg00029.html

http://avr-gcc-list.nongnu.narkive.com/SMMzdBkW/foo-subi-vs-inc

+0

J'ai inclus les instructions suivantes ... est-ce que cela aide à affiner les choses? Je n'ai toujours pas le point de "SUBI R25,0xFF" vs "INC R25", les deux sont 1 heure. Et si R25 passe de 255 à 0, l'instruction TST R25 fonctionnera très bien. –

+0

Ok. J'ai réfléchi un peu et j'ai réalisé que dans les maths non signées, soustraire 0xFF revient à ajouter 0x01. Wierd, mais pourquoi le faire de cette façon? Est-ce que INC ne définit pas de drapeaux pour la branche? –

+2

Il semble que INC définit les drapeaux V, N, S, Z, mais SUBI définit H, V, N, S, Z, C. Puisque le compilateur a généré une instruction TST, il ne semble pas utiliser les indicateurs du SUBI. En outre, l'utilisation d'un SUBI semble étrange car un ADDI avec 0x01 serait à nouveau équivalent. C'est vraiment un mystère. –

Questions connexes