2009-04-28 17:32:19

by Jeff Garzik

[permalink] [raw]
Subject: [x86] Strange 64-bit put_user ?

In arch/x86/include/asm/uaccess.h, if !CONFIG_X86_32, we see

> #define __put_user_x8(x, ptr, __ret_pu) \
> ({ u64 __ret_pu; __put_user_x(8, x, ptr, __ret_pu); (int)__ret_pu; })

which was preceded by

> #define __put_user_x(size, x, ptr, __ret_pu) \
> asm volatile("call __put_user_" #size : "=a" (__ret_pu) \
> :"0" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx")


My question, from an admitted inline asm newbie:

Why is 32-bit register 'ebx' being used for a 64-bit put_user?

And a dumb-question follow-up, probably easy, for any x86 expert: why
are registers 'bl' and 'bx' not used for 8-bit and 16-bit put_user,
respectively?

Thanks,

Jeff



2009-04-29 00:33:52

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [x86] Strange 64-bit put_user ?

Jeff Garzik wrote:
> In arch/x86/include/asm/uaccess.h, if !CONFIG_X86_32, we see
>
>> #define __put_user_x8(x, ptr, __ret_pu) \
>> ({ u64 __ret_pu; __put_user_x(8, x, ptr, __ret_pu);
>> (int)__ret_pu; })
>
> which was preceded by
>
>> #define __put_user_x(size, x, ptr, __ret_pu) \
>> asm volatile("call __put_user_" #size : "=a" (__ret_pu) \
>> :"0" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx")
>
>
> My question, from an admitted inline asm newbie:
>
> Why is 32-bit register 'ebx' being used for a 64-bit put_user?
>
> And a dumb-question follow-up, probably easy, for any x86 expert: why
> are registers 'bl' and 'bx' not used for 8-bit and 16-bit put_user,
> respectively?
>

The answer is simply that gcc doesn't make a distinction between bl, bx,
ebx, and rbx -- it considers it a single regioster which can contain an
8-, 16-, 32- or 64-bit number. In particular, gcc can't use ah, bh, ch,
and dh as independent registers at all.

-hpa

2009-04-29 20:01:27

by Jeff Garzik

[permalink] [raw]
Subject: Re: [x86] Strange 64-bit put_user ?

H. Peter Anvin wrote:
> Jeff Garzik wrote:
>> In arch/x86/include/asm/uaccess.h, if !CONFIG_X86_32, we see
>>
>>> #define __put_user_x8(x, ptr, __ret_pu) \
>>> ({ u64 __ret_pu; __put_user_x(8, x, ptr, __ret_pu);
>>> (int)__ret_pu; })
>> which was preceded by
>>
>>> #define __put_user_x(size, x, ptr, __ret_pu) \
>>> asm volatile("call __put_user_" #size : "=a" (__ret_pu) \
>>> :"0" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx")
>>
>> My question, from an admitted inline asm newbie:
>>
>> Why is 32-bit register 'ebx' being used for a 64-bit put_user?
>>
>> And a dumb-question follow-up, probably easy, for any x86 expert: why
>> are registers 'bl' and 'bx' not used for 8-bit and 16-bit put_user,
>> respectively?
>>
>
> The answer is simply that gcc doesn't make a distinction between bl, bx,
> ebx, and rbx -- it considers it a single regioster which can contain an
> 8-, 16-, 32- or 64-bit number. In particular, gcc can't use ah, bh, ch,
> and dh as independent registers at all.

So, it isn't really referring to 'ebx' register specifically, it is
referring to the hardware register that contains 'ebx'. Gotcha.

Thanks!

Jeff