[GNU as / amd64] Forcing disp32 offset for MODRM
Mason
slash.tmp@free.fr
Fri Jul 12 01:00:01 GMT 2024
On 12/07/2024 01:25, H.J. Lu wrote:
> On Fri, Jul 12, 2024, 6:50 AM Mason <slash.tmp@free.fr <mailto:slash.tmp@free.fr>> wrote:
>
> Hello everyone,
>
> Hope this is an appropriate place for my question.
> If not, I'd appreciate being pointed in the right
> direction. Please CC me on answers.
>
> Using GNU as - on amd64 target.
>
> My example code:
>
> movq 48*1(%rsi), %rax
> movq 48*2(%rsi), %rax
> movq 48*3(%rsi), %rax
> movq 48*4(%rsi), %rax
>
> which is assembled to
>
> 0: 48 8b 46 30 mov 0x30(%rsi),%rax
> 4: 48 8b 46 60 mov 0x60(%rsi),%rax
> 8: 48 8b 86 90 00 00 00 mov 0x90(%rsi),%rax
> f: 48 8b 86 c0 00 00 00 mov 0xc0(%rsi),%rax
>
> Since offsets 0x30 and 0x60 are less than 0x80,
> they fit in an s8, thus gas logically uses disp8.
>
> I am looking for a way to force gas to generate the
> disp32 variant for the first two instructions:
>
> 0: 48 8b 86 30 00 00 00 mov 0x30(%rsi),%rax
> 4: 48 8b 86 60 00 00 00 mov 0x60(%rsi),%rax
> 8: 48 8b 86 90 00 00 00 mov 0x90(%rsi),%rax
> f: 48 8b 86 c0 00 00 00 mov 0xc0(%rsi),%rax
>
> Is there some magical syntax to say "s32 not s8" ?
>
>
> Try {disp32} ({d32})? pseudo prefix.
Yes, you are the man/woman/boss!
https://stackoverflow.com/questions/47673177/how-do-gnu-assembler-x86-instruction-suffixes-like-s-in-mov-s-work
https://sourceware.org/binutils/docs/as/i386_002dMnemonics.html
{disp32} movq 48*1(%rsi), %rax
{disp32} movq 48*2(%rsi), %rax
{disp32} movq 48*3(%rsi), %rax
{disp32} movq 48*4(%rsi), %rax
is assembled into
0: 48 8b 86 30 00 00 00 mov 0x30(%rsi),%rax
7: 48 8b 86 60 00 00 00 mov 0x60(%rsi),%rax
e: 48 8b 86 90 00 00 00 mov 0x90(%rsi),%rax
15: 48 8b 86 c0 00 00 00 mov 0xc0(%rsi),%rax
Basically I had a crazy idea that has probably already
been proposed many times, and that sounds good on paper,
but apparently fails because of branch (mis)prediction.
Basically, I have a simple loop:
for (i = 0; i < n; ++i) foo(i);
with n only known only at run-time.
In assembly I am doing a Duff device of sorts, with computed
goto for the loop tail.
//unroll 64 times
L1: foo(0) .. foo(63)
loop_count -= 64;
if (loop_count >= 64) goto L1;
// otherwise adjust pointers and jump in the middle of the loop
// compute correct jump offset
jmp *%rax
But the performance is disappointing.
Branch mispredicts grow 50% vs a simple loop
to handle the tail :(
So my genius idea falls flat...
Will try increasing the unroll factor
(but I needed the {disp32} trick to make all
iterations the same size)
Open to suggestions.
Regards
More information about the Binutils
mailing list