[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v9 2/5] x86/asm, x86/boot: expose inline memcmp()



On Wed, 09 Sep 2026 12:33:40 -0700
"H. Peter Anvin" <hpa@xxxxxxxxx> wrote:

> On September 9, 2026 12:28:38 PM PDT, David Laight 
> <david.laight.linux@xxxxxxxxx> wrote:
> >On Wed, 9 Sep 2026 06:43:01 -0700
> >"H. Peter Anvin" <hpa@xxxxxxxxx> wrote:
> >  
> >> On 2026-09-09 01:38, David Laight wrote:  
> >> >>
> >> >> Here is an out-of-line compact memcmp() which works for both 16/32 and 
> >> >> 64 bits:
> >> >>    
> >> <broken code removed>
> >>   
> >> >>
> >> >> On 64 bits it compiles to:
> >> >>
> >> >> 0000000000000000 <memcmp>:
> >> >>    0:   48 89 d1                mov    %rdx,%rcx
> >> >>    3:   31 d2                   xor    %edx,%edx
> >> >>    5:   31 c0                   xor    %eax,%eax
> >> >>    7:   f3 a6                   repz cmpsb (%rdi),(%rsi)
> >> >>    9:   0f 97 c2                seta   %dl
> >> >>    c:   0f 92 c0                setb   %al
> >> >>    f:   29 d0                   sub    %edx,%eax    
> >> > 
> >> > That isn't the object code from the source ...
> >> >     
> >> And that's the ultimate hint that a cut and paste error had happened.
> >> 
> >> This was the actual source code.
> >> 
> >> int memcmp(const void *s1, const void *s2, size_t len)
> >> {
> >>     int lt, gt;
> >> 
> >>     /*
> >>      * Note: for the benefit of 64-bit code, xDI and xSI are reversed
> >>      * compared with what CMPSB uses; hence SETA and SETB are also 
> >> reversed.
> >>      *
> >>      * The XOR statements set ZF = 1, CF = 0, which is required to handle
> >>      * the case len == 0 correctly.
> >>      */
> >>     asm volatile("xor %[lt],%[lt] ; "
> >>                  "xor %[gt],%[gt] ; "
> >>                  "repe cmpsb ; "
> >>                  "seta %b[lt] ; "
> >>                  "setb %b[gt]"
> >>                  : "+D" (s1), "+S" (s2), "+c" (len),
> >>                    [lt] "=&q" (lt), [gt] "=&q" (gt)
> >>                  : : "cc", "memory");
> >>     return gt - lt;
> >> }
> >>   
> >
> >Try:
> >
> >int memcmp_2(const void *s1, const void *s2, unsigned long len)
> >{
> >    signed char lt, gt;
> >
> >    asm volatile("repe cmpsb ; "
> >                 "seta %[lt] ; "
> >                 "setb %[gt]"
> >                 : "+D" (s1), "+S" (s2), "+c" (len),
> >                   [lt] "=&q" (lt), [gt] "=&q" (gt)
> >                 : : "cc", "memory");
> >    return (signed char)(gt - lt);
> >}
> >
> >https://www.godbolt.org/z/6hrxGxb18
> >
> >Saves the XORs - go away completely in the usual case of 'if (memcpy(....))'.
> >The 'mess' on the return statement moves the sign extend after the
> >subtract.
> >
> >David  
> 
> The xors are explicitly in the asm to deal with the len = 0 case (this is for 
> the out of line version!)
> 
> We need to enter with ZF = 1 CF = 0.

And, of course, I knew that.
They also zero the high 24bits of the registers.
Given the setup cost of 'repe cmpsb' I suspect the xor just add code
bytes.

David





 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.