|
|
1.1 root 1: /* Save and restore call-clobbered registers which are live across a call.
2: Copyright (C) 1989 Free Software Foundation, Inc.
3:
4: This file is part of GNU CC.
5:
6: GNU CC is free software; you can redistribute it and/or modify
7: it under the terms of the GNU General Public License as published by
8: the Free Software Foundation; either version 1, or (at your option)
9: any later version.
10:
11: GNU CC is distributed in the hope that it will be useful,
12: but WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14: GNU General Public License for more details.
15:
16: You should have received a copy of the GNU General Public License
17: along with GNU CC; see the file COPYING. If not, write to
18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19:
20: #include "config.h"
21: #include "rtl.h"
22: #include "insn-config.h"
23: #include "flags.h"
24: #include "regs.h"
25: #include "hard-reg-set.h"
26: #include "reload.h"
27: #include "recog.h"
28: #include "basic-block.h"
29:
30: /* Set of hard regs currently live (during scan of all insns). */
31:
32: static HARD_REG_SET hard_regs_live;
33:
34: /* The block of storage on the stack where regs are saved */
35:
36: static rtx save_block_addr;
37: static int save_block_size;
38:
39: /* A REG rtx for each hard register that has been saved. */
40:
41: static rtx save_reg_rtx[FIRST_PSEUDO_REGISTER];
42:
43: static void set_reg_live ();
44: static void clear_reg_live ();
45: static void insert_call_saves ();
46: static void emit_mult_save ();
47: static void emit_mult_restore ();
48: static rtx grow_save_block ();
49: static enum machine_mode choose_hard_reg_mode ();
50:
51: /* Find the places where hard regs are live across calls and save them. */
52:
53: save_call_clobbered_regs ()
54: {
55: rtx insn;
56: int b;
57:
58: if (obey_regdecls)
59: return;
60:
61: save_block_size = 0;
62: save_block_addr = 0;
63: bzero (save_reg_rtx, sizeof save_reg_rtx);
64:
65: for (b = 0; b < n_basic_blocks; b++)
66: {
67: regset regs_live = basic_block_live_at_start[b];
68: int offset, bit, i;
69:
70: /* Compute hard regs live at start of block -- this is the
71: real hard regs marked live, plus live pseudo regs that
72: have been renumbered to hard regs. */
73:
74: #ifdef HARD_REG_SET
75: hard_regs_live = *regs_live;
76: #else
77: COPY_HARD_REG_SET (hard_regs_live, regs_live);
78: #endif
79:
80: for (offset = 0, i = 0; offset < regset_size; offset++)
81: {
82: if (regs_live[offset] == 0)
83: i += HOST_BITS_PER_INT;
84: else
85: for (bit = 1; bit && i < max_regno; bit <<= 1, i++)
86: if ((regs_live[offset] & bit) && reg_renumber[i] >= 0)
87: SET_HARD_REG_BIT (hard_regs_live, reg_renumber[i]);
88: }
89:
90: /* Now scan the insns in the block, keeping track of what hard
91: regs are live as we go. When we see a call, save the live
92: call-clobbered hard regs. */
93:
94: for (insn = basic_block_head[b]; TRUE; insn = NEXT_INSN (insn))
95: {
96: RTX_CODE code = GET_CODE (insn);
97:
98: if (code == CALL_INSN)
99: insert_call_saves (insn);
100:
101: if (code == INSN || code == CALL_INSN || code == JUMP_INSN)
102: {
103: rtx link;
104:
105: /* NB: the normal procedure is to first enliven any
106: registers set by insn, then deaden any registers that
107: had their last use at insn. This is incorrect now,
108: since multiple pseudos may have been mapped to the
109: same hard reg, and the death notes are ambiguous. So
110: it must be done in the other, safe, order. */
111:
112: for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
113: if (REG_NOTE_KIND (link) == REG_DEAD)
114: clear_reg_live (XEXP (link, 0));
115:
116: note_stores (PATTERN (insn), set_reg_live);
117: }
118:
119: if (insn == basic_block_end[b])
120: break;
121: }
122: }
123: }
124:
125: /* Here from note_stores when an insn stores a value in a register.
126: Set the proper bit or bits in hard_regs_live. */
127:
128: static void
129: set_reg_live (reg, setter)
130: rtx reg, setter;
131: {
132: register int regno;
133:
134: /* WORD is which word of a multi-register group is being stored.
135: For the case where the store is actually into a SUBREG of REG.
136: Except we don't use it; I believe the entire REG needs to be
137: live. */
138: int word = 0;
139:
140: if (GET_CODE (reg) == SUBREG)
141: {
142: word = SUBREG_WORD (reg);
143: reg = SUBREG_REG (reg);
144: }
145:
146: if (GET_CODE (reg) != REG)
147: return;
148:
149: regno = REGNO (reg);
150:
151: /* For pseudo reg, see if it has been assigned a hardware reg. */
152: if (reg_renumber[regno] >= 0)
153: regno = reg_renumber[regno] /* + word */;
154:
155: /* Handle hardware regs (and pseudos allocated to hard regs). */
156: if (regno < FIRST_PSEUDO_REGISTER && ! call_fixed_regs[regno])
157: {
158: register int last = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg));
159: while (regno < last)
160: {
161: SET_HARD_REG_BIT (hard_regs_live, regno);
162: regno++;
163: }
164: }
165: }
166:
167: /* Here when a REG_DEAD note records the last use of a reg. Clear
168: the appropriate bit or bits in hard_regs_live. */
169:
170: static void
171: clear_reg_live (reg)
172: rtx reg;
173: {
174: register int regno = REGNO (reg);
175:
176: /* For pseudo reg, see if it has been assigned a hardware reg. */
177: if (reg_renumber[regno] >= 0)
178: regno = reg_renumber[regno];
179:
180: /* Handle hardware regs (and pseudos allocated to hard regs). */
181: if (regno < FIRST_PSEUDO_REGISTER && ! call_fixed_regs[regno])
182: {
183: /* Pseudo regs already assigned hardware regs are treated
184: almost the same as explicit hardware regs. */
185: register int last = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg));
186: while (regno < last)
187: {
188: CLEAR_HARD_REG_BIT (hard_regs_live, regno);
189: regno++;
190: }
191: }
192: }
193:
194: /* Insert insns to save and restore live call-clobbered regs around
195: call insn INSN. */
196:
197: static void
198: insert_call_saves (insn)
199: rtx insn;
200: {
201: int regno;
202: int save_block_size_needed;
203: int save_block_offset[FIRST_PSEUDO_REGISTER];
204:
205: save_block_size_needed = 0;
206:
207: for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
208: {
209: save_block_offset[regno] = -1;
210: if (call_used_regs[regno] && ! call_fixed_regs[regno]
211: && TEST_HARD_REG_BIT (hard_regs_live, regno))
212: {
213: enum machine_mode mode = choose_hard_reg_mode (regno);
214: int align = GET_MODE_UNIT_SIZE (mode);
215: if (align > BIGGEST_ALIGNMENT / BITS_PER_UNIT)
216: align = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
217: save_block_size_needed =
218: ((save_block_size_needed + align - 1) / align) * align;
219: save_block_offset[regno] = save_block_size_needed;
220: save_block_size_needed += GET_MODE_SIZE (mode);
221: if (! save_reg_rtx[regno])
222: save_reg_rtx[regno] = gen_rtx (REG, mode, regno);
223: }
224: }
225:
226: if (save_block_size < save_block_size_needed)
227: save_block_addr = grow_save_block (save_block_addr,
228: save_block_size_needed);
229: emit_mult_save (insn, save_block_addr, save_block_offset);
230: emit_mult_restore (insn, save_block_addr, save_block_offset);
231: }
232:
233: /* Emit a string of stores to save the hard regs listed in
1.1.1.2 ! root 234: OFFSET[] at address ADDR. Emit them before INSN.
1.1 root 235: OFFSET[reg] is -1 if reg should not be saved, or a
236: suitably-aligned offset from ADDR.
237: The offsets actually used do not have to be those listed
238: in OFFSET, but should fit in a block of the same size. */
239:
240: static void
241: emit_mult_save (insn, addr, offset)
242: rtx insn, addr;
243: int offset[];
244: {
245: int regno;
1.1.1.2 ! root 246: /* A register to use as a temporary for address calculations. */
! 247: rtx tempreg;
! 248: /* A register that could be used as that temp if we save and restore it. */
! 249: rtx can_push_reg;
! 250: /* Nonzero means we need to save a register to use it as TEMPREG. */
! 251: int needpush;
! 252: /* The amount the stack is decremented to save that register (if we do). */
! 253: int decrement;
! 254: /* Record which regs we save, in case we branch to retry. */
! 255: char already_saved[FIRST_PSEUDO_REGISTER];
! 256:
! 257: bzero (already_saved, sizeof already_saved);
! 258:
! 259: /* Hair is needed because sometimes the addresses to save in are
! 260: not valid (offsets too big).
! 261: So we need a reg, TEMPREG, to compute addresses in.
! 262:
! 263: We look first for an empty reg to use.
! 264: Sometimes no reg is empty. Then we push a reg, use it, and pop it.
! 265:
! 266: Sometimes the only reg to push and pop this way is one we want to save.
! 267: We can't save it while using it as a temporary.
! 268: So we save all the other registers, pop it, and go back to `retry'.
! 269: At that point, only this reg remains to be saved;
! 270: all the others already saved are empty.
! 271: So one of them can be the temporary for this one. */
! 272:
! 273: /* Sometimes we can't save all the regs conveniently at once, just some.
! 274: If that happens, we branch back here to save the rest. */
! 275: retry:
! 276: needpush = 0;
! 277: tempreg = 0;
! 278: can_push_reg = 0;
! 279:
! 280: /* Set NEEDPUSH if any save-addresses are not valid memory addresses.
! 281: If any register is available, record it in TEMPREG.
! 282: If any register doesn't need saving here, record it in CAN_PUSH_REG. */
! 283: for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
! 284: {
! 285: if (offset[regno] >= 0 && ! already_saved[regno])
! 286: {
! 287: rtx reg = save_reg_rtx[regno];
! 288: rtx addr1 = plus_constant (addr, offset[regno]);
! 289: if (memory_address_p (GET_MODE (reg), addr1))
! 290: needpush = 1;
! 291: }
! 292:
! 293: /* A call-clobbered reg that is dead, or already saved,
! 294: can be used as a temporary for sure, at no extra cost. */
! 295: if (tempreg == 0 && call_used_regs[regno] && ! fixed_regs[regno]
! 296: && !(offset[regno] >= 0 && ! already_saved[regno])
! 297: && HARD_REGNO_MODE_OK (regno, Pmode))
! 298: {
! 299: tempreg = gen_rtx (REG, Pmode, regno);
! 300: /* Don't use it if not valid for addressing. */
! 301: if (! strict_memory_address_p (QImode, tempreg))
! 302: tempreg = 0;
! 303: }
! 304:
! 305: /* A call-saved reg can be a temporary if we push and pop it. */
! 306: if (can_push_reg == 0 && ! call_used_regs[regno]
! 307: && HARD_REGNO_MODE_OK (regno, Pmode))
! 308: {
! 309: can_push_reg = gen_rtx (REG, Pmode, regno);
! 310: /* Don't use it if not valid for addressing. */
! 311: if (! strict_memory_address_p (QImode, can_push_reg))
! 312: can_push_reg = 0;
! 313: }
! 314: }
! 315:
! 316: /* Clear NEEDPUSH if we already found an empty reg. */
! 317: if (tempreg != 0)
! 318: needpush = 0;
! 319:
! 320: /* If we need a temp reg and none is free, make one free. */
! 321: if (needpush)
! 322: {
! 323: /* Choose a reg, preferably not among those it is our job to save. */
! 324: if (can_push_reg != 0)
! 325: tempreg = can_push_reg;
! 326: else
! 327: {
! 328: for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
! 329: if (offset[regno] >= 0 && !already_saved[regno]
! 330: && HARD_REGNO_MODE_OK (regno, Pmode))
! 331: {
! 332: tempreg = gen_rtx (REG, Pmode, regno);
! 333: /* Don't use it if not valid for addressing. */
! 334: if (! strict_memory_address_p (QImode, tempreg))
! 335: tempreg = 0;
! 336: else
! 337: break;
! 338: }
! 339: }
! 340:
! 341: /* Push it on the stack. */
! 342: #ifdef STACK_GROWS_DOWNWARD
! 343: decrement = UNITS_PER_WORD;
! 344: #else
! 345: decrement = - UNITS_PER_WORD;
! 346: #endif
! 347:
! 348: emit_insn_before (gen_add2_insn (stack_pointer_rtx,
! 349: gen_rtx (CONST_INT, VOIDmode, -decrement)),
! 350: insn);
! 351: emit_insn_before (gen_move_insn (gen_rtx (MEM, Pmode, stack_pointer_rtx),
! 352: tempreg),
! 353: insn);
! 354: }
1.1 root 355:
1.1.1.2 ! root 356: /* Save the regs we are supposed to save, aside from TEMPREG.
! 357: Use TEMPREG for address calculations when needed. */
1.1 root 358: for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
1.1.1.2 ! root 359: if (offset[regno] >= 0 && ! already_saved[regno]
! 360: && tempreg != 0 && REGNO (tempreg) != regno)
1.1 root 361: {
362: rtx reg = save_reg_rtx[regno];
1.1.1.2 ! root 363: rtx addr1 = plus_constant (addr, offset[regno]);
! 364: rtx temp;
! 365: if (! memory_address_p (GET_MODE (reg), addr1))
! 366: {
! 367: if (GET_CODE (addr1) != PLUS)
! 368: abort ();
! 369: if (GET_CODE (XEXP (addr1, 1)) != CONST_INT
! 370: || GET_CODE (XEXP (addr1, 0)) != REG)
! 371: abort ();
! 372: emit_insn_before (gen_move_insn (tempreg, XEXP (addr1, 0)), insn);
! 373: emit_insn_before (gen_add2_insn (tempreg, XEXP (addr1, 1)), insn);
! 374: addr1 = tempreg;
! 375: }
! 376: temp = gen_rtx (MEM, GET_MODE (reg), addr1);
1.1 root 377: emit_insn_before (gen_move_insn (temp, reg), insn);
1.1.1.2 ! root 378: already_saved[regno] = 1;
1.1 root 379: }
1.1.1.2 ! root 380:
! 381: /* If we pushed TEMPREG to make it free, pop it. */
! 382: if (needpush)
! 383: {
! 384: emit_insn_before (gen_move_insn (tempreg,
! 385: gen_rtx (MEM, Pmode, stack_pointer_rtx)),
! 386: insn);
! 387: emit_insn_before (gen_add2_insn (stack_pointer_rtx,
! 388: gen_rtx (CONST_INT, VOIDmode, decrement)),
! 389: insn);
! 390: }
! 391:
! 392: /* If TEMPREG itself needs saving, go back and save it.
! 393: There are plenty of free regs now, those already saved. */
! 394: if (tempreg != 0
! 395: && offset[REGNO (tempreg)] >= 0 && ! already_saved[REGNO (tempreg)])
! 396: goto retry;
1.1 root 397: }
398:
399: /* Emit a string of loads to restore the hard regs listed in
1.1.1.2 ! root 400: OFFSET[] from address ADDR; insert the loads after INSN.
1.1 root 401: OFFSET[reg] is -1 if reg should not be loaded, or a
402: suitably-aligned offset from ADDR.
403: The offsets actually used do not need to be those provided in
404: OFFSET, but should agree with whatever emit_mult_save does. */
405:
406: static void
407: emit_mult_restore (insn, addr, offset)
408: rtx insn, addr;
1.1.1.2 ! root 409: int offset[];
1.1 root 410: {
411: int regno;
412:
1.1.1.2 ! root 413: /* Number of regs now needing to be restored. */
! 414: int restore_count;
! 415: /* A register to use as a temporary for address calculations. */
! 416: rtx tempreg;
! 417: /* A register available for that purpose but less desirable. */
! 418: rtx maybe_tempreg;
! 419: /* A register that could be used as that temp if we push and pop it. */
! 420: rtx can_push_reg;
! 421: /* Nonzero means we need to push and pop a register to use it as TEMPREG. */
! 422: int needpush;
! 423: /* The amount the stack is decremented to save that register (if we do). */
! 424: int decrement;
! 425: /* Record which regs we restore, in case we branch to retry. */
! 426: char already_restored[FIRST_PSEUDO_REGISTER];
! 427:
! 428: bzero (already_restored, sizeof already_restored);
! 429:
! 430: /* Note: INSN can't be the last insn, since if it were,
! 431: no regs would live across it. */
! 432: insn = NEXT_INSN (insn);
! 433: if (insn == 0)
! 434: abort ();
! 435: /* Now we can insert before INSN.
! 436: That is convenient because we can insert them in the order
! 437: that they should ultimately appear. */
! 438:
! 439: /* Hair is needed because sometimes the addresses to restore from are
! 440: not valid (offsets too big).
! 441: So we need a reg, TEMPREG, to compute addresses in.
! 442:
! 443: We look first for an empty reg to use.
! 444: Sometimes no reg is empty. Then we push a reg, use it, and pop it.
! 445:
! 446: If all the suitable regs need to be restored,
! 447: that strategy won't work. So we restore all but one, using that one
! 448: as a temporary. Then we jump to `retry' to restore that one,
! 449: pushing and popping another (already restored) as a temporary. */
! 450:
! 451: retry:
! 452: needpush = 0;
! 453: tempreg = 0;
! 454: can_push_reg = 0;
! 455: restore_count = 0;
! 456:
! 457: /* Set NEEDPUSH if any restore-addresses are not valid memory addresses.
! 458: If any register is available, record it in TEMPREG.
! 459: Otherwise, one register yet to be restored goes in MAYBE_TEMPREG,
! 460: and can be used as TEMPREG for any other regs to be restored.
! 461: If any register doesn't need restoring, record it in CAN_PUSH_REG. */
! 462: for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
! 463: {
! 464: if (offset[regno] >= 0 && ! already_restored[regno])
! 465: {
! 466: rtx reg = save_reg_rtx[regno];
! 467: rtx addr1 = plus_constant (addr, offset[regno]);
! 468:
! 469: restore_count++;
! 470:
! 471: if (memory_address_p (GET_MODE (reg), addr1))
! 472: needpush = 1;
! 473:
! 474: /* Find a call-clobbered reg that needs restoring.
! 475: We can use it as a temporary if we defer restoring it. */
! 476: if (maybe_tempreg == 0)
! 477: {
! 478: maybe_tempreg = gen_rtx (REG, Pmode, regno);
! 479: /* Don't use it if not valid for addressing. */
! 480: if (! strict_memory_address_p (QImode, maybe_tempreg))
! 481: maybe_tempreg = 0;
! 482: }
! 483: }
! 484:
! 485: /* If any call-clobbered reg is dead, put it in TEMPREG.
! 486: It can be used as a temporary at no extra cost. */
! 487: if (tempreg == 0 && call_used_regs[regno] && ! fixed_regs[regno]
! 488: && ! offset[regno] >= 0
! 489: && HARD_REGNO_MODE_OK (regno, Pmode))
! 490: {
! 491: tempreg = gen_rtx (REG, Pmode, regno);
! 492: /* Don't use it if not valid for addressing. */
! 493: if (! strict_memory_address_p (QImode, tempreg))
! 494: tempreg = 0;
! 495: }
! 496:
! 497: /* Any non-call-clobbered reg, put in CAN_PUSH_REG.
! 498: It can be used as a temporary if we push and pop it. */
! 499: if (can_push_reg == 0 && ! call_used_regs[regno]
! 500: && HARD_REGNO_MODE_OK (regno, Pmode))
! 501: {
! 502: can_push_reg = gen_rtx (REG, Pmode, regno);
! 503: /* Don't use it if not valid for addressing. */
! 504: if (! strict_memory_address_p (QImode, can_push_reg))
! 505: can_push_reg = 0;
! 506: }
! 507: /* Any reg we already restored can be a temporary
! 508: if we push and pop it. */
! 509: if (can_push_reg == 0 && already_restored[regno]
! 510: && HARD_REGNO_MODE_OK (regno, Pmode))
! 511: {
! 512: can_push_reg = gen_rtx (REG, Pmode, regno);
! 513: /* Don't use it if not valid for addressing. */
! 514: if (! strict_memory_address_p (QImode, can_push_reg))
! 515: can_push_reg = 0;
! 516: }
! 517: }
! 518:
! 519: /* If 2 or more regs need to be restored, use one as a temp reg
! 520: for the rest (if we need a tempreg). */
! 521: if (tempreg == 0 && maybe_tempreg != 0 && restore_count > 1)
! 522: tempreg = maybe_tempreg;
! 523:
! 524: /* Clear NEEDPUSH if we already found an empty reg. */
! 525: if (tempreg != 0)
! 526: needpush = 0;
! 527:
! 528: /* If we need a temp reg and none is free, make one free. */
! 529: if (needpush)
! 530: {
! 531: tempreg = can_push_reg;
! 532:
! 533: /* Push it on the stack. */
! 534: #ifdef STACK_GROWS_DOWNWARD
! 535: decrement = UNITS_PER_WORD;
! 536: #else
! 537: decrement = - UNITS_PER_WORD;
! 538: #endif
! 539:
! 540: emit_insn_before (gen_add2_insn (stack_pointer_rtx,
! 541: gen_rtx (CONST_INT, VOIDmode, -decrement)),
! 542: insn);
! 543: emit_insn_before (gen_move_insn (gen_rtx (MEM, Pmode, stack_pointer_rtx),
! 544: tempreg),
! 545: insn);
! 546: }
! 547:
! 548: /* Restore the regs we are supposed to restore, aside from TEMPREG.
! 549: Use TEMPREG for address calculations when needed. */
! 550: for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
! 551: if (offset[regno] >= 0 && ! already_restored[regno]
! 552: && tempreg != 0 && REGNO (tempreg) != regno)
1.1 root 553: {
554: rtx reg = save_reg_rtx[regno];
1.1.1.2 ! root 555: rtx addr1 = plus_constant (addr, offset[regno]);
! 556: rtx temp;
! 557: if (! memory_address_p (GET_MODE (reg), addr1))
! 558: {
! 559: if (GET_CODE (addr1) != PLUS)
! 560: abort ();
! 561: if (GET_CODE (XEXP (addr1, 1)) != CONST_INT
! 562: || GET_CODE (XEXP (addr1, 0)) != REG)
! 563: abort ();
! 564: emit_insn_before (gen_move_insn (tempreg, XEXP (addr1, 0)), insn);
! 565: emit_insn_before (gen_add2_insn (tempreg, XEXP (addr1, 1)), insn);
! 566: addr1 = tempreg;
! 567: }
! 568: temp = gen_rtx (MEM, GET_MODE (reg), addr1);
! 569: emit_insn_before (gen_move_insn (reg, temp), insn);
! 570: already_restored[regno] = 1;
1.1 root 571: }
1.1.1.2 ! root 572:
! 573: /* If we pushed TEMPREG to make it free, pop it. */
! 574: if (needpush)
! 575: {
! 576: emit_insn_before (gen_move_insn (tempreg,
! 577: gen_rtx (MEM, Pmode, stack_pointer_rtx)),
! 578: insn);
! 579: emit_insn_before (gen_add2_insn (stack_pointer_rtx,
! 580: gen_rtx (CONST_INT, VOIDmode, decrement)),
! 581: insn);
! 582: }
! 583:
! 584: /* If TEMPREG itself needs restoring, go back and restore it.
! 585: We can find a reg already restored to push and use as a temporary. */
! 586: if (tempreg != 0
! 587: && offset[REGNO (tempreg)] >= 0 && ! already_restored[REGNO (tempreg)])
! 588: goto retry;
1.1 root 589: }
590:
591: /* Return the address of a new block of size SIZE on the stack.
592: The old save block is at ADDR; ADDR is 0 if no block exists yet. */
593:
594: static rtx
595: grow_save_block (addr, size)
596: rtx addr;
597: int size;
598: {
599: rtx newaddr;
600:
601: /* Keep the size a multiple of the main allocation unit. */
602: size = (((size + (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1)
603: / (BIGGEST_ALIGNMENT / BITS_PER_UNIT))
604: * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
605:
606: /* If no save block exists yet, create one and return it. */
607: if (! addr)
608: {
609: save_block_size = size;
610: return XEXP (assign_stack_local (BLKmode, size), 0);
611: }
612:
613: /* Get a new block and coalesce it with the old one. */
614: newaddr = XEXP (assign_stack_local (BLKmode, size - save_block_size), 0);
615: if (GET_CODE (newaddr) == PLUS
616: && XEXP (newaddr, 0) == frame_pointer_rtx
617: && GET_CODE (XEXP (newaddr, 1)) == CONST_INT
618: && GET_CODE (addr) == PLUS
619: && XEXP (addr, 0) == frame_pointer_rtx
620: && GET_CODE (XEXP (addr, 1)) == CONST_INT
621: && ((INTVAL (XEXP (newaddr, 1)) - INTVAL (XEXP (addr, 1))
622: == size - save_block_size)
623: || (INTVAL (XEXP (addr, 1)) - INTVAL (XEXP (newaddr, 1))
624: == size - save_block_size)))
625: {
626: save_block_size = size;
627: if (INTVAL (XEXP (newaddr, 1)) < INTVAL (XEXP (addr, 1)))
628: return newaddr;
629: else
630: return addr;
631: }
632:
633: /* They didn't coalesce, find out why */
634: abort ();
635:
636: save_block_size = size;
637: return XEXP (assign_stack_local (BLKmode, size), 0);
638: }
639:
640: /* Return a machine mode that is legitimate for hard reg REGNO
641: and large enough to save the whole register. */
642:
643: static enum machine_mode
644: choose_hard_reg_mode (regno)
645: int regno;
646: {
647: enum reg_class class = REGNO_REG_CLASS (regno);
648:
649: if (CLASS_MAX_NREGS (class, DImode) == 1
650: && HARD_REGNO_MODE_OK (regno, DImode))
651: return DImode;
652: else if (CLASS_MAX_NREGS (class, DFmode) == 1
653: && HARD_REGNO_MODE_OK (regno, DFmode))
654: return DFmode;
655: else if (CLASS_MAX_NREGS (class, SImode) == 1
656: && HARD_REGNO_MODE_OK (regno, SImode))
657: return SImode;
658: else if (CLASS_MAX_NREGS (class, SFmode) == 1
659: && HARD_REGNO_MODE_OK (regno, SFmode))
660: return SFmode;
661: else if (CLASS_MAX_NREGS (class, HImode) == 1
662: && HARD_REGNO_MODE_OK (regno, HImode))
663: return HImode;
664: else
665: abort ();
666: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.