Incorporação de montagem em C com registros constatação do compilador para você
-
06-09-2019 - |
Pergunta
Ao incorporar montagem código em um programa C / C ++, você pode evitar sobrepor registros salvando-os com uma instrução push (ou especificar lista clobber de suportes compilador TI).
Se você estiver incluindo montagem em linha e quer evitar a sobrecarga de empurrar e popping registros derrotado, há uma maneira de deixá-gcc escolher registros achados para você (por exemplo, aqueles que sabem não têm informação útil neles).
Solução
Sim. Você pode especificar que deseja uma determinada variável (entrada ou saída) a ser armazenado em um registro, mas você não tem que especificar um registo. Consulte este documento para uma explicação detalhada. Essencialmente, a linha de montagem se parece com isso:
asm("your assembly instructions"
: output1("=a"), // I want output1 in the eax register
output2("=r"), // output2 can be in any general-purpose register
output3("=q"), // output3 can be in eax, ebx, ecx, or edx
output4("=A") // output4 can be in eax or edx
: /* inputs */
: /* clobbered registers */
);
Outras dicas
Compiler intrínsecos são uma maneira muito útil para misturar montagem e de código C / C ++. Eles são declarações que parecem funções, mas na verdade compilar diretamente para instruções nativas individuais (via um caso especial dentro do compilador). Isto dá-lhe a maior parte do controle de trabalhar em conjunto, mas deixa o registo coloração e agendamento até o compilador.
Uma vantagem é que, em seguida, você pode passar uma variável C ordinário em um intrínseco, e deixar o compilador cuidar de carregá-lo para o registo e agendamento de outros ops em torno dele. Por exemplo,
struct TwoVectors
{
__m128 a; __m128b;
}
// adds two vectors A += B using the native SSE opcode
inline void SimdADD( TwoVectors *v )
{
v->a = _mm_add_ps( v->a , v->b ); // compiles directly to ADDSS opcode
}
OK, então eu não pode deixar um comentário acima, mas eu tenho certeza que a sintaxe correta (diferente da mostrada acima) é:
asm ( "your assembly instructions"
: "=a"(output1),
"=r"(output2),
"=q"(output3),
"=A"(output4)
: /* inputs */
: /* clobbered registers */
);
Embora você pode deixar a alocação de registros de entrada e saída para o compilador, não há nenhuma maneira óbvia de deixar a alocação de registradores scratch / Temp (ou seja usada para valores intermediários, mas não uma entrada ou saída) para o compilador. Historicamente, eu apenas listados-los explicitamente na lista clobber (por exemplo, "% XMM1", "% rcx"), mas agora eu acho que pode ser melhor para incluí-los como saídas, a fim de permitir que o compilador para escolhê-los. Eu não sei de qualquer fonte que resolve este problema definitivamente.