What does 'sp' mean in an asm clobber list?
I'm struggling to get some x86 assembly to compile on a Core 2 Duo Mac. Using clang returns an invalid operand
error for statements like the following:
asm volatile ("subl %0,%%esp" :: "r"(foobar) : "cc", "sp");
Where foobar
is a long
. I was wondering what the sp
keyword means in the clobber list as neither the GCC / llvm doc nor Google can shed much light on them. Does anybody kno开发者_开发知识库w of a comprehensive list of clobber keywords?
Surely that would be the stack pointer, especially since you're actually subtracting something from the stack pointer esp
. You probably already know this bit but, just in case, the cc
is the condition code register (the flags and so forth).
Why it's sp
and not esp
, I couldn't tell you but, if you're getting errors, that's the first thing I'd change to see if that was the problem.
The values that you're supposed to be able to put in there are all the registers that may be clobbered (other than those explicitly listed for output which gcc
already knows will change) and the special value memory
if you don't want gcc
to assume any cached memory values will remain valid.
The registers, of course, depend on the underlying architecture. Not sure that's a comprehensive list but it's all I've ever used, or needed to use.
Looking at gcc-4.4.3/gcc/config/i386/i386.h :2036 file I conclude that "sp" is gcc-specific alias of "esp":
/* How to refer to registers in assembler output.
This sequence is indexed by compiler's hard-register-number (see above). */
/* In order to refer to the first 8 regs as 32-bit regs, prefix an "e".
For non floating point regs, the following are the HImode names.
For float regs, the stack top is sometimes referred to as "%st(0)"
instead of just "%st". PRINT_OPERAND handles this with the "y" code. */
#define HI_REGISTER_NAMES \
{"ax","dx","cx","bx","si","di","bp","sp", \
"st","st(1)","st(2)","st(3)","st(4)","st(5)","st(6)","st(7)", \
"argp", "flags", "fpsr", "fpcr", "frame", \
"xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7", \
"mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", \
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \
"xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"}
#define REGISTER_NAMES HI_REGISTER_NAMES
/* Table of additional register names to use in user input. */
#define ADDITIONAL_REGISTER_NAMES \
{ { "eax", 0 }, { "edx", 1 }, { "ecx", 2 }, { "ebx", 3 }, \
{ "esi", 4 }, { "edi", 5 }, { "ebp", 6 }, { "esp", 7 }, \
{ "rax", 0 }, { "rdx", 1 }, { "rcx", 2 }, { "rbx", 3 }, \
{ "rsi", 4 }, { "rdi", 5 }, { "rbp", 6 }, { "rsp", 7 }, \
{ "al", 0 }, { "dl", 1 }, { "cl", 2 }, { "bl", 3 }, \
{ "ah", 0 }, { "dh", 1 }, { "ch", 2 }, { "bh", 3 } }
Both "sp" and "esp" (and "rsp" too) will code register number 7.
So, this code is legal for GCC; but is you want to make it portable (compilable by clang), change "sp" to "esp". This patch will not change gcc logic and will enable you to build this with clang.
== Update==
there is a possibility that gcc stores size of register access for clobbers too. Here is the the checker function of asm registers - clobbers conflict (gcc/stmt.c):
tree_conflicts_with_clobbers_p (tree t, HARD_REG_SET *clobbered_regs)
{
/* Conflicts between asm-declared register variables and the clobber
list are not allowed. */
tree overlap = tree_overlaps_hard_reg_set (t, clobbered_regs);
The conflict (overlap) is checked via HARD_REG_SET, which has size 52 bits:
gcc/hard-reg-set.h :50. Hard_reg_set has length of FIRST_PSEUDO bits, rounded up to fill fastint fully.
#define HARD_REG_SET_LONGS \
((FIRST_PSEUDO_REGISTER + HOST_BITS_PER_WIDEST_FAST_INT - 1) \
/ HOST_BITS_PER_WIDEST_FAST_INT)
typedef HARD_REG_ELT_TYPE HARD_REG_SET[HARD_REG_SET_LONGS];
i386/i386.h :865: #define FIRST_PSEUDO_REGISTER 53
:882 same file has a list of registers in the HARD_REG_SET:
#define FIXED_REGISTERS \
/*ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7*/ \
{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, \
/*arg,flags,fpsr,fpcr,frame*/ \
1, 1, 1, 1, 1, \
/*xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7*/ \
0, 0, 0, 0, 0, 0, 0, 0, \
/* mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7*/ \
0, 0, 0, 0, 0, 0, 0, 0, \
/* r8, r9, r10, r11, r12, r13, r14, r15*/ \
2, 2, 2, 2, 2, 2, 2, 2, \
/*xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15*/ \
2, 2, 2, 2, 2, 2, 2, 2 }
So register-clobber conflict is checked without size field check (for non-mm/xmm regs).
精彩评论