Annotation of gcc/config/sh/sh.c, revision 1.1.1.4

1.1.1.4 ! root        1: /* Output routines for GCC for Hitachi Super-H.
        !             2:    Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
1.1       root        3: 
1.1.1.4 ! root        4: This file is part of GNU CC.
1.1       root        5: 
1.1.1.4 ! root        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 2, 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, 59 Temple Place - Suite 330,
        !            19: Boston, MA 02111-1307, USA.  */
1.1.1.3   root       20: 
1.1.1.4 ! root       21: /* Contributed by Steve Chamberlain ([email protected]).
        !            22:    Improved by Jim Wilson ([email protected]).  */
1.1.1.3   root       23: 
1.1.1.4 ! root       24: #include "config.h"
1.1       root       25: 
                     26: #include <stdio.h>
1.1.1.4 ! root       27: 
1.1       root       28: #include "rtl.h"
                     29: #include "tree.h"
                     30: #include "flags.h"
1.1.1.4 ! root       31: #include "insn-flags.h"
1.1       root       32: #include "expr.h"
1.1.1.4 ! root       33: #include "regs.h"
        !            34: #include "hard-reg-set.h"
        !            35: #include "output.h"
1.1       root       36: 
1.1.1.4 ! root       37: #define MSW (TARGET_LITTLE_ENDIAN ? 1 : 0)
        !            38: #define LSW (TARGET_LITTLE_ENDIAN ? 0 : 1)
1.1       root       39: 
1.1.1.4 ! root       40: /* ??? The pragma interrupt support will not work for SH3.  */
        !            41: /* This is set by #pragma interrupt and #pragma trapa, and causes gcc to
        !            42:    output code for the next function appropriate for an interrupt handler.  */
1.1.1.3   root       43: int pragma_interrupt;
1.1       root       44: 
1.1.1.4 ! root       45: /* This is set by #pragma trapa, and is similar to the above, except that
        !            46:    the compiler doesn't emit code to preserve all registers.  */
        !            47: static int pragma_trapa;
        !            48: 
        !            49: /* This is used for communication between SETUP_INCOMING_VARARGS and
        !            50:    sh_expand_prologue.  */
1.1       root       51: int current_function_anonymous_args;
1.1.1.2   root       52: 
1.1.1.4 ! root       53: /* Global variables from toplev.c and final.c that are used within, but
        !            54:    not declared in any header file.  */
        !            55: extern char *version_string;
        !            56: extern int *insn_addresses;
1.1       root       57: 
                     58: /* Global variables for machine-dependent things. */
                     59: 
1.1.1.4 ! root       60: /* Which cpu are we scheduling for.  */
        !            61: enum processor_type sh_cpu;
        !            62: 
1.1       root       63: /* Saved operands from the last compare to use when we generate an scc
1.1.1.4 ! root       64:    or bcc insn.  */
1.1       root       65: 
                     66: rtx sh_compare_op0;
                     67: rtx sh_compare_op1;
                     68: 
                     69: /* Provides the class number of the smallest class containing
1.1.1.4 ! root       70:    reg number.  */
1.1       root       71: 
                     72: int regno_reg_class[FIRST_PSEUDO_REGISTER] =
                     73: {
                     74:   R0_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
                     75:   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
                     76:   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
                     77:   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
1.1.1.3   root       78:   GENERAL_REGS, PR_REGS, T_REGS, NO_REGS,
                     79:   MAC_REGS, MAC_REGS,
1.1       root       80: };
                     81: 
                     82: /* Provide reg_class from a letter such as appears in the machine
1.1.1.4 ! root       83:    description.  */
1.1       root       84: 
                     85: enum reg_class reg_class_from_letter[] =
                     86: {
                     87:   /* a */ NO_REGS, /* b */ NO_REGS, /* c */ NO_REGS, /* d */ NO_REGS,
                     88:   /* e */ NO_REGS, /* f */ NO_REGS, /* g */ NO_REGS, /* h */ NO_REGS,
                     89:   /* i */ NO_REGS, /* j */ NO_REGS, /* k */ NO_REGS, /* l */ PR_REGS,
                     90:   /* m */ NO_REGS, /* n */ NO_REGS, /* o */ NO_REGS, /* p */ NO_REGS,
                     91:   /* q */ NO_REGS, /* r */ NO_REGS, /* s */ NO_REGS, /* t */ T_REGS,
                     92:   /* u */ NO_REGS, /* v */ NO_REGS, /* w */ NO_REGS, /* x */ MAC_REGS,
                     93:   /* y */ NO_REGS, /* z */ R0_REGS
                     94: };
1.1.1.2   root       95: 
1.1.1.4 ! root       96: /* Print the operand address in x to the stream.  */
1.1       root       97: 
                     98: void
                     99: print_operand_address (stream, x)
                    100:      FILE *stream;
                    101:      rtx x;
                    102: {
                    103:   switch (GET_CODE (x))
                    104:     {
                    105:     case REG:
                    106:       fprintf (stream, "@%s", reg_names[REGNO (x)]);
                    107:       break;
1.1.1.4 ! root      108: 
1.1       root      109:     case PLUS:
                    110:       {
                    111:        rtx base = XEXP (x, 0);
                    112:        rtx index = XEXP (x, 1);
                    113: 
                    114:        switch (GET_CODE (index))
                    115:          {
                    116:          case CONST_INT:
1.1.1.4 ! root      117:            fprintf (stream, "@(%d,%s)", INTVAL (index),
1.1       root      118:                     reg_names[REGNO (base)]);
                    119:            break;
                    120: 
                    121:          case REG:
1.1.1.2   root      122:            fprintf (stream, "@(r0,%s)",
                    123:                     reg_names[MAX (REGNO (base), REGNO (index))]);
1.1       root      124:            break;
                    125: 
                    126:          default:
1.1.1.2   root      127:            debug_rtx (x);
1.1       root      128:            abort ();
                    129:          }
                    130:       }
                    131:       break;
1.1.1.4 ! root      132: 
1.1       root      133:     case PRE_DEC:
                    134:       fprintf (stream, "@-%s", reg_names[REGNO (XEXP (x, 0))]);
                    135:       break;
                    136: 
                    137:     case POST_INC:
                    138:       fprintf (stream, "@%s+", reg_names[REGNO (XEXP (x, 0))]);
                    139:       break;
                    140: 
                    141:     default:
                    142:       output_addr_const (stream, x);
                    143:       break;
                    144:     }
                    145: }
                    146: 
                    147: /* Print operand x (an rtx) in assembler syntax to file stream
                    148:    according to modifier code.
                    149: 
1.1.1.2   root      150:    '.'  print a .s if insn needs delay slot
1.1.1.3   root      151:    '@'  print rte or rts depending upon pragma interruptness
1.1.1.4 ! root      152:    '#'  output a nop if there is nothing to put in the delay slot
1.1.1.2   root      153:    'O'  print a constant without the #
1.1.1.4 ! root      154:    'R'  print the LSW of a dp value - changes if in little endian
        !           155:    'S'  print the MSW of a dp value - changes if in little endian
        !           156:    'T'  print the next word of a dp value - same as 'R' in big endian mode.  */
1.1       root      157: 
                    158: void
                    159: print_operand (stream, x, code)
                    160:      FILE *stream;
                    161:      rtx x;
                    162:      int code;
                    163: {
                    164:   switch (code)
                    165:     {
1.1.1.2   root      166:     case '.':
1.1.1.4 ! root      167:       if (final_sequence
        !           168:          && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
1.1.1.2   root      169:        fprintf (stream, ".s");
                    170:       break;
1.1.1.3   root      171:     case '@':
                    172:       if (pragma_interrupt)
                    173:        fprintf (stream, "rte");
                    174:       else
                    175:        fprintf (stream, "rts");
                    176:       break;
1.1       root      177:     case '#':
1.1.1.4 ! root      178:       /* Output a nop if there's nothing in the delay slot.  */
1.1       root      179:       if (dbr_sequence_length () == 0)
1.1.1.4 ! root      180:        fprintf (stream, "\n\tnop");
1.1       root      181:       break;
1.1.1.2   root      182:     case 'O':
1.1.1.3   root      183:       output_addr_const (stream, x);
1.1       root      184:       break;
1.1.1.4 ! root      185:     case 'R':
        !           186:       fputs (reg_names[REGNO (x) + LSW], (stream));
1.1.1.2   root      187:       break;
1.1.1.4 ! root      188:     case 'S':
        !           189:       fputs (reg_names[REGNO (x) + MSW], (stream));
1.1.1.3   root      190:       break;
1.1.1.4 ! root      191:     case 'T':
        !           192:       /* Next word of a double.  */
1.1       root      193:       switch (GET_CODE (x))
                    194:        {
                    195:        case REG:
                    196:          fputs (reg_names[REGNO (x) + 1], (stream));
                    197:          break;
                    198:        case MEM:
1.1.1.4 ! root      199:          print_operand_address (stream,
        !           200:                                 XEXP (adj_offsettable_operand (x, 4), 0));
1.1       root      201:          break;
                    202:        }
                    203:       break;
                    204:     default:
                    205:       switch (GET_CODE (x))
                    206:        {
                    207:        case REG:
                    208:          fputs (reg_names[REGNO (x)], (stream));
                    209:          break;
                    210:        case MEM:
                    211:          output_address (XEXP (x, 0));
                    212:          break;
                    213:        default:
                    214:          fputc ('#', stream);
                    215:          output_addr_const (stream, x);
                    216:          break;
                    217:        }
                    218:       break;
                    219:     }
                    220: }
                    221: 
1.1.1.3   root      222: /* Emit code to perform a block move.  Choose the best method.
                    223: 
                    224:    OPERANDS[0] is the destination.
                    225:    OPERANDS[1] is the source.
                    226:    OPERANDS[2] is the size.
                    227:    OPERANDS[3] is the alignment safe to use.  */
                    228: 
                    229: int
                    230: expand_block_move (operands)
                    231:      rtx *operands;
                    232: {
                    233:   int align = INTVAL (operands[3]);
                    234:   int constp = (GET_CODE (operands[2]) == CONST_INT);
                    235:   int bytes = (constp ? INTVAL (operands[2]) : 0);
                    236: 
1.1.1.4 ! root      237:   /* If it isn't a constant number of bytes, or if it doesn't have 4 byte
        !           238:      alignment, or if it isn't a multiple of 4 bytes, then fail.  */
        !           239:   if (! constp || align < 4 || (bytes % 4 != 0))
1.1.1.3   root      240:     return 0;
                    241: 
1.1.1.4 ! root      242:   if (bytes < 64)
1.1.1.3   root      243:     {
                    244:       char entry[30];
                    245:       tree entry_name;
                    246:       rtx func_addr_rtx;
                    247:       rtx r4 = gen_rtx (REG, SImode, 4);
                    248:       rtx r5 = gen_rtx (REG, SImode, 5);
1.1.1.4 ! root      249: 
        !           250:       sprintf (entry, "__movstrSI%d", bytes);
1.1.1.3   root      251:       entry_name = get_identifier (entry);
                    252: 
1.1.1.4 ! root      253:       func_addr_rtx
        !           254:        = copy_to_mode_reg (Pmode,
        !           255:                            gen_rtx (SYMBOL_REF, Pmode,
        !           256:                                     IDENTIFIER_POINTER (entry_name)));
1.1.1.3   root      257:       emit_insn (gen_move_insn (r4, XEXP (operands[0], 0)));
                    258:       emit_insn (gen_move_insn (r5, XEXP (operands[1], 0)));
                    259:       emit_insn (gen_block_move_real (func_addr_rtx));
                    260:       return 1;
                    261:     }
1.1.1.4 ! root      262: 
        !           263:   /* This is the same number of bytes as a memcpy call, but to a different
        !           264:      less common function name, so this will occasionally use more space.  */
        !           265:   if (! TARGET_SMALLCODE)
1.1.1.3   root      266:     {
                    267:       tree entry_name;
                    268:       rtx func_addr_rtx;
1.1.1.4 ! root      269:       int final_switch, while_loop;
1.1.1.3   root      270:       rtx r4 = gen_rtx (REG, SImode, 4);
                    271:       rtx r5 = gen_rtx (REG, SImode, 5);
                    272:       rtx r6 = gen_rtx (REG, SImode, 6);
                    273: 
1.1.1.4 ! root      274:       entry_name = get_identifier ("__movstr");
        !           275:       func_addr_rtx
        !           276:        = copy_to_mode_reg (Pmode,
        !           277:                            gen_rtx (SYMBOL_REF, Pmode,
        !           278:                                     IDENTIFIER_POINTER (entry_name)));
1.1.1.3   root      279:       emit_insn (gen_move_insn (r4, XEXP (operands[0], 0)));
                    280:       emit_insn (gen_move_insn (r5, XEXP (operands[1], 0)));
                    281: 
1.1.1.4 ! root      282:       /* r6 controls the size of the move.  16 is decremented from it
        !           283:         for each 64 bytes moved.  Then the negative bit left over is used
        !           284:         as an index into a list of move instructions.  e.g., a 72 byte move
        !           285:         would be set up with size(r6) = 14, for one iteration through the
        !           286:         big while loop, and a switch of -2 for the last part.  */
        !           287: 
        !           288:       final_switch = 16 - ((bytes / 4) % 16);
        !           289:       while_loop = ((bytes / 4) / 16 - 1) * 16;
        !           290:       emit_insn (gen_move_insn (r6, GEN_INT (while_loop + final_switch)));
        !           291:       emit_insn (gen_block_lump_real (func_addr_rtx));
        !           292:       return 1;
1.1.1.3   root      293:     }
                    294: 
                    295:   return 0;
                    296: }
                    297: 
1.1       root      298: /* Prepare operands for a move define_expand; specifically, one of the
1.1.1.4 ! root      299:    operands must be in a register.  */
1.1       root      300: 
1.1.1.2   root      301: int
1.1       root      302: prepare_move_operands (operands, mode)
                    303:      rtx operands[];
                    304:      enum machine_mode mode;
                    305: {
1.1.1.4 ! root      306:   /* Copy the source to a register if both operands aren't registers.  */
        !           307:   if (! reload_in_progress && ! reload_completed
        !           308:       && ! register_operand (operands[0], mode)
        !           309:       && ! register_operand (operands[1], mode))
        !           310:     operands[1] = copy_to_mode_reg (mode, operands[1]);
        !           311: 
        !           312:   return 0;
        !           313: }
        !           314: 
        !           315: /* Prepare the operands for an scc instruction; make sure that the
        !           316:    compare has been done.  */
        !           317: rtx
        !           318: prepare_scc_operands (code)
        !           319:      enum rtx_code code;
        !           320: {
        !           321:   rtx t_reg = gen_rtx (REG, SImode, T_REG);
        !           322:   enum rtx_code oldcode = code;
        !           323:   enum machine_mode mode;
        !           324: 
        !           325:   /* First need a compare insn.  */
        !           326:   switch (code)
1.1       root      327:     {
1.1.1.4 ! root      328:     case NE:
        !           329:       /* It isn't possible to handle this case.  */
        !           330:       abort ();
        !           331:     case LT:
        !           332:       code = GT;
        !           333:       break;
        !           334:     case LE:
        !           335:       code = GE;
        !           336:       break;
        !           337:     case LTU:
        !           338:       code = GTU;
        !           339:       break;
        !           340:     case LEU:
        !           341:       code = GEU;
        !           342:       break;
1.1       root      343:     }
1.1.1.4 ! root      344:   if (code != oldcode)
1.1.1.3   root      345:     {
1.1.1.4 ! root      346:       rtx tmp = sh_compare_op0;
        !           347:       sh_compare_op0 = sh_compare_op1;
        !           348:       sh_compare_op1 = tmp;
1.1.1.3   root      349:     }
1.1.1.2   root      350: 
1.1.1.4 ! root      351:   mode = GET_MODE (sh_compare_op0);
        !           352:   if (mode == VOIDmode)
        !           353:     mode = GET_MODE (sh_compare_op1);
1.1.1.3   root      354: 
1.1.1.4 ! root      355:   sh_compare_op0 = force_reg (mode, sh_compare_op0);
        !           356:   if (code != EQ && code != NE
        !           357:       && (sh_compare_op1 != const0_rtx
        !           358:          || code == GTU  || code == GEU || code == LTU || code == LEU))
        !           359:     sh_compare_op1 = force_reg (mode, sh_compare_op1);
1.1.1.3   root      360: 
1.1.1.4 ! root      361:   emit_insn (gen_rtx (SET, VOIDmode, t_reg,
        !           362:                      gen_rtx (code, SImode, sh_compare_op0,
        !           363:                               sh_compare_op1)));
1.1.1.3   root      364: 
1.1.1.4 ! root      365:   return t_reg;
1.1       root      366: }
                    367: 
1.1.1.4 ! root      368: /* Called from the md file, set up the operands of a compare instruction.  */
        !           369: 
        !           370: void
        !           371: from_compare (operands, code)
        !           372:      rtx *operands;
1.1.1.3   root      373:      int code;
1.1       root      374: {
1.1.1.4 ! root      375:   if (code != EQ && code != NE)
1.1       root      376:     {
1.1.1.4 ! root      377:       /* Force args into regs, since we can't use constants here.  */
1.1.1.3   root      378:       sh_compare_op0 = force_reg (SImode, sh_compare_op0);
1.1.1.4 ! root      379:       if (sh_compare_op1 != const0_rtx
        !           380:          || code == GTU  || code == GEU || code == LTU || code == LEU)
        !           381:        sh_compare_op1 = force_reg (SImode, sh_compare_op1);
1.1       root      382:     }
1.1.1.4 ! root      383:   operands[1] = sh_compare_op0;
        !           384:   operands[2] = sh_compare_op1;
1.1       root      385: }
                    386: 
1.1.1.4 ! root      387: /* Functions to output assembly code.  */
1.1       root      388: 
1.1.1.2   root      389: /* Return a sequence of instructions to perform DI or DF move.
1.1       root      390: 
1.1.1.2   root      391:    Since the SH cannot move a DI or DF in one instruction, we have
1.1.1.4 ! root      392:    to take care when we see overlapping source and dest registers.  */
1.1.1.3   root      393: 
1.1       root      394: char *
1.1.1.3   root      395: output_movedouble (insn, operands, mode)
                    396:      rtx insn;
1.1       root      397:      rtx operands[];
                    398:      enum machine_mode mode;
                    399: {
1.1.1.2   root      400:   rtx dst = operands[0];
                    401:   rtx src = operands[1];
                    402: 
1.1.1.3   root      403:   if (GET_CODE (dst) == MEM
1.1.1.4 ! root      404:       && GET_CODE (XEXP (dst, 0)) == PRE_DEC)
        !           405:     return "mov.l      %T1,%0\n\tmov.l %1,%0";
        !           406: 
1.1.1.2   root      407:   if (register_operand (dst, mode)
                    408:       && register_operand (src, mode))
1.1       root      409:     {
1.1.1.2   root      410:       if (REGNO (src) == MACH_REG)
1.1.1.4 ! root      411:        return "sts     mach,%S0\n\tsts macl,%R0";
1.1       root      412: 
1.1.1.4 ! root      413:       /* When mov.d r1,r2 do r2->r3 then r1->r2;
        !           414:          when mov.d r1,r0 do r1->r0 then r2->r1.  */
1.1.1.2   root      415: 
                    416:       if (REGNO (src) + 1 == REGNO (dst))
1.1.1.4 ! root      417:        return "mov     %T1,%T0\n\tmov  %1,%0";
1.1.1.2   root      418:       else
1.1.1.4 ! root      419:        return "mov     %1,%0\n\tmov    %T1,%T0";
1.1.1.2   root      420:     }
                    421:   else if (GET_CODE (src) == CONST_INT)
1.1       root      422:     {
1.1.1.4 ! root      423:       if (INTVAL (src) < 0)
        !           424:        output_asm_insn ("mov   #-1,%S0", operands);
1.1       root      425:       else
1.1.1.4 ! root      426:        output_asm_insn ("mov   #0,%S0", operands);
1.1       root      427: 
1.1.1.4 ! root      428:       return "mov      %1,%R0";
1.1.1.3   root      429:     }
1.1.1.2   root      430:   else if (GET_CODE (src) == MEM)
1.1       root      431:     {
1.1.1.4 ! root      432:       int ptrreg = -1;
1.1.1.2   root      433:       int dreg = REGNO (dst);
                    434:       rtx inside = XEXP (src, 0);
1.1       root      435: 
                    436:       if (GET_CODE (inside) == REG)
1.1.1.4 ! root      437:        ptrreg = REGNO (inside);
        !           438:       else if (GET_CODE (inside) == SUBREG)
        !           439:        ptrreg = REGNO (SUBREG_REG (inside)) + SUBREG_WORD (inside);
1.1       root      440:       else if (GET_CODE (inside) == PLUS)
                    441:        {
1.1.1.4 ! root      442:          ptrreg = REGNO (XEXP (inside, 0));
        !           443:          /* ??? A r0+REG address shouldn't be possible here, because it isn't
        !           444:             an offsettable address.  Unfortunately, offsettable addresses use
        !           445:             QImode to check the offset, and a QImode offsettable address
        !           446:             requires r0 for the other operand, which is not currently
        !           447:             supported, so we can't use the 'o' constraint.
        !           448:             Thus we must check for and handle r0+REG addresses here.
        !           449:             We punt for now, since this is likely very rare.  */
        !           450:          if (GET_CODE (XEXP (inside, 1)) == REG)
        !           451:            abort ();
1.1       root      452:        }
1.1.1.3   root      453:       else if (GET_CODE (inside) == LABEL_REF)
1.1.1.4 ! root      454:        return "mov.l   %1,%0\n\tmov.l  %1+4,%T0";
1.1.1.3   root      455:       else if (GET_CODE (inside) == POST_INC)
1.1.1.4 ! root      456:        return "mov.l   %1,%0\n\tmov.l  %1,%T0";
1.1       root      457:       else
                    458:        abort ();
                    459: 
1.1.1.4 ! root      460:       /* Work out the safe way to copy.  Copy into the second half first.  */
        !           461:       if (dreg == ptrreg)
        !           462:        return "mov.l   %T1,%T0\n\tmov.l        %1,%0";
1.1       root      463:     }
                    464: 
1.1.1.4 ! root      465:   return "mov.l        %1,%0\n\tmov.l  %T1,%T0";
1.1       root      466: }
                    467: 
1.1.1.4 ! root      468: /* Print an instruction which would have gone into a delay slot after
        !           469:    another instruction, but couldn't because the other instruction expanded
        !           470:    into a sequence where putting the slot insn at the end wouldn't work.  */
1.1.1.2   root      471: 
1.1.1.4 ! root      472: static void
        !           473: print_slot (insn)
        !           474:      rtx insn;
1.1       root      475: {
1.1.1.4 ! root      476:   final_scan_insn (XVECEXP (insn, 0, 1), asm_out_file, optimize, 0, 1);
1.1.1.3   root      477: 
1.1.1.4 ! root      478:   INSN_DELETED_P (XVECEXP (insn, 0, 1)) = 1;
1.1.1.3   root      479: }
                    480: 
1.1.1.4 ! root      481: /* We can't tell if we need a register as a scratch for the jump
        !           482:    until after branch shortening, and then it's too late to allocate a
        !           483:    register the 'proper' way.  These instruction sequences are rare
        !           484:    anyway, so to avoid always using a reg up from our limited set, we'll
        !           485:    grab one when we need one on output.  */
1.1.1.3   root      486: 
1.1.1.4 ! root      487: /* ??? Should fix compiler so that using a clobber scratch in jump
        !           488:    instructions works, and then this will be unnecessary.  */
1.1.1.3   root      489: 
                    490: char *
                    491: output_far_jump (insn, op)
                    492:      rtx insn;
                    493:      rtx op;
                    494: {
                    495:   rtx thislab = gen_label_rtx ();
                    496: 
1.1.1.4 ! root      497:   /* Output the delay slot insn first if any.  */
1.1.1.3   root      498:   if (dbr_sequence_length ())
1.1.1.4 ! root      499:     print_slot (final_sequence);
1.1.1.2   root      500: 
1.1.1.4 ! root      501:   output_asm_insn ("mov.l      r13,@-r15", 0);
        !           502:   output_asm_insn ("mov.l      %O0,r13", &thislab);
        !           503:   output_asm_insn ("jmp        @r13", 0);
        !           504:   output_asm_insn ("mov.l      @r15+,r13", 0);
1.1.1.3   root      505:   output_asm_insn (".align     2", 0);
                    506:   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (thislab));
                    507:   output_asm_insn (".long      %O0", &op);
                    508:   return "";
                    509: }
1.1       root      510: 
1.1.1.4 ! root      511: /* Local label counter, used for constants in the pool and inside
        !           512:    pattern branches.  */
        !           513: 
        !           514: static int lf = 100;
        !           515: 
        !           516: /* Output code for ordinary branches.  */
        !           517: 
1.1       root      518: char *
1.1.1.4 ! root      519: output_branch (logic, insn, operands)
1.1       root      520:      int logic;
1.1.1.2   root      521:      rtx insn;
1.1.1.4 ! root      522:      rtx *operands;
1.1       root      523: {
                    524:   int label = lf++;
1.1.1.3   root      525: 
1.1       root      526:   switch (get_attr_length (insn))
                    527:     {
                    528:     case 2:
1.1.1.4 ! root      529:       /* A branch with an unfilled delay slot.  */
        !           530:     case 4:
        !           531:       /* Simple branch in range -252..+258 bytes */
1.1.1.2   root      532:       return logic ? "bt%.     %l0" : "bf%.    %l0";
1.1       root      533: 
                    534:     case 6:
1.1.1.4 ! root      535:       /* A branch with an unfilled delay slot.  */
        !           536:     case 8:
        !           537:       /* Branch in range -4092..+4098 bytes.  */
1.1.1.2   root      538:       {
1.1.1.4 ! root      539:        /* The call to print_slot will clobber the operands.  */
        !           540:        rtx op0 = operands[0];
1.1.1.2   root      541: 
1.1.1.4 ! root      542:        /* If the instruction in the delay slot is annulled (true), then
        !           543:           there is no delay slot where we can put it now.  The only safe
        !           544:           place for it is after the label.  */
1.1.1.2   root      545: 
1.1.1.4 ! root      546:        if (final_sequence)
1.1.1.2   root      547:          {
1.1.1.4 ! root      548:            fprintf (asm_out_file, "\tb%c%s\tLF%d\n", logic ? 'f' : 't',
        !           549:                     INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))
        !           550:                     ? "" : ".s", label);
        !           551:            if (! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
        !           552:              print_slot (final_sequence);
1.1.1.2   root      553:          }
                    554:        else
1.1.1.4 ! root      555:          fprintf (asm_out_file, "\tb%c\tLF%d\n", logic ? 'f' : 't', label);
1.1.1.2   root      556: 
1.1.1.4 ! root      557:        output_asm_insn ("bra   %l0", &op0);
        !           558:        fprintf (asm_out_file, "\tnop\n");
1.1.1.2   root      559:        fprintf (asm_out_file, "LF%d:\n", label);
1.1.1.4 ! root      560: 
        !           561:        if (final_sequence
        !           562:            && INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
        !           563:          print_slot (final_sequence);
1.1.1.2   root      564:       }
1.1       root      565:       return "";
1.1.1.2   root      566: 
1.1.1.3   root      567:     case 16:
1.1.1.4 ! root      568:       /* A branch with an unfilled delay slot.  */
        !           569:     case 18:
        !           570:       /* Branches a long way away.  */
1.1.1.2   root      571:       {
1.1.1.4 ! root      572:        /* The call to print_slot will clobber the operands.  */
        !           573:        rtx op0 = operands[0];
1.1.1.2   root      574: 
1.1.1.4 ! root      575:        /* If the instruction in the delay slot is annulled (true), then
        !           576:           there is no delay slot where we can put it now.  The only safe
        !           577:           place for it is after the label.  */
1.1.1.2   root      578: 
1.1.1.4 ! root      579:        if (final_sequence)
1.1.1.2   root      580:          {
1.1.1.4 ! root      581:            fprintf (asm_out_file, "\tb%c%s\tLF%d\n", logic ? 'f' : 't',
        !           582:                     INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))
        !           583:                     ? "" : ".s", label);
        !           584:            if (! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
        !           585:              print_slot (final_sequence);
1.1.1.2   root      586:          }
1.1.1.4 ! root      587:        else
        !           588:          fprintf (asm_out_file, "\tb%c\tLF%d\n", logic ? 'f' : 't', label);
1.1.1.2   root      589: 
1.1.1.4 ! root      590:        output_far_jump (insn, op0);
1.1.1.2   root      591:        fprintf (asm_out_file, "LF%d:\n", label);
1.1.1.4 ! root      592: 
        !           593:        if (final_sequence
        !           594:            && INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
        !           595:          print_slot (final_sequence);
1.1.1.2   root      596:       }
1.1.1.4 ! root      597:       return "";
1.1       root      598:     }
                    599:   return "bad";
                    600: }
                    601: 
1.1.1.4 ! root      602: /* A copy of the option structure defined in toplev.c.  */
1.1       root      603: 
1.1.1.3   root      604: struct option
1.1       root      605: {
1.1.1.3   root      606:   char *string;
                    607:   int *variable;
                    608:   int on_value;
                    609: };
1.1.1.2   root      610: 
1.1.1.4 ! root      611: /* Output a single output option string NAME to FILE, without generating
        !           612:    lines longer than MAX.  */
        !           613: 
1.1.1.3   root      614: static int
                    615: output_option (file, sep, type, name, indent, pos, max)
                    616:      FILE *file;
                    617:      char *sep;
                    618:      char *type;
                    619:      char *name;
                    620:      char *indent;
                    621:      int pos;
                    622:      int max;
                    623: {
                    624:   if (strlen (sep) + strlen (type) + strlen (name) + pos > max)
1.1       root      625:     {
1.1.1.3   root      626:       fprintf (file, indent);
                    627:       return fprintf (file, "%s%s", type, name);
1.1.1.2   root      628:     }
1.1.1.3   root      629:   return pos + fprintf (file, "%s%s%s", sep, type, name);
                    630: }
1.1       root      631: 
1.1.1.4 ! root      632: /* A copy of the target_switches variable in toplev.c.  */
        !           633: 
1.1.1.3   root      634: static struct
                    635: {
                    636:   char *name;
                    637:   int value;
1.1.1.4 ! root      638: } m_options[] = TARGET_SWITCHES;
1.1       root      639: 
1.1.1.4 ! root      640: /* Output all options to the assembly language file.  */
1.1       root      641: 
1.1.1.3   root      642: static void
                    643: output_options (file, f_options, f_len, W_options, W_len,
                    644:                pos, max, sep, indent, term)
                    645:      FILE *file;
                    646:      struct option *f_options;
                    647:      struct option *W_options;
                    648:      int f_len, W_len;
                    649:      int pos;
                    650:      int max;
                    651:      char *sep;
                    652:      char *indent;
                    653:      char *term;
                    654: {
                    655:   register int j;
1.1       root      656: 
1.1.1.3   root      657:   if (optimize)
                    658:     pos = output_option (file, sep, "-O", "", indent, pos, max);
                    659:   if (write_symbols != NO_DEBUG)
                    660:     pos = output_option (file, sep, "-g", "", indent, pos, max);
                    661:   if (profile_flag)
                    662:     pos = output_option (file, sep, "-p", "", indent, pos, max);
                    663:   if (profile_block_flag)
                    664:     pos = output_option (file, sep, "-a", "", indent, pos, max);
1.1       root      665: 
1.1.1.3   root      666:   for (j = 0; j < f_len; j++)
                    667:     if (*f_options[j].variable == f_options[j].on_value)
                    668:       pos = output_option (file, sep, "-f", f_options[j].string,
                    669:                           indent, pos, max);
1.1       root      670: 
1.1.1.3   root      671:   for (j = 0; j < W_len; j++)
                    672:     if (*W_options[j].variable == W_options[j].on_value)
                    673:       pos = output_option (file, sep, "-W", W_options[j].string,
                    674:                           indent, pos, max);
1.1       root      675: 
1.1.1.3   root      676:   for (j = 0; j < sizeof m_options / sizeof m_options[0]; j++)
                    677:     if (m_options[j].name[0] != '\0'
                    678:        && m_options[j].value > 0
                    679:        && ((m_options[j].value & target_flags)
                    680:            == m_options[j].value))
                    681:       pos = output_option (file, sep, "-m", m_options[j].name,
                    682:                           indent, pos, max);
1.1       root      683: 
1.1.1.3   root      684:   fprintf (file, term);
                    685: }
                    686: 
1.1.1.4 ! root      687: /* Output to FILE the start of the assembler file.  */
        !           688: 
1.1.1.3   root      689: void
                    690: output_file_start (file, f_options, f_len, W_options, W_len)
                    691:      FILE *file;
                    692:      struct option *f_options;
                    693:      struct option *W_options;
                    694:      int f_len, W_len;
                    695: {
                    696:   register int pos;
                    697: 
                    698:   output_file_directive (file, main_input_filename);
                    699: 
                    700:   /* Switch to the data section so that the coffsem symbol and the
                    701:      gcc2_compiled. symbol aren't in the text section.  */
                    702:   data_section ();
                    703: 
1.1.1.4 ! root      704:   pos = fprintf (file, "\n! Hitachi SH cc1 (%s) arguments:", version_string);
1.1.1.3   root      705:   output_options (file, f_options, f_len, W_options, W_len,
                    706:                  pos, 75, " ", "\n! ", "\n\n");
1.1.1.4 ! root      707: 
        !           708:   if (TARGET_LITTLE_ENDIAN)
        !           709:     fprintf (file, "\t.little\n");
1.1.1.3   root      710: }
                    711: 
1.1.1.4 ! root      712: /* Actual number of instructions used to make a shift by N.  */
        !           713: static char ashiftrt_insns[] =
        !           714:   { 0,1,2,3,4,5,8,8,8,8,8,8,8,8,8,8,2,3,4,5,8,8,8,8,8,8,8,8,8,8,8,2};
        !           715: 
        !           716: /* Left shift and logical right shift are the same.  */
        !           717: static char shift_insns[]    =
        !           718:   { 0,1,1,2,2,3,3,4,1,2,2,3,3,4,3,3,1,2,2,3,3,4,3,3,2,3,3,4,4,4,3,3};
        !           719: 
        !           720: /* Individual shift amounts needed to get the above length sequences.
        !           721:    One bit right shifts clobber the T bit, so when possible, put one bit
        !           722:    shifts in the middle of the sequence, so the ends are eligible for
        !           723:    branch delay slots.  */
        !           724: static short shift_amounts[32][5] = {
        !           725:   {0}, {1}, {2}, {2, 1},
        !           726:   {2, 2}, {2, 1, 2}, {2, 2, 2}, {2, 2, 1, 2},
        !           727:   {8}, {8, 1}, {8, 2}, {8, 1, 2},
        !           728:   {8, 2, 2}, {8, 2, 1, 2}, {8, -2, 8}, {8, -1, 8},
        !           729:   {16}, {16, 1}, {16, 2}, {16, 1, 2},
        !           730:   {16, 2, 2}, {16, 2, 1, 2}, {16, -2, 8}, {16, -1, 8},
        !           731:   {16, 8}, {16, 1, 8}, {16, 8, 2}, {16, 8, 1, 2},
        !           732:   {16, 8, 2, 2}, {16, -1, -2, 16}, {16, -2, 16}, {16, -1, 16}};
        !           733: 
        !           734: /* This is used in length attributes in sh.md to help compute the length
        !           735:    of arbitrary constant shift instructions.  */
1.1.1.3   root      736: 
1.1.1.4 ! root      737: int
        !           738: shift_insns_rtx (insn)
        !           739:      rtx insn;
        !           740: {
        !           741:   rtx set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
        !           742:   int shift_count = INTVAL (XEXP (set_src, 1));
        !           743:   enum rtx_code shift_code = GET_CODE (set_src);
        !           744: 
        !           745:   switch (shift_code)
        !           746:     {
        !           747:     case ASHIFTRT:
        !           748:       return ashiftrt_insns[shift_count];
        !           749:     case LSHIFTRT:
        !           750:     case ASHIFT:
        !           751:       return shift_insns[shift_count];
        !           752:     default:
        !           753:       abort();
        !           754:     }
        !           755: }
1.1.1.3   root      756: 
1.1.1.4 ! root      757: /* Return the cost of a shift.  */
1.1.1.3   root      758: 
                    759: int
1.1.1.4 ! root      760: shiftcosts (x)
        !           761:      rtx x;
1.1.1.3   root      762: {
1.1.1.4 ! root      763:   int value = INTVAL (XEXP (x, 1));
1.1.1.3   root      764: 
1.1.1.4 ! root      765:   /* If shift by a non constant, then this will be expensive.  */
        !           766:   if (GET_CODE (XEXP (x, 1)) != CONST_INT)
        !           767:     {
        !           768:       if (TARGET_SH3)
        !           769:        return 2;
        !           770:       /* If not an sh3 then we don't even have an instruction for it.  */
        !           771:       return 20;
        !           772:     }
        !           773: 
        !           774:   /* Otherwise, return the true cost in instructions.  */
        !           775:   if (GET_CODE (x) == ASHIFTRT)
        !           776:     return ashiftrt_insns[value];
        !           777:   else
        !           778:     return shift_insns[value];
1.1.1.3   root      779: }
1.1.1.2   root      780: 
1.1.1.4 ! root      781: /* Return the cost of an AND operation.  */
        !           782: 
1.1.1.2   root      783: int
1.1.1.4 ! root      784: andcosts (x)
        !           785:      rtx x;
1.1       root      786: {
                    787:   int i;
1.1.1.4 ! root      788: 
        !           789:   /* Anding with a register is a single cycle and instruction.  */
        !           790:   if (GET_CODE (XEXP (x, 1)) != CONST_INT)
        !           791:     return 1;
        !           792: 
        !           793:   i = INTVAL (XEXP (x, 1));
        !           794:   /* These constants are single cycle extu.[bw] instructions.  */
1.1.1.3   root      795:   if (i == 0xff || i == 0xffff)
1.1.1.4 ! root      796:     return 1;
        !           797:   /* Constants that can be used in an and immediate instruction is a single
        !           798:      cycle, but this requires r0, so make it a little more expensive.  */
        !           799:   if (CONST_OK_FOR_L (i))
1.1.1.3   root      800:     return 2;
1.1.1.4 ! root      801:   /* Constants that can be loaded with a mov immediate and an and.
        !           802:      This case is probably unnecessary.  */
1.1.1.3   root      803:   if (CONST_OK_FOR_I (i))
1.1.1.4 ! root      804:     return 2;
        !           805:   /* Any other constants requires a 2 cycle pc-relative load plus an and.
        !           806:      This case is probably unnecessary.  */
        !           807:   return 3;
1.1.1.3   root      808: }
1.1.1.2   root      809: 
1.1.1.4 ! root      810: /* Return the cost of a multiply.  */
        !           811: int
        !           812: multcosts (x)
        !           813:      rtx x;
1.1.1.3   root      814: {
1.1.1.4 ! root      815:   if (TARGET_SH2)
1.1       root      816:     {
1.1.1.4 ! root      817:       /* We have a mul insn, so we can never take more than the mul and the
        !           818:         read of the mac reg, but count more because of the latency and extra
        !           819:         reg usage.  */
        !           820:       if (TARGET_SMALLCODE)
        !           821:        return 2;
        !           822:       return 3;
        !           823:     }
        !           824: 
        !           825:   /* If we're aiming at small code, then just count the number of
        !           826:      insns in a multiply call sequence.  */
        !           827:   if (TARGET_SMALLCODE)
        !           828:     return 5;
        !           829: 
        !           830:   /* Otherwise count all the insns in the routine we'd be calling too.  */
        !           831:   return 20;
        !           832: }
        !           833: 
        !           834: /* Code to expand a shift.  */
        !           835: 
        !           836: void
        !           837: gen_ashift (type, n, reg)
        !           838:      int type;
        !           839:      int n;
        !           840:      rtx reg;
        !           841: {
        !           842:   /* Negative values here come from the shift_amounts array.  */
        !           843:   if (n < 0)
        !           844:     {
        !           845:       if (type == ASHIFT)
        !           846:        type = LSHIFTRT;
        !           847:       else
        !           848:        type = ASHIFT;
        !           849:       n = -n;
        !           850:     }
        !           851: 
        !           852:   switch (type)
        !           853:     {
        !           854:     case ASHIFTRT:
        !           855:       emit_insn (gen_ashrsi3_k (reg, reg, GEN_INT (n)));
        !           856:       break;
        !           857:     case LSHIFTRT:
        !           858:       if (n == 1)
        !           859:        emit_insn (gen_lshrsi3_m (reg, reg, GEN_INT (n)));
        !           860:       else
        !           861:        emit_insn (gen_lshrsi3_k (reg, reg, GEN_INT (n)));
        !           862:       break;
        !           863:     case ASHIFT:
        !           864:       emit_insn (gen_ashlsi3_k (reg, reg, GEN_INT (n)));
        !           865:       break;
        !           866:     }
        !           867: }
        !           868: 
        !           869: /* Output RTL to split a constant shift into its component SH constant
        !           870:    shift instructions.  */
        !           871:    
        !           872: /* ??? For SH3, should reject constant shifts when slower than loading the
        !           873:    shift count into a register?  */
        !           874: 
        !           875: int
        !           876: gen_shifty_op (code, operands)
        !           877:      int code;
        !           878:      rtx *operands;
        !           879: {
        !           880:   int value = INTVAL (operands[2]);
        !           881:   int max, i;
        !           882: 
        !           883:   if (value == 31)
        !           884:     {
        !           885:       if (code == LSHIFTRT)
1.1.1.3   root      886:        {
1.1.1.4 ! root      887:          emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
        !           888:          emit_insn (gen_movt (operands[0]));
        !           889:          return;
1.1.1.3   root      890:        }
1.1.1.4 ! root      891:       else if (code == ASHIFT)
1.1.1.3   root      892:        {
1.1.1.4 ! root      893:          /* There is a two instruction sequence for 31 bit left shifts,
        !           894:             but it requires r0.  */
        !           895:          if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 0)
        !           896:            {
        !           897:              emit_insn (gen_andsi3 (operands[0], operands[0], const1_rtx));
        !           898:              emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
        !           899:              return;
        !           900:            }
1.1.1.3   root      901:        }
                    902:     }
1.1.1.4 ! root      903: 
        !           904:   max = shift_insns[value];
        !           905:   for (i = 0; i < max; i++)
        !           906:     gen_ashift (code, shift_amounts[value][i], operands[0]);
1.1.1.3   root      907: }
1.1.1.2   root      908: 
1.1.1.4 ! root      909: /* Output RTL for an arithmetic right shift.  */
        !           910: 
        !           911: /* ??? Rewrite to use super-optimizer sequences.  */
        !           912: 
1.1.1.3   root      913: int
1.1.1.4 ! root      914: expand_ashiftrt (operands)
        !           915:      rtx *operands;
1.1.1.3   root      916: {
1.1.1.4 ! root      917:   rtx wrk;
        !           918:   char func[18];
        !           919:   tree func_name;
        !           920:   int value;
        !           921: 
        !           922:   if (TARGET_SH3 && GET_CODE (operands[2]) != CONST_INT)
        !           923:     {
        !           924:       rtx count = copy_to_mode_reg (SImode, operands[2]);
        !           925:       emit_insn (gen_negsi2 (count, count));
        !           926:       emit_insn (gen_ashrsi3_d (operands[0], operands[1], count));
        !           927:       return 1;
        !           928:     }
        !           929:   if (GET_CODE (operands[2]) != CONST_INT)
        !           930:     return 0;
        !           931: 
        !           932:   value = INTVAL (operands[2]);
        !           933: 
        !           934:   if (value == 31)
        !           935:     {
        !           936:       emit_insn (gen_ashrsi2_31 (operands[0], operands[1]));
        !           937:       return 1;
        !           938:     }
        !           939:   else if (value >= 16 && value <= 19)
        !           940:     {
        !           941:       wrk = gen_reg_rtx (SImode);
        !           942:       emit_insn (gen_ashrsi2_16 (wrk, operands[1]));
        !           943:       value -= 16;
        !           944:       while (value--)
        !           945:        gen_ashift (ASHIFTRT, 1, wrk);
        !           946:       emit_move_insn (operands[0], wrk);
        !           947:       return 1;
        !           948:     }
        !           949:   /* Expand a short sequence inline, longer call a magic routine.  */
        !           950:   else if (value <= 5)
        !           951:     {
        !           952:       wrk = gen_reg_rtx (SImode);
        !           953:       emit_move_insn (wrk, operands[1]);
        !           954:       while (value--)
        !           955:        gen_ashift (ASHIFTRT, 1, wrk);
        !           956:       emit_move_insn (operands[0], wrk);
        !           957:       return 1;
        !           958:     }
        !           959: 
        !           960:   wrk = gen_reg_rtx (Pmode);
        !           961: 
        !           962:   /* Load the value into an arg reg and call a helper.  */
        !           963:   emit_move_insn (gen_rtx (REG, SImode, 4), operands[1]);
        !           964:   sprintf (func, "__ashiftrt_r4_%d", value);
        !           965:   func_name = get_identifier (func);
        !           966:   emit_move_insn (wrk, gen_rtx (SYMBOL_REF, Pmode,
        !           967:                                IDENTIFIER_POINTER (func_name)));
        !           968:   emit_insn (gen_ashrsi3_n (GEN_INT (value), wrk));
        !           969:   emit_move_insn (operands[0], gen_rtx (REG, SImode, 4));
        !           970:   return 1;
        !           971: }
        !           972: 
        !           973: /* The SH cannot load a large constant into a register, constants have to
        !           974:    come from a pc relative load.  The reference of a pc relative load
        !           975:    instruction must be less than 1k infront of the instruction.  This
        !           976:    means that we often have to dump a constant inside a function, and
        !           977:    generate code to branch around it.
        !           978: 
        !           979:    It is important to minimize this, since the branches will slow things
        !           980:    down and make things bigger.
        !           981: 
        !           982:    Worst case code looks like:
        !           983: 
        !           984:    mov.l L1,rn
        !           985:    bra   L2
        !           986:    nop
        !           987:    align
        !           988:    L1:   .long value
        !           989:    L2:
        !           990:    ..
1.1.1.3   root      991: 
1.1.1.4 ! root      992:    mov.l L3,rn
        !           993:    bra   L4
        !           994:    nop
        !           995:    align
        !           996:    L3:   .long value
        !           997:    L4:
        !           998:    ..
1.1.1.3   root      999: 
1.1.1.4 ! root     1000:    We fix this by performing a scan before scheduling, which notices which
        !          1001:    instructions need to have their operands fetched from the constant table
        !          1002:    and builds the table.
1.1.1.3   root     1003: 
1.1.1.4 ! root     1004:    The algorithm is:
1.1.1.3   root     1005: 
1.1.1.4 ! root     1006:    scan, find an instruction which needs a pcrel move.  Look forward, find the
        !          1007:    last barrier which is within MAX_COUNT bytes of the requirement.
        !          1008:    If there isn't one, make one.  Process all the instructions between
        !          1009:    the find and the barrier.
1.1.1.3   root     1010: 
1.1.1.4 ! root     1011:    In the above example, we can tell that L3 is within 1k of L1, so
        !          1012:    the first move can be shrunk from the 3 insn+constant sequence into
        !          1013:    just 1 insn, and the constant moved to L3 to make:
1.1.1.3   root     1014: 
1.1.1.4 ! root     1015:    mov.l        L1,rn
        !          1016:    ..
        !          1017:    mov.l        L3,rn
        !          1018:    bra          L4
        !          1019:    nop
        !          1020:    align
        !          1021:    L3:.long value
        !          1022:    L4:.long value
1.1.1.3   root     1023: 
1.1.1.4 ! root     1024:    Then the second move becomes the target for the shortening process.  */
1.1.1.3   root     1025: 
1.1.1.4 ! root     1026: typedef struct
        !          1027: {
        !          1028:   rtx value;                   /* Value in table.  */
        !          1029:   rtx label;                   /* Label of value.  */
        !          1030:   enum machine_mode mode;      /* Mode of value.  */
        !          1031: } pool_node;
1.1.1.2   root     1032: 
1.1.1.4 ! root     1033: /* The maximum number of constants that can fit into one pool, since
        !          1034:    the pc relative range is 0...1020 bytes and constants are at least 4
        !          1035:    bytes long.  */
1.1.1.2   root     1036: 
1.1.1.4 ! root     1037: #define MAX_POOL_SIZE (1020/4)
        !          1038: static pool_node pool_vector[MAX_POOL_SIZE];
        !          1039: static int pool_size;
1.1.1.2   root     1040: 
1.1.1.4 ! root     1041: /* ??? If we need a constant in HImode which is the truncated value of a
        !          1042:    constant we need in SImode, we could combine the two entries thus saving
        !          1043:    two bytes.  Is this common enough to be worth the effort of implementing
        !          1044:    it?  */
        !          1045: 
        !          1046: /* ??? This stuff should be done at the same time that we shorten branches.
        !          1047:    As it is now, we must assume that all branches are the maximum size, and
        !          1048:    this causes us to almost always output constant pools sooner than
        !          1049:    necessary.  */
1.1.1.2   root     1050: 
1.1.1.4 ! root     1051: /* Add a constant to the pool and return its label.  */
1.1.1.2   root     1052: 
1.1.1.4 ! root     1053: static rtx
        !          1054: add_constant (x, mode)
        !          1055:      rtx x;
        !          1056:      enum machine_mode mode;
1.1.1.3   root     1057: {
                   1058:   int i;
1.1.1.4 ! root     1059:   rtx lab;
        !          1060: 
        !          1061:   /* First see if we've already got it.  */
        !          1062:   for (i = 0; i < pool_size; i++)
1.1.1.3   root     1063:     {
1.1.1.4 ! root     1064:       if (x->code == pool_vector[i].value->code
        !          1065:          && mode == pool_vector[i].mode)
1.1.1.3   root     1066:        {
1.1.1.4 ! root     1067:          if (x->code == CODE_LABEL)
        !          1068:            {
        !          1069:              if (XINT (x, 3) != XINT (pool_vector[i].value, 3))
        !          1070:                continue;
        !          1071:            }
        !          1072:          if (rtx_equal_p (x, pool_vector[i].value))
        !          1073:            return pool_vector[i].label;
1.1.1.3   root     1074:        }
                   1075:     }
1.1.1.2   root     1076: 
1.1.1.4 ! root     1077:   /* Need a new one.  */
        !          1078:   pool_vector[pool_size].value = x;
        !          1079:   lab = gen_label_rtx ();
        !          1080:   pool_vector[pool_size].mode = mode;
        !          1081:   pool_vector[pool_size].label = lab;
        !          1082:   pool_size++;
        !          1083:   return lab;
1.1       root     1084: }
1.1.1.4 ! root     1085: 
        !          1086: /* Output the literal table.  */
1.1       root     1087: 
1.1.1.3   root     1088: static void
                   1089: dump_table (scan)
                   1090:      rtx scan;
                   1091: {
                   1092:   int i;
                   1093:   int need_align = 1;
1.1       root     1094: 
1.1.1.4 ! root     1095:   /* Do two passes, first time dump out the HI sized constants.  */
1.1       root     1096: 
1.1.1.3   root     1097:   for (i = 0; i < pool_size; i++)
                   1098:     {
1.1.1.4 ! root     1099:       pool_node *p = &pool_vector[i];
        !          1100: 
1.1.1.3   root     1101:       if (p->mode == HImode)
                   1102:        {
                   1103:          if (need_align)
                   1104:            {
                   1105:              scan = emit_insn_after (gen_align_2 (), scan);
                   1106:              need_align = 0;
                   1107:            }
                   1108:          scan = emit_label_after (p->label, scan);
                   1109:          scan = emit_insn_after (gen_consttable_2 (p->value), scan);
                   1110:        }
                   1111:     }
1.1.1.4 ! root     1112: 
1.1.1.3   root     1113:   need_align = 1;
1.1       root     1114: 
1.1.1.3   root     1115:   for (i = 0; i < pool_size; i++)
1.1       root     1116:     {
1.1.1.4 ! root     1117:       pool_node *p = &pool_vector[i];
1.1       root     1118: 
1.1.1.3   root     1119:       switch (p->mode)
                   1120:        {
                   1121:        case HImode:
                   1122:          break;
                   1123:        case SImode:
                   1124:          if (need_align)
                   1125:            {
                   1126:              need_align = 0;
                   1127:              scan = emit_label_after (gen_label_rtx (), scan);
                   1128:              scan = emit_insn_after (gen_align_4 (), scan);
                   1129:            }
                   1130:          scan = emit_label_after (p->label, scan);
                   1131:          scan = emit_insn_after (gen_consttable_4 (p->value), scan);
                   1132:          break;
                   1133:        case DImode:
                   1134:          if (need_align)
                   1135:            {
                   1136:              need_align = 0;
                   1137:              scan = emit_label_after (gen_label_rtx (), scan);
                   1138:              scan = emit_insn_after (gen_align_4 (), scan);
                   1139:            }
                   1140:          scan = emit_label_after (p->label, scan);
                   1141:          scan = emit_insn_after (gen_consttable_8 (p->value), scan);
                   1142:          break;
                   1143:        default:
                   1144:          abort ();
                   1145:          break;
                   1146:        }
1.1.1.2   root     1147:     }
                   1148: 
1.1.1.3   root     1149:   scan = emit_insn_after (gen_consttable_end (), scan);
                   1150:   scan = emit_barrier_after (scan);
                   1151:   pool_size = 0;
                   1152: }
                   1153: 
1.1.1.4 ! root     1154: /* Return non-zero if constant would be an ok source for a
        !          1155:    mov.w instead of a mov.l.  */
1.1.1.2   root     1156: 
1.1.1.4 ! root     1157: static int
        !          1158: hi_const (src)
1.1.1.3   root     1159:      rtx src;
                   1160: {
1.1.1.4 ! root     1161:   return (GET_CODE (src) == CONST_INT
        !          1162:          && INTVAL (src) >= -32768
        !          1163:          && INTVAL (src) <= 32767);
1.1       root     1164: }
                   1165: 
1.1.1.4 ! root     1166: /* Non-zero if the insn is a move instruction which needs to be fixed.  */
        !          1167: 
        !          1168: /* ??? For a DImode/DFmode moves, we don't need to fix it if each half of the
        !          1169:    CONST_DOUBLE input value is CONST_OK_FOR_I.  For a SFmode move, we don't
        !          1170:    need to fix it if the input value is CONST_OK_FOR_I.  */
1.1       root     1171: 
1.1.1.4 ! root     1172: static int
        !          1173: broken_move (insn)
        !          1174:      rtx insn;
        !          1175: {
        !          1176:   if (GET_CODE (insn) == INSN
        !          1177:       && GET_CODE (PATTERN (insn)) == SET
        !          1178:       /* We can load any 8 bit value if we don't care what the high
        !          1179:         order bits end up as.  */
        !          1180:       && GET_MODE (SET_DEST (PATTERN (insn))) != QImode
        !          1181:       && CONSTANT_P (SET_SRC (PATTERN (insn)))
        !          1182:       && (GET_CODE (SET_SRC (PATTERN (insn))) != CONST_INT
        !          1183:          || ! CONST_OK_FOR_I (INTVAL (SET_SRC (PATTERN (insn))))))
1.1.1.3   root     1184:     return 1;
1.1       root     1185: 
1.1.1.4 ! root     1186:   return 0;
1.1.1.3   root     1187: }
1.1       root     1188: 
1.1.1.4 ! root     1189: /* Find the last barrier from insn FROM which is close enough to hold the
        !          1190:    constant pool.  If we can't find one, then create one near the end of
        !          1191:    the range.  */
        !          1192: 
        !          1193: /* ??? It would be good to put constant pool tables between a case jump and
        !          1194:    the jump table.  This fails for two reasons.  First, there is no
        !          1195:    barrier after the case jump.  This is a bug in the casesi pattern.
        !          1196:    Second, inserting the table here may break the mova instruction that
        !          1197:    loads the jump table address, by moving the jump table too far away.
        !          1198:    We fix that problem by never outputting the constant pool between a mova
        !          1199:    and its label.  */
1.1       root     1200: 
1.1.1.4 ! root     1201: static rtx
1.1.1.3   root     1202: find_barrier (from)
                   1203:      rtx from;
                   1204: {
                   1205:   int count_si = 0;
                   1206:   int count_hi = 0;
                   1207:   int found_hi = 0;
                   1208:   int found_si = 0;
                   1209:   rtx found_barrier = 0;
1.1.1.4 ! root     1210:   rtx found_mova = 0;
        !          1211: 
        !          1212:   /* For HImode: range is 510, add 4 because pc counts from address of
        !          1213:      second instruction after this one, subtract 2 for the jump instruction
        !          1214:      that we may need to emit before the table.  This gives 512.
        !          1215:      For SImode: range is 1020, add 4 because pc counts from address of
        !          1216:      second instruction after this one, subtract 2 in case pc is 2 byte
        !          1217:      aligned, subtract 2 for the jump instruction that we may need to emit
        !          1218:      before the table.  This gives 1020.  */
        !          1219:   while (from && count_si < 1020 && count_hi < 512)
1.1.1.3   root     1220:     {
1.1.1.4 ! root     1221:       int inc = get_attr_length (from);
        !          1222: 
1.1.1.3   root     1223:       if (GET_CODE (from) == BARRIER)
1.1.1.4 ! root     1224:        found_barrier = from;
1.1.1.3   root     1225: 
1.1.1.4 ! root     1226:       if (broken_move (from))
1.1.1.3   root     1227:        {
                   1228:          rtx src = SET_SRC (PATTERN (from));
1.1.1.4 ! root     1229: 
1.1.1.3   root     1230:          if (hi_const (src))
1.1.1.4 ! root     1231:            {
        !          1232:              found_hi = 1;
        !          1233:              /* We put the short constants before the long constants, so
        !          1234:                 we must count the length of short constants in the range
        !          1235:                 for the long constants.  */
        !          1236:              /* ??? This isn't optimal, but is easy to do.  */
        !          1237:              if (found_si)
        !          1238:                count_si += 2;
        !          1239:            }
1.1.1.3   root     1240:          else
                   1241:            found_si = 1;
                   1242:        }
1.1.1.4 ! root     1243: 
        !          1244:       if (GET_CODE (from) == INSN
        !          1245:          && GET_CODE (PATTERN (from)) == SET
        !          1246:          && GET_CODE (SET_SRC (PATTERN (from))) == UNSPEC
        !          1247:          && XINT (SET_SRC (PATTERN (from)), 1) == 1)
        !          1248:        found_mova = from;
        !          1249:       else if (GET_CODE (from) == JUMP_INSN
        !          1250:               && (GET_CODE (PATTERN (from)) == ADDR_VEC
        !          1251:                   || GET_CODE (PATTERN (from)) == ADDR_DIFF_VEC))
        !          1252:        found_mova = 0;
        !          1253: 
1.1.1.3   root     1254:       if (found_si)
                   1255:        count_si += inc;
                   1256:       if (found_hi)
                   1257:        count_hi += inc;
                   1258:       from = NEXT_INSN (from);
1.1       root     1259:     }
                   1260: 
1.1.1.4 ! root     1261:   /* Insert the constant pool table before the mova instruction, to prevent
        !          1262:      the mova label reference from going out of range.  */
        !          1263:   if (found_mova)
        !          1264:     from = found_mova;
        !          1265: 
        !          1266:   if (! found_barrier)
1.1       root     1267:     {
1.1.1.4 ! root     1268:       /* We didn't find a barrier in time to dump our stuff,
        !          1269:         so we'll make one.  */
1.1.1.3   root     1270:       rtx label = gen_label_rtx ();
1.1.1.4 ! root     1271: 
        !          1272:       /* If we exceeded the range, then we must back up over the last
        !          1273:         instruction we looked at.  Otherwise, we just need to undo the
        !          1274:         NEXT_INSN at the end of the loop.  */
        !          1275:       if (count_hi > 512 || count_si > 1020)
        !          1276:        from = PREV_INSN (PREV_INSN (from));
        !          1277:       else
        !          1278:        from = PREV_INSN (from);
        !          1279: 
        !          1280:       /* Walk back to be just before any jump or label.
        !          1281:         Putting it before a label reduces the number of times the branch
        !          1282:         around the constant pool table will be hit.  Putting it before
        !          1283:         a jump makes it more likely that the bra delay slot will be
        !          1284:         filled.  */
        !          1285:       while (GET_CODE (from) == JUMP_INSN || GET_CODE (from) == NOTE
1.1.1.3   root     1286:             || GET_CODE (from) == CODE_LABEL)
1.1.1.4 ! root     1287:        from = PREV_INSN (from);
        !          1288: 
1.1.1.3   root     1289:       from = emit_jump_insn_after (gen_jump (label), from);
                   1290:       JUMP_LABEL (from) = label;
1.1.1.4 ! root     1291:       LABEL_NUSES (label) = 1;
1.1.1.3   root     1292:       found_barrier = emit_barrier_after (from);
                   1293:       emit_label_after (label, found_barrier);
1.1       root     1294:     }
                   1295: 
1.1.1.4 ! root     1296:   return found_barrier;
1.1.1.3   root     1297: }
1.1.1.2   root     1298: 
1.1.1.4 ! root     1299: /* Exported to toplev.c.
1.1.1.2   root     1300: 
1.1.1.3   root     1301:    Scan the function looking for move instructions which have to be changed to
1.1.1.4 ! root     1302:    pc-relative loads and insert the literal tables.  */
1.1.1.2   root     1303: 
1.1.1.3   root     1304: void
                   1305: machine_dependent_reorg (first)
                   1306:      rtx first;
                   1307: {
                   1308:   rtx insn;
1.1.1.4 ! root     1309: 
1.1.1.3   root     1310:   for (insn = first; insn; insn = NEXT_INSN (insn))
1.1.1.2   root     1311:     {
1.1.1.3   root     1312:       if (broken_move (insn))
1.1.1.2   root     1313:        {
1.1.1.3   root     1314:          rtx scan;
1.1.1.4 ! root     1315:          /* Scan ahead looking for a barrier to stick the constant table
        !          1316:             behind.  */
1.1.1.3   root     1317:          rtx barrier = find_barrier (insn);
                   1318: 
1.1.1.4 ! root     1319:          /* Now find all the moves between the points and modify them.  */
1.1.1.3   root     1320:          for (scan = insn; scan != barrier; scan = NEXT_INSN (scan))
1.1.1.2   root     1321:            {
1.1.1.3   root     1322:              if (broken_move (scan))
                   1323:                {
                   1324:                  rtx pat = PATTERN (scan);
                   1325:                  rtx src = SET_SRC (pat);
                   1326:                  rtx dst = SET_DEST (pat);
                   1327:                  enum machine_mode mode = GET_MODE (dst);
                   1328:                  rtx lab;
                   1329:                  rtx newinsn;
                   1330:                  rtx newsrc;
                   1331: 
                   1332:                  if (mode == SImode && hi_const (src))
                   1333:                    {
1.1.1.4 ! root     1334:                      int offset = 0;
        !          1335: 
1.1.1.3   root     1336:                      mode = HImode;
                   1337:                      while (GET_CODE (dst) == SUBREG)
1.1.1.4 ! root     1338:                        {
        !          1339:                          offset += SUBREG_WORD (dst);
        !          1340:                          dst = SUBREG_REG (dst);
        !          1341:                        }
        !          1342:                      dst = gen_rtx (REG, HImode, REGNO (dst) + offset);
1.1.1.3   root     1343:                    }
1.1.1.4 ! root     1344: 
1.1.1.3   root     1345:                  lab = add_constant (src, mode);
                   1346:                  newsrc = gen_rtx (MEM, mode,
                   1347:                                    gen_rtx (LABEL_REF, VOIDmode, lab));
1.1.1.4 ! root     1348:                  RTX_UNCHANGING_P (newsrc) = 1;
        !          1349:                  newinsn = emit_insn_after (gen_rtx (SET, VOIDmode,
        !          1350:                                                      dst, newsrc), scan);
1.1.1.3   root     1351: 
                   1352:                  delete_insn (scan);
                   1353:                  scan = newinsn;
                   1354:                }
1.1.1.2   root     1355:            }
1.1.1.3   root     1356:          dump_table (barrier);
1.1.1.2   root     1357:        }
                   1358:     }
                   1359: }
                   1360: 
1.1.1.4 ! root     1361: /* Dump out instruction addresses, which is useful for debugging the
        !          1362:    constant pool table stuff.  */
        !          1363: 
        !          1364: /* ??? This is unnecessary, and probably should be deleted.  This makes
        !          1365:    the insn_addresses declaration above unnecessary.  */
        !          1366: 
        !          1367: /* ??? The addresses printed by this routine for insns are nonsense for
        !          1368:    insns which are inside of a sequence where none of the inner insns have
        !          1369:    variable length.  This is because the second pass of shorten_branches
        !          1370:    does not bother to update them.  */
        !          1371: 
        !          1372: void
        !          1373: final_prescan_insn (insn, opvec, noperands)
        !          1374:      rtx insn;
        !          1375:      rtx *opvec;
        !          1376:      int noperands;
        !          1377: {
        !          1378:   if (TARGET_DUMPISIZE)
        !          1379:     fprintf (asm_out_file, "\n! at %04x\n", insn_addresses[INSN_UID (insn)]);
        !          1380: }
        !          1381: 
        !          1382: /* Dump out any constants accumulated in the final pass.  These will
        !          1383:    will only be labels.  */
        !          1384: 
        !          1385: char *
        !          1386: output_jump_label_table ()
        !          1387: {
        !          1388:   int i;
        !          1389: 
        !          1390:   if (pool_size)
        !          1391:     {
        !          1392:       fprintf (asm_out_file, "\t.align 2\n");
        !          1393:       for (i = 0; i < pool_size; i++)
        !          1394:        {
        !          1395:          pool_node *p = &pool_vector[i];
        !          1396: 
        !          1397:          ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
        !          1398:                                     CODE_LABEL_NUMBER (p->label));
        !          1399:          output_asm_insn (".long       %O0", &p->value);
        !          1400:        }
        !          1401:       pool_size = 0;
        !          1402:     }
        !          1403: 
        !          1404:   return "";
        !          1405: }
        !          1406: 
        !          1407: /* A full frame looks like:
        !          1408: 
        !          1409:    arg-5
        !          1410:    arg-4
        !          1411:    [ if current_function_anonymous_args
        !          1412:    arg-3
        !          1413:    arg-2
        !          1414:    arg-1
        !          1415:    arg-0 ]
        !          1416:    saved-fp
        !          1417:    saved-r10
        !          1418:    saved-r11
        !          1419:    saved-r12
        !          1420:    saved-pr
        !          1421:    local-n
        !          1422:    ..
        !          1423:    local-1
        !          1424:    local-0        <- fp points here.  */
        !          1425: 
        !          1426: /* Number of bytes pushed for anonymous args, used to pass information
        !          1427:    between expand_prologue and expand_epilogue.  */
        !          1428: 
        !          1429: static int extra_push;
        !          1430: 
        !          1431: /* Adjust the stack and return the number of bytes taken to do it.  */
        !          1432: 
        !          1433: static void
        !          1434: output_stack_adjust (size, reg)
        !          1435:      int size;
        !          1436:      rtx reg;
        !          1437: {
        !          1438:   if (size)
        !          1439:     {
        !          1440:       rtx val = GEN_INT (size);
        !          1441:       rtx insn;
        !          1442: 
        !          1443:       if (! CONST_OK_FOR_I (size))
        !          1444:        {
        !          1445:          rtx reg = gen_rtx (REG, SImode, 3);
        !          1446:          emit_insn (gen_movsi (reg, val));
        !          1447:          val = reg;
        !          1448:        }
        !          1449: 
        !          1450:       insn = gen_addsi3 (reg, reg, val);
        !          1451:       emit_insn (insn);
        !          1452:     }
        !          1453: }
        !          1454: 
        !          1455: /* Output RTL to push register RN onto the stack.  */
1.1.1.3   root     1456: 
1.1.1.4 ! root     1457: static void
        !          1458: push (rn)
        !          1459:      int rn;
1.1.1.2   root     1460: {
1.1.1.4 ! root     1461:   rtx x;
        !          1462:   x = emit_insn (gen_push (gen_rtx (REG, SImode, rn)));
        !          1463:   REG_NOTES (x) = gen_rtx (EXPR_LIST, REG_INC,
        !          1464:                           gen_rtx(REG, SImode, STACK_POINTER_REGNUM), 0);
1.1.1.2   root     1465: }
                   1466: 
1.1.1.4 ! root     1467: /* Output RTL to pop register RN from the stack.  */
1.1.1.2   root     1468: 
1.1.1.4 ! root     1469: static void
        !          1470: pop (rn)
        !          1471:      int rn;
1.1.1.2   root     1472: {
1.1.1.4 ! root     1473:   rtx x;
        !          1474:   x = emit_insn (gen_pop (gen_rtx (REG, SImode, rn)));
        !          1475:   REG_NOTES (x) = gen_rtx (EXPR_LIST, REG_INC,
        !          1476:                           gen_rtx(REG, SImode, STACK_POINTER_REGNUM), 0);
1.1.1.2   root     1477: }
                   1478: 
1.1.1.4 ! root     1479: /* Generate code to push the regs specified in the mask, and return
        !          1480:    the number of bytes the insns take.  */
1.1.1.2   root     1481: 
1.1.1.3   root     1482: static void
1.1.1.4 ! root     1483: push_regs (mask)
        !          1484:      int mask;
1.1.1.2   root     1485: {
1.1.1.4 ! root     1486:   int i;
        !          1487: 
        !          1488:   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
        !          1489:     if (mask & (1 << i))
        !          1490:       push (i);
1.1.1.2   root     1491: }
                   1492: 
1.1.1.4 ! root     1493: /* Work out the registers which need to be saved, both as a mask and a
        !          1494:    count.
        !          1495: 
        !          1496:    If doing a pragma interrupt function, then push all regs used by the
        !          1497:    function, and if we call another function (we can tell by looking at PR),
        !          1498:    make sure that all the regs it clobbers are safe too.  */
        !          1499: 
1.1.1.3   root     1500: static int
1.1.1.4 ! root     1501: calc_live_regs (count_ptr)
        !          1502:      int *count_ptr;
1.1.1.2   root     1503: {
1.1.1.4 ! root     1504:   int reg;
        !          1505:   int live_regs_mask = 0;
        !          1506:   int count = 0;
        !          1507: 
        !          1508:   for (reg = 0; reg < FIRST_PSEUDO_REGISTER; reg++)
1.1.1.3   root     1509:     {
1.1.1.4 ! root     1510:       if (pragma_interrupt && ! pragma_trapa)
        !          1511:        {
        !          1512:          /* Need to save all the regs ever live.  */
        !          1513:          if ((regs_ever_live[reg]
        !          1514:               || (call_used_regs[reg] && regs_ever_live[PR_REG]))
        !          1515:              && reg != STACK_POINTER_REGNUM && reg != ARG_POINTER_REGNUM
        !          1516:              && reg != T_REG && reg != GBR_REG)
        !          1517:            {
        !          1518:              live_regs_mask |= 1 << reg;
        !          1519:              count++;
        !          1520:            }
        !          1521:        }
        !          1522:       else
        !          1523:        {
        !          1524:          /* Only push those regs which are used and need to be saved.  */
        !          1525:          if (regs_ever_live[reg] && ! call_used_regs[reg])
        !          1526:            {
        !          1527:              live_regs_mask |= (1 << reg);
        !          1528:              count++;
        !          1529:            }
        !          1530:        }
1.1.1.3   root     1531:     }
1.1.1.2   root     1532: 
1.1.1.4 ! root     1533:   *count_ptr = count;
        !          1534:   return live_regs_mask;
        !          1535: }
1.1.1.2   root     1536: 
1.1.1.4 ! root     1537: /* Code to generate prologue and epilogue sequences */
1.1.1.2   root     1538: 
                   1539: void
                   1540: sh_expand_prologue ()
                   1541: {
                   1542:   int live_regs_mask;
1.1.1.4 ! root     1543:   int d, i;
1.1.1.2   root     1544:   live_regs_mask = calc_live_regs (&d);
                   1545: 
1.1.1.3   root     1546:   /* We have pretend args if we had an object sent partially in registers
1.1.1.4 ! root     1547:      and partially on the stack, e.g. a large structure.  */
        !          1548:   output_stack_adjust (-current_function_pretend_args_size, stack_pointer_rtx);
1.1.1.2   root     1549: 
1.1.1.4 ! root     1550:   extra_push = 0;
        !          1551: 
        !          1552:   /* This is set by SETUP_VARARGS to indicate that this is a varargs
        !          1553:      routine.  Clear it here so that the next function isn't affected.  */
1.1.1.2   root     1554:   if (current_function_anonymous_args)
                   1555:     {
1.1.1.4 ! root     1556:       current_function_anonymous_args = 0;
        !          1557: 
        !          1558:       /* Push arg regs as if they'd been provided by caller in stack.  */
1.1.1.2   root     1559:       for (i = 0; i < NPARM_REGS; i++)
                   1560:        {
                   1561:          int rn = NPARM_REGS + FIRST_PARM_REG - i - 1;
1.1.1.4 ! root     1562:          if (i > (NPARM_REGS - current_function_args_info
        !          1563:                   - current_function_varargs))
1.1.1.2   root     1564:            break;
                   1565:          push (rn);
                   1566:          extra_push += 4;
                   1567:        }
                   1568:     }
1.1.1.3   root     1569:   push_regs (live_regs_mask);
1.1.1.4 ! root     1570:   output_stack_adjust (-get_frame_size (), stack_pointer_rtx);
1.1.1.2   root     1571: 
                   1572:   if (frame_pointer_needed)
1.1.1.4 ! root     1573:     emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
1.1.1.2   root     1574: }
                   1575: 
                   1576: void
                   1577: sh_expand_epilogue ()
                   1578: {
                   1579:   int live_regs_mask;
1.1.1.4 ! root     1580:   int d, i;
1.1.1.2   root     1581: 
                   1582:   live_regs_mask = calc_live_regs (&d);
                   1583: 
                   1584:   if (frame_pointer_needed)
                   1585:     {
1.1.1.4 ! root     1586:       /* We deliberately make the add dependent on the frame_pointer,
        !          1587:         to ensure that instruction scheduling won't move the stack pointer
        !          1588:         adjust before instructions reading from the frame.  This can fail
        !          1589:         if there is an interrupt which then writes to the stack.  */
        !          1590:       output_stack_adjust (get_frame_size (), frame_pointer_rtx);
1.1.1.2   root     1591:       emit_insn (gen_movsi (stack_pointer_rtx, frame_pointer_rtx));
                   1592:     }
1.1.1.4 ! root     1593:   else
        !          1594:     output_stack_adjust (get_frame_size (), stack_pointer_rtx);
1.1.1.2   root     1595: 
1.1.1.4 ! root     1596:   /* Pop all the registers.  */
1.1.1.3   root     1597: 
1.1.1.2   root     1598:   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
                   1599:     {
                   1600:       int j = (FIRST_PSEUDO_REGISTER - 1) - i;
                   1601:       if (live_regs_mask & (1 << j))
1.1.1.4 ! root     1602:        pop (j);
1.1.1.2   root     1603:     }
                   1604: 
1.1.1.4 ! root     1605:   output_stack_adjust (extra_push + current_function_pretend_args_size,
        !          1606:                       stack_pointer_rtx);
        !          1607: }
1.1.1.2   root     1608: 
1.1.1.4 ! root     1609: /* Clear variables at function end.  */
1.1.1.3   root     1610: 
1.1.1.4 ! root     1611: void
        !          1612: function_epilogue (stream, size)
        !          1613:      FILE *stream;
        !          1614:      int size;
        !          1615: {
        !          1616:   pragma_interrupt = pragma_trapa = 0;
1.1.1.2   root     1617: }
                   1618: 
1.1.1.3   root     1619: /* Define the offset between two registers, one to be eliminated, and
                   1620:    the other its replacement, at the start of a routine.  */
1.1.1.2   root     1621: 
1.1.1.3   root     1622: int
                   1623: initial_elimination_offset (from, to)
                   1624:      int from;
                   1625:      int to;
                   1626: {
                   1627:   int regs_saved;
                   1628:   int total_saved_regs_space;
                   1629:   int total_auto_space = get_frame_size ();
                   1630: 
                   1631:   calc_live_regs (&regs_saved);
                   1632:   total_saved_regs_space = (regs_saved) * 4;
                   1633: 
                   1634:   if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
1.1.1.4 ! root     1635:     return total_saved_regs_space + total_auto_space;
        !          1636: 
1.1.1.3   root     1637:   if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
1.1.1.4 ! root     1638:     return total_saved_regs_space + total_auto_space;
        !          1639: 
        !          1640:   /* Initial gap between fp and sp is 0.  */
1.1.1.3   root     1641:   if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
1.1.1.4 ! root     1642:     return 0;
        !          1643: 
1.1.1.3   root     1644:   abort ();
                   1645: }
1.1.1.4 ! root     1646: 
1.1.1.3   root     1647: /* Handle machine specific pragmas to be semi-compatible with Hitachi
1.1.1.4 ! root     1648:    compiler.  */
1.1.1.2   root     1649: 
                   1650: int
1.1.1.3   root     1651: handle_pragma (file)
                   1652:      FILE *file;
1.1.1.2   root     1653: {
1.1.1.3   root     1654:   int c;
                   1655:   char pbuf[200];
                   1656:   int psize = 0;
1.1.1.2   root     1657: 
1.1.1.3   root     1658:   c = getc (file);
                   1659:   while (c == ' ' || c == '\t')
                   1660:     c = getc (file);
                   1661: 
                   1662:   if (c == '\n' || c == EOF)
                   1663:     return c;
                   1664: 
                   1665:   while (psize < sizeof (pbuf) - 1 && c != '\n')
                   1666:     {
                   1667:       pbuf[psize++] = c;
                   1668:       if (psize == 9 && strncmp (pbuf, "interrupt", 9) == 0)
                   1669:        {
                   1670:          pragma_interrupt = 1;
                   1671:          return ' ';
                   1672:        }
                   1673:       if (psize == 5 && strncmp (pbuf, "trapa", 5) == 0)
                   1674:        {
                   1675:          pragma_interrupt = pragma_trapa = 1;
                   1676:          return ' ';
                   1677:        }
                   1678:       c = getc (file);
                   1679:     }
                   1680:   return c;
                   1681: }
                   1682: 
1.1.1.4 ! root     1683: /* Predicates used by the templates.  */
1.1.1.3   root     1684: 
1.1.1.4 ! root     1685: /* Returns 1 if OP is MACL, MACH or PR.  The input must be a REG rtx.
        !          1686:    Used only in general_movsrc_operand.  */
1.1.1.3   root     1687: 
1.1.1.4 ! root     1688: int
        !          1689: system_reg_operand (op, mode)
        !          1690:      rtx op;
        !          1691:      enum machine_mode mode;
1.1.1.3   root     1692: {
1.1.1.4 ! root     1693:   switch (REGNO (op))
1.1.1.3   root     1694:     {
1.1.1.4 ! root     1695:     case PR_REG:
        !          1696:     case MACL_REG:
        !          1697:     case MACH_REG:
        !          1698:       return 1;
1.1.1.3   root     1699:     }
1.1.1.4 ! root     1700:   return 0;
1.1.1.3   root     1701: }
                   1702: 
                   1703: /* Returns 1 if OP can be source of a simple move operation.
                   1704:    Same as general_operand, but a LABEL_REF is valid, PRE_DEC is
1.1.1.4 ! root     1705:    invalid as are subregs of system registers.  */
1.1.1.3   root     1706: 
                   1707: int
                   1708: general_movsrc_operand (op, mode)
                   1709:      rtx op;
                   1710:      enum machine_mode mode;
                   1711: {
                   1712:   if (GET_CODE (op) == MEM)
                   1713:     {
                   1714:       rtx inside = XEXP (op, 0);
                   1715:       if (GET_CODE (inside) == CONST)
                   1716:        inside = XEXP (inside, 0);
                   1717: 
                   1718:       if (GET_CODE (inside) == LABEL_REF)
                   1719:        return 1;
                   1720: 
                   1721:       if (GET_CODE (inside) == PLUS
1.1.1.4 ! root     1722:          && GET_CODE (XEXP (inside, 0)) == LABEL_REF
        !          1723:          && GET_CODE (XEXP (inside, 1)) == CONST_INT)
1.1.1.3   root     1724:        return 1;
                   1725: 
1.1.1.4 ! root     1726:       /* Only post inc allowed.  */
        !          1727:       if (GET_CODE (inside) == PRE_DEC)
1.1.1.3   root     1728:        return 0;
                   1729:     }
                   1730: 
                   1731:   if ((mode == QImode || mode == HImode)
                   1732:       && (GET_CODE (op) == SUBREG
                   1733:          && GET_CODE (XEXP (op, 0)) == REG
                   1734:          && system_reg_operand (XEXP (op, 0), mode)))
                   1735:     return 0;
                   1736: 
                   1737:   return general_operand (op, mode);
1.1.1.2   root     1738: }
                   1739: 
1.1.1.3   root     1740: /* Returns 1 if OP can be a destination of a move.
                   1741:    Same as general_operand, but no preinc allowed.  */
                   1742: 
1.1.1.2   root     1743: int
1.1.1.3   root     1744: general_movdst_operand (op, mode)
                   1745:      rtx op;
                   1746:      enum machine_mode mode;
1.1.1.2   root     1747: {
1.1.1.4 ! root     1748:   /* Only pre dec allowed.  */
        !          1749:   if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == POST_INC)
1.1.1.3   root     1750:     return 0;
                   1751: 
                   1752:   return general_operand (op, mode);
                   1753: }
                   1754: 
                   1755: /* Returns 1 if OP is a normal arithmetic register.  */
                   1756: 
                   1757: int
                   1758: arith_reg_operand (op, mode)
                   1759:      rtx op;
                   1760:      enum machine_mode mode;
                   1761: {
                   1762:   if (register_operand (op, mode))
                   1763:     {
                   1764:       if (GET_CODE (op) == REG)
                   1765:        return (REGNO (op) != T_REG
1.1.1.4 ! root     1766:                && REGNO (op) != PR_REG
        !          1767:                && REGNO (op) != MACH_REG
        !          1768:                && REGNO (op) != MACL_REG);
1.1.1.3   root     1769:       return 1;
                   1770:     }
                   1771:   return 0;
                   1772: }
                   1773: 
                   1774: /* Returns 1 if OP is a valid source operand for an arithmetic insn.  */
                   1775: 
                   1776: int
                   1777: arith_operand (op, mode)
                   1778:      rtx op;
                   1779:      enum machine_mode mode;
                   1780: {
                   1781:   if (arith_reg_operand (op, mode))
                   1782:     return 1;
                   1783: 
1.1.1.4 ! root     1784:   if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_I (INTVAL (op)))
        !          1785:     return 1;
        !          1786: 
1.1.1.3   root     1787:   return 0;
                   1788: }
                   1789: 
1.1.1.4 ! root     1790: /* Returns 1 if OP is a valid source operand for a compare insn.  */
1.1.1.3   root     1791: 
                   1792: int
1.1.1.4 ! root     1793: arith_reg_or_0_operand (op, mode)
1.1.1.3   root     1794:      rtx op;
                   1795:      enum machine_mode mode;
                   1796: {
                   1797:   if (arith_reg_operand (op, mode))
                   1798:     return 1;
                   1799: 
1.1.1.4 ! root     1800:   if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_N (INTVAL (op)))
        !          1801:     return 1;
        !          1802: 
1.1.1.3   root     1803:   return 0;
                   1804: }
                   1805: 
1.1.1.4 ! root     1806: /* Returns 1 if OP is a valid source operand for a logical operation.  */
1.1.1.3   root     1807: 
                   1808: int
1.1.1.4 ! root     1809: logical_operand (op, mode)
1.1.1.3   root     1810:      rtx op;
                   1811:      enum machine_mode mode;
                   1812: {
                   1813:   if (arith_reg_operand (op, mode))
                   1814:     return 1;
1.1.1.4 ! root     1815: 
        !          1816:   if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_L (INTVAL (op)))
1.1.1.3   root     1817:     return 1;
1.1.1.4 ! root     1818: 
1.1.1.3   root     1819:   return 0;
                   1820: }
1.1.1.4 ! root     1821: 
1.1.1.3   root     1822: /* Determine where to put an argument to a function.
                   1823:    Value is zero to push the argument on the stack,
                   1824:    or a hard register in which to store the argument.
                   1825: 
                   1826:    MODE is the argument's machine mode.
                   1827:    TYPE is the data type of the argument (as a tree).
                   1828:     This is null for libcalls where that information may
                   1829:     not be available.
                   1830:    CUM is a variable of type CUMULATIVE_ARGS which gives info about
                   1831:     the preceding args and about the function being called.
                   1832:    NAMED is nonzero if this argument is a named parameter
                   1833:     (otherwise it is an extra parameter matching an ellipsis).  */
                   1834: 
                   1835: rtx
                   1836: sh_function_arg (cum, mode, type, named)
                   1837:      CUMULATIVE_ARGS cum;
                   1838:      enum machine_mode mode;
                   1839:      tree type;
                   1840:      int named;
                   1841: {
                   1842:   if (named)
                   1843:     {
1.1.1.4 ! root     1844:       int rr = (ROUND_REG (cum, mode));
1.1.1.3   root     1845: 
                   1846:       if (rr < NPARM_REGS)
1.1.1.4 ! root     1847:        return ((type == 0 || ! TREE_ADDRESSABLE (type))
        !          1848:                ? gen_rtx (REG, mode, FIRST_PARM_REG + rr) : 0);
1.1.1.3   root     1849:     }
                   1850:   return 0;
                   1851: }
                   1852: 
                   1853: /* For an arg passed partly in registers and partly in memory,
                   1854:    this is the number of registers used.
                   1855:    For args passed entirely in registers or entirely in memory, zero.
                   1856:    Any arg that starts in the first 4 regs but won't entirely fit in them
                   1857:    needs partial registers on the SH.  */
                   1858: 
                   1859: int
1.1.1.4 ! root     1860: sh_function_arg_partial_nregs (cum, mode, type, named)
        !          1861:      CUMULATIVE_ARGS cum;
        !          1862:      enum machine_mode mode;
        !          1863:      tree type;
        !          1864:      int named;
        !          1865: {
        !          1866:   if (cum < NPARM_REGS)
        !          1867:     {
        !          1868:       if ((type == 0 || ! TREE_ADDRESSABLE (type))
        !          1869:          && (cum + (mode == BLKmode
        !          1870:                     ? ROUND_ADVANCE (int_size_in_bytes (type))
        !          1871:                     : ROUND_ADVANCE (GET_MODE_SIZE (mode))) - NPARM_REGS > 0))
        !          1872:        return NPARM_REGS - cum;
1.1.1.3   root     1873:     }
                   1874:   return 0;
                   1875: }
1.1.1.4 ! root     1876: 
        !          1877: /* Return non-zero if REG is not used after INSN.
        !          1878:    We assume REG is a reload reg, and therefore does
        !          1879:    not live past labels or calls or jumps.  */
        !          1880: int
        !          1881: reg_unused_after (reg, insn)
        !          1882:      rtx reg;
        !          1883:      rtx insn;
        !          1884: {
        !          1885:   enum rtx_code code;
        !          1886:   rtx set;
1.1.1.3   root     1887: 
1.1.1.4 ! root     1888:   /* If the reg is set by this instruction, then it is safe for our
        !          1889:      case.  Disregard the case where this is a store to memory, since
        !          1890:      we are checking a register used in the store address.  */
        !          1891:   set = single_set (insn);
        !          1892:   if (set && GET_CODE (SET_DEST (set)) != MEM
        !          1893:       && reg_overlap_mentioned_p (reg, SET_DEST (set)))
        !          1894:     return 1;
1.1.1.3   root     1895: 
1.1.1.4 ! root     1896:   while (insn = NEXT_INSN (insn))
        !          1897:     {
        !          1898:       code = GET_CODE (insn);
        !          1899: 
        !          1900: #if 0
        !          1901:       /* If this is a label that existed before reload, then the register
        !          1902:         if dead here.  However, if this is a label added by reorg, then
        !          1903:         the register may still be live here.  We can't tell the difference,
        !          1904:         so we just ignore labels completely.  */
        !          1905:       if (code == CODE_LABEL)
        !          1906:        return 1;
        !          1907:       /* else */
        !          1908: #endif
        !          1909: 
        !          1910:       /* If this is a sequence, we must handle them all at once.
        !          1911:         We could have for instance a call that sets the target register,
        !          1912:         and a insn in a delay slot that uses the register.  In this case,
        !          1913:         we must return 0.  */
        !          1914:       if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
        !          1915:        {
        !          1916:          int i;
        !          1917:          int retval = 0;
        !          1918: 
        !          1919:          for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
        !          1920:            {
        !          1921:              rtx this_insn = XVECEXP (PATTERN (insn), 0, i);
        !          1922:              rtx set = single_set (this_insn);
        !          1923: 
        !          1924:              if (GET_CODE (this_insn) == CALL_INSN)
        !          1925:                code = CALL_INSN;
        !          1926: 
        !          1927:              if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
        !          1928:                return 0;
        !          1929:              if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
        !          1930:                {
        !          1931:                  if (GET_CODE (SET_DEST (set)) != MEM)
        !          1932:                    retval = 1;
        !          1933:                  else
        !          1934:                    return 0;
        !          1935:                }
        !          1936:              if (set == 0
        !          1937:                  && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
        !          1938:                return 0;
        !          1939:            }
        !          1940:          if (retval == 1)
        !          1941:            return 1;
        !          1942:        }
        !          1943:       else if (GET_RTX_CLASS (code) == 'i')
        !          1944:        {
        !          1945:          rtx set = single_set (insn);
        !          1946: 
        !          1947:          if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
        !          1948:            return 0;
        !          1949:          if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
        !          1950:            return GET_CODE (SET_DEST (set)) != MEM;
        !          1951:          if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
        !          1952:            return 0;
        !          1953:        }
        !          1954: 
        !          1955:       if (code == CALL_INSN && call_used_regs[REGNO (reg)])
        !          1956:        return 1;
        !          1957:     }
        !          1958:   return 1;
1.1.1.2   root     1959: }

unix.superglobalmegacorp.com

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