You can ask gcc how to write code in the assembly: gcc -S foo.c or gcc -Wa,-alh=foo.s -c foo.c Of course, you can improve the results. You will need to do a little more: use %0 for the parameter that you pass for the assembly, and declare the registers that you bound. See the C Expression Operand Assembler Instructions in the GCC Guide if you are not familiar. Here's what it might look like (a warning entered directly in the browser and don't know the x86 assembly syntax).
#define SAVE_STACK_POINTER(tid) __asm__ __volatile__ (" \ cmpl $0, %0 \n\ je .SAVE_STACK_POINTER_0 \n\ cmpl $1, %0 \n\ je .SAVE_STACK_POINTER_1 \n\ cmpl $2, %0 \n\ je .SAVE_STACK_POINTER_2 \n\ cmpl $3, %0 \n\ je .SAVE_STACK_POINTER_3 \n\ jmp .SAVE_STACK_POINTER_done \n\ .SAVE_STACK_POINTER_0: \n\ movq %%rsp, msp0 \n\ movq ts0, %%rsp \n\ jmp SAVE_STACK_POINTER_done \n\ .SAVE_STACK_POINTER_1: \n\ movq %%rsp, msp1 \n\ movq ts1, %%rsp \n\ jmp SAVE_STACK_POINTER_done \n\ .SAVE_STACK_POINTER_2: \n\ movq %%rsp, msp2 \n\ movq ts2, %%rsp \n\ jmp SAVE_STACK_POINTER_done \n\ .SAVE_STACK_POINTER_3: \n\ movq %%rsp, msp3 \n\ movq ts3, %%rsp \n\ .SAVE_STACK_POINTER_done: \n\ " : : "r" (tid))
The fancier method will include determining the number of bytes of each block movq - movq - jmp (note: I did not check, I use 8) and taking a calculated jump into it; something like
__asm__(" \n\ movl %0, %eax \n\ mul 8, %eax \n\ add 4, %eax \n\ jmp . + %eax \n\ movq %%rsp, msp0 \n\ movq ts0, %%rsp \n\ jmp .SAVE_STACK_POINTER_done \n\ … .SAVE_STACK_POINTER_done: \n\ " : : "r" (tid) : "%eax")
Gilles
source share