Annotation of gcc/caller-save.c, revision 1.1.1.3

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]
1.1.1.3 ! root      488:          && offset[regno] < 0
1.1.1.2   root      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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.