rtx indx;
rtx disp;
bool pointer;
+ bool literal_pool;
};
/* Which cpu are we tuning for. */
bool pointer = false;
bool base_ptr = false;
bool indx_ptr = false;
+ bool literal_pool = false;
+
+ /* We may need to substitute the literal pool base register into the address
+ below. However, at this point we do not know which register is going to
+ be used as base, so we substitute the arg pointer register. This is going
+ to be treated as holding a pointer below -- it shouldn't be used for any
+ other purpose. */
+ rtx fake_pool_base = gen_rtx_REG (Pmode, ARG_POINTER_REGNUM);
/* Decompose address into base + index + displacement. */
{
/* Either base or index must be free to hold the base register. */
if (!base)
- base = gen_rtx_REG (Pmode, BASE_REGNUM);
+ base = fake_pool_base, literal_pool = true;
else if (!indx)
- indx = gen_rtx_REG (Pmode, BASE_REGNUM);
+ indx = fake_pool_base, literal_pool = true;
else
return false;
else
return false;
- base = gen_rtx_REG (Pmode, BASE_REGNUM);
+ base = XVECEXP (base, 0, 1);
break;
case UNSPEC_LTREL_BASE:
- base = gen_rtx_REG (Pmode, BASE_REGNUM);
+ if (XVECLEN (base, 0) == 1)
+ base = fake_pool_base, literal_pool = true;
+ else
+ base = XVECEXP (base, 0, 1);
break;
default:
if (GET_CODE (base) != REG || GET_MODE (base) != Pmode)
return false;
- if (REGNO (base) == BASE_REGNUM
- || REGNO (base) == STACK_POINTER_REGNUM
+ if (REGNO (base) == STACK_POINTER_REGNUM
|| REGNO (base) == FRAME_POINTER_REGNUM
|| ((reload_completed || reload_in_progress)
&& frame_pointer_needed
|| (flag_pic
&& REGNO (base) == PIC_OFFSET_TABLE_REGNUM))
pointer = base_ptr = true;
+
+ if ((reload_completed || reload_in_progress)
+ && base == cfun->machine->base_reg)
+ pointer = base_ptr = literal_pool = true;
}
/* Validate index register. */
else
return false;
- indx = gen_rtx_REG (Pmode, BASE_REGNUM);
+ indx = XVECEXP (indx, 0, 1);
break;
case UNSPEC_LTREL_BASE:
- indx = gen_rtx_REG (Pmode, BASE_REGNUM);
+ if (XVECLEN (indx, 0) == 1)
+ indx = fake_pool_base, literal_pool = true;
+ else
+ indx = XVECEXP (indx, 0, 1);
break;
default:
if (GET_CODE (indx) != REG || GET_MODE (indx) != Pmode)
return false;
- if (REGNO (indx) == BASE_REGNUM
- || REGNO (indx) == STACK_POINTER_REGNUM
+ if (REGNO (indx) == STACK_POINTER_REGNUM
|| REGNO (indx) == FRAME_POINTER_REGNUM
|| ((reload_completed || reload_in_progress)
&& frame_pointer_needed
|| (flag_pic
&& REGNO (indx) == PIC_OFFSET_TABLE_REGNUM))
pointer = indx_ptr = true;
+
+ if ((reload_completed || reload_in_progress)
+ && indx == cfun->machine->base_reg)
+ pointer = indx_ptr = literal_pool = true;
}
/* Prefer to use pointer as base, not index. */
out->indx = indx;
out->disp = orig_disp;
out->pointer = pointer;
+ out->literal_pool = literal_pool;
}
return true;
return 0;
if (!s390_decompose_address (XEXP (op, 0), &addr))
return 0;
- if (addr.base && REG_P (addr.base) && REGNO (addr.base) == BASE_REGNUM)
- return 0;
- if (addr.indx && REG_P (addr.indx) && REGNO (addr.indx) == BASE_REGNUM)
+ if (addr.literal_pool)
return 0;
c = str[1];
--- /dev/null
+
+struct w
+{
+ int top;
+ int left;
+ int height;
+ int width;
+ struct w *next;
+ struct w *parent;
+ struct w *child;
+};
+
+extern struct w *Qnil;
+
+void
+set_size (struct w *w, int new_size, int nodelete, int set_height)
+{
+ int old_size = set_height? w->height : w->width;
+
+ if (nodelete || w->parent == Qnil)
+ {
+ int last_pos, last_old_pos, pos, old_pos, first;
+ int div_val = old_size << 1;
+ struct w *c;
+
+ last_pos = first = set_height? w->top : w->left;
+ last_old_pos = 0;
+
+ for (c = w->child; c != Qnil; c = c->next)
+ {
+ if (set_height)
+ old_pos = last_old_pos + c->height;
+ else
+ old_pos = last_old_pos + c->width;
+
+ pos = (((old_pos * new_size) << 1) + old_size) / div_val;
+ set_size (c, pos + first - last_pos, 1, set_height);
+ last_pos = pos + first;
+ last_old_pos = old_pos;
+ }
+
+ if (!nodelete)
+ for (c = w->child; c != Qnil; c = c->next)
+ use (c);
+ }
+}
+