This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH, i386]: Fix (some) wrong insn length calculations


Hello!

This patch is based on observations by Steven Bosscher in PR tartet/23524
(comment #11), where he found that the length of displacement only move to AX
reg is wrong:

A100000000       movl    x, %eax # 11    *movsi_1/1      [length = 6]

The problem is in the calculation on "modrm" attribute, that misses a couple of
special cases. In the case above, A0, A1, A2 and A3 opcodes do _not_ need a
modrm byte.

This patch fixes the calculations, and the testcase:
int x, y;
int z;

int foo(void) {

  z = y;
  x = z;

  return x + y;
}

returns correct lengths (-O0):

foo:
        pushl   %ebp    # 35    *pushsi2        [length = 1]
        movl    %esp, %ebp      # 36    *movsi_1/1      [length = 2]
        movl    y, %eax # 8     *movsi_1/1      [length = 5]
        movl    %eax, z # 9     *movsi_1/2      [length = 5]
        movl    z, %eax # 11    *movsi_1/1      [length = 5]
        movl    %eax, x # 12    *movsi_1/2      [length = 5]
        movl    x, %edx # 14    *movsi_1/1      [length = 6]
        movl    y, %eax # 15    *movsi_1/1      [length = 5]
        leal    (%edx,%eax), %eax       # 34    *lea_1  [length = 3]
        popl    %ebp    # 39    popsi1  [length = 1]
        ret     # 40    return_internal [length = 1]

these can be verified by objdump:

00000000 <foo>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   a1 00 00 00 00          mov    0x0,%eax
   8:   a3 00 00 00 00          mov    %eax,0x0
   d:   a1 00 00 00 00          mov    0x0,%eax
  12:   a3 00 00 00 00          mov    %eax,0x0
  17:   8b 15 00 00 00 00       mov    0x0,%edx
  1d:   a1 00 00 00 00          mov    0x0,%eax
  22:   8d 04 02                lea    (%edx,%eax,1),%eax
  25:   5d                      pop    %ebp
  26:   c3                      ret    

The patch was regtested on i686-pc-linux-gnu.

2005-11-05  Uros Bizjak  <uros@kss-loka.si>

	* config/i386/predicates.md (ax_reg_operand): New predicate.
	(memory_displacement_only_operand): New predicate.
	* config/i386/i386.md ("modrm" attribute): Return 0 if one
	operand is AX register and the other operand is memory operand
	with displacement only.

OK for mainline?


BTW: The calculation of "modrm" attribute does not consider other special cases
involving AX register. For example, adding immediate to ax is calculated as:

        addl    $132, %eax      # 17    *addsi_1/1      [length = 6]

where in fact, the correct length is 5:

  18:   05 84 00 00 00          add    $0x84,%eax

This can be checked in Intel's documnetation, where addition (and other
operations) of immediate to AX reg is special-cased with opcode 04 and 05,
without additional modrm bytes.

I plan to fix these by adding a check to "modrm" attribute for operations with
immediate and AX reg in following patch(es).

Uros.

Attachment: modrm.diff
Description: Binary data


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]