Re: [PATCH v9 2/5] x86/asm, x86/boot: expose inline memcmp()
From: H. Peter Anvin
Date: Wed Sep 09 2026 - 15:51:33 EST
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.