Hello! We don't need to check for REG_P on base and index, we are sure that non-null RTXes are registers only. Also, we should determine the mode of RTXes in addr32 calculation from original RTXes.
2012-10-22 Uros Bizjak <ubiz...@gmail.com> * config/i386/i386.c (memory_address_length): Assert that non-null base or index RTXes are registers. Do not check for REG RTXes. Determine addr32 prefix from original base and index RTXes. Simplify code. Tested on x86_64-pc-linux-gnu {,-m32}, committed to mainline SVN. Uros.
Index: config/i386/i386.c =================================================================== --- config/i386/i386.c (revision 192664) +++ config/i386/i386.c (working copy) @@ -23764,7 +23764,7 @@ memory_address_length (rtx addr, bool lea) { struct ix86_address parts; rtx base, index, disp; - int len = 0; + int len; int ok; if (GET_CODE (addr) == PRE_DEC @@ -23776,15 +23776,26 @@ memory_address_length (rtx addr, bool lea) ok = ix86_decompose_address (addr, &parts); gcc_assert (ok); - if (parts.base && GET_CODE (parts.base) == SUBREG) - parts.base = SUBREG_REG (parts.base); - if (parts.index && GET_CODE (parts.index) == SUBREG) - parts.index = SUBREG_REG (parts.index); + len = (parts.seg == SEG_DEFAULT) ? 0 : 1; + /* If this is not LEA instruction, add the length of addr32 prefix. */ + if (TARGET_64BIT && !lea + && ((parts.base && GET_MODE (parts.base) == SImode) + || (parts.index && GET_MODE (parts.index) == SImode))) + len++; + base = parts.base; index = parts.index; disp = parts.disp; + if (base && GET_CODE (base) == SUBREG) + base = SUBREG_REG (base); + if (index && GET_CODE (index) == SUBREG) + index = SUBREG_REG (index); + + gcc_assert (base == NULL_RTX || REG_P (base)); + gcc_assert (index == NULL_RTX || REG_P (index)); + /* Rule of thumb: - esp as the base always wants an index, - ebp as the base always wants a displacement, @@ -23797,14 +23808,13 @@ memory_address_length (rtx addr, bool lea) /* esp (for its index) and ebp (for its displacement) need the two-byte modrm form. Similarly for r12 and r13 in 64-bit code. */ - if (REG_P (base) - && (base == arg_pointer_rtx - || base == frame_pointer_rtx - || REGNO (base) == SP_REG - || REGNO (base) == BP_REG - || REGNO (base) == R12_REG - || REGNO (base) == R13_REG)) - len = 1; + if (base == arg_pointer_rtx + || base == frame_pointer_rtx + || REGNO (base) == SP_REG + || REGNO (base) == BP_REG + || REGNO (base) == R12_REG + || REGNO (base) == R13_REG) + len++; } /* Direct Addressing. In 64-bit mode mod 00 r/m 5 @@ -23814,7 +23824,7 @@ memory_address_length (rtx addr, bool lea) by UNSPEC. */ else if (disp && !base && !index) { - len = 4; + len += 4; if (TARGET_64BIT) { rtx symbol = disp; @@ -23832,7 +23842,7 @@ memory_address_length (rtx addr, bool lea) || (XINT (symbol, 1) != UNSPEC_GOTPCREL && XINT (symbol, 1) != UNSPEC_PCREL && XINT (symbol, 1) != UNSPEC_GOTNTPOFF))) - len += 1; + len++; } } else @@ -23841,41 +23851,23 @@ memory_address_length (rtx addr, bool lea) if (disp) { if (base && satisfies_constraint_K (disp)) - len = 1; + len += 1; else - len = 4; + len += 4; } /* ebp always wants a displacement. Similarly r13. */ - else if (base && REG_P (base) - && (REGNO (base) == BP_REG || REGNO (base) == R13_REG)) - len = 1; + else if (base && (REGNO (base) == BP_REG || REGNO (base) == R13_REG)) + len++; /* An index requires the two-byte modrm form.... */ if (index /* ...like esp (or r12), which always wants an index. */ || base == arg_pointer_rtx || base == frame_pointer_rtx - || (base && REG_P (base) - && (REGNO (base) == SP_REG || REGNO (base) == R12_REG))) - len += 1; + || (base && (REGNO (base) == SP_REG || REGNO (base) == R12_REG))) + len++; } - switch (parts.seg) - { - case SEG_FS: - case SEG_GS: - len += 1; - break; - default: - break; - } - - /* If this is not LEA instruction, add the length of addr32 prefix. */ - if (TARGET_64BIT && !lea - && ((base && GET_MODE (base) == SImode) - || (index && GET_MODE (index) == SImode))) - len += 1; - return len; }