2017-08-18 10 views
0

J'écris le code C et je le compile pour l'architecture PowerPC. Je veux dire au compilateur de remplacer toutes les instructions de retour avec des branches à la fin du code de la fonction à la place. Ceci est dû à des exigences bizarres où je ne peux pas utiliser de retour dans ce morceau de code pour assurer l'exécution de quelques lignes de montage par la suite.GCC Eviter de compiler des instructions de registre de branchement (blr)

Par exemple, je compilé C code dans le code assembleur suivant:

lis r9,4096 
lis r8,255 
lwz r10,0(r9) 
ori r8,r8,65535 
addi r9,r10,192 
cmplw cr7,r9,r8 
blelr- cr7 # Return if the cr7 register is "less than or equal" 
lis r8,512 
cmplw cr7,r9,r8 
bgtlr- cr7 # Return if the cr7 register is "greater than or equal" 
lwz r10,192(r10) 
lis r8,303 
ori r8,r8,65535 
addi r9,r10,320 
cmplw cr7,r9,r8 
blelr- cr7 # Return if the cr7 register is "less than or equal" 
lis r8,528 
cmplw cr7,r9,r8 
bgtlr- cr7 # Return if the cr7 register is "greater than or equal" 
lwz r10,320(r10) 
lis r8,287 
ori r8,r8,65535 
subi r9,r10,448 
cmplw cr7,r9,r8 
blelr- cr7 
lis r8,544 
cmplw cr7,r9,r8 
bgtlr- cr7 # Return if the cr7 register is "greater than or equal" 
lis r9,4919 
ori r9,r9,4919 
stw r9,-448(r10) 
blr # Return 

Ce que je veux toutes les déclarations comme retour à être remplacé par une branche toujours à la fin du code de la fonction comme en suit:

lis r9,4096 
lis r8,255 
lwz r10,0(r9) 
ori r8,r8,65535 
addi r9,r10,192 
cmplw cr7,r9,r8 
ble _END # Branch to the _END label if "less than" 
lis r8,512 
cmplw cr7,r9,r8 
bgt _END # Branch to the _END label if "greater than" 
lwz r10,192(r10) 
lis r8,303 
ori r8,r8,65535 
addi r9,r10,320 
cmplw cr7,r9,r8 
ble cr7 # Branch to the _END label if "less than" 
lis r8,528 
cmplw cr7,r9,r8 
bgt _END # Branch to the _END label if "greater than" 
lwz r10,320(r10) 
lis r8,287 
ori r8,r8,65535 
subi r9,r10,448 
cmplw cr7,r9,r8 
blelr- cr7 
lis r8,544 
cmplw cr7,r9,r8 
bgt _END # Branch to the _END label if "greater than" 
lis r9,4919 
ori r9,r9,4919 
stw r9,-448(r10) 
_END: 
blr # I guess it should stay otherwise the function call will continue executing "random" garbage such as the next function in the .text section. Via post-processing this would be easy to strip though! 

Un moyen d'automatiser cette préférence de compilation?

+0

'Je ne peux pas utiliser de retour dans ce morceau de code pour assurer l'exécution de quelques lignes de plus par la suite'. Appelez ces «lignes d'assemblage» séparément de C après le retour? –

+1

Je veux dire, vous suggérez que le compilateur optimise négativement :( –

+0

Oui, car le même assembly sera ajouté à la fin de la fonction 'C', ce qui fait que le retour n'est pas bon, il doit encore l'exécuter et il est construit le code machine de la fonction C et la partie d'assemblage – BullyWiiPlaza

Répondre

2

Les commentaires de @Jester et @fuz fournissent une réponse, je vais juste l'écrire.

Vous devez:

  1. renoncions au milieu d'une fonction, dans le code C. Remplacez donc return par goto.
  2. Empêcher le compilateur de comprendre que goto end; et return; sont la même chose. L'assemblage en ligne est un bon moyen de dire au compilateur "ne plaisante pas avec ça".

Avec quelques macros:

#define RETURN goto _end
#define END _end: asm volatile("")
void foo(int x) { if (x==1) RETURN; if (x==2) RETURN; printf("Hello, world\n"); END; }

asm volatile("") indique au compilateur d'insérer un code d'assemblage. Le compilateur ne sait pas ce que fait ce code d'assemblage, donc il ne peut faire aucune optimisation qui l'ignorera (même si c'est 0 instructions).

+0

Oui, le 'asm volatile (" ")' a fait l'affaire. Cela fonctionne comme prévu :) – BullyWiiPlaza