Annotation of gcc/config/out-mips.c, revision 1.1.1.3

1.1       root        1: /* Subroutines for insn-output.c for MIPS
                      2:    Contributed by A. Lichnewsky, [email protected].
1.1.1.3 ! root        3:    Changes by     Michael Meissner, [email protected].
        !             4:    Copyright (C) 1989, 1990 Free Software Foundation, Inc.
1.1       root        5: 
                      6: This file is part of GNU CC.
                      7: 
                      8: GNU CC is free software; you can redistribute it and/or modify
                      9: it under the terms of the GNU General Public License as published by
                     10: the Free Software Foundation; either version 1, or (at your option)
                     11: any later version.
                     12: 
                     13: GNU CC is distributed in the hope that it will be useful,
                     14: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     15: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     16: GNU General Public License for more details.
                     17: 
                     18: You should have received a copy of the GNU General Public License
                     19: along with GNU CC; see the file COPYING.  If not, write to
                     20: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     21: 
                     22: 
                     23: #include <stdio.h>
1.1.1.3 ! root       24: #include "tree.h"
        !            25: #include "flags.h"
        !            26: 
        !            27: extern void  debug_rtx ();
1.1       root       28: extern void  abort_with_insn ();
                     29: 
1.1.1.3 ! root       30: extern FILE *asm_out_file;
        !            31: extern tree current_function_decl;
1.1       root       32: 
                     33: /* Global variables for machine-dependent things.  */
                     34: 
                     35: char *reg_numchar[] = REGISTER_NUMCHAR;
                     36: 
1.1.1.3 ! root       37: /* Threshold for data being put into the small data/bss area, instead
        !            38:    of the normal data area (references to the small data/bss area take
        !            39:    1 instruction, and use the global pointer, references to the normal
        !            40:    data area takes 2 instructions).  */
        !            41: int mips_section_threshold = -1;
        !            42: 
        !            43: /* Count the number of .file directives, so that .loc is up to date.  */
        !            44: int num_source_filenames = 0;
        !            45: 
        !            46: /* Count the number of words that are pushed to pass arguments.  */
        !            47: int stack_args_pushed = 0;
        !            48: 
        !            49: /* # bytes for args preallocated by function_prolog. */
        !            50: int stack_args_preallocated = 0;
        !            51: 
        !            52: /* Count of the number of functions created so far, in order to make
        !            53:    unique labels for omitting the frame pointer.  */
        !            54: int number_functions_processed = 0;
        !            55: 
        !            56: /* Count the number of sdb related labels are generated (to find block
        !            57:    start and end boundaries).  */
        !            58: int sdb_label_count = 0;
        !            59: 
        !            60: /* Next label # for each statment for Silicon Graphics IRIS systems. */
        !            61: int sym_lineno = 0;
        !            62: 
        !            63: /* Non-zero if inside of a function, because the stupid MIPS asm can't
        !            64:    handle .files inside of functions.  */
        !            65: int inside_function = 0;
        !            66: 
        !            67: /* String to be used for the unique name given to the difference between
        !            68:    the stack pointer and frame pointer when the frame pointer is to be
        !            69:    omitted.  */
        !            70: char *sp_fp_difference = 0;
        !            71: 
        !            72: /* Files to separate the text and the data output, so that all of the data
        !            73:    can be emitted before the text, which will mean that the assembler will
        !            74:    generate smaller code, based on the global pointer.  */
        !            75: FILE *asm_out_data_file;
        !            76: FILE *asm_out_text_file;
        !            77: 
        !            78: /* Linked list of all externals that are to be emitted when optimizing
        !            79:    for the global pointer if they haven't been declared by the end of
        !            80:    the program with an appropriate .comm or initialization.  */
        !            81: 
        !            82: struct extern_list {
        !            83:   struct extern_list *next;    /* next external */
        !            84:   char *name;                  /* name of the external */
        !            85:   int size;                    /* size in bytes */
        !            86: } *extern_head = 0;
        !            87: 
        !            88: /* Name of the current function.  */
        !            89: char *current_function_name;
        !            90: 
        !            91: /* Size of the frame allocated for this function.  */
        !            92: int current_function_total_framesize;
        !            93: 
        !            94: /* Number of bytes used to hold saved registers.  */
        !            95: int current_function_saved_reg_size;
        !            96: 
        !            97: /* Return truth value of whether OP can be used as an operands
        !            98:    where a register or 16 bit unsigned integer is needed.  */
        !            99: 
        !           100: int
        !           101: uns_arith_operand (op, mode)
        !           102:      rtx op;
        !           103:      enum machine_mode mode;
        !           104: {
        !           105:   return (register_operand (op, mode)
        !           106:          || (GET_CODE (op) == CONST_INT && SMALL_INT_UNSIGNED (op)));
        !           107: }
1.1       root      108: 
                    109: /* Return truth value of whether OP can be used as an operands
                    110:    where a 16 bit integer is needed  */
                    111: 
                    112: int
                    113: arith_operand (op, mode)
                    114:      rtx op;
                    115:      enum machine_mode mode;
                    116: {
                    117:   return (register_operand (op, mode)
                    118:          || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
                    119: }
                    120: 
                    121: /* Return truth value of whether OP can be used as an operand in a two
                    122:    address arithmetic insn (such as set 123456,%o4) of mode MODE.  */
                    123: 
                    124: int
                    125: arith32_operand (op, mode)
                    126:      rtx op;
                    127:      enum machine_mode mode;
                    128: {
                    129:   return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
                    130: }
                    131: 
                    132: /* Return truth value of whether OP is a integer which fits in 16 bits  */
                    133: 
                    134: int
                    135: small_int (op, mode)
                    136:      rtx op;
                    137:      enum machine_mode mode;
                    138: {
                    139:   return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
                    140: }
                    141: 
                    142: 
1.1.1.3 ! root      143: /* Argument support functions.  */
        !           144: 
        !           145: /* Initialize CUMULATIVE_ARGS for a function.  */
        !           146: 
        !           147: void
        !           148: init_cumulative_args (cum, fntype)
        !           149:      CUMULATIVE_ARGS cum;      /* argument info to initialize */
        !           150:      tree fntype;              /* tree ptr for function decl */
1.1       root      151: {
1.1.1.3 ! root      152:   tree param, next_param;
1.1       root      153: 
1.1.1.3 ! root      154:   if (TARGET_DEBUGE_MODE)
1.1       root      155:     {
1.1.1.3 ! root      156:       fprintf (stderr, "\ninit_cumulative_args\n");
        !           157:       if (fntype != (tree)0)
1.1       root      158:        {
1.1.1.3 ! root      159:          putc ('\n', stderr);
        !           160:          debug_tree (fntype);
        !           161:          putc ('\n', stderr);
1.1       root      162:        }
                    163:     }
1.1.1.3 ! root      164: 
        !           165:   cum->gp_reg_found = 0;
        !           166:   cum->arg_number = 0;
        !           167:   cum->arg_words = 0;
        !           168: 
        !           169:   /* Determine if this function has variable arguments.  This is
        !           170:      indicated by the last argument being 'void_type_mode' if there
        !           171:      are no variable arguments.  The standard MIPS calling sequence
        !           172:      passes all arguments in the general purpose registers in this
        !           173:      case. */
        !           174: 
        !           175:   for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0;
        !           176:        param != (tree)0;
        !           177:        param = next_param)
1.1       root      178:     {
1.1.1.3 ! root      179:       next_param = TREE_CHAIN (param);
        !           180:       if (next_param == (tree)0 && TREE_VALUE (param) != void_type_node)
        !           181:        cum->gp_reg_found = 1;
1.1       root      182:     }
1.1.1.3 ! root      183: 
        !           184:   /* Determine if the function is returning a structure, if so,
        !           185:      advance by one argument.  */
        !           186: 
        !           187:   if (fntype
        !           188:       && (TREE_CODE (fntype) == FUNCTION_TYPE || TREE_CODE (fntype) == METHOD_TYPE)
        !           189:       && TREE_TYPE (fntype) != 0)
1.1       root      190:     {
1.1.1.3 ! root      191:       tree ret_type = TREE_TYPE (fntype);
        !           192:       enum tree_code ret_code = TREE_CODE (ret_type);
        !           193: 
        !           194:       if (ret_code == RECORD_TYPE || ret_code == UNION_TYPE)
        !           195:        {
        !           196:          cum->gp_reg_found = 1;
        !           197:          cum->arg_number = 1;
        !           198:          cum->arg_words = 1;
        !           199:        }
1.1       root      200:     }
                    201: }
                    202: 
1.1.1.3 ! root      203: /* Advance the argument to the next argument position.  */
1.1       root      204: 
1.1.1.3 ! root      205: void
        !           206: function_arg_advance (cum, mode, type, named)
        !           207:      CUMULATIVE_ARGS cum;      /* current arg information */
        !           208:      enum machine_mode mode;   /* current arg mode */
        !           209:      tree type;                        /* type of the argument or 0 if lib support */
        !           210: {
        !           211:   if (TARGET_DEBUGE_MODE)
        !           212:     fprintf (stderr,
        !           213:             "function_adv( {gp reg found = %d, arg # = %2d, words = %2d}, %4s, 0x%.8x, %d )\n",
        !           214:             cum->gp_reg_found, cum->arg_number, cum->arg_words, GET_MODE_NAME (mode),
        !           215:             type, named);
        !           216: 
        !           217:   cum->arg_number++;
        !           218:   switch (mode)
        !           219:     {
        !           220:     default:
        !           221:       error ("Illegal mode given to function_arg_advance");
        !           222:       break;
        !           223: 
        !           224:     case VOIDmode:
        !           225:       break;
        !           226: 
        !           227:     case BLKmode:
        !           228:       cum->gp_reg_found = 1;
        !           229:       cum->arg_words += (int_size_in_bytes (type) + 3) / 4;
        !           230:       break;
        !           231: 
        !           232:     case SFmode:
        !           233:       cum->arg_words++;
        !           234:       break;
        !           235: 
        !           236:     case DFmode:
        !           237:       cum->arg_words += 2;
        !           238:       break;
        !           239: 
        !           240:     case DImode:
        !           241:       cum->gp_reg_found = 1;
        !           242:       cum->arg_words += 2;
        !           243:       break;
        !           244: 
        !           245:     case QImode:
        !           246:     case HImode:
        !           247:     case SImode:
        !           248:       cum->gp_reg_found = 1;
        !           249:       cum->arg_words++;
        !           250:       break;
1.1       root      251:     }
                    252: }
                    253: 
1.1.1.3 ! root      254: /* Return a RTL expression containing the register for the given mode,
        !           255:    or 0 if the argument is too be passed on the stack.  */
1.1       root      256: 
1.1.1.3 ! root      257: struct rtx_def *
        !           258: function_arg (cum, mode, type, named)
        !           259:      CUMULATIVE_ARGS cum;      /* current arg information */
        !           260:      enum machine_mode mode;   /* current arg mode */
        !           261:      tree type;                        /* type of the argument or 0 if lib support */
        !           262:      int named;                        /* != 0 for normal args, == 0 for ... args */
        !           263: {
        !           264:   int regbase = -1;
        !           265:   int bias = 0;
1.1       root      266: 
1.1.1.3 ! root      267:   if (TARGET_DEBUGE_MODE)
        !           268:     fprintf (stderr,
        !           269:             "function_arg( {gp reg found = %d, arg # = %2d, words = %2d}, %4s, 0x%.8x, %d ) = ",
        !           270:             cum->gp_reg_found, cum->arg_number, cum->arg_words, GET_MODE_NAME (mode),
        !           271:             type, named);
1.1       root      272: 
1.1.1.3 ! root      273:   switch (mode)
        !           274:     {
        !           275:     default:
        !           276:       error ("Illegal mode given to function_arg");
        !           277:       break;
1.1       root      278: 
1.1.1.3 ! root      279:     case SFmode:
        !           280:       if (cum->gp_reg_found || cum->arg_number >= 2)
        !           281:        regbase = GP_ARG_FIRST;
        !           282:       else {
        !           283:        regbase = FP_ARG_FIRST;
        !           284:        if (cum->arg_words == 1)        /* first arg was float */
        !           285:          bias = 1;                     /* use correct reg */
        !           286:       }
1.1       root      287: 
1.1.1.3 ! root      288:       break;
1.1       root      289: 
1.1.1.3 ! root      290:     case DFmode:
        !           291:       cum->arg_words += (cum->arg_words & 1);
        !           292:       regbase = (cum->gp_reg_found) ? GP_ARG_FIRST : FP_ARG_FIRST;
        !           293:       break;
1.1       root      294: 
1.1.1.3 ! root      295:     case VOIDmode:
        !           296:     case BLKmode:
        !           297:     case QImode:
        !           298:     case HImode:
        !           299:     case SImode:
        !           300:     case DImode:
        !           301:       regbase = GP_ARG_FIRST;
        !           302:       break;
        !           303:     }
1.1       root      304: 
1.1.1.3 ! root      305:   if (cum->arg_words >= MAX_ARGS_IN_REGISTERS)
        !           306:     {
        !           307:       if (TARGET_DEBUGE_MODE)
        !           308:        fprintf (stderr, "<stack>\n");
1.1       root      309: 
1.1.1.3 ! root      310:       return 0;
        !           311:     }
        !           312: 
        !           313:   if (regbase == -1)
        !           314:     abort ();
        !           315: 
        !           316:   if (TARGET_DEBUGE_MODE)
        !           317:     fprintf (stderr, "%s\n", reg_numchar[ regbase + cum->arg_number + bias ]);
1.1       root      318: 
1.1.1.3 ! root      319:   return gen_rtx (REG, mode, regbase + cum->arg_words + bias);
1.1       root      320: }
                    321: 
1.1.1.3 ! root      322: 
        !           323: int
        !           324: function_arg_partial_nregs (cum, mode, type, named)
        !           325:      CUMULATIVE_ARGS cum;      /* current arg information */
        !           326:      enum machine_mode mode;   /* current arg mode */
        !           327:      tree type;                        /* type of the argument or 0 if lib support */
        !           328:      int named;                        /* != 0 for normal args, == 0 for ... args */
1.1       root      329: {
1.1.1.3 ! root      330:   if (mode == BLKmode && cum->arg_number < MAX_ARGS_IN_REGISTERS)
        !           331:     {
        !           332:       int words = (int_size_in_bytes (type) + 3) / 4;
        !           333: 
        !           334:       if (words + cum->arg_words < MAX_ARGS_IN_REGISTERS)
        !           335:        return 0;               /* structure fits in registers */
        !           336: 
        !           337:       if (TARGET_DEBUGE_MODE)
        !           338:        fprintf (stderr, "function_arg_partial_nregs = %d\n",
        !           339:                 MAX_ARGS_IN_REGISTERS - cum->arg_words);
1.1       root      340: 
1.1.1.3 ! root      341:       return MAX_ARGS_IN_REGISTERS - cum->arg_words;
        !           342:     }
        !           343: 
        !           344:   else if (mode == DImode && cum->arg_number == MAX_ARGS_IN_REGISTERS-1)
1.1.1.2   root      345:     {
1.1.1.3 ! root      346:       if (TARGET_DEBUGE_MODE)
        !           347:        fprintf (stderr, "function_arg_partial_nregs = 1\n");
        !           348: 
        !           349:       return 1;
1.1.1.2   root      350:     }
1.1       root      351: 
1.1.1.3 ! root      352:   return 0;
        !           353: }
1.1       root      354: 
                    355: 
1.1.1.3 ! root      356: /* Routines to merge the compare and branch operators into a single entity.  */
        !           357: 
1.1       root      358: static  rtx branch_cmp_op[2];
                    359: static  enum machine_mode branch_cmp_mode;
                    360: 
1.1.1.3 ! root      361: /* Save the mode and operands on the current compare operator.  */
        !           362: 
        !           363: void
1.1       root      364: compare_collect (mode, op0, op1)
                    365:      enum machine_mode mode;
                    366:      rtx op0;
                    367:      rtx op1;
                    368: {
                    369:   if (TARGET_DEBUGD_MODE)
                    370:     {
1.1.1.3 ! root      371:       fprintf (stderr, "compare_collect mode = %s, operands::",
        !           372:               GET_MODE_NAME (mode));
        !           373:       debug_rtx (op0);
        !           374:       debug_rtx (op1);
1.1       root      375:     }
                    376:   branch_cmp_op[0] = op0;
                    377:   branch_cmp_op[1] = op1;
                    378:   branch_cmp_mode = mode;
                    379: }
                    380: 
1.1.1.3 ! root      381: /* Return the mode and operands saved with compare_collect for use
        !           382:    in a branch operator.  */
1.1       root      383: 
1.1.1.3 ! root      384: void
1.1       root      385: compare_restore (operands, mode, insn)
                    386:      rtx *operands;
                    387:      enum machine_mode *mode;
                    388:      rtx insn;
                    389: {
1.1.1.3 ! root      390:   if (!branch_cmp_op[0] || !branch_cmp_op[1])
        !           391:     abort_with_insn (insn, "Compare_restore did not follow compare_collect");
1.1       root      392: 
1.1.1.3 ! root      393:   if (TARGET_DEBUGD_MODE)
1.1       root      394:     {
1.1.1.3 ! root      395:       fprintf (stderr,
        !           396:               "compare_restore returning mode = %s, operands:%X,%X:",
        !           397:               GET_MODE_NAME (branch_cmp_mode),
        !           398:               branch_cmp_op[0],
        !           399:               branch_cmp_op[1]);
1.1       root      400: 
1.1.1.3 ! root      401:       debug_rtx (branch_cmp_op[0]);
        !           402:       debug_rtx (branch_cmp_op[1]);
1.1       root      403:     }
                    404: 
1.1.1.3 ! root      405:   operands[0] = branch_cmp_op[0];
        !           406:   operands[1] = branch_cmp_op[1];
1.1       root      407:   *mode = branch_cmp_mode;
                    408: 
1.1.1.3 ! root      409:   /* If the next insn is not a JUMP (after accounting for line numbers),
        !           410:      zero out the branch_cmp_array.  Switch statements implemented as if's
        !           411:      tend to have multiple jumps.  */
        !           412:   do
        !           413:     {
        !           414:       insn = NEXT_INSN (insn);
        !           415:     }
        !           416:   while (insn && GET_CODE (insn) == NOTE);
        !           417: 
        !           418:   if (!insn || GET_CODE (insn) != JUMP_INSN)
        !           419:     {
        !           420:       branch_cmp_op[0] = NULL;
        !           421:       branch_cmp_op[1] = NULL;
        !           422:       branch_cmp_mode = VOIDmode;
        !           423:     }
1.1       root      424: 
                    425: }
                    426: 
1.1.1.3 ! root      427: /* Print the options used in the assembly file.  */
        !           428: 
        !           429: static struct {char *name; int value;} target_switches []
        !           430:   = TARGET_SWITCHES;
1.1       root      431: 
                    432: void
                    433: print_options (out)
                    434:      FILE *out;
                    435: {
1.1.1.3 ! root      436:   int line_len;
        !           437:   int len;
        !           438:   int j;
        !           439:   char **p;
        !           440:   int mask = TARGET_DEFAULT;
        !           441:   extern char **save_argv;
        !           442:   extern char *version_string, *language_string;
1.1       root      443: 
1.1.1.3 ! root      444: #if 0
        !           445:   /* Allow assembly language comparisons with -mdebug eliminating the
        !           446:      compiler version number and switch lists.  */
        !           447:   if (!TARGET_DEBUG_MODE)
        !           448:     {
        !           449:       fprintf (out, "\n # %s %s", language_string, version_string);
        !           450: #ifdef TARGET_VERSION_INTERNAL
        !           451:       TARGET_VERSION_INTERNAL (out);
1.1       root      452: #endif
1.1.1.3 ! root      453: #ifdef __GNUC__
        !           454:       fprintf (out, " compiled by GNU C\n\n");
1.1       root      455: #else
1.1.1.3 ! root      456:       fprintf (out, " compiled by CC\n\n");
1.1       root      457: #endif
                    458: 
1.1.1.3 ! root      459:       fprintf (out, " # Cc1 defaults:");
        !           460:       line_len = 32767;
        !           461:       for (j = 0; j < sizeof target_switches / sizeof target_switches[0]; j++)
        !           462:        if (target_switches[j].name[0] != '\0'
        !           463:            && target_switches[j].value > 0
        !           464:            && (target_switches[j].value & mask) == target_switches[j].value)
        !           465:          {
        !           466:            len = strlen (target_switches[j].name) + 1;
        !           467:            if (len + line_len > 79)
        !           468:              {
        !           469:                line_len = 2;
        !           470:                fputs ("\n #", out);
        !           471:              }
        !           472:            fprintf (out, " -m%s", target_switches[j].name);
        !           473:            line_len += len;
        !           474:          }
1.1       root      475: 
1.1.1.3 ! root      476:       fprintf (out, "\n\n # Cc1 arguments (-G value = %d):",
        !           477:               mips_section_threshold);
1.1       root      478: 
1.1.1.3 ! root      479:       line_len = 32767;
        !           480:       for (p = &save_argv[1]; *p != (char *)0; p++)
        !           481:        if (**p == '-')
        !           482:          {
        !           483:            len = strlen (*p) + 1;
        !           484:            if (len + line_len > 79)
        !           485:              {
        !           486:                line_len = 2;
        !           487:                fputs ("\n #", out);
        !           488:              }
        !           489:            fprintf (out, " %s", *p);
        !           490:            line_len += len;
        !           491:          }
        !           492:       fputs ("\n\n", out);
        !           493:     }
1.1       root      494: 
1.1.1.3 ! root      495: #endif
1.1       root      496: }
                    497: 
1.1.1.3 ! root      498: 
1.1       root      499: 
1.1.1.3 ! root      500: /* Abort after printing out a specific insn.  */
1.1       root      501: 
                    502: void
                    503: abort_with_insn (insn, reason)
                    504:      rtx insn;
                    505:      char *reason;
                    506: {
1.1.1.3 ! root      507:   error (reason);
        !           508:   debug_rtx (insn);
1.1       root      509:   abort ();
                    510: }
                    511: 
1.1.1.3 ! root      512: /* Write a message to stderr (for use in macros expanded in files that do not
        !           513:    include stdio.h).  */
1.1       root      514: 
                    515: void
1.1.1.3 ! root      516: trace (s, s1, s2)
        !           517:      char *s, *s1, *s2;
1.1       root      518: {
1.1.1.3 ! root      519:   fprintf (stderr, s, s1, s2);
1.1       root      520: }
                    521: 
1.1.1.3 ! root      522: 
        !           523: /* Set up the threshold for data to go into the small data area, instead
        !           524:    of the normal data area, and detect any conflicts in the switches.  */
1.1       root      525: 
1.1.1.3 ! root      526: void
        !           527: overide_options ()
1.1       root      528: {
                    529:   register int i;
                    530: 
1.1.1.3 ! root      531:   i = TARGET_GVALUE;
        !           532:   if (i >= 6)
        !           533:     i += 3;
        !           534:   mips_section_threshold = (i != 0) ? 1 << i : 0;
1.1       root      535: }
1.1.1.3 ! root      536: 
        !           537: /* If optimizing for the global pointer, keep track of all of
        !           538:    the externs, so that at the end of the file, we can emit
        !           539:    the appropriate .extern declaration for them, before writing
        !           540:    out the text section.  We assume that all names passed to
        !           541:    us are in the permanent obstack, so that they will be valid
        !           542:    at the end of the compilation.
        !           543: 
        !           544:    If we have -G 0, or the extern size is unknown, don't bother
        !           545:    emitting the .externs.  */
1.1       root      546: 
                    547: int
1.1.1.3 ! root      548: mips_output_external (file, decl, name)
1.1       root      549:      FILE *file;
1.1.1.3 ! root      550:      tree decl;
1.1       root      551:      char *name;
                    552: {
1.1.1.3 ! root      553:   extern char *permalloc ();
        !           554:   register struct extern_list *p;
        !           555:   int len;
        !           556: 
1.1       root      557:   if (TARGET_GP_OPT
1.1.1.3 ! root      558:       && mips_section_threshold != 0
        !           559:       && ((TREE_CODE (decl)) != FUNCTION_DECL)
        !           560:       && ((len = int_size_in_bytes (TREE_TYPE (decl))) > 0))
        !           561:     {
        !           562:       p = (struct extern_list *)permalloc ((long) sizeof (struct extern_list));
        !           563:       p->next = extern_head;
        !           564:       p->name = name;
        !           565:       p->size = len;
        !           566:       extern_head = p;
1.1       root      567:     }
                    568:   return 0;
                    569: }
1.1.1.3 ! root      570: 
        !           571: /* If we are optimizing the global pointer, emit the text section now
        !           572:    and any small externs which did not have .comm, etc that are
        !           573:    needed.  Also, give a warning if the data area is more than 32K and
        !           574:    -pic because 3 instructions are needed to reference the data
        !           575:    pointers.  */
1.1       root      576: 
                    577: int
                    578: mips_asm_file_end (file)
                    579:      FILE *file;
                    580: {
1.1.1.3 ! root      581:   char buffer[8192];
        !           582:   tree name_tree;
        !           583:   struct extern_list *p;
        !           584:   int len;
        !           585:   extern tree lookup_name ();
        !           586: 
1.1       root      587:   if (TARGET_GP_OPT)
                    588:     {
1.1.1.3 ! root      589:       if (extern_head)
        !           590:        fputs ("\n", file);
        !           591: 
        !           592:       for (p = extern_head; p != 0; p = p->next)
        !           593:        {
        !           594:          name_tree = get_identifier (p->name);
        !           595:          if (!TREE_ADDRESSABLE (name_tree))
        !           596:            {
        !           597:              TREE_ADDRESSABLE (name_tree) = 1;
        !           598:              fprintf (file, "\t.extern\t%s, %d\n", p->name, p->size);
        !           599:            }
        !           600:        }
        !           601: 
        !           602:       fprintf (file, "\n\t.text\n");
        !           603:       rewind (asm_out_text_file);
        !           604:       if (ferror (asm_out_text_file))
        !           605:        fatal_io_error ("write of text assembly file in mips_asm_file_end");
        !           606: 
        !           607:       while ((len = fread (buffer, 1, sizeof (buffer), asm_out_text_file)) > 0)
        !           608:        if (fwrite (buffer, 1, len, file) != len)
        !           609:          pfatal_with_name ("write of final assembly file in mips_asm_file_end");
        !           610: 
        !           611:       if (len < 0)
        !           612:        pfatal_with_name ("read of text assembly file in mips_asm_file_end");
        !           613: 
        !           614:       if (fclose (asm_out_text_file) != 0)
        !           615:        pfatal_with_name ("close of tempfile in mips_asm_file_end");
        !           616:     }
        !           617: }
        !           618: 
        !           619: /* Fix references to the frame pointer to be off of the stack pointer.  */
        !           620: 
        !           621: struct rtx_def *
        !           622: mips_fix_frame_pointer (oldaddr, depth)
        !           623:      rtx oldaddr;
        !           624:      int depth;
        !           625: {
        !           626:   rtx newaddr;
        !           627:   rtx sp_diff_rtx;
        !           628:   char temp[40];
        !           629:   int frame_offset = 0;
        !           630:   extern rtx eliminate_constant_term ();
        !           631: 
        !           632:   newaddr = eliminate_constant_term (oldaddr, &frame_offset);
        !           633:   if (newaddr != frame_pointer_rtx)
        !           634:     return oldaddr;
        !           635: 
        !           636:   if (sp_fp_difference == (char *)0)
        !           637:     {
        !           638:       sprintf (temp, "$Ls%d", number_functions_processed);
        !           639:       sp_fp_difference = IDENTIFIER_POINTER (get_identifier (temp));
1.1       root      640:     }
1.1.1.3 ! root      641: 
        !           642:   sp_diff_rtx = gen_rtx (SYMBOL_REF, SImode, sp_fp_difference);
        !           643:   if (frame_offset + depth == 0)
        !           644:     newaddr = gen_rtx (PLUS, Pmode, stack_pointer_rtx, sp_diff_rtx);
        !           645:   else
        !           646:     newaddr = gen_rtx (PLUS, Pmode,
        !           647:                       stack_pointer_rtx,
        !           648:                       gen_rtx (CONST, Pmode,
        !           649:                                gen_rtx (PLUS, Pmode,
        !           650:                                         sp_diff_rtx,
        !           651:                                         gen_rtx (CONST_INT, VOIDmode,
        !           652:                                                  frame_offset + depth))));
        !           653: 
        !           654:   if (TARGET_DEBUGC_MODE)
        !           655:     {
        !           656:       fprintf (stderr,
        !           657:               "\n==================== FIX_FRAME, depth = %d, sp prealloc = %d, offset = %d\n",
        !           658:               depth, stack_args_preallocated, frame_offset);
        !           659: 
        !           660:       fprintf (stderr, "old INSN:");
        !           661:       debug_rtx (oldaddr);
        !           662: 
        !           663:       fprintf (stderr, "\nnew INSN:");
        !           664:       debug_rtx (newaddr);
        !           665:     }
        !           666: 
        !           667:   return newaddr;
        !           668: }
        !           669: 
        !           670: 
        !           671: /* Set up the stack and frame (if desired) for the function.  */
        !           672: 
        !           673: void
        !           674: function_prologue (file, size)
        !           675:      FILE *file;
        !           676:      int size;
        !           677: {
        !           678:   extern char call_used_regs[];
        !           679:   extern char *reg_numchar[];
        !           680:   extern tree current_function_decl;
        !           681:   int regno;
        !           682:   int mask;
        !           683:   int fmask;
        !           684:   int push_loc;
        !           685:   int tsize;
        !           686:   int num_regs;
        !           687:   char **reg_name_ptr = (TARGET_NAME_REGS) ? reg_names : reg_numchar;
        !           688:   char *base_str;
        !           689:   char *sp_str = reg_name_ptr[STACK_POINTER_REGNUM];
        !           690:   char *fp_str = (!frame_pointer_needed)
        !           691:                        ? sp_str
        !           692:                        : reg_name_ptr[FRAME_POINTER_REGNUM];
        !           693:   tree fndecl = current_function_decl; /* current... is tooo long */
        !           694:   tree fntype = TREE_TYPE (fndecl);
        !           695:   tree fnargs = (TREE_CODE (fntype) != METHOD_TYPE)
        !           696:                        ? DECL_ARGUMENTS (fndecl)
        !           697:                        : 0;
        !           698:   tree next_arg;
        !           699:   tree cur_arg;
        !           700:   char *arg_name = (char *)0;
        !           701:   CUMULATIVE_ARGS args_so_far;
        !           702: 
        !           703: 
        !           704:   inside_function = 1;
        !           705: 
        !           706: 
        !           707:   if (write_symbols != NO_DEBUG)
        !           708:     ASM_OUTPUT_SOURCE_LINE (file,
        !           709:                            DECL_SOURCE_LINE (current_function_decl));
        !           710: 
        !           711:   fprintf (file, "\t.ent\t%s\n%s:\n", current_function_name,
        !           712:           current_function_name);
        !           713: 
        !           714:   fprintf (file, " #PROLOGUE\n");
        !           715: 
        !           716:   /* Determine the last argument, and get it's name.  */
        !           717:   for (cur_arg = fnargs; cur_arg != (tree)0; cur_arg = next_arg)
        !           718:     {
        !           719:       next_arg = TREE_CHAIN (cur_arg);
        !           720:       if (next_arg == (tree)0)
        !           721:        {
        !           722:          if (DECL_NAME (cur_arg))
        !           723:            arg_name = IDENTIFIER_POINTER (DECL_NAME (cur_arg));
        !           724: 
        !           725:          break;
        !           726:        }
        !           727:     }
        !           728: 
        !           729:   /* If this function is a varargs function, store any registers that
        !           730:      would normally hold arguments ($4 - $7) on the stack.  */
        !           731:   if ((TYPE_ARG_TYPES (fntype) != 0
        !           732:        && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) != void_type_node))
        !           733:       || (arg_name
        !           734:          && (strcmp (arg_name, "__builtin_va_alist") == 0
        !           735:              || strcmp (arg_name, "va_alist") == 0)))
        !           736:     {
        !           737:       tree parm;
        !           738: 
        !           739:       regno = 4;
        !           740:       INIT_CUMULATIVE_ARGS (args_so_far, fntype);
        !           741:           
        !           742:       for (parm = fnargs; (parm && (regno <= 7)); parm = TREE_CHAIN (parm))
        !           743:        {
        !           744:          rtx entry_parm;
        !           745:          enum machine_mode passed_mode;
        !           746:          tree type;
        !           747: 
        !           748:          type = DECL_ARG_TYPE (parm);
        !           749:          passed_mode = TYPE_MODE (type);
        !           750:          entry_parm = FUNCTION_ARG (args_so_far, passed_mode,
        !           751:                                     DECL_ARG_TYPE (parm), 1);
        !           752: 
        !           753:          if (entry_parm)
        !           754:            {
        !           755:              int words;
        !           756: 
        !           757:              /* passed in a register, so will get homed automatically */
        !           758:              if (GET_MODE (entry_parm) == BLKmode)
        !           759:                words = (int_size_in_bytes (type) + 3) / 4;
        !           760:              else
        !           761:                words = (GET_MODE_SIZE (GET_MODE (entry_parm)) + 3) / 4;
        !           762: 
        !           763:              regno = REGNO (entry_parm) + words - 1;
        !           764:            }
        !           765:          else
        !           766:            {
        !           767:              regno = 8;
        !           768:              break;
        !           769:            }
        !           770: 
        !           771:          FUNCTION_ARG_ADVANCE (args_so_far, passed_mode,
        !           772:                                DECL_ARG_TYPE (parm), 1);
        !           773:        }
        !           774: 
        !           775:       switch (regno)
        !           776:        {
        !           777:        case 4:
        !           778:          fprintf(file, "\tsd\t%s,0(%s)\t#varargs: home regs 4-5\n",
        !           779:                  reg_name_ptr[4], sp_str);
        !           780: 
        !           781:          fprintf(file, "\tsd\t%s,8(%s)\t#varargs: home regs 6-7\n",
        !           782:                  reg_name_ptr[6], sp_str);
        !           783:          break;
        !           784: 
        !           785:        case 5:
        !           786:          fprintf(file, "\tsw\t%s,4(%s)\t#varargs: home reg  5\n",
        !           787:                  reg_name_ptr[5], sp_str);
        !           788: 
        !           789:          fprintf(file, "\tsd\t%s,8(%s)\t#varargs: home regs 6-7\n",
        !           790:                  reg_name_ptr[6], sp_str);
        !           791:          break;
        !           792: 
        !           793:        case 6:
        !           794:          fprintf(file, "\tsd\t%s,8(%s)\t#varargs: home regs 6-7\n",
        !           795:                  reg_name_ptr[6], sp_str);
        !           796:          break;
        !           797: 
        !           798:        case 7: 
        !           799:          fprintf(file, "\tsw\t%s,12(%s)\t#varargs: home reg 7\n",
        !           800:                  reg_name_ptr[7], sp_str);
        !           801:          break;
        !           802: 
        !           803:        default:
        !           804:          break;
        !           805:        }
        !           806:     }
        !           807: 
        !           808:   mask = 0;
        !           809:   fmask = 0;
        !           810:   num_regs = 0;
        !           811:   push_loc = stack_args_preallocated;
        !           812:   tsize = AL_ADJUST_ALIGN (size) + stack_args_preallocated;
        !           813: 
        !           814:   for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
        !           815:     if (MUST_SAVE_REGISTER (regno))
        !           816:       {
        !           817:        tsize += 4;
        !           818:        num_regs += 4;
        !           819:        mask |= 1 << (regno - GP_REG_FIRST);
        !           820:       }
        !           821: 
        !           822:   tsize = AL_ADJUST_ALIGN (tsize);
        !           823:   num_regs = AL_ADJUST_ALIGN (num_regs);
        !           824:   for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno += 2)
        !           825:     if (regs_ever_live[regno] && !call_used_regs[regno])
        !           826:       {
        !           827:        tsize += 8;
        !           828:        num_regs += 8;
        !           829:        fmask |= 1 << (regno - FP_REG_FIRST);
        !           830:       }
        !           831: 
        !           832:   if (tsize)
        !           833:     tsize -= STARTING_FRAME_OFFSET;
        !           834: 
        !           835: 
        !           836:   if (!frame_pointer_needed && sp_fp_difference != (char *)0)
        !           837:     fprintf (file,"%s\t= %d\t\t\t#Difference between SP & FP\n\n",
        !           838:             sp_fp_difference, tsize);
        !           839: 
        !           840:   current_function_total_framesize = tsize;
        !           841:   current_function_saved_reg_size = num_regs;
        !           842:   if (tsize > 0)
        !           843:     {
        !           844:       if (tsize <= 32767)
        !           845:        fprintf (file,
        !           846:                 "\tsubu\t%s,%s,%d\t# temp= %d, regs= %d, args= %d, sfo= %d\n",
        !           847:                 sp_str, sp_str, tsize, size, num_regs,
        !           848:                 stack_args_preallocated, STARTING_FRAME_OFFSET);
        !           849:       else
        !           850:        fprintf (file,
        !           851:                 "\tli\t%s,%d\n\tsubu\t%s,%s,%s\t# temp= %d, regs= %d, args= %d, sfo= %d\n",
        !           852:                 reg_name_ptr[MIPS_TEMP1_REGNUM], tsize, sp_str, sp_str,
        !           853:                 reg_name_ptr[MIPS_TEMP1_REGNUM], size, num_regs,
        !           854:                 stack_args_preallocated, STARTING_FRAME_OFFSET);
        !           855:     }
        !           856: 
        !           857:   fprintf (file, "\t.frame\t%s,%d,%s\n", fp_str,
        !           858:           (frame_pointer_needed) ? 0 : tsize,
        !           859:           reg_name_ptr[31]);
        !           860: 
        !           861:   if (push_loc > 32767 && num_regs > 0)
        !           862:     {
        !           863:       if ((tsize - (push_loc + num_regs)) <= 32767)
        !           864:        {
        !           865:          base_str = reg_name_ptr[MIPS_TEMP1_REGNUM];
        !           866:          push_loc = tsize - push_loc;
        !           867:        }
        !           868:       else 
        !           869:        {
        !           870:          base_str = reg_name_ptr[MIPS_TEMP2_REGNUM];
        !           871:          fprintf (file, "\tli\t%s,%d\n", base_str, push_loc);
        !           872:          push_loc = 0;
        !           873:        }
        !           874:     }
        !           875:   else
        !           876:     base_str = sp_str;
        !           877: 
        !           878:   for  (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
        !           879:     if ((mask & (1 << (regno - GP_REG_FIRST))) != 0)
        !           880:       {
        !           881:        fprintf (file, "\tsw\t%s,%d(%s)\n", reg_name_ptr[regno], push_loc,
        !           882:                 base_str);
        !           883:        push_loc += 4;
        !           884:       }
        !           885: 
        !           886:   fprintf (file, "\t.mask\t0x%08x,%d\n", mask, push_loc - tsize - 4);
        !           887: 
        !           888:   push_loc = AL_ADJUST_ALIGN (push_loc);
        !           889:   for  (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno += 2)
        !           890:     if ((fmask & (1 << (regno - FP_REG_FIRST))) != 0)
        !           891:       {
        !           892:        fprintf (file, "\ts.d\t%s,%d(%s)\n", reg_name_ptr[regno], push_loc,
        !           893:                 base_str);
        !           894:        push_loc += 8;
        !           895:       }
        !           896: 
        !           897:   fprintf (file, "\t.fmask\t0x%08x,%d\n", fmask, push_loc - tsize - 4);
        !           898: 
        !           899:   if (frame_pointer_needed)
        !           900:     {
        !           901:       if (tsize <= 32767)
        !           902:        fprintf (file, "\taddu\t%s,%s,%d\t# set up frame pointer\n", fp_str, sp_str, tsize);
        !           903:       else
        !           904:        fprintf (file, "\taddu\t%s,%s,%s\t# set up frame pointer\n", fp_str, sp_str,
        !           905:                 reg_name_ptr[MIPS_TEMP1_REGNUM]);
        !           906:     }
        !           907: 
        !           908:   fprintf (file," #END PROLOGUE\n");
        !           909: }
        !           910: 
        !           911: 
        !           912: /* Do any necessary cleanup after a function to restore stack, frame, and regs. */
        !           913: 
        !           914: void
        !           915: function_epilogue (file, size)
        !           916:      FILE *file;
        !           917:      int size;
        !           918: {
        !           919:   extern FILE *asm_out_data_file, *asm_out_file;
        !           920:   extern char call_used_regs[];
        !           921:   extern char *reg_numchar[];
        !           922:   extern char *current_function_name;
        !           923:   extern int frame_pointer_needed;
        !           924:   int regno;
        !           925:   int push_loc = stack_args_preallocated;
        !           926:   int tsize = current_function_total_framesize;
        !           927:   int num_regs = current_function_saved_reg_size;
        !           928:   char **reg_name_ptr = (TARGET_NAME_REGS) ? reg_names : reg_numchar;
        !           929:   char *sp_str = reg_name_ptr[STACK_POINTER_REGNUM];
        !           930:   char *t1_str = reg_name_ptr[MIPS_TEMP1_REGNUM];
        !           931:   char *base_str;
        !           932: 
        !           933: 
        !           934:   fprintf (file," #EPILOGUE\n");
        !           935: 
        !           936:   if (tsize > 32767)
        !           937:     fprintf (file, "\tli\t%s,%d\n", t1_str, tsize);
        !           938: 
        !           939:   if (frame_pointer_needed)
        !           940:     {
        !           941:       char *fp_str = reg_name_ptr[FRAME_POINTER_REGNUM];
        !           942:       if (tsize > 32767)
        !           943:        fprintf (file,"\tsubu\t%s,%s,%s\t# sp not trusted  here\n",
        !           944:                 sp_str, fp_str, t1_str);
        !           945:       else
        !           946:        fprintf (file,"\tsubu\t%s,%s,%d\t# sp not trusted  here\n",
        !           947:                 sp_str, fp_str, tsize);
        !           948:     }
        !           949: 
        !           950:   if (push_loc > 32767 && num_regs > 0)
        !           951:     {
        !           952:       if ((tsize - (push_loc + num_regs)) <= 32767)
        !           953:        {
        !           954:          base_str = t1_str;
        !           955:          push_loc = tsize - push_loc;
        !           956:        }
        !           957:       else 
        !           958:        {
        !           959:          base_str = reg_name_ptr[MIPS_TEMP2_REGNUM];
        !           960:          fprintf (file, "\tli\t%s,%d\n", base_str, push_loc);
        !           961:          push_loc = 0;
        !           962:        }
        !           963:     }
        !           964:   else
        !           965:     base_str = sp_str;
        !           966: 
        !           967:   for  (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
        !           968:     if (MUST_SAVE_REGISTER (regno))
        !           969:       {
        !           970:        fprintf (file,"\tlw\t%s,%d(%s)\n", reg_name_ptr[regno], push_loc,
        !           971:                 base_str);
        !           972:        push_loc += 4;
        !           973:       }
        !           974: 
        !           975:   push_loc = AL_ADJUST_ALIGN (push_loc);
        !           976:   for  (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno += 2)
        !           977:     if  (regs_ever_live[regno] && !call_used_regs[regno])
        !           978:       {
        !           979:        fprintf (file, "\tl.d\t%s,%d(%s)\n", reg_name_ptr[regno], push_loc,
        !           980:                 base_str);
        !           981:        push_loc += 8;
        !           982:       }
        !           983: 
        !           984:   if (tsize > 32767)
        !           985:     fprintf (file, "\taddu\t%s,%s,%s\n", sp_str, sp_str, t1_str);
        !           986: 
        !           987:   else if (tsize > 0)
        !           988:     fprintf (file, "\taddu\t%s,%s,%d\n", sp_str, sp_str, tsize);
        !           989: 
        !           990:   fprintf (file,"\tj\t%s\n", reg_name_ptr[31]);
        !           991:   fprintf (file," #END EPILOGUE\n");
        !           992:   fprintf (file,"\t.end\t%s\n", current_function_name);
        !           993: 
        !           994:   /* Reset state info for each function.  */
        !           995:   stack_args_pushed = 0;
        !           996:   stack_args_preallocated = 0;
        !           997:   inside_function = 0;
        !           998:   sp_fp_difference = (char *)0;
        !           999:   number_functions_processed++;
        !          1000: 
        !          1001:   /* Restore the output file if optimizing the GP (optimizing the GP causes
        !          1002:      the text to be diverted to a tempfile, so that data decls come before
        !          1003:      references to the data).  */
        !          1004: 
        !          1005:   if (TARGET_GP_OPT)
        !          1006:     asm_out_file = asm_out_data_file;
1.1       root     1007: }

unix.superglobalmegacorp.com

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