int
ix86_decompose_address (rtx addr, struct ix86_address *out)
{
- rtx base = NULL_RTX;
- rtx index = NULL_RTX;
- rtx disp = NULL_RTX;
+ rtx base = NULL_RTX, index = NULL_RTX, disp = NULL_RTX;
+ rtx base_reg, index_reg;
HOST_WIDE_INT scale = 1;
rtx scale_rtx = NULL_RTX;
int retval = 1;
scale = INTVAL (scale_rtx);
}
+ base_reg = base && GET_CODE (base) == SUBREG ? SUBREG_REG (base) : base;
+ index_reg = index && GET_CODE (index) == SUBREG ? SUBREG_REG (index) : index;
+
/* Allow arg pointer and stack pointer as index if there is not scaling. */
- if (base && index && scale == 1
- && (index == arg_pointer_rtx
- || index == frame_pointer_rtx
- || (REG_P (index) && REGNO (index) == STACK_POINTER_REGNUM)))
+ if (base_reg && index_reg && scale == 1
+ && (index_reg == arg_pointer_rtx
+ || index_reg == frame_pointer_rtx
+ || (REG_P (index_reg) && REGNO (index_reg) == STACK_POINTER_REGNUM)))
{
- rtx tmp = base;
- base = index;
- index = tmp;
+ rtx tmp;
+ tmp = base, base = index, index = tmp;
+ tmp = base_reg, base_reg = index_reg, index_reg = tmp;
}
/* Special case: %ebp cannot be encoded as a base without a displacement. */
- if ((base == hard_frame_pointer_rtx
- || base == frame_pointer_rtx
- || base == arg_pointer_rtx) && !disp)
+ if ((base_reg == hard_frame_pointer_rtx
+ || base_reg == frame_pointer_rtx
+ || base_reg == arg_pointer_rtx) && !disp)
disp = const0_rtx;
/* Special case: on K6, [%esi] makes the instruction vector decoded.
Avoid this by transforming to [%esi+0]. */
if (ix86_tune == PROCESSOR_K6 && !optimize_size
- && base && !index && !disp
- && REG_P (base)
- && REGNO_REG_CLASS (REGNO (base)) == SIREG)
+ && base_reg && !index_reg && !disp
+ && REG_P (base_reg)
+ && REGNO_REG_CLASS (REGNO (base_reg)) == SIREG)
disp = const0_rtx;
/* Special case: encode reg+reg instead of reg*2. */
if (!base && index && scale && scale == 2)
- base = index, scale = 1;
+ base = index, base_reg = index_reg, scale = 1;
/* Special case: scaling cannot be encoded without base or displacement. */
if (!base && !disp && index && scale != 1)
if (!ix86_decompose_address (x, &parts))
abort ();
+ 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);
+
/* More complex memory references are better. */
if (parts.disp && parts.disp != const0_rtx)
cost--;
/* Validate base register.
- Don't allow SUBREG's here, it can lead to spill failures when the base
- is one word out of a two word structure, which is represented internally
- as a DImode int. */
+ Don't allow SUBREG's that span more than a word here. It can lead to spill
+ failures when the base is one word out of a two word structure, which is
+ represented internally as a DImode int. */
if (base)
{
+ rtx reg;
reason_rtx = base;
-
- if (GET_CODE (base) != REG)
+
+ if (REG_P (base))
+ reg = base;
+ else if (GET_CODE (base) == SUBREG
+ && REG_P (SUBREG_REG (base))
+ && GET_MODE_SIZE (GET_MODE (SUBREG_REG (base)))
+ <= UNITS_PER_WORD)
+ reg = SUBREG_REG (base);
+ else
{
reason = "base is not a register";
goto report_error;
goto report_error;
}
- if ((strict && ! REG_OK_FOR_BASE_STRICT_P (base))
- || (! strict && ! REG_OK_FOR_BASE_NONSTRICT_P (base)))
+ if ((strict && ! REG_OK_FOR_BASE_STRICT_P (reg))
+ || (! strict && ! REG_OK_FOR_BASE_NONSTRICT_P (reg)))
{
reason = "base is not valid";
goto report_error;
/* Validate index register.
- Don't allow SUBREG's here, it can lead to spill failures when the index
- is one word out of a two word structure, which is represented internally
- as a DImode int. */
+ Don't allow SUBREG's that span more than a word here -- same as above. */
if (index)
{
+ rtx reg;
reason_rtx = index;
- if (GET_CODE (index) != REG)
+ if (REG_P (index))
+ reg = index;
+ else if (GET_CODE (index) == SUBREG
+ && REG_P (SUBREG_REG (index))
+ && GET_MODE_SIZE (GET_MODE (SUBREG_REG (index)))
+ <= UNITS_PER_WORD)
+ reg = SUBREG_REG (index);
+ else
{
reason = "index is not a register";
goto report_error;
goto report_error;
}
- if ((strict && ! REG_OK_FOR_INDEX_STRICT_P (index))
- || (! strict && ! REG_OK_FOR_INDEX_NONSTRICT_P (index)))
+ if ((strict && ! REG_OK_FOR_INDEX_STRICT_P (reg))
+ || (! strict && ! REG_OK_FOR_INDEX_NONSTRICT_P (reg)))
{
reason = "index is not valid";
goto report_error;
if (! ix86_decompose_address (addr, &parts))
abort ();
+ 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);
+
base = parts.base;
index = parts.index;
disp = parts.disp;