|
|
1.1 ! root 1: /* Convert RTL to assembler code and output it, for GNU compiler. ! 2: Copyright (C) 1987, 1988, 1989, 1992 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GNU CC. ! 5: ! 6: GNU CC is free software; you can redistribute it and/or modify ! 7: it under the terms of the GNU General Public License as published by ! 8: the Free Software Foundation; either version 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 19: ! 20: ! 21: /* This is the final pass of the compiler. ! 22: It looks at the rtl code for a function and outputs assembler code. ! 23: ! 24: Call `final_start_function' to output the assembler code for function entry, ! 25: `final' to output assembler code for some RTL code, ! 26: `final_end_function' to output assembler code for function exit. ! 27: If a function is compiled in several pieces, each piece is ! 28: output separately with `final'. ! 29: ! 30: Some optimizations are also done at this level. ! 31: Move instructions that were made unnecessary by good register allocation ! 32: are detected and omitted from the output. (Though most of these ! 33: are removed by the last jump pass.) ! 34: ! 35: Instructions to set the condition codes are omitted when it can be ! 36: seen that the condition codes already had the desired values. ! 37: ! 38: In some cases it is sufficient if the inherited condition codes ! 39: have related values, but this may require the following insn ! 40: (the one that tests the condition codes) to be modified. ! 41: ! 42: The code for the function prologue and epilogue are generated ! 43: directly as assembler code by the macros FUNCTION_PROLOGUE and ! 44: FUNCTION_EPILOGUE. Those instructions never exist as rtl. */ ! 45: ! 46: #include <stdio.h> ! 47: #include "config.h" ! 48: #include "gvarargs.h" ! 49: #include "rtl.h" ! 50: #include "regs.h" ! 51: #include "insn-config.h" ! 52: #include "insn-attr.h" ! 53: #include "insn-codes.h" ! 54: #include "recog.h" ! 55: #include "conditions.h" ! 56: #include "flags.h" ! 57: #include "real.h" ! 58: #include "output.h" ! 59: #include "hard-reg-set.h" ! 60: ! 61: #ifndef ASM_STABD_OP ! 62: #define ASM_STABD_OP ".stabd" ! 63: #endif ! 64: ! 65: /* Get N_SLINE and N_SOL from stab.h if we can expect the file to exist. */ ! 66: #ifdef DBX_DEBUGGING_INFO ! 67: #ifdef USG ! 68: #include "gstab.h" /* If doing DBX on sysV, use our own stab.h. */ ! 69: #else ! 70: #include <stab.h> /* On BSD, use the system's stab.h. */ ! 71: #endif /* not USG */ ! 72: #endif /* DBX_DEBUGGING_INFO */ ! 73: ! 74: /* .stabd code for line number. */ ! 75: #ifndef N_SLINE ! 76: #define N_SLINE 0x44 ! 77: #endif ! 78: ! 79: /* .stabs code for included file name. */ ! 80: #ifndef N_SOL ! 81: #define N_SOL 0x84 ! 82: #endif ! 83: ! 84: #ifndef INT_TYPE_SIZE ! 85: #define INT_TYPE_SIZE BITS_PER_WORD ! 86: #endif ! 87: ! 88: /* If we aren't using cc0, CC_STATUS_INIT shouldn't exist. So define a ! 89: null default for it to save conditionalization later. */ ! 90: #ifndef CC_STATUS_INIT ! 91: #define CC_STATUS_INIT ! 92: #endif ! 93: ! 94: /* How to start an assembler comment. */ ! 95: #ifndef ASM_COMMENT_START ! 96: #define ASM_COMMENT_START ";#" ! 97: #endif ! 98: ! 99: rtx peephole (); ! 100: void output_asm_insn (); ! 101: rtx alter_subreg (); ! 102: static int alter_cond (); ! 103: void output_asm_label (); ! 104: static void output_operand (); ! 105: void output_address (); ! 106: void output_addr_const (); ! 107: static void output_source_line (); ! 108: rtx final_scan_insn (); ! 109: void profile_function (); ! 110: ! 111: #ifdef HAVE_ATTR_length ! 112: static int asm_insn_count (); ! 113: #endif ! 114: ! 115: /* Nonzero means this function is a leaf function, with no function calls. ! 116: This variable exists to be examined in FUNCTION_PROLOGUE ! 117: and FUNCTION_EPILOGUE. Always zero, unless set by some action. */ ! 118: int leaf_function; ! 119: ! 120: int leaf_function_p (); ! 121: ! 122: #ifdef LEAF_REGISTERS ! 123: int only_leaf_regs_used (); ! 124: static void leaf_renumber_regs (); ! 125: void leaf_renumber_regs_insn (); ! 126: #endif ! 127: ! 128: /* Last insn processed by final_scan_insn. */ ! 129: static rtx debug_insn = 0; ! 130: ! 131: /* Line number of last NOTE. */ ! 132: static int last_linenum; ! 133: ! 134: /* Number of basic blocks seen so far; ! 135: used if profile_block_flag is set. */ ! 136: static int count_basic_blocks; ! 137: ! 138: /* Nonzero while outputting an `asm' with operands. ! 139: This means that inconsistencies are the user's fault, so don't abort. ! 140: The precise value is the insn being output, to pass to error_for_asm. */ ! 141: static rtx this_is_asm_operands; ! 142: ! 143: /* Number of operands of this insn, for an `asm' with operands. */ ! 144: static int insn_noperands; ! 145: ! 146: /* Compare optimization flag. */ ! 147: ! 148: static rtx last_ignored_compare = 0; ! 149: ! 150: /* Flag indicating this insn is the start of a new basic block. */ ! 151: ! 152: static int new_block = 1; ! 153: ! 154: /* All the symbol-blocks (levels of scoping) in the compilation ! 155: are assigned sequence numbers in order of appearance of the ! 156: beginnings of the symbol-blocks. Both final and dbxout do this, ! 157: and assume that they will both give the same number to each block. ! 158: Final uses these sequence numbers to generate assembler label names ! 159: LBBnnn and LBEnnn for the beginning and end of the symbol-block. ! 160: Dbxout uses the sequence nunbers to generate references to the same labels ! 161: from the dbx debugging information. ! 162: ! 163: Sdb records this level at the beginning of each function, ! 164: in order to find the current level when recursing down declarations. ! 165: It outputs the block beginning and endings ! 166: at the point in the asm file where the blocks would begin and end. */ ! 167: ! 168: int next_block_index; ! 169: ! 170: /* Assign a unique number to each insn that is output. ! 171: This can be used to generate unique local labels. */ ! 172: ! 173: static int insn_counter = 0; ! 174: ! 175: #ifdef HAVE_cc0 ! 176: /* This variable contains machine-dependent flags (defined in tm.h) ! 177: set and examined by output routines ! 178: that describe how to interpret the condition codes properly. */ ! 179: ! 180: CC_STATUS cc_status; ! 181: ! 182: /* During output of an insn, this contains a copy of cc_status ! 183: from before the insn. */ ! 184: ! 185: CC_STATUS cc_prev_status; ! 186: #endif ! 187: ! 188: /* Indexed by hardware reg number, is 1 if that register is ever ! 189: used in the current function. ! 190: ! 191: In life_analysis, or in stupid_life_analysis, this is set ! 192: up to record the hard regs used explicitly. Reload adds ! 193: in the hard regs used for holding pseudo regs. Final uses ! 194: it to generate the code in the function prologue and epilogue ! 195: to save and restore registers as needed. */ ! 196: ! 197: char regs_ever_live[FIRST_PSEUDO_REGISTER]; ! 198: ! 199: /* Nonzero means current function must be given a frame pointer. ! 200: Set in stmt.c if anything is allocated on the stack there. ! 201: Set in reload1.c if anything is allocated on the stack there. */ ! 202: ! 203: int frame_pointer_needed; ! 204: ! 205: /* Assign unique numbers to labels generated for profiling. */ ! 206: ! 207: int profile_label_no; ! 208: ! 209: /* Length so far allocated in PENDING_BLOCKS. */ ! 210: ! 211: static int max_block_depth; ! 212: ! 213: /* Stack of sequence numbers of symbol-blocks of which we have seen the ! 214: beginning but not yet the end. Sequence numbers are assigned at ! 215: the beginning; this stack allows us to find the sequence number ! 216: of a block that is ending. */ ! 217: ! 218: static int *pending_blocks; ! 219: ! 220: /* Number of elements currently in use in PENDING_BLOCKS. */ ! 221: ! 222: static int block_depth; ! 223: ! 224: /* Nonzero if have enabled APP processing of our assembler output. */ ! 225: ! 226: static int app_on; ! 227: ! 228: /* If we are outputting an insn sequence, this contains the sequence rtx. ! 229: Zero otherwise. */ ! 230: ! 231: rtx final_sequence; ! 232: ! 233: /* Indexed by line number, nonzero if there is a note for that line. */ ! 234: ! 235: static char *line_note_exists; ! 236: ! 237: /* Initialize data in final at the beginning of a compilation. */ ! 238: ! 239: void ! 240: init_final (filename) ! 241: char *filename; ! 242: { ! 243: next_block_index = 2; ! 244: app_on = 0; ! 245: max_block_depth = 20; ! 246: pending_blocks = (int *) xmalloc (20 * sizeof *pending_blocks); ! 247: final_sequence = 0; ! 248: } ! 249: ! 250: /* Called at end of source file, ! 251: to output the block-profiling table for this entire compilation. */ ! 252: ! 253: void ! 254: end_final (filename) ! 255: char *filename; ! 256: { ! 257: int i; ! 258: ! 259: if (profile_block_flag) ! 260: { ! 261: char name[12]; ! 262: ! 263: data_section (); ! 264: ! 265: /* Output the main header, of 6 words: ! 266: 0: 1 if this file's initialized, else 0. ! 267: 1: address of file name. ! 268: 2: address of table of counts. ! 269: 4: number of counts in the table. ! 270: 5: always 0, for compatibility with Sun. ! 271: 6: extra word added by GNU: address of address table ! 272: which contains addresses of basic blocks, ! 273: in parallel with the table of counts. */ ! 274: ASM_OUTPUT_ALIGN (asm_out_file, ! 275: exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); ! 276: ! 277: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 0); ! 278: assemble_integer (const0_rtx, UNITS_PER_WORD, 1); ! 279: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 1); ! 280: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1); ! 281: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2); ! 282: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1); ! 283: assemble_integer (gen_rtx (CONST_INT, VOIDmode, count_basic_blocks), ! 284: UNITS_PER_WORD, 1); ! 285: assemble_integer (const0_rtx, UNITS_PER_WORD, 1); ! 286: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 3); ! 287: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1); ! 288: ! 289: /* Output the file name. */ ! 290: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 1); ! 291: { ! 292: int len = strlen (filename); ! 293: char *data_file = (char *) alloca (len + 3); ! 294: strcpy (data_file, filename); ! 295: strip_off_ending (data_file, len); ! 296: strcat (data_file, ".d"); ! 297: assemble_string (data_file, strlen (data_file) + 1); ! 298: } ! 299: ! 300: /* Realign data section. */ ! 301: ASM_OUTPUT_ALIGN (asm_out_file, ! 302: exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); ! 303: ! 304: /* Make space for the table of counts. */ ! 305: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 2); ! 306: assemble_zeros (INT_TYPE_SIZE / BITS_PER_UNIT * count_basic_blocks); ! 307: ! 308: /* Output the table of addresses. */ ! 309: readonly_data_section (); ! 310: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 3); ! 311: for (i = 0; i < count_basic_blocks; i++) ! 312: { ! 313: char name[12]; ! 314: ASM_GENERATE_INTERNAL_LABEL (name, "LPB", i); ! 315: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), ! 316: UNITS_PER_WORD, 1); ! 317: } ! 318: ! 319: /* End with the address of the table of addresses, ! 320: so we can find it easily, as the last word in the file's text. */ ! 321: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 3); ! 322: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1); ! 323: } ! 324: } ! 325: ! 326: /* Enable APP processing of subsequent output. ! 327: Used before the output from an `asm' statement. */ ! 328: ! 329: void ! 330: app_enable () ! 331: { ! 332: if (! app_on) ! 333: { ! 334: fprintf (asm_out_file, ASM_APP_ON); ! 335: app_on = 1; ! 336: } ! 337: } ! 338: ! 339: /* Enable APP processing of subsequent output. ! 340: Called from varasm.c before most kinds of output. */ ! 341: ! 342: void ! 343: app_disable () ! 344: { ! 345: if (app_on) ! 346: { ! 347: fprintf (asm_out_file, ASM_APP_OFF); ! 348: app_on = 0; ! 349: } ! 350: } ! 351: ! 352: /* Return the number of slots filled in the current ! 353: delayed branch sequence (we don't count the insn needing the ! 354: delay slot). Zero if not in a delayed branch sequence. */ ! 355: ! 356: #ifdef DELAY_SLOTS ! 357: int ! 358: dbr_sequence_length () ! 359: { ! 360: if (final_sequence != 0) ! 361: return XVECLEN (final_sequence, 0) - 1; ! 362: else ! 363: return 0; ! 364: } ! 365: #endif ! 366: ! 367: /* The next two pages contain routines used to compute the length of an insn ! 368: and to shorten branches. */ ! 369: ! 370: /* Arrays for insn lengths, and addresses. The latter is referenced by ! 371: `insn_current_length'. */ ! 372: ! 373: static short *insn_lengths; ! 374: int *insn_addresses; ! 375: ! 376: /* Address of insn being processed. Used by `insn_current_length'. */ ! 377: int insn_current_address; ! 378: ! 379: /* Indicate the branch shortening hasn't yet been done. */ ! 380: ! 381: void ! 382: init_insn_lengths () ! 383: { ! 384: insn_lengths = 0; ! 385: } ! 386: ! 387: /* Obtain the current length of an insn. If branch shortening has been done, ! 388: get its actual length. Otherwise, get its maximum length. */ ! 389: ! 390: int ! 391: get_attr_length (insn) ! 392: rtx insn; ! 393: { ! 394: #ifdef HAVE_ATTR_length ! 395: rtx body; ! 396: int i; ! 397: int length = 0; ! 398: ! 399: if (insn_lengths) ! 400: return insn_lengths[INSN_UID (insn)]; ! 401: else ! 402: switch (GET_CODE (insn)) ! 403: { ! 404: case NOTE: ! 405: case BARRIER: ! 406: case CODE_LABEL: ! 407: return 0; ! 408: ! 409: case CALL_INSN: ! 410: length = insn_default_length (insn); ! 411: break; ! 412: ! 413: case JUMP_INSN: ! 414: body = PATTERN (insn); ! 415: if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC) ! 416: { ! 417: /* This only takes room if jump tables go into the text section. */ ! 418: #if !defined(READONLY_DATA_SECTION) || defined(JUMP_TABLES_IN_TEXT_SECTION) ! 419: length = (XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC) ! 420: * GET_MODE_SIZE (GET_MODE (body))); ! 421: ! 422: /* Be pessimistic and assume worst-case alignment. */ ! 423: length += (GET_MODE_SIZE (GET_MODE (body)) - 1); ! 424: #else ! 425: return 0; ! 426: #endif ! 427: } ! 428: else ! 429: length = insn_default_length (insn); ! 430: break; ! 431: ! 432: case INSN: ! 433: body = PATTERN (insn); ! 434: if (GET_CODE (body) == USE || GET_CODE (body) == CLOBBER) ! 435: return 0; ! 436: ! 437: else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0) ! 438: length = asm_insn_count (insn) * insn_default_length (insn); ! 439: else if (GET_CODE (body) == SEQUENCE) ! 440: for (i = 0; i < XVECLEN (body, 0); i++) ! 441: length += get_attr_length (XVECEXP (body, 0, i)); ! 442: else ! 443: length = insn_default_length (insn); ! 444: } ! 445: ! 446: #ifdef ADJUST_INSN_LENGTH ! 447: ADJUST_INSN_LENGTH (insn, length); ! 448: #endif ! 449: return length; ! 450: #else /* not HAVE_ATTR_length */ ! 451: return 0; ! 452: #endif /* not HAVE_ATTR_length */ ! 453: } ! 454: ! 455: /* Make a pass over all insns and compute their actual lengths by shortening ! 456: any branches of variable length if possible. */ ! 457: ! 458: /* Give a default value for the lowest address in a function. */ ! 459: ! 460: #ifndef FIRST_INSN_ADDRESS ! 461: #define FIRST_INSN_ADDRESS 0 ! 462: #endif ! 463: ! 464: void ! 465: shorten_branches (first) ! 466: rtx first; ! 467: { ! 468: #ifdef HAVE_ATTR_length ! 469: rtx insn; ! 470: int something_changed = 1; ! 471: int max_uid = 0; ! 472: char *varying_length; ! 473: rtx body; ! 474: int uid; ! 475: ! 476: /* Compute maximum UID and allocate arrays. */ ! 477: for (insn = first; insn; insn = NEXT_INSN (insn)) ! 478: if (INSN_UID (insn) > max_uid) ! 479: max_uid = INSN_UID (insn); ! 480: ! 481: max_uid++; ! 482: insn_lengths = (short *) oballoc (max_uid * sizeof (short)); ! 483: insn_addresses = (int *) oballoc (max_uid * sizeof (int)); ! 484: varying_length = (char *) oballoc (max_uid * sizeof (char)); ! 485: ! 486: /* Compute initial lengths, addresses, and varying flags for each insn. */ ! 487: for (insn_current_address = FIRST_INSN_ADDRESS, insn = first; ! 488: insn != 0; ! 489: insn_current_address += insn_lengths[uid], insn = NEXT_INSN (insn)) ! 490: { ! 491: uid = INSN_UID (insn); ! 492: insn_addresses[uid] = insn_current_address; ! 493: insn_lengths[uid] = 0; ! 494: varying_length[uid] = 0; ! 495: ! 496: if (GET_CODE (insn) == NOTE || GET_CODE (insn) == BARRIER ! 497: || GET_CODE (insn) == CODE_LABEL) ! 498: continue; ! 499: ! 500: body = PATTERN (insn); ! 501: if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC) ! 502: { ! 503: /* This only takes room if read-only data goes into the text ! 504: section. */ ! 505: #if !defined(READONLY_DATA_SECTION) || defined(JUMP_TABLES_IN_TEXT_SECTION) ! 506: int unitsize = GET_MODE_SIZE (GET_MODE (body)); ! 507: ! 508: insn_lengths[uid] = (XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC) ! 509: * GET_MODE_SIZE (GET_MODE (body))); ! 510: ! 511: /* Account for possible alignment. */ ! 512: insn_lengths[uid] ! 513: += unitsize - (insn_current_address & (unitsize - 1)); ! 514: #else ! 515: ; ! 516: #endif ! 517: } ! 518: else if (asm_noperands (body) >= 0) ! 519: insn_lengths[uid] = asm_insn_count (body) * insn_default_length (insn); ! 520: else if (GET_CODE (body) == SEQUENCE) ! 521: { ! 522: int i; ! 523: ! 524: /* Inside a delay slot sequence, we do not do any branch shortening ! 525: (on the only machine known to have both variable-length branches ! 526: and delay slots, the ROMP, branch-with-execute is the same size ! 527: as the maximum branch anyway). So we only have to handle normal ! 528: insns (actually, reorg never puts ASM insns in a delay slot, but ! 529: we don't take advantage of that knowlege here). */ ! 530: for (i = 0; i < XVECLEN (body, 0); i++) ! 531: { ! 532: rtx inner_insn = XVECEXP (body, 0, i); ! 533: int inner_uid = INSN_UID (inner_insn); ! 534: int inner_length; ! 535: ! 536: if (asm_noperands (PATTERN (XVECEXP (body, 0, i))) >= 0) ! 537: inner_length = (asm_insn_count (PATTERN (inner_insn)) ! 538: * insn_default_length (inner_insn)); ! 539: else ! 540: inner_length = insn_default_length (inner_insn); ! 541: ! 542: insn_lengths[inner_uid] = inner_length; ! 543: varying_length[inner_uid] = 0; ! 544: insn_lengths[uid] += inner_length; ! 545: } ! 546: } ! 547: else if (GET_CODE (body) != USE && GET_CODE (body) != CLOBBER) ! 548: { ! 549: insn_lengths[uid] = insn_default_length (insn); ! 550: varying_length[uid] = insn_variable_length_p (insn); ! 551: } ! 552: ! 553: /* If needed, do any adjustment. */ ! 554: #ifdef ADJUST_INSN_LENGTH ! 555: ADJUST_INSN_LENGTH (insn, insn_lengths[uid]); ! 556: #endif ! 557: } ! 558: ! 559: /* Now loop over all the insns finding varying length insns. For each, ! 560: get the current insn length. If it has changed, reflect the change. ! 561: When nothing changes for a full pass, we are done. */ ! 562: ! 563: while (something_changed) ! 564: { ! 565: something_changed = 0; ! 566: for (insn_current_address = FIRST_INSN_ADDRESS, insn = first; ! 567: insn != 0; ! 568: insn_current_address += insn_lengths[uid], insn = NEXT_INSN (insn)) ! 569: { ! 570: int new_length; ! 571: ! 572: uid = INSN_UID (insn); ! 573: insn_addresses[uid] = insn_current_address; ! 574: if (! varying_length[uid]) ! 575: continue; ! 576: ! 577: new_length = insn_current_length (insn); ! 578: if (new_length != insn_lengths[uid]) ! 579: { ! 580: insn_lengths[uid] = new_length; ! 581: something_changed = 1; ! 582: } ! 583: } ! 584: } ! 585: #endif /* HAVE_ATTR_length */ ! 586: } ! 587: ! 588: #ifdef HAVE_ATTR_length ! 589: /* Given the body of an INSN known to be generated by an ASM statement, return ! 590: the number of machine instructions likely to be generated for this insn. ! 591: This is used to compute its length. */ ! 592: ! 593: static int ! 594: asm_insn_count (body) ! 595: rtx body; ! 596: { ! 597: char *template; ! 598: int count = 1; ! 599: ! 600: for (template = decode_asm_operands (body, 0, 0, 0, 0); ! 601: *template; template++) ! 602: if (*template == ';' || *template == '\n') ! 603: count++; ! 604: ! 605: return count; ! 606: } ! 607: #endif ! 608: ! 609: /* Output assembler code for the start of a function, ! 610: and initialize some of the variables in this file ! 611: for the new function. The label for the function and associated ! 612: assembler pseudo-ops have already been output in `assemble_start_function'. ! 613: ! 614: FIRST is the first insn of the rtl for the function being compiled. ! 615: FILE is the file to write assembler code to. ! 616: OPTIMIZE is nonzero if we should eliminate redundant ! 617: test and compare insns. */ ! 618: ! 619: void ! 620: final_start_function (first, file, optimize) ! 621: rtx first; ! 622: FILE *file; ! 623: int optimize; ! 624: { ! 625: block_depth = 0; ! 626: ! 627: this_is_asm_operands = 0; ! 628: ! 629: #ifdef NON_SAVING_SETJMP ! 630: /* A function that calls setjmp should save and restore all the ! 631: call-saved registers on a system where longjmp clobbers them. */ ! 632: if (NON_SAVING_SETJMP && current_function_calls_setjmp) ! 633: { ! 634: int i; ! 635: ! 636: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) ! 637: if (!call_used_regs[i] && !call_fixed_regs[i]) ! 638: regs_ever_live[i] = 1; ! 639: } ! 640: #endif ! 641: ! 642: /* Initial line number is supposed to be output ! 643: before the function's prologue and label ! 644: so that the function's address will not appear to be ! 645: in the last statement of the preceding function. */ ! 646: if (NOTE_LINE_NUMBER (first) != NOTE_INSN_DELETED) ! 647: { ! 648: if (write_symbols == SDB_DEBUG) ! 649: /* For sdb, let's not, but say we did. ! 650: We need to set last_linenum for sdbout_function_begin, ! 651: but we can't have an actual line number before the .bf symbol. ! 652: (sdb_begin_function_line is not set, ! 653: and other compilers don't do it.) */ ! 654: last_linenum = NOTE_LINE_NUMBER (first); ! 655: else ! 656: output_source_line (file, first); ! 657: } ! 658: ! 659: #ifdef LEAF_REG_REMAP ! 660: if (leaf_function) ! 661: leaf_renumber_regs (first); ! 662: #endif ! 663: ! 664: /* The Sun386i and perhaps other machines don't work right ! 665: if the profiling code comes after the prologue. */ ! 666: #ifdef PROFILE_BEFORE_PROLOGUE ! 667: if (profile_flag) ! 668: profile_function (file); ! 669: #endif /* PROFILE_BEFORE_PROLOGUE */ ! 670: ! 671: #ifdef FUNCTION_PROLOGUE ! 672: /* First output the function prologue: code to set up the stack frame. */ ! 673: FUNCTION_PROLOGUE (file, get_frame_size ()); ! 674: #endif ! 675: ! 676: #ifdef SDB_DEBUGGING_INFO ! 677: if (write_symbols == SDB_DEBUG) ! 678: next_block_index = 1; ! 679: #endif ! 680: ! 681: #ifdef FUNCTION_BLOCK_PROFILER ! 682: if (profile_block_flag) ! 683: { ! 684: FUNCTION_BLOCK_PROFILER (file, profile_label_no); ! 685: } ! 686: #endif /* FUNCTION_BLOCK_PROFILER */ ! 687: ! 688: #ifndef PROFILE_BEFORE_PROLOGUE ! 689: if (profile_flag) ! 690: profile_function (file); ! 691: #endif /* not PROFILE_BEFORE_PROLOGUE */ ! 692: ! 693: profile_label_no++; ! 694: } ! 695: ! 696: void ! 697: profile_function (file) ! 698: FILE *file; ! 699: { ! 700: int align = MIN (BIGGEST_ALIGNMENT, INT_TYPE_SIZE); ! 701: int sval = current_function_returns_struct; ! 702: int cxt = current_function_needs_context; ! 703: ! 704: data_section (); ! 705: ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT)); ! 706: ASM_OUTPUT_INTERNAL_LABEL (file, "LP", profile_label_no); ! 707: assemble_integer (const0_rtx, UNITS_PER_WORD, 1); ! 708: ! 709: text_section (); ! 710: ! 711: #ifdef STRUCT_VALUE_INCOMING_REGNUM ! 712: if (sval) ! 713: ASM_OUTPUT_REG_PUSH (file, STRUCT_VALUE_INCOMING_REGNUM); ! 714: #else ! 715: #ifdef STRUCT_VALUE_REGNUM ! 716: if (sval) ! 717: ASM_OUTPUT_REG_PUSH (file, STRUCT_VALUE_REGNUM); ! 718: #endif ! 719: #endif ! 720: ! 721: #if 0 ! 722: #ifdef STATIC_CHAIN_INCOMING_REGNUM ! 723: if (cxt) ! 724: ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_INCOMING_REGNUM); ! 725: #else ! 726: #ifdef STATIC_CHAIN_REGNUM ! 727: if (cxt) ! 728: ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_REGNUM); ! 729: #endif ! 730: #endif ! 731: #endif /* 0 */ ! 732: ! 733: FUNCTION_PROFILER (file, profile_label_no); ! 734: ! 735: #if 0 ! 736: #ifdef STATIC_CHAIN_INCOMING_REGNUM ! 737: if (cxt) ! 738: ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_INCOMING_REGNUM); ! 739: #else ! 740: #ifdef STATIC_CHAIN_REGNUM ! 741: if (cxt) ! 742: ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_REGNUM); ! 743: #endif ! 744: #endif ! 745: #endif /* 0 */ ! 746: ! 747: #ifdef STRUCT_VALUE_INCOMING_REGNUM ! 748: if (sval) ! 749: ASM_OUTPUT_REG_POP (file, STRUCT_VALUE_INCOMING_REGNUM); ! 750: #else ! 751: #ifdef STRUCT_VALUE_REGNUM ! 752: if (sval) ! 753: ASM_OUTPUT_REG_POP (file, STRUCT_VALUE_REGNUM); ! 754: #endif ! 755: #endif ! 756: } ! 757: ! 758: /* Output assembler code for the end of a function. ! 759: For clarity, args are same as those of `final_start_function' ! 760: even though not all of them are needed. */ ! 761: ! 762: void ! 763: final_end_function (first, file, optimize) ! 764: rtx first; ! 765: FILE *file; ! 766: int optimize; ! 767: { ! 768: if (app_on) ! 769: { ! 770: fprintf (file, ASM_APP_OFF); ! 771: app_on = 0; ! 772: } ! 773: ! 774: #ifdef SDB_DEBUGGING_INFO ! 775: if (write_symbols == SDB_DEBUG) ! 776: sdbout_end_function (last_linenum); ! 777: #endif ! 778: ! 779: #ifdef FUNCTION_EPILOGUE ! 780: /* Finally, output the function epilogue: ! 781: code to restore the stack frame and return to the caller. */ ! 782: FUNCTION_EPILOGUE (file, get_frame_size ()); ! 783: #endif ! 784: ! 785: #ifdef SDB_DEBUGGING_INFO ! 786: if (write_symbols == SDB_DEBUG) ! 787: sdbout_end_epilogue (); ! 788: #endif ! 789: ! 790: #ifdef DWARF_DEBUGGING_INFO ! 791: if (write_symbols == DWARF_DEBUG) ! 792: dwarfout_end_epilogue (); ! 793: #endif ! 794: ! 795: /* If FUNCTION_EPILOGUE is not defined, then the function body ! 796: itself contains return instructions wherever needed. */ ! 797: } ! 798: ! 799: /* Output assembler code for some insns: all or part of a function. ! 800: For description of args, see `final_start_function', above. ! 801: ! 802: PRESCAN is 1 if we are not really outputting, ! 803: just scanning as if we were outputting. ! 804: Prescanning deletes and rearranges insns just like ordinary output. ! 805: PRESCAN is -2 if we are outputting after having prescanned. ! 806: In this case, don't try to delete or rearrange insns ! 807: because that has already been done. ! 808: Prescanning is done only on certain machines. */ ! 809: ! 810: void ! 811: final (first, file, optimize, prescan) ! 812: rtx first; ! 813: FILE *file; ! 814: int optimize; ! 815: int prescan; ! 816: { ! 817: register rtx insn; ! 818: int max_line = 0; ! 819: ! 820: last_ignored_compare = 0; ! 821: new_block = 1; ! 822: ! 823: /* Make a map indicating which line numbers appear in this function. */ ! 824: for (insn = first; insn; insn = NEXT_INSN (insn)) ! 825: if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > max_line) ! 826: max_line = NOTE_LINE_NUMBER (insn); ! 827: ! 828: line_note_exists = (char *) oballoc (max_line + 1); ! 829: bzero (line_note_exists, max_line + 1); ! 830: ! 831: for (insn = first; insn; insn = NEXT_INSN (insn)) ! 832: if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0) ! 833: line_note_exists[NOTE_LINE_NUMBER (insn)] = 1; ! 834: ! 835: init_recog (); ! 836: ! 837: CC_STATUS_INIT; ! 838: ! 839: /* Output the insns. */ ! 840: for (insn = NEXT_INSN (first); insn;) ! 841: insn = final_scan_insn (insn, file, optimize, prescan, 0); ! 842: ! 843: /* Do basic-block profiling here ! 844: if the last insn was a conditional branch. */ ! 845: if (profile_block_flag && new_block) ! 846: { ! 847: new_block = 0; ! 848: /* Enable the table of basic-block use counts ! 849: to point at the code it applies to. */ ! 850: ASM_OUTPUT_INTERNAL_LABEL (file, "LPB", count_basic_blocks); ! 851: /* Before first insn of this basic block, increment the ! 852: count of times it was entered. */ ! 853: #ifdef BLOCK_PROFILER ! 854: BLOCK_PROFILER (file, count_basic_blocks); ! 855: CC_STATUS_INIT; ! 856: #endif ! 857: count_basic_blocks++; ! 858: } ! 859: } ! 860: ! 861: /* The final scan for one insn, INSN. ! 862: Args are same as in `final', except that INSN ! 863: is the insn being scanned. ! 864: Value returned is the next insn to be scanned. ! 865: ! 866: NOPEEPHOLES is the flag to disallow peephole processing (currently ! 867: used for within delayed branch sequence output). */ ! 868: ! 869: rtx ! 870: final_scan_insn (insn, file, optimize, prescan, nopeepholes) ! 871: rtx insn; ! 872: FILE *file; ! 873: int optimize; ! 874: int prescan; ! 875: int nopeepholes; ! 876: { ! 877: register int i; ! 878: insn_counter++; ! 879: ! 880: /* Ignore deleted insns. These can occur when we split insns (due to a ! 881: template of "#") while not optimizing. */ ! 882: if (INSN_DELETED_P (insn)) ! 883: return NEXT_INSN (insn); ! 884: ! 885: switch (GET_CODE (insn)) ! 886: { ! 887: case NOTE: ! 888: if (prescan > 0) ! 889: break; ! 890: ! 891: /* Align the beginning of a loop, for higher speed ! 892: on certain machines. */ ! 893: ! 894: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG && optimize > 0) ! 895: { ! 896: #ifdef ASM_OUTPUT_LOOP_ALIGN ! 897: rtx next = next_nonnote_insn (insn); ! 898: if (next && GET_CODE (next) == CODE_LABEL) ! 899: { ! 900: ASM_OUTPUT_LOOP_ALIGN (asm_out_file); ! 901: } ! 902: #endif ! 903: break; ! 904: } ! 905: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END) ! 906: break; ! 907: ! 908: if (write_symbols == NO_DEBUG) ! 909: break; ! 910: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG) ! 911: { ! 912: #ifdef SDB_DEBUGGING_INFO ! 913: if (write_symbols == SDB_DEBUG) ! 914: sdbout_begin_function (last_linenum); ! 915: #endif ! 916: break; ! 917: } ! 918: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED) ! 919: break; /* An insn that was "deleted" */ ! 920: if (app_on) ! 921: { ! 922: fprintf (file, ASM_APP_OFF); ! 923: app_on = 0; ! 924: } ! 925: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG ! 926: && (debug_info_level == DINFO_LEVEL_NORMAL ! 927: || debug_info_level == DINFO_LEVEL_VERBOSE)) ! 928: { ! 929: /* Beginning of a symbol-block. Assign it a sequence number ! 930: and push the number onto the stack PENDING_BLOCKS. */ ! 931: ! 932: if (block_depth == max_block_depth) ! 933: { ! 934: /* PENDING_BLOCKS is full; make it longer. */ ! 935: max_block_depth *= 2; ! 936: pending_blocks ! 937: = (int *) xrealloc (pending_blocks, ! 938: max_block_depth * sizeof (int)); ! 939: } ! 940: pending_blocks[block_depth++] = next_block_index; ! 941: ! 942: /* Output debugging info about the symbol-block beginning. */ ! 943: ! 944: #ifdef SDB_DEBUGGING_INFO ! 945: if (write_symbols == SDB_DEBUG) ! 946: sdbout_begin_block (file, last_linenum, next_block_index); ! 947: #endif ! 948: #ifdef DBX_DEBUGGING_INFO ! 949: if (write_symbols == DBX_DEBUG) ! 950: ASM_OUTPUT_INTERNAL_LABEL (file, "LBB", next_block_index); ! 951: #endif ! 952: #ifdef DWARF_DEBUGGING_INFO ! 953: if (write_symbols == DWARF_DEBUG && block_depth > 1) ! 954: dwarfout_begin_block (next_block_index); ! 955: #endif ! 956: ! 957: next_block_index++; ! 958: } ! 959: else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END ! 960: && (debug_info_level == DINFO_LEVEL_NORMAL ! 961: || debug_info_level == DINFO_LEVEL_VERBOSE)) ! 962: { ! 963: /* End of a symbol-block. Pop its sequence number off ! 964: PENDING_BLOCKS and output debugging info based on that. */ ! 965: ! 966: --block_depth; ! 967: ! 968: #ifdef DBX_DEBUGGING_INFO ! 969: if (write_symbols == DBX_DEBUG && block_depth >= 0) ! 970: ASM_OUTPUT_INTERNAL_LABEL (file, "LBE", ! 971: pending_blocks[block_depth]); ! 972: #endif ! 973: #ifdef SDB_DEBUGGING_INFO ! 974: if (write_symbols == SDB_DEBUG && block_depth >= 0) ! 975: sdbout_end_block (file, last_linenum); ! 976: #endif ! 977: #ifdef DWARF_DEBUGGING_INFO ! 978: if (write_symbols == DWARF_DEBUG && block_depth >= 1) ! 979: dwarfout_end_block (pending_blocks[block_depth]); ! 980: #endif ! 981: } ! 982: else if (NOTE_LINE_NUMBER (insn) > 0) ! 983: /* This note is a line-number. */ ! 984: { ! 985: register rtx note; ! 986: ! 987: #if 0 /* This is what we used to do. */ ! 988: output_source_line (file, insn); ! 989: #endif ! 990: int note_after = 0; ! 991: ! 992: /* If there is anything real after this note, ! 993: output it. If another line note follows, omit this one. */ ! 994: for (note = NEXT_INSN (insn); note; note = NEXT_INSN (note)) ! 995: { ! 996: if (GET_CODE (note) != NOTE && GET_CODE (note) != CODE_LABEL) ! 997: break; ! 998: else if (GET_CODE (note) == NOTE && NOTE_LINE_NUMBER (note) > 0) ! 999: { ! 1000: /* Another note follows; we can delete this note provided ! 1001: no intervening line numbers have notes elsewhere. */ ! 1002: int num; ! 1003: for (num = NOTE_LINE_NUMBER (insn) + 1; ! 1004: num < NOTE_LINE_NUMBER (note); ! 1005: num++) ! 1006: if (line_note_exists[num]) ! 1007: break; ! 1008: ! 1009: if (num == NOTE_LINE_NUMBER (note)) ! 1010: note_after = 1; ! 1011: break; ! 1012: } ! 1013: } ! 1014: ! 1015: /* Output this line note ! 1016: if it is the first or the last line note in a row. */ ! 1017: if (!note_after) ! 1018: output_source_line (file, insn); ! 1019: } ! 1020: break; ! 1021: ! 1022: case BARRIER: ! 1023: #ifdef ASM_OUTPUT_ALIGN_CODE ! 1024: ASM_OUTPUT_ALIGN_CODE (file); ! 1025: #endif ! 1026: break; ! 1027: ! 1028: case CODE_LABEL: ! 1029: CC_STATUS_INIT; ! 1030: if (prescan > 0) ! 1031: break; ! 1032: new_block = 1; ! 1033: #ifdef SDB_DEBUGGING_INFO ! 1034: if (write_symbols == SDB_DEBUG && LABEL_NAME (insn)) ! 1035: sdbout_label (insn); ! 1036: #endif ! 1037: #ifdef DWARF_DEBUGGING_INFO ! 1038: if (write_symbols == DWARF_DEBUG && LABEL_NAME (insn)) ! 1039: dwarfout_label (insn); ! 1040: #endif ! 1041: if (app_on) ! 1042: { ! 1043: fprintf (file, ASM_APP_OFF); ! 1044: app_on = 0; ! 1045: } ! 1046: if (NEXT_INSN (insn) != 0 ! 1047: && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN) ! 1048: { ! 1049: rtx nextbody = PATTERN (NEXT_INSN (insn)); ! 1050: ! 1051: /* If this label is followed by a jump-table, ! 1052: make sure we put the label in the read-only section. Also ! 1053: possibly write the label and jump table together. */ ! 1054: ! 1055: if (GET_CODE (nextbody) == ADDR_VEC ! 1056: || GET_CODE (nextbody) == ADDR_DIFF_VEC) ! 1057: { ! 1058: #ifndef JUMP_TABLES_IN_TEXT_SECTION ! 1059: readonly_data_section (); ! 1060: #else ! 1061: text_section (); ! 1062: #endif ! 1063: #ifdef ASM_OUTPUT_CASE_LABEL ! 1064: ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn), ! 1065: NEXT_INSN (insn)); ! 1066: #else ! 1067: ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn)); ! 1068: #endif ! 1069: break; ! 1070: } ! 1071: } ! 1072: ! 1073: ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn)); ! 1074: break; ! 1075: ! 1076: default: ! 1077: { ! 1078: register rtx body = PATTERN (insn); ! 1079: int insn_code_number; ! 1080: char *template; ! 1081: rtx note; ! 1082: ! 1083: /* An INSN, JUMP_INSN or CALL_INSN. ! 1084: First check for special kinds that recog doesn't recognize. */ ! 1085: ! 1086: if (GET_CODE (body) == USE /* These are just declarations */ ! 1087: || GET_CODE (body) == CLOBBER) ! 1088: break; ! 1089: ! 1090: #ifdef HAVE_cc0 ! 1091: /* If there is a REG_CC_SETTER note on this insn, it means that ! 1092: the setting of the condition code was done in the delay slot ! 1093: of the insn that branched here. So recover the cc status ! 1094: from the insn that set it. */ ! 1095: ! 1096: note = find_reg_note (insn, REG_CC_SETTER, 0); ! 1097: if (note) ! 1098: { ! 1099: NOTICE_UPDATE_CC (PATTERN (XEXP (note, 0)), XEXP (note, 0)); ! 1100: cc_prev_status = cc_status; ! 1101: } ! 1102: #endif ! 1103: ! 1104: /* Detect insns that are really jump-tables ! 1105: and output them as such. */ ! 1106: ! 1107: if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC) ! 1108: { ! 1109: register int vlen, idx; ! 1110: ! 1111: if (prescan > 0) ! 1112: break; ! 1113: ! 1114: if (app_on) ! 1115: { ! 1116: fprintf (file, ASM_APP_OFF); ! 1117: app_on = 0; ! 1118: } ! 1119: ! 1120: vlen = XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC); ! 1121: for (idx = 0; idx < vlen; idx++) ! 1122: { ! 1123: if (GET_CODE (body) == ADDR_VEC) ! 1124: ASM_OUTPUT_ADDR_VEC_ELT ! 1125: (file, CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0))); ! 1126: else ! 1127: ASM_OUTPUT_ADDR_DIFF_ELT ! 1128: (file, ! 1129: CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 1, idx), 0)), ! 1130: CODE_LABEL_NUMBER (XEXP (XEXP (body, 0), 0))); ! 1131: } ! 1132: #ifdef ASM_OUTPUT_CASE_END ! 1133: ASM_OUTPUT_CASE_END (file, ! 1134: CODE_LABEL_NUMBER (PREV_INSN (insn)), ! 1135: insn); ! 1136: #endif ! 1137: ! 1138: text_section (); ! 1139: ! 1140: break; ! 1141: } ! 1142: ! 1143: /* Do basic-block profiling when we reach a new block. ! 1144: Done here to avoid jump tables. */ ! 1145: if (profile_block_flag && new_block) ! 1146: { ! 1147: new_block = 0; ! 1148: /* Enable the table of basic-block use counts ! 1149: to point at the code it applies to. */ ! 1150: ASM_OUTPUT_INTERNAL_LABEL (file, "LPB", count_basic_blocks); ! 1151: /* Before first insn of this basic block, increment the ! 1152: count of times it was entered. */ ! 1153: #ifdef BLOCK_PROFILER ! 1154: BLOCK_PROFILER (file, count_basic_blocks); ! 1155: CC_STATUS_INIT; ! 1156: #endif ! 1157: count_basic_blocks++; ! 1158: } ! 1159: ! 1160: if (GET_CODE (body) == ASM_INPUT) ! 1161: { ! 1162: /* There's no telling what that did to the condition codes. */ ! 1163: CC_STATUS_INIT; ! 1164: if (prescan > 0) ! 1165: break; ! 1166: if (! app_on) ! 1167: { ! 1168: fprintf (file, ASM_APP_ON); ! 1169: app_on = 1; ! 1170: } ! 1171: fprintf (asm_out_file, "\t%s\n", XSTR (body, 0)); ! 1172: break; ! 1173: } ! 1174: ! 1175: /* Detect `asm' construct with operands. */ ! 1176: if (asm_noperands (body) >= 0) ! 1177: { ! 1178: int noperands = asm_noperands (body); ! 1179: rtx *ops; ! 1180: char *string; ! 1181: ! 1182: /* There's no telling what that did to the condition codes. */ ! 1183: CC_STATUS_INIT; ! 1184: if (prescan > 0) ! 1185: break; ! 1186: ! 1187: /* alloca won't do here, since only return from `final' ! 1188: would free it. */ ! 1189: if (noperands > 0) ! 1190: ops = (rtx *) xmalloc (noperands * sizeof (rtx)); ! 1191: ! 1192: if (! app_on) ! 1193: { ! 1194: fprintf (file, ASM_APP_ON); ! 1195: app_on = 1; ! 1196: } ! 1197: ! 1198: /* Get out the operand values. */ ! 1199: string = decode_asm_operands (body, ops, 0, 0, 0); ! 1200: /* Inhibit aborts on what would otherwise be compiler bugs. */ ! 1201: insn_noperands = noperands; ! 1202: this_is_asm_operands = insn; ! 1203: /* Output the insn using them. */ ! 1204: output_asm_insn (string, ops); ! 1205: this_is_asm_operands = 0; ! 1206: if (noperands > 0) ! 1207: free (ops); ! 1208: break; ! 1209: } ! 1210: ! 1211: if (prescan <= 0 && app_on) ! 1212: { ! 1213: fprintf (file, ASM_APP_OFF); ! 1214: app_on = 0; ! 1215: } ! 1216: ! 1217: if (GET_CODE (body) == SEQUENCE) ! 1218: { ! 1219: /* A delayed-branch sequence */ ! 1220: register int i; ! 1221: rtx next; ! 1222: ! 1223: if (prescan > 0) ! 1224: break; ! 1225: final_sequence = body; ! 1226: ! 1227: /* The first insn in this SEQUENCE might be a JUMP_INSN that will ! 1228: force the restoration of a comparison that was previously ! 1229: thought unnecessary. If that happens, cancel this sequence ! 1230: and cause that insn to be restored. */ ! 1231: ! 1232: next = final_scan_insn (XVECEXP (body, 0, 0), file, 0, prescan, 1); ! 1233: if (next != XVECEXP (body, 0, 1)) ! 1234: { ! 1235: final_sequence = 0; ! 1236: return next; ! 1237: } ! 1238: ! 1239: for (i = 1; i < XVECLEN (body, 0); i++) ! 1240: final_scan_insn (XVECEXP (body, 0, i), file, 0, prescan, 1); ! 1241: #ifdef DBR_OUTPUT_SEQEND ! 1242: DBR_OUTPUT_SEQEND (file); ! 1243: #endif ! 1244: final_sequence = 0; ! 1245: ! 1246: /* If the insn requiring the delay slot was a CALL_INSN, the ! 1247: insns in the delay slot are actually executed before the ! 1248: called function. Hence we don't preserve any CC-setting ! 1249: actions in these insns and the CC must be marked as being ! 1250: clobbered by the function. */ ! 1251: if (GET_CODE (XVECEXP (body, 0, 0)) == CALL_INSN) ! 1252: CC_STATUS_INIT; ! 1253: break; ! 1254: } ! 1255: ! 1256: /* We have a real machine instruction as rtl. */ ! 1257: ! 1258: body = PATTERN (insn); ! 1259: ! 1260: #ifdef HAVE_cc0 ! 1261: /* Check for redundant test and compare instructions ! 1262: (when the condition codes are already set up as desired). ! 1263: This is done only when optimizing; if not optimizing, ! 1264: it should be possible for the user to alter a variable ! 1265: with the debugger in between statements ! 1266: and the next statement should reexamine the variable ! 1267: to compute the condition codes. */ ! 1268: ! 1269: if (optimize ! 1270: && GET_CODE (body) == SET ! 1271: && GET_CODE (SET_DEST (body)) == CC0 ! 1272: && insn != last_ignored_compare) ! 1273: { ! 1274: if (GET_CODE (SET_SRC (body)) == SUBREG) ! 1275: SET_SRC (body) = alter_subreg (SET_SRC (body)); ! 1276: else if (GET_CODE (SET_SRC (body)) == COMPARE) ! 1277: { ! 1278: if (GET_CODE (XEXP (SET_SRC (body), 0)) == SUBREG) ! 1279: XEXP (SET_SRC (body), 0) ! 1280: = alter_subreg (XEXP (SET_SRC (body), 0)); ! 1281: if (GET_CODE (XEXP (SET_SRC (body), 1)) == SUBREG) ! 1282: XEXP (SET_SRC (body), 1) ! 1283: = alter_subreg (XEXP (SET_SRC (body), 1)); ! 1284: } ! 1285: if ((cc_status.value1 != 0 ! 1286: && rtx_equal_p (SET_SRC (body), cc_status.value1)) ! 1287: || (cc_status.value2 != 0 ! 1288: && rtx_equal_p (SET_SRC (body), cc_status.value2))) ! 1289: { ! 1290: /* Don't delete insn if it has an addressing side-effect. */ ! 1291: if (! FIND_REG_INC_NOTE (insn, 0) ! 1292: /* or if anything in it is volatile. */ ! 1293: && ! volatile_refs_p (PATTERN (insn))) ! 1294: { ! 1295: /* We don't really delete the insn; just ignore it. */ ! 1296: last_ignored_compare = insn; ! 1297: break; ! 1298: } ! 1299: } ! 1300: } ! 1301: #endif ! 1302: ! 1303: /* Following a conditional branch, we have a new basic block. */ ! 1304: if ((GET_CODE (insn) == JUMP_INSN && GET_CODE (body) == SET ! 1305: && GET_CODE (SET_SRC (body)) != LABEL_REF) ! 1306: || (GET_CODE (insn) == JUMP_INSN && GET_CODE (body) == PARALLEL ! 1307: && GET_CODE (XVECEXP (body, 0, 0)) == SET ! 1308: && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) != LABEL_REF)) ! 1309: new_block = 1; ! 1310: ! 1311: #ifndef STACK_REGS ! 1312: /* Don't bother outputting obvious no-ops, even without -O. ! 1313: This optimization is fast and doesn't interfere with debugging. ! 1314: Don't do this if the insn is in a delay slot, since this ! 1315: will cause an improper number of delay insns to be written. */ ! 1316: if (final_sequence == 0 ! 1317: && prescan >= 0 ! 1318: && GET_CODE (insn) == INSN && GET_CODE (body) == SET ! 1319: && GET_CODE (SET_SRC (body)) == REG ! 1320: && GET_CODE (SET_DEST (body)) == REG ! 1321: && REGNO (SET_SRC (body)) == REGNO (SET_DEST (body))) ! 1322: break; ! 1323: #endif ! 1324: ! 1325: #ifdef HAVE_cc0 ! 1326: /* If this is a conditional branch, maybe modify it ! 1327: if the cc's are in a nonstandard state ! 1328: so that it accomplishes the same thing that it would ! 1329: do straightforwardly if the cc's were set up normally. */ ! 1330: ! 1331: if (cc_status.flags != 0 ! 1332: && GET_CODE (insn) == JUMP_INSN ! 1333: && GET_CODE (body) == SET ! 1334: && SET_DEST (body) == pc_rtx ! 1335: && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE ! 1336: /* This is done during prescan; it is not done again ! 1337: in final scan when prescan has been done. */ ! 1338: && prescan >= 0) ! 1339: { ! 1340: /* This function may alter the contents of its argument ! 1341: and clear some of the cc_status.flags bits. ! 1342: It may also return 1 meaning condition now always true ! 1343: or -1 meaning condition now always false ! 1344: or 2 meaning condition nontrivial but altered. */ ! 1345: register int result = alter_cond (XEXP (SET_SRC (body), 0)); ! 1346: /* If condition now has fixed value, replace the IF_THEN_ELSE ! 1347: with its then-operand or its else-operand. */ ! 1348: if (result == 1) ! 1349: SET_SRC (body) = XEXP (SET_SRC (body), 1); ! 1350: if (result == -1) ! 1351: SET_SRC (body) = XEXP (SET_SRC (body), 2); ! 1352: ! 1353: /* The jump is now either unconditional or a no-op. ! 1354: If it has become a no-op, don't try to output it. ! 1355: (It would not be recognized.) */ ! 1356: if (SET_SRC (body) == pc_rtx) ! 1357: { ! 1358: PUT_CODE (insn, NOTE); ! 1359: NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; ! 1360: NOTE_SOURCE_FILE (insn) = 0; ! 1361: break; ! 1362: } ! 1363: else if (GET_CODE (SET_SRC (body)) == RETURN) ! 1364: /* Replace (set (pc) (return)) with (return). */ ! 1365: PATTERN (insn) = body = SET_SRC (body); ! 1366: ! 1367: /* Rerecognize the instruction if it has changed. */ ! 1368: if (result != 0) ! 1369: INSN_CODE (insn) = -1; ! 1370: } ! 1371: ! 1372: /* Make same adjustments to instructions that examine the ! 1373: condition codes without jumping (if this machine has them). */ ! 1374: ! 1375: if (cc_status.flags != 0 ! 1376: && GET_CODE (body) == SET) ! 1377: { ! 1378: switch (GET_CODE (SET_SRC (body))) ! 1379: { ! 1380: case GTU: ! 1381: case GT: ! 1382: case LTU: ! 1383: case LT: ! 1384: case GEU: ! 1385: case GE: ! 1386: case LEU: ! 1387: case LE: ! 1388: case EQ: ! 1389: case NE: ! 1390: { ! 1391: register int result; ! 1392: if (XEXP (SET_SRC (body), 0) != cc0_rtx) ! 1393: break; ! 1394: result = alter_cond (SET_SRC (body)); ! 1395: if (result == 1) ! 1396: validate_change (insn, &SET_SRC (body), const_true_rtx, 0); ! 1397: else if (result == -1) ! 1398: validate_change (insn, &SET_SRC (body), const0_rtx, 0); ! 1399: else if (result == 2) ! 1400: INSN_CODE (insn) = -1; ! 1401: } ! 1402: } ! 1403: } ! 1404: #endif ! 1405: ! 1406: /* Do machine-specific peephole optimizations if desired. */ ! 1407: ! 1408: if (optimize && !flag_no_peephole && !nopeepholes) ! 1409: { ! 1410: rtx next = peephole (insn); ! 1411: /* When peepholing, if there were notes within the peephole, ! 1412: emit them before the peephole. */ ! 1413: if (next != 0 && next != NEXT_INSN (insn)) ! 1414: { ! 1415: rtx prev = PREV_INSN (insn); ! 1416: rtx note; ! 1417: ! 1418: for (note = NEXT_INSN (insn); note != next; ! 1419: note = NEXT_INSN (note)) ! 1420: final_scan_insn (note, file, optimize, prescan, nopeepholes); ! 1421: ! 1422: /* In case this is prescan, put the notes ! 1423: in proper position for later rescan. */ ! 1424: note = NEXT_INSN (insn); ! 1425: PREV_INSN (note) = prev; ! 1426: NEXT_INSN (prev) = note; ! 1427: NEXT_INSN (PREV_INSN (next)) = insn; ! 1428: PREV_INSN (insn) = PREV_INSN (next); ! 1429: NEXT_INSN (insn) = next; ! 1430: PREV_INSN (next) = insn; ! 1431: } ! 1432: ! 1433: /* PEEPHOLE might have changed this. */ ! 1434: body = PATTERN (insn); ! 1435: } ! 1436: ! 1437: /* Try to recognize the instruction. ! 1438: If successful, verify that the operands satisfy the ! 1439: constraints for the instruction. Crash if they don't, ! 1440: since `reload' should have changed them so that they do. */ ! 1441: ! 1442: insn_code_number = recog_memoized (insn); ! 1443: insn_extract (insn); ! 1444: for (i = 0; i < insn_n_operands[insn_code_number]; i++) ! 1445: { ! 1446: if (GET_CODE (recog_operand[i]) == SUBREG) ! 1447: recog_operand[i] = alter_subreg (recog_operand[i]); ! 1448: } ! 1449: ! 1450: #ifdef REGISTER_CONSTRAINTS ! 1451: if (! constrain_operands (insn_code_number, 1)) ! 1452: fatal_insn_not_found (insn); ! 1453: #endif ! 1454: ! 1455: /* Some target machines need to prescan each insn before ! 1456: it is output. */ ! 1457: ! 1458: #ifdef FINAL_PRESCAN_INSN ! 1459: FINAL_PRESCAN_INSN (insn, recog_operand, ! 1460: insn_n_operands[insn_code_number]); ! 1461: #endif ! 1462: ! 1463: #ifdef HAVE_cc0 ! 1464: cc_prev_status = cc_status; ! 1465: ! 1466: /* Update `cc_status' for this instruction. ! 1467: The instruction's output routine may change it further. ! 1468: If the output routine for a jump insn needs to depend ! 1469: on the cc status, it should look at cc_prev_status. */ ! 1470: ! 1471: NOTICE_UPDATE_CC (body, insn); ! 1472: #endif ! 1473: ! 1474: debug_insn = insn; ! 1475: ! 1476: /* If the proper template needs to be chosen by some C code, ! 1477: run that code and get the real template. */ ! 1478: ! 1479: template = insn_template[insn_code_number]; ! 1480: if (template == 0) ! 1481: { ! 1482: template = (*insn_outfun[insn_code_number]) (recog_operand, insn); ! 1483: ! 1484: /* If the C code returns 0, it means that it is a jump insn ! 1485: which follows a deleted test insn, and that test insn ! 1486: needs to be reinserted. */ ! 1487: if (template == 0) ! 1488: { ! 1489: if (prev_nonnote_insn (insn) != last_ignored_compare) ! 1490: abort (); ! 1491: new_block = 0; ! 1492: return prev_nonnote_insn (insn); ! 1493: } ! 1494: } ! 1495: ! 1496: /* If the template is the string "#", it means that this insn must ! 1497: be split. */ ! 1498: if (template[0] == '#' && template[1] == '\0') ! 1499: { ! 1500: rtx new = try_split (body, insn, 0); ! 1501: ! 1502: /* If we didn't split the insn, go away. */ ! 1503: if (new == insn && PATTERN (new) == body) ! 1504: abort (); ! 1505: ! 1506: new_block = 0; ! 1507: return new; ! 1508: } ! 1509: ! 1510: if (prescan > 0) ! 1511: break; ! 1512: ! 1513: /* Output assembler code from the template. */ ! 1514: ! 1515: output_asm_insn (template, recog_operand); ! 1516: ! 1517: #if 0 ! 1518: /* It's not at all clear why we did this and doing so interferes ! 1519: with tests we'd like to do to use REG_WAS_0 notes, so let's try ! 1520: with this out. */ ! 1521: ! 1522: /* Mark this insn as having been output. */ ! 1523: INSN_DELETED_P (insn) = 1; ! 1524: #endif ! 1525: ! 1526: debug_insn = 0; ! 1527: } ! 1528: } ! 1529: return NEXT_INSN (insn); ! 1530: } ! 1531: ! 1532: /* Output debugging info to the assembler file FILE ! 1533: based on the NOTE-insn INSN, assumed to be a line number. */ ! 1534: ! 1535: static void ! 1536: output_source_line (file, insn) ! 1537: FILE *file; ! 1538: rtx insn; ! 1539: { ! 1540: char ltext_label_name[100]; ! 1541: register char *filename = NOTE_SOURCE_FILE (insn); ! 1542: ! 1543: last_linenum = NOTE_LINE_NUMBER (insn); ! 1544: ! 1545: if (write_symbols != NO_DEBUG) ! 1546: { ! 1547: #ifdef SDB_DEBUGGING_INFO ! 1548: if (write_symbols == SDB_DEBUG ! 1549: #if 0 /* People like having line numbers even in wrong file! */ ! 1550: /* COFF can't handle multiple source files--lose, lose. */ ! 1551: && !strcmp (filename, main_input_filename) ! 1552: #endif ! 1553: /* COFF relative line numbers must be positive. */ ! 1554: && last_linenum > sdb_begin_function_line) ! 1555: { ! 1556: #ifdef ASM_OUTPUT_SOURCE_LINE ! 1557: ASM_OUTPUT_SOURCE_LINE (file, last_linenum); ! 1558: #else ! 1559: fprintf (file, "\t.ln\t%d\n", ! 1560: ((sdb_begin_function_line > -1) ! 1561: ? last_linenum - sdb_begin_function_line : 1)); ! 1562: #endif ! 1563: } ! 1564: #endif ! 1565: ! 1566: #ifdef DBX_DEBUGGING_INFO ! 1567: if (write_symbols == DBX_DEBUG) ! 1568: { ! 1569: dbxout_source_file (file, filename); ! 1570: ! 1571: #ifdef ASM_OUTPUT_SOURCE_LINE ! 1572: ASM_OUTPUT_SOURCE_LINE (file, NOTE_LINE_NUMBER (insn)); ! 1573: #else ! 1574: fprintf (file, "\t%s %d,0,%d\n", ASM_STABD_OP, ! 1575: N_SLINE, NOTE_LINE_NUMBER (insn)); ! 1576: #endif ! 1577: } ! 1578: #endif /* DBX_DEBUGGING_INFO */ ! 1579: ! 1580: #ifdef DWARF_DEBUGGING_INFO ! 1581: if (write_symbols == DWARF_DEBUG) ! 1582: dwarfout_line (filename, NOTE_LINE_NUMBER (insn)); ! 1583: #endif ! 1584: } ! 1585: } ! 1586: ! 1587: /* If X is a SUBREG, replace it with a REG or a MEM, ! 1588: based on the thing it is a subreg of. */ ! 1589: ! 1590: rtx ! 1591: alter_subreg (x) ! 1592: register rtx x; ! 1593: { ! 1594: register rtx y = SUBREG_REG (x); ! 1595: if (GET_CODE (y) == SUBREG) ! 1596: y = alter_subreg (y); ! 1597: ! 1598: if (GET_CODE (y) == REG) ! 1599: { ! 1600: /* If the containing reg really gets a hard reg, so do we. */ ! 1601: PUT_CODE (x, REG); ! 1602: REGNO (x) = REGNO (y) + SUBREG_WORD (x); ! 1603: } ! 1604: else if (GET_CODE (y) == MEM) ! 1605: { ! 1606: register int offset = SUBREG_WORD (x) * UNITS_PER_WORD; ! 1607: #if BYTES_BIG_ENDIAN ! 1608: offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))) ! 1609: - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (y)))); ! 1610: #endif ! 1611: PUT_CODE (x, MEM); ! 1612: MEM_VOLATILE_P (x) = MEM_VOLATILE_P (y); ! 1613: XEXP (x, 0) = plus_constant (XEXP (y, 0), offset); ! 1614: } ! 1615: ! 1616: return x; ! 1617: } ! 1618: ! 1619: /* Do alter_subreg on all the SUBREGs contained in X. */ ! 1620: ! 1621: static rtx ! 1622: walk_alter_subreg (x) ! 1623: rtx x; ! 1624: { ! 1625: switch (GET_CODE (x)) ! 1626: { ! 1627: case PLUS: ! 1628: case MULT: ! 1629: XEXP (x, 0) = walk_alter_subreg (XEXP (x, 0)); ! 1630: XEXP (x, 1) = walk_alter_subreg (XEXP (x, 1)); ! 1631: break; ! 1632: ! 1633: case MEM: ! 1634: XEXP (x, 0) = walk_alter_subreg (XEXP (x, 0)); ! 1635: break; ! 1636: ! 1637: case SUBREG: ! 1638: return alter_subreg (x); ! 1639: } ! 1640: ! 1641: return x; ! 1642: } ! 1643: ! 1644: #ifdef HAVE_cc0 ! 1645: ! 1646: /* Given BODY, the body of a jump instruction, alter the jump condition ! 1647: as required by the bits that are set in cc_status.flags. ! 1648: Not all of the bits there can be handled at this level in all cases. ! 1649: ! 1650: The value is normally 0. ! 1651: 1 means that the condition has become always true. ! 1652: -1 means that the condition has become always false. ! 1653: 2 means that COND has been altered. */ ! 1654: ! 1655: static int ! 1656: alter_cond (cond) ! 1657: register rtx cond; ! 1658: { ! 1659: int value = 0; ! 1660: ! 1661: if (cc_status.flags & CC_REVERSED) ! 1662: { ! 1663: value = 2; ! 1664: PUT_CODE (cond, swap_condition (GET_CODE (cond))); ! 1665: } ! 1666: ! 1667: if (cc_status.flags & CC_INVERTED) ! 1668: { ! 1669: value = 2; ! 1670: PUT_CODE (cond, reverse_condition (GET_CODE (cond))); ! 1671: } ! 1672: ! 1673: if (cc_status.flags & CC_NOT_POSITIVE) ! 1674: switch (GET_CODE (cond)) ! 1675: { ! 1676: case LE: ! 1677: case LEU: ! 1678: case GEU: ! 1679: /* Jump becomes unconditional. */ ! 1680: return 1; ! 1681: ! 1682: case GT: ! 1683: case GTU: ! 1684: case LTU: ! 1685: /* Jump becomes no-op. */ ! 1686: return -1; ! 1687: ! 1688: case GE: ! 1689: PUT_CODE (cond, EQ); ! 1690: value = 2; ! 1691: break; ! 1692: ! 1693: case LT: ! 1694: PUT_CODE (cond, NE); ! 1695: value = 2; ! 1696: break; ! 1697: } ! 1698: ! 1699: if (cc_status.flags & CC_NOT_NEGATIVE) ! 1700: switch (GET_CODE (cond)) ! 1701: { ! 1702: case GE: ! 1703: case GEU: ! 1704: /* Jump becomes unconditional. */ ! 1705: return 1; ! 1706: ! 1707: case LT: ! 1708: case LTU: ! 1709: /* Jump becomes no-op. */ ! 1710: return -1; ! 1711: ! 1712: case LE: ! 1713: case LEU: ! 1714: PUT_CODE (cond, EQ); ! 1715: value = 2; ! 1716: break; ! 1717: ! 1718: case GT: ! 1719: case GTU: ! 1720: PUT_CODE (cond, NE); ! 1721: value = 2; ! 1722: break; ! 1723: } ! 1724: ! 1725: if (cc_status.flags & CC_NO_OVERFLOW) ! 1726: switch (GET_CODE (cond)) ! 1727: { ! 1728: case GEU: ! 1729: /* Jump becomes unconditional. */ ! 1730: return 1; ! 1731: ! 1732: case LEU: ! 1733: PUT_CODE (cond, EQ); ! 1734: value = 2; ! 1735: break; ! 1736: ! 1737: case GTU: ! 1738: PUT_CODE (cond, NE); ! 1739: value = 2; ! 1740: break; ! 1741: ! 1742: case LTU: ! 1743: /* Jump becomes no-op. */ ! 1744: return -1; ! 1745: } ! 1746: ! 1747: if (cc_status.flags & (CC_Z_IN_NOT_N | CC_Z_IN_N)) ! 1748: switch (GET_CODE (cond)) ! 1749: { ! 1750: case LE: ! 1751: case LEU: ! 1752: case GE: ! 1753: case GEU: ! 1754: case LT: ! 1755: case LTU: ! 1756: case GT: ! 1757: case GTU: ! 1758: abort (); ! 1759: ! 1760: case NE: ! 1761: PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? GE : LT); ! 1762: value = 2; ! 1763: break; ! 1764: ! 1765: case EQ: ! 1766: PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? LT : GE); ! 1767: value = 2; ! 1768: break; ! 1769: } ! 1770: ! 1771: return value; ! 1772: } ! 1773: #endif ! 1774: ! 1775: /* Report inconsistency between the assembler template and the operands. ! 1776: In an `asm', it's the user's fault; otherwise, the compiler's fault. */ ! 1777: ! 1778: void ! 1779: output_operand_lossage (str) ! 1780: char *str; ! 1781: { ! 1782: if (this_is_asm_operands) ! 1783: error_for_asm (this_is_asm_operands, "invalid `asm': %s", str); ! 1784: else ! 1785: abort (); ! 1786: } ! 1787: ! 1788: /* Output of assembler code from a template, and its subroutines. */ ! 1789: ! 1790: /* Output text from TEMPLATE to the assembler output file, ! 1791: obeying %-directions to substitute operands taken from ! 1792: the vector OPERANDS. ! 1793: ! 1794: %N (for N a digit) means print operand N in usual manner. ! 1795: %lN means require operand N to be a CODE_LABEL or LABEL_REF ! 1796: and print the label name with no punctuation. ! 1797: %cN means require operand N to be a constant ! 1798: and print the constant expression with no punctuation. ! 1799: %aN means expect operand N to be a memory address ! 1800: (not a memory reference!) and print a reference ! 1801: to that address. ! 1802: %nN means expect operand N to be a constant ! 1803: and print a constant expression for minus the value ! 1804: of the operand, with no other punctuation. */ ! 1805: ! 1806: void ! 1807: output_asm_insn (template, operands) ! 1808: char *template; ! 1809: rtx *operands; ! 1810: { ! 1811: register char *p; ! 1812: register int c; ! 1813: ! 1814: /* An insn may return a null string template ! 1815: in a case where no assembler code is needed. */ ! 1816: if (*template == 0) ! 1817: return; ! 1818: ! 1819: p = template; ! 1820: putc ('\t', asm_out_file); ! 1821: ! 1822: #ifdef ASM_OUTPUT_OPCODE ! 1823: ASM_OUTPUT_OPCODE (asm_out_file, p); ! 1824: #endif ! 1825: ! 1826: while (c = *p++) ! 1827: { ! 1828: #ifdef ASM_OUTPUT_OPCODE ! 1829: if (c == '\n') ! 1830: { ! 1831: putc (c, asm_out_file); ! 1832: while ((c = *p) == '\t') ! 1833: { ! 1834: putc (c, asm_out_file); ! 1835: p++; ! 1836: } ! 1837: ASM_OUTPUT_OPCODE (asm_out_file, p); ! 1838: } ! 1839: else ! 1840: #endif ! 1841: if (c != '%') ! 1842: putc (c, asm_out_file); ! 1843: else ! 1844: { ! 1845: /* %% outputs a single %. */ ! 1846: if (*p == '%') ! 1847: { ! 1848: p++; ! 1849: putc (c, asm_out_file); ! 1850: } ! 1851: /* %= outputs a number which is unique to each insn in the entire ! 1852: compilation. This is useful for making local labels that are ! 1853: referred to more than once in a given insn. */ ! 1854: else if (*p == '=') ! 1855: fprintf (asm_out_file, "%d", insn_counter); ! 1856: /* % followed by a letter and some digits ! 1857: outputs an operand in a special way depending on the letter. ! 1858: Letters `acln' are implemented directly. ! 1859: Other letters are passed to `output_operand' so that ! 1860: the PRINT_OPERAND macro can define them. */ ! 1861: else if ((*p >= 'a' && *p <= 'z') ! 1862: || (*p >= 'A' && *p <= 'Z')) ! 1863: { ! 1864: int letter = *p++; ! 1865: c = atoi (p); ! 1866: ! 1867: if (! (*p >= '0' && *p <= '9')) ! 1868: output_operand_lossage ("operand number missing after %-letter"); ! 1869: else if (this_is_asm_operands && c >= (unsigned) insn_noperands) ! 1870: output_operand_lossage ("operand number out of range"); ! 1871: else if (letter == 'l') ! 1872: output_asm_label (operands[c]); ! 1873: else if (letter == 'a') ! 1874: output_address (operands[c]); ! 1875: else if (letter == 'c') ! 1876: { ! 1877: if (CONSTANT_ADDRESS_P (operands[c])) ! 1878: output_addr_const (asm_out_file, operands[c]); ! 1879: else ! 1880: output_operand (operands[c], 'c'); ! 1881: } ! 1882: else if (letter == 'n') ! 1883: { ! 1884: if (GET_CODE (operands[c]) == CONST_INT) ! 1885: fprintf (asm_out_file, "%d", - INTVAL (operands[c])); ! 1886: else ! 1887: { ! 1888: putc ('-', asm_out_file); ! 1889: output_addr_const (asm_out_file, operands[c]); ! 1890: } ! 1891: } ! 1892: else ! 1893: output_operand (operands[c], letter); ! 1894: ! 1895: while ((c = *p) >= '0' && c <= '9') p++; ! 1896: } ! 1897: /* % followed by a digit outputs an operand the default way. */ ! 1898: else if (*p >= '0' && *p <= '9') ! 1899: { ! 1900: c = atoi (p); ! 1901: if (this_is_asm_operands && c >= (unsigned) insn_noperands) ! 1902: output_operand_lossage ("operand number out of range"); ! 1903: else ! 1904: output_operand (operands[c], 0); ! 1905: while ((c = *p) >= '0' && c <= '9') p++; ! 1906: } ! 1907: /* % followed by punctuation: output something for that ! 1908: punctuation character alone, with no operand. ! 1909: The PRINT_OPERAND macro decides what is actually done. */ ! 1910: #ifdef PRINT_OPERAND_PUNCT_VALID_P ! 1911: else if (PRINT_OPERAND_PUNCT_VALID_P (*p)) ! 1912: output_operand (0, *p++); ! 1913: #endif ! 1914: else ! 1915: output_operand_lossage ("invalid %%-code"); ! 1916: } ! 1917: } ! 1918: ! 1919: if (flag_print_asm_name) ! 1920: { ! 1921: /* Annotate the assembly with a comment describing the pattern and ! 1922: alternative used. */ ! 1923: if (debug_insn) ! 1924: { ! 1925: register int num = INSN_CODE (debug_insn); ! 1926: fprintf (asm_out_file, " %s %d %s", ! 1927: ASM_COMMENT_START, INSN_UID (debug_insn), insn_name[num]); ! 1928: if (insn_n_alternatives[num] > 1) ! 1929: fprintf (asm_out_file, "/%d", which_alternative + 1); ! 1930: ! 1931: /* Clear this so only the first assembler insn ! 1932: of any rtl insn will get the special comment for -dp. */ ! 1933: debug_insn = 0; ! 1934: } ! 1935: } ! 1936: ! 1937: putc ('\n', asm_out_file); ! 1938: } ! 1939: ! 1940: /* Output a LABEL_REF, or a bare CODE_LABEL, as an assembler symbol. */ ! 1941: ! 1942: void ! 1943: output_asm_label (x) ! 1944: rtx x; ! 1945: { ! 1946: char buf[256]; ! 1947: ! 1948: if (GET_CODE (x) == LABEL_REF) ! 1949: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0))); ! 1950: else if (GET_CODE (x) == CODE_LABEL) ! 1951: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x)); ! 1952: else ! 1953: output_operand_lossage ("`%l' operand isn't a label"); ! 1954: ! 1955: assemble_name (asm_out_file, buf); ! 1956: } ! 1957: ! 1958: /* Print operand X using machine-dependent assembler syntax. ! 1959: The macro PRINT_OPERAND is defined just to control this function. ! 1960: CODE is a non-digit that preceded the operand-number in the % spec, ! 1961: such as 'z' if the spec was `%z3'. CODE is 0 if there was no char ! 1962: between the % and the digits. ! 1963: When CODE is a non-letter, X is 0. ! 1964: ! 1965: The meanings of the letters are machine-dependent and controlled ! 1966: by PRINT_OPERAND. */ ! 1967: ! 1968: static void ! 1969: output_operand (x, code) ! 1970: rtx x; ! 1971: int code; ! 1972: { ! 1973: if (x && GET_CODE (x) == SUBREG) ! 1974: x = alter_subreg (x); ! 1975: PRINT_OPERAND (asm_out_file, x, code); ! 1976: } ! 1977: ! 1978: /* Print a memory reference operand for address X ! 1979: using machine-dependent assembler syntax. ! 1980: The macro PRINT_OPERAND_ADDRESS exists just to control this function. */ ! 1981: ! 1982: void ! 1983: output_address (x) ! 1984: rtx x; ! 1985: { ! 1986: walk_alter_subreg (x); ! 1987: PRINT_OPERAND_ADDRESS (asm_out_file, x); ! 1988: } ! 1989: ! 1990: /* Print an integer constant expression in assembler syntax. ! 1991: Addition and subtraction are the only arithmetic ! 1992: that may appear in these expressions. */ ! 1993: ! 1994: void ! 1995: output_addr_const (file, x) ! 1996: FILE *file; ! 1997: rtx x; ! 1998: { ! 1999: char buf[256]; ! 2000: ! 2001: restart: ! 2002: switch (GET_CODE (x)) ! 2003: { ! 2004: case PC: ! 2005: if (flag_pic) ! 2006: putc ('.', file); ! 2007: else ! 2008: abort (); ! 2009: break; ! 2010: ! 2011: case SYMBOL_REF: ! 2012: assemble_name (file, XSTR (x, 0)); ! 2013: break; ! 2014: ! 2015: case LABEL_REF: ! 2016: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0))); ! 2017: assemble_name (asm_out_file, buf); ! 2018: break; ! 2019: ! 2020: case CODE_LABEL: ! 2021: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x)); ! 2022: assemble_name (asm_out_file, buf); ! 2023: break; ! 2024: ! 2025: case CONST_INT: ! 2026: fprintf (file, "%d", INTVAL (x)); ! 2027: break; ! 2028: ! 2029: case CONST: ! 2030: /* This used to output parentheses around the expression, ! 2031: but that does not work on the 386 (either ATT or BSD assembler). */ ! 2032: output_addr_const (file, XEXP (x, 0)); ! 2033: break; ! 2034: ! 2035: case CONST_DOUBLE: ! 2036: if (GET_MODE (x) == VOIDmode) ! 2037: { ! 2038: /* We can use %d if the number is <32 bits and positive. */ ! 2039: if (CONST_DOUBLE_HIGH (x) || CONST_DOUBLE_LOW (x) < 0) ! 2040: fprintf (file, "0x%x%08x", ! 2041: CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x)); ! 2042: else ! 2043: fprintf (file, "%d", CONST_DOUBLE_LOW (x)); ! 2044: } ! 2045: else ! 2046: /* We can't handle floating point constants; ! 2047: PRINT_OPERAND must handle them. */ ! 2048: output_operand_lossage ("floating constant misused"); ! 2049: break; ! 2050: ! 2051: case PLUS: ! 2052: /* Some assemblers need integer constants to appear last (eg masm). */ ! 2053: if (GET_CODE (XEXP (x, 0)) == CONST_INT) ! 2054: { ! 2055: output_addr_const (file, XEXP (x, 1)); ! 2056: if (INTVAL (XEXP (x, 0)) >= 0) ! 2057: fprintf (file, "+"); ! 2058: output_addr_const (file, XEXP (x, 0)); ! 2059: } ! 2060: else ! 2061: { ! 2062: output_addr_const (file, XEXP (x, 0)); ! 2063: if (INTVAL (XEXP (x, 1)) >= 0) ! 2064: fprintf (file, "+"); ! 2065: output_addr_const (file, XEXP (x, 1)); ! 2066: } ! 2067: break; ! 2068: ! 2069: case MINUS: ! 2070: output_addr_const (file, XEXP (x, 0)); ! 2071: fprintf (file, "-"); ! 2072: output_addr_const (file, XEXP (x, 1)); ! 2073: break; ! 2074: ! 2075: default: ! 2076: output_operand_lossage ("invalid expression as operand"); ! 2077: } ! 2078: } ! 2079: ! 2080: /* A poor man's fprintf, with the added features of %I, %R, %L, and %U. ! 2081: %R prints the value of REGISTER_PREFIX. ! 2082: %L prints the value of LOCAL_LABEL_PREFIX. ! 2083: %U prints the value of USER_LABEL_PREFIX. ! 2084: %I prints the value of IMMEDIATE_PREFIX. ! 2085: Also supported are %d, %x, %s, %e, %f, %g and %%. */ ! 2086: ! 2087: void ! 2088: asm_fprintf (va_alist) ! 2089: va_dcl ! 2090: { ! 2091: va_list argptr; ! 2092: FILE *file; ! 2093: char buf[10]; ! 2094: char *p, *q, c; ! 2095: ! 2096: va_start (argptr); ! 2097: ! 2098: file = va_arg (argptr, FILE *); ! 2099: p = va_arg (argptr, char *); ! 2100: buf[0] = '%'; ! 2101: ! 2102: while (c = *p++) ! 2103: switch (c) ! 2104: { ! 2105: case '%': ! 2106: c = *p++; ! 2107: q = &buf[1]; ! 2108: while ((c >= '0' && c <= '9') || c == '.') ! 2109: { ! 2110: *q++ = c; ! 2111: c = *p++; ! 2112: } ! 2113: switch (c) ! 2114: { ! 2115: case '%': ! 2116: fprintf (file, "%%"); ! 2117: break; ! 2118: ! 2119: case 'd': case 'i': case 'u': ! 2120: case 'x': case 'p': case 'X': ! 2121: case 'o': ! 2122: *q++ = c; ! 2123: *q = 0; ! 2124: fprintf (file, buf, va_arg (argptr, int)); ! 2125: break; ! 2126: ! 2127: case 'e': ! 2128: case 'f': ! 2129: case 'g': ! 2130: *q++ = c; ! 2131: *q = 0; ! 2132: fprintf (file, buf, va_arg (argptr, double)); ! 2133: break; ! 2134: ! 2135: case 's': ! 2136: *q++ = c; ! 2137: *q = 0; ! 2138: fprintf (file, buf, va_arg (argptr, char *)); ! 2139: break; ! 2140: ! 2141: case 'R': ! 2142: #ifdef REGISTER_PREFIX ! 2143: fprintf (file, "%s", REGISTER_PREFIX); ! 2144: #endif ! 2145: break; ! 2146: ! 2147: case 'I': ! 2148: #ifdef IMMEDIATE_PREFIX ! 2149: fprintf (file, "%s", IMMEDIATE_PREFIX); ! 2150: #endif ! 2151: break; ! 2152: ! 2153: case 'L': ! 2154: #ifdef LOCAL_LABEL_PREFIX ! 2155: fprintf (file, "%s", LOCAL_LABEL_PREFIX); ! 2156: #endif ! 2157: break; ! 2158: ! 2159: case 'U': ! 2160: #ifdef USER_LABEL_PREFIX ! 2161: fprintf (file, "%s", USER_LABEL_PREFIX); ! 2162: #endif ! 2163: break; ! 2164: ! 2165: default: ! 2166: abort (); ! 2167: } ! 2168: break; ! 2169: ! 2170: default: ! 2171: fputc (c, file); ! 2172: } ! 2173: } ! 2174: ! 2175: /* Split up a CONST_DOUBLE or integer constant rtx ! 2176: into two rtx's for single words, ! 2177: storing in *FIRST the word that comes first in memory in the target ! 2178: and in *SECOND the other. */ ! 2179: ! 2180: void ! 2181: split_double (value, first, second) ! 2182: rtx value; ! 2183: rtx *first, *second; ! 2184: { ! 2185: if (GET_CODE (value) == CONST_INT) ! 2186: { ! 2187: /* The rule for using CONST_INT for a wider mode ! 2188: is that we regard the value as signed. ! 2189: So sign-extend it. */ ! 2190: rtx high = (INTVAL (value) < 0 ? constm1_rtx : const0_rtx); ! 2191: #if WORDS_BIG_ENDIAN ! 2192: *first = high; ! 2193: *second = value; ! 2194: #else ! 2195: *first = value; ! 2196: *second = high; ! 2197: #endif ! 2198: } ! 2199: else if (GET_CODE (value) != CONST_DOUBLE) ! 2200: { ! 2201: #if WORDS_BIG_ENDIAN ! 2202: *first = const0_rtx; ! 2203: *second = value; ! 2204: #else ! 2205: *first = value; ! 2206: *second = const0_rtx; ! 2207: #endif ! 2208: } ! 2209: else if (GET_MODE (value) == VOIDmode ! 2210: /* This is the old way we did CONST_DOUBLE integers. */ ! 2211: || GET_MODE_CLASS (GET_MODE (value)) == MODE_INT) ! 2212: { ! 2213: /* In an integer, the words are defined as most and least significant. ! 2214: So order them by the target's convention. */ ! 2215: #if WORDS_BIG_ENDIAN ! 2216: *first = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (value)); ! 2217: *second = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (value)); ! 2218: #else ! 2219: *first = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (value)); ! 2220: *second = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (value)); ! 2221: #endif ! 2222: } ! 2223: else ! 2224: { ! 2225: if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT ! 2226: || HOST_BITS_PER_INT != BITS_PER_WORD) ! 2227: && ! flag_pretend_float) ! 2228: abort (); ! 2229: ! 2230: #if defined (HOST_WORDS_BIG_ENDIAN) == WORDS_BIG_ENDIAN ! 2231: /* Host and target agree => no need to swap. */ ! 2232: *first = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (value)); ! 2233: *second = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (value)); ! 2234: #else ! 2235: *second = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (value)); ! 2236: *first = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (value)); ! 2237: #endif ! 2238: } ! 2239: } ! 2240: ! 2241: /* Return nonzero if this function has no function calls. */ ! 2242: ! 2243: int ! 2244: leaf_function_p () ! 2245: { ! 2246: rtx insn; ! 2247: ! 2248: if (profile_flag || profile_block_flag) ! 2249: return 0; ! 2250: ! 2251: for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) ! 2252: { ! 2253: if (GET_CODE (insn) == CALL_INSN) ! 2254: return 0; ! 2255: if (GET_CODE (insn) == INSN ! 2256: && GET_CODE (PATTERN (insn)) == SEQUENCE ! 2257: && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == CALL_INSN) ! 2258: return 0; ! 2259: } ! 2260: for (insn = current_function_epilogue_delay_list; insn; insn = XEXP (insn, 1)) ! 2261: { ! 2262: if (GET_CODE (XEXP (insn, 0)) == CALL_INSN) ! 2263: return 0; ! 2264: if (GET_CODE (XEXP (insn, 0)) == INSN ! 2265: && GET_CODE (PATTERN (XEXP (insn, 0))) == SEQUENCE ! 2266: && GET_CODE (XVECEXP (PATTERN (XEXP (insn, 0)), 0, 0)) == CALL_INSN) ! 2267: return 0; ! 2268: } ! 2269: ! 2270: return 1; ! 2271: } ! 2272: ! 2273: /* On some machines, a function with no call insns ! 2274: can run faster if it doesn't create its own register window. ! 2275: When output, the leaf function should use only the "output" ! 2276: registers. Ordinarily, the function would be compiled to use ! 2277: the "input" registers to find its arguments; it is a candidate ! 2278: for leaf treatment if it uses only the "input" registers. ! 2279: Leaf function treatment means renumbering so the function ! 2280: uses the "output" registers instead. */ ! 2281: ! 2282: #ifdef LEAF_REGISTERS ! 2283: ! 2284: static char permitted_reg_in_leaf_functions[] = LEAF_REGISTERS; ! 2285: ! 2286: /* Return 1 if this function uses only the registers that can be ! 2287: safely renumbered. */ ! 2288: ! 2289: int ! 2290: only_leaf_regs_used () ! 2291: { ! 2292: int i; ! 2293: ! 2294: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) ! 2295: { ! 2296: if (regs_ever_live[i] > permitted_reg_in_leaf_functions[i]) ! 2297: return 0; ! 2298: } ! 2299: return 1; ! 2300: } ! 2301: ! 2302: /* Scan all instructions and renumber all registers into those ! 2303: available in leaf functions. */ ! 2304: ! 2305: static void ! 2306: leaf_renumber_regs (first) ! 2307: rtx first; ! 2308: { ! 2309: rtx insn; ! 2310: ! 2311: /* Renumber only the actual patterns. ! 2312: The reg-notes can contain frame pointer refs, ! 2313: and renumbering them could crash, and should not be needed. */ ! 2314: for (insn = first; insn; insn = NEXT_INSN (insn)) ! 2315: if (GET_RTX_CLASS (GET_CODE (insn)) == 'i') ! 2316: leaf_renumber_regs_insn (PATTERN (insn)); ! 2317: for (insn = current_function_epilogue_delay_list; insn; insn = XEXP (insn, 1)) ! 2318: if (GET_RTX_CLASS (GET_CODE (XEXP (insn, 0))) == 'i') ! 2319: leaf_renumber_regs_insn (PATTERN (XEXP (insn, 0))); ! 2320: } ! 2321: ! 2322: /* Scan IN_RTX and its subexpressions, and renumber all regs into those ! 2323: available in leaf functions. */ ! 2324: ! 2325: void ! 2326: leaf_renumber_regs_insn (in_rtx) ! 2327: register rtx in_rtx; ! 2328: { ! 2329: register int i, j; ! 2330: register char *format_ptr; ! 2331: ! 2332: if (in_rtx == 0) ! 2333: return; ! 2334: ! 2335: /* Renumber all input-registers into output-registers. ! 2336: renumbered_regs would be 1 for an output-register; ! 2337: they */ ! 2338: ! 2339: if (GET_CODE (in_rtx) == REG) ! 2340: { ! 2341: int newreg; ! 2342: ! 2343: /* Don't renumber the same reg twice. */ ! 2344: if (in_rtx->used) ! 2345: return; ! 2346: ! 2347: newreg = REGNO (in_rtx); ! 2348: /* Don't try to renumber pseudo regs. It is possible for a psuedo reg ! 2349: to reach here as part of a REG_NOTE. */ ! 2350: if (newreg >= FIRST_PSEUDO_REGISTER) ! 2351: { ! 2352: in_rtx->used = 1; ! 2353: return; ! 2354: } ! 2355: newreg = LEAF_REG_REMAP (newreg); ! 2356: if (newreg < 0) ! 2357: abort (); ! 2358: regs_ever_live[REGNO (in_rtx)] = 0; ! 2359: regs_ever_live[newreg] = 1; ! 2360: REGNO (in_rtx) = newreg; ! 2361: in_rtx->used = 1; ! 2362: } ! 2363: ! 2364: if (GET_RTX_CLASS (GET_CODE (in_rtx)) == 'i') ! 2365: { ! 2366: /* Inside a SEQUENCE, we find insns. ! 2367: Renumber just the patterns of these insns, ! 2368: just as we do for the top-level insns. */ ! 2369: leaf_renumber_regs_insn (PATTERN (in_rtx)); ! 2370: return; ! 2371: } ! 2372: ! 2373: format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx)); ! 2374: ! 2375: for (i = 0; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++) ! 2376: switch (*format_ptr++) ! 2377: { ! 2378: case 'e': ! 2379: leaf_renumber_regs_insn (XEXP (in_rtx, i)); ! 2380: break; ! 2381: ! 2382: case 'E': ! 2383: if (NULL != XVEC (in_rtx, i)) ! 2384: { ! 2385: for (j = 0; j < XVECLEN (in_rtx, i); j++) ! 2386: leaf_renumber_regs_insn (XVECEXP (in_rtx, i, j)); ! 2387: } ! 2388: break; ! 2389: ! 2390: case 'S': ! 2391: case 's': ! 2392: case '0': ! 2393: case 'i': ! 2394: case 'n': ! 2395: case 'u': ! 2396: break; ! 2397: ! 2398: default: ! 2399: abort (); ! 2400: } ! 2401: } ! 2402: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.