}
else if (out == 2)
{
+ auto address_mode = targetm.addr_space.address_mode (info->as);
+ rtx inner_op0 = *inner_ops[0];
+ rtx inner_op1 = *inner_ops[1];
+ int base;
+ /* If one inner operand has the expected mode for a base and the other
+ doesn't, assume that the other one is the index. This is useful
+ for addresses such as:
+
+ (plus (zero_extend X) Y)
+
+ zero_extend is not in itself enough to assume an index, since bases
+ can be zero-extended on POINTERS_EXTEND_UNSIGNED targets. But if
+ Y has address mode and X doesn't, there should be little doubt that
+ Y is the base. */
+ if (GET_MODE (inner_op0) == address_mode
+ && GET_MODE (inner_op1) != address_mode)
+ base = 0;
+ else if (GET_MODE (inner_op1) == address_mode
+ && GET_MODE (inner_op0) != address_mode)
+ base = 1;
/* In the event of a tie, assume the base comes first. */
- if (baseness (*inner_ops[0], info->mode, info->as, PLUS,
- GET_CODE (*ops[1]))
- >= baseness (*inner_ops[1], info->mode, info->as, PLUS,
- GET_CODE (*ops[0])))
- {
- set_address_base (info, ops[0], inner_ops[0]);
- set_address_index (info, ops[1], inner_ops[1]);
- }
+ else if (baseness (inner_op0, info->mode, info->as, PLUS,
+ GET_CODE (*ops[1]))
+ >= baseness (inner_op1, info->mode, info->as, PLUS,
+ GET_CODE (*ops[0])))
+ base = 0;
else
- {
- set_address_base (info, ops[1], inner_ops[1]);
- set_address_index (info, ops[0], inner_ops[0]);
- }
+ base = 1;
+ set_address_base (info, ops[base], inner_ops[base]);
+ set_address_index (info, ops[1 - base], inner_ops[1 - base]);
}
else
gcc_assert (out == 0);