|
|
1.1 root 1: /* Convert RTL to assembler code and output it, for GNU compiler. 1.1.1.6 ! root 2: Copyright (C) 1987, 1988, 1989, 1992, 1993 Free Software Foundation, Inc. 1.1 root 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 "config.h" 47: #include "gvarargs.h" 1.1.1.6 ! root 48: #include "tree.h" 1.1 root 49: #include "rtl.h" 50: #include "regs.h" 51: #include "insn-config.h" 1.1.1.4 root 52: #include "insn-flags.h" 1.1 root 53: #include "insn-attr.h" 54: #include "insn-codes.h" 55: #include "recog.h" 56: #include "conditions.h" 57: #include "flags.h" 58: #include "real.h" 59: #include "hard-reg-set.h" 1.1.1.4 root 60: #include "defaults.h" 1.1 root 61: 1.1.1.4 root 62: #include <stdio.h> 1.1.1.6 ! root 63: #include <ctype.h> 1.1.1.4 root 64: 65: #include "output.h" 1.1 root 66: 67: /* Get N_SLINE and N_SOL from stab.h if we can expect the file to exist. */ 1.1.1.2 root 68: #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO) 69: #if defined (USG) || defined (NO_STAB_H) 1.1 root 70: #include "gstab.h" /* If doing DBX on sysV, use our own stab.h. */ 71: #else 72: #include <stab.h> /* On BSD, use the system's stab.h. */ 73: #endif /* not USG */ 1.1.1.2 root 74: #endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */ 75: 76: #ifdef XCOFF_DEBUGGING_INFO 77: #include "xcoffout.h" 78: #endif 1.1 root 79: 80: /* .stabd code for line number. */ 81: #ifndef N_SLINE 82: #define N_SLINE 0x44 83: #endif 84: 85: /* .stabs code for included file name. */ 86: #ifndef N_SOL 87: #define N_SOL 0x84 88: #endif 89: 90: #ifndef INT_TYPE_SIZE 91: #define INT_TYPE_SIZE BITS_PER_WORD 92: #endif 93: 94: /* If we aren't using cc0, CC_STATUS_INIT shouldn't exist. So define a 95: null default for it to save conditionalization later. */ 96: #ifndef CC_STATUS_INIT 97: #define CC_STATUS_INIT 98: #endif 99: 100: /* How to start an assembler comment. */ 101: #ifndef ASM_COMMENT_START 102: #define ASM_COMMENT_START ";#" 103: #endif 104: 105: rtx peephole (); 106: void output_asm_insn (); 107: rtx alter_subreg (); 1.1.1.6 ! root 108: static rtx walk_alter_subreg (); 1.1 root 109: static int alter_cond (); 110: void output_asm_label (); 111: static void output_operand (); 112: void output_address (); 113: void output_addr_const (); 114: static void output_source_line (); 115: rtx final_scan_insn (); 116: void profile_function (); 1.1.1.4 root 117: static void profile_after_prologue (); 1.1 root 118: 119: #ifdef HAVE_ATTR_length 120: static int asm_insn_count (); 121: #endif 122: 123: /* Nonzero means this function is a leaf function, with no function calls. 124: This variable exists to be examined in FUNCTION_PROLOGUE 125: and FUNCTION_EPILOGUE. Always zero, unless set by some action. */ 126: int leaf_function; 127: 128: int leaf_function_p (); 129: 130: #ifdef LEAF_REGISTERS 131: int only_leaf_regs_used (); 132: static void leaf_renumber_regs (); 133: void leaf_renumber_regs_insn (); 134: #endif 135: 136: /* Last insn processed by final_scan_insn. */ 137: static rtx debug_insn = 0; 138: 139: /* Line number of last NOTE. */ 140: static int last_linenum; 141: 1.1.1.6 ! root 142: /* Filename of last NOTE. */ ! 143: static char *last_filename; ! 144: 1.1 root 145: /* Number of basic blocks seen so far; 146: used if profile_block_flag is set. */ 147: static int count_basic_blocks; 148: 149: /* Nonzero while outputting an `asm' with operands. 150: This means that inconsistencies are the user's fault, so don't abort. 151: The precise value is the insn being output, to pass to error_for_asm. */ 152: static rtx this_is_asm_operands; 153: 154: /* Number of operands of this insn, for an `asm' with operands. */ 155: static int insn_noperands; 156: 157: /* Compare optimization flag. */ 158: 159: static rtx last_ignored_compare = 0; 160: 161: /* Flag indicating this insn is the start of a new basic block. */ 162: 163: static int new_block = 1; 164: 165: /* All the symbol-blocks (levels of scoping) in the compilation 166: are assigned sequence numbers in order of appearance of the 167: beginnings of the symbol-blocks. Both final and dbxout do this, 168: and assume that they will both give the same number to each block. 169: Final uses these sequence numbers to generate assembler label names 170: LBBnnn and LBEnnn for the beginning and end of the symbol-block. 1.1.1.4 root 171: Dbxout uses the sequence numbers to generate references to the same labels 1.1 root 172: from the dbx debugging information. 173: 174: Sdb records this level at the beginning of each function, 175: in order to find the current level when recursing down declarations. 176: It outputs the block beginning and endings 177: at the point in the asm file where the blocks would begin and end. */ 178: 179: int next_block_index; 180: 181: /* Assign a unique number to each insn that is output. 182: This can be used to generate unique local labels. */ 183: 184: static int insn_counter = 0; 185: 186: #ifdef HAVE_cc0 187: /* This variable contains machine-dependent flags (defined in tm.h) 188: set and examined by output routines 189: that describe how to interpret the condition codes properly. */ 190: 191: CC_STATUS cc_status; 192: 193: /* During output of an insn, this contains a copy of cc_status 194: from before the insn. */ 195: 196: CC_STATUS cc_prev_status; 197: #endif 198: 199: /* Indexed by hardware reg number, is 1 if that register is ever 200: used in the current function. 201: 202: In life_analysis, or in stupid_life_analysis, this is set 203: up to record the hard regs used explicitly. Reload adds 204: in the hard regs used for holding pseudo regs. Final uses 205: it to generate the code in the function prologue and epilogue 206: to save and restore registers as needed. */ 207: 208: char regs_ever_live[FIRST_PSEUDO_REGISTER]; 209: 210: /* Nonzero means current function must be given a frame pointer. 211: Set in stmt.c if anything is allocated on the stack there. 212: Set in reload1.c if anything is allocated on the stack there. */ 213: 214: int frame_pointer_needed; 215: 216: /* Assign unique numbers to labels generated for profiling. */ 217: 218: int profile_label_no; 219: 220: /* Length so far allocated in PENDING_BLOCKS. */ 221: 222: static int max_block_depth; 223: 224: /* Stack of sequence numbers of symbol-blocks of which we have seen the 225: beginning but not yet the end. Sequence numbers are assigned at 226: the beginning; this stack allows us to find the sequence number 227: of a block that is ending. */ 228: 229: static int *pending_blocks; 230: 231: /* Number of elements currently in use in PENDING_BLOCKS. */ 232: 233: static int block_depth; 234: 235: /* Nonzero if have enabled APP processing of our assembler output. */ 236: 237: static int app_on; 238: 239: /* If we are outputting an insn sequence, this contains the sequence rtx. 240: Zero otherwise. */ 241: 242: rtx final_sequence; 243: 1.1.1.6 ! root 244: #ifdef ASSEMBLER_DIALECT ! 245: ! 246: /* Number of the assembler dialect to use, starting at 0. */ ! 247: static int dialect_number; ! 248: #endif ! 249: 1.1 root 250: /* Indexed by line number, nonzero if there is a note for that line. */ 251: 252: static char *line_note_exists; 1.1.1.6 ! root 253: ! 254: /* Linked list to hold line numbers for each basic block. */ ! 255: ! 256: struct bb_list { ! 257: struct bb_list *next; /* pointer to next basic block */ ! 258: int line_num; /* line number */ ! 259: int file_label_num; /* LPBC<n> label # for stored filename */ ! 260: int func_label_num; /* LPBC<n> label # for stored function name */ ! 261: }; ! 262: ! 263: static struct bb_list *bb_head = 0; /* Head of basic block list */ ! 264: static struct bb_list **bb_tail = &bb_head; /* Ptr to store next bb ptr */ ! 265: static int bb_file_label_num = -1; /* Current label # for file */ ! 266: static int bb_func_label_num = -1; /* Current label # for func */ ! 267: ! 268: /* Linked list to hold the strings for each file and function name output. */ ! 269: ! 270: struct bb_str { ! 271: struct bb_str *next; /* pointer to next string */ ! 272: char *string; /* string */ ! 273: int label_num; /* label number */ ! 274: int length; /* string length */ ! 275: }; ! 276: ! 277: static struct bb_str *sbb_head = 0; /* Head of string list. */ ! 278: static struct bb_str **sbb_tail = &sbb_head; /* Ptr to store next bb str */ ! 279: static int sbb_label_num = 0; /* Last label used */ ! 280: ! 281: static int add_bb_string PROTO((char *, int)); ! 282: static void add_bb PROTO((FILE *)); ! 283: 1.1 root 284: 285: /* Initialize data in final at the beginning of a compilation. */ 286: 287: void 288: init_final (filename) 289: char *filename; 290: { 291: next_block_index = 2; 292: app_on = 0; 293: max_block_depth = 20; 294: pending_blocks = (int *) xmalloc (20 * sizeof *pending_blocks); 295: final_sequence = 0; 1.1.1.6 ! root 296: ! 297: #ifdef ASSEMBLER_DIALECT ! 298: dialect_number = ASSEMBLER_DIALECT; ! 299: #endif 1.1 root 300: } 301: 302: /* Called at end of source file, 303: to output the block-profiling table for this entire compilation. */ 304: 305: void 306: end_final (filename) 307: char *filename; 308: { 309: int i; 310: 311: if (profile_block_flag) 312: { 1.1.1.6 ! root 313: char name[20]; ! 314: int align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT); ! 315: int size = (INT_TYPE_SIZE / BITS_PER_UNIT) * count_basic_blocks; ! 316: int rounded = size; ! 317: struct bb_list *ptr; ! 318: struct bb_str *sptr; ! 319: ! 320: rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1; ! 321: rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT) ! 322: * (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); 1.1 root 323: 324: data_section (); 325: 1.1.1.6 ! root 326: /* Output the main header, of 10 words: 1.1 root 327: 0: 1 if this file's initialized, else 0. 1.1.1.6 ! root 328: 1: address of file name (LPBX1). ! 329: 2: address of table of counts (LPBX2). ! 330: 3: number of counts in the table. ! 331: 4: always 0, for compatibility with Sun. ! 332: ! 333: The following are GNU extensions: ! 334: ! 335: 5: address of table of start addrs of basic blocks (LPBX3). ! 336: 6: Number of bytes in this header. ! 337: 7: address of table of function names (LPBX4). ! 338: 8: address of table of line numbers (LPBX5) or 0. ! 339: 9: address of table of file names (LPBX6) or 0. */ ! 340: ! 341: ASM_OUTPUT_ALIGN (asm_out_file, align); 1.1 root 342: 343: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 0); 1.1.1.6 ! root 344: /* zero word */ 1.1 root 345: assemble_integer (const0_rtx, UNITS_PER_WORD, 1); 1.1.1.6 ! root 346: ! 347: /* address of filename */ 1.1 root 348: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 1); 349: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1); 1.1.1.6 ! root 350: ! 351: /* address of count table */ 1.1 root 352: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2); 353: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1); 1.1.1.6 ! root 354: ! 355: /* count of the # of basic blocks */ 1.1.1.4 root 356: assemble_integer (GEN_INT (count_basic_blocks), UNITS_PER_WORD, 1); 1.1.1.6 ! root 357: ! 358: /* zero word (link field) */ 1.1 root 359: assemble_integer (const0_rtx, UNITS_PER_WORD, 1); 1.1.1.6 ! root 360: ! 361: /* address of basic block start address table */ 1.1 root 362: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 3); 363: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1); 364: 1.1.1.6 ! root 365: /* byte count for extended structure. */ ! 366: assemble_integer (GEN_INT (10 * UNITS_PER_WORD), UNITS_PER_WORD, 1); ! 367: ! 368: /* address of function name table */ ! 369: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 4); ! 370: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1); ! 371: ! 372: /* address of line number and filename tables if debugging. */ ! 373: if (write_symbols != NO_DEBUG) ! 374: { ! 375: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 5); ! 376: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1); ! 377: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 6); ! 378: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1); ! 379: } ! 380: else ! 381: { ! 382: assemble_integer (const0_rtx, UNITS_PER_WORD, 1); ! 383: assemble_integer (const0_rtx, UNITS_PER_WORD, 1); ! 384: } ! 385: ! 386: /* Output the file name changing the suffix to .d for Sun tcov ! 387: compatibility. */ 1.1 root 388: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 1); 389: { 390: int len = strlen (filename); 391: char *data_file = (char *) alloca (len + 3); 392: strcpy (data_file, filename); 393: strip_off_ending (data_file, len); 394: strcat (data_file, ".d"); 395: assemble_string (data_file, strlen (data_file) + 1); 396: } 397: 398: /* Make space for the table of counts. */ 1.1.1.6 ! root 399: if (flag_no_common || size == 0) ! 400: { ! 401: /* Realign data section. */ ! 402: ASM_OUTPUT_ALIGN (asm_out_file, align); ! 403: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 2); ! 404: if (size != 0) ! 405: assemble_zeros (size); ! 406: } ! 407: else ! 408: { ! 409: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2); ! 410: #ifdef ASM_OUTPUT_SHARED_LOCAL ! 411: if (flag_shared_data) ! 412: ASM_OUTPUT_SHARED_LOCAL (asm_out_file, name, size, rounded); ! 413: else ! 414: #endif ! 415: #ifdef ASM_OUTPUT_ALIGNED_LOCAL ! 416: ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size, align); ! 417: #else ! 418: ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded); ! 419: #endif ! 420: } 1.1 root 421: 1.1.1.6 ! root 422: /* Output any basic block strings */ 1.1 root 423: readonly_data_section (); 1.1.1.6 ! root 424: if (sbb_head) ! 425: { ! 426: ASM_OUTPUT_ALIGN (asm_out_file, align); ! 427: for (sptr = sbb_head; sptr != 0; sptr = sptr->next) ! 428: { ! 429: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBC", sptr->label_num); ! 430: assemble_string (sptr->string, sptr->length); ! 431: } ! 432: } ! 433: ! 434: /* Output the table of addresses. */ 1.1.1.4 root 435: /* Realign in new section */ 1.1.1.6 ! root 436: ASM_OUTPUT_ALIGN (asm_out_file, align); 1.1 root 437: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 3); 438: for (i = 0; i < count_basic_blocks; i++) 439: { 440: ASM_GENERATE_INTERNAL_LABEL (name, "LPB", i); 441: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), 442: UNITS_PER_WORD, 1); 443: } 444: 1.1.1.6 ! root 445: /* Output the table of function names. */ ! 446: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 4); ! 447: for ((ptr = bb_head), (i = 0); ptr != 0; (ptr = ptr->next), i++) ! 448: { ! 449: if (ptr->func_label_num >= 0) ! 450: { ! 451: ASM_GENERATE_INTERNAL_LABEL (name, "LPBC", ptr->func_label_num); ! 452: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), ! 453: UNITS_PER_WORD, 1); ! 454: } ! 455: else ! 456: assemble_integer (const0_rtx, UNITS_PER_WORD, 1); ! 457: } ! 458: ! 459: for ( ; i < count_basic_blocks; i++) ! 460: assemble_integer (const0_rtx, UNITS_PER_WORD, 1); ! 461: ! 462: if (write_symbols != NO_DEBUG) ! 463: { ! 464: /* Output the table of line numbers. */ ! 465: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 5); ! 466: for ((ptr = bb_head), (i = 0); ptr != 0; (ptr = ptr->next), i++) ! 467: assemble_integer (GEN_INT (ptr->line_num), UNITS_PER_WORD, 1); ! 468: ! 469: for ( ; i < count_basic_blocks; i++) ! 470: assemble_integer (const0_rtx, UNITS_PER_WORD, 1); ! 471: ! 472: /* Output the table of file names. */ ! 473: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 6); ! 474: for ((ptr = bb_head), (i = 0); ptr != 0; (ptr = ptr->next), i++) ! 475: { ! 476: if (ptr->file_label_num >= 0) ! 477: { ! 478: ASM_GENERATE_INTERNAL_LABEL (name, "LPBC", ptr->file_label_num); ! 479: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), ! 480: UNITS_PER_WORD, 1); ! 481: } ! 482: else ! 483: assemble_integer (const0_rtx, UNITS_PER_WORD, 1); ! 484: } ! 485: ! 486: for ( ; i < count_basic_blocks; i++) ! 487: assemble_integer (const0_rtx, UNITS_PER_WORD, 1); ! 488: } ! 489: 1.1 root 490: /* End with the address of the table of addresses, 491: so we can find it easily, as the last word in the file's text. */ 492: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 3); 493: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1); 494: } 495: } 496: 497: /* Enable APP processing of subsequent output. 498: Used before the output from an `asm' statement. */ 499: 500: void 501: app_enable () 502: { 503: if (! app_on) 504: { 505: fprintf (asm_out_file, ASM_APP_ON); 506: app_on = 1; 507: } 508: } 509: 510: /* Enable APP processing of subsequent output. 511: Called from varasm.c before most kinds of output. */ 512: 513: void 514: app_disable () 515: { 516: if (app_on) 517: { 518: fprintf (asm_out_file, ASM_APP_OFF); 519: app_on = 0; 520: } 521: } 522: 523: /* Return the number of slots filled in the current 524: delayed branch sequence (we don't count the insn needing the 525: delay slot). Zero if not in a delayed branch sequence. */ 526: 527: #ifdef DELAY_SLOTS 528: int 529: dbr_sequence_length () 530: { 531: if (final_sequence != 0) 532: return XVECLEN (final_sequence, 0) - 1; 533: else 534: return 0; 535: } 536: #endif 537: 538: /* The next two pages contain routines used to compute the length of an insn 539: and to shorten branches. */ 540: 541: /* Arrays for insn lengths, and addresses. The latter is referenced by 542: `insn_current_length'. */ 543: 544: static short *insn_lengths; 545: int *insn_addresses; 546: 547: /* Address of insn being processed. Used by `insn_current_length'. */ 548: int insn_current_address; 549: 550: /* Indicate the branch shortening hasn't yet been done. */ 551: 552: void 553: init_insn_lengths () 554: { 555: insn_lengths = 0; 556: } 557: 558: /* Obtain the current length of an insn. If branch shortening has been done, 559: get its actual length. Otherwise, get its maximum length. */ 560: 561: int 562: get_attr_length (insn) 563: rtx insn; 564: { 565: #ifdef HAVE_ATTR_length 566: rtx body; 567: int i; 568: int length = 0; 569: 570: if (insn_lengths) 571: return insn_lengths[INSN_UID (insn)]; 572: else 573: switch (GET_CODE (insn)) 574: { 575: case NOTE: 576: case BARRIER: 577: case CODE_LABEL: 578: return 0; 579: 580: case CALL_INSN: 581: length = insn_default_length (insn); 582: break; 583: 584: case JUMP_INSN: 585: body = PATTERN (insn); 586: if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC) 587: { 588: /* This only takes room if jump tables go into the text section. */ 589: #if !defined(READONLY_DATA_SECTION) || defined(JUMP_TABLES_IN_TEXT_SECTION) 590: length = (XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC) 591: * GET_MODE_SIZE (GET_MODE (body))); 592: 593: /* Be pessimistic and assume worst-case alignment. */ 594: length += (GET_MODE_SIZE (GET_MODE (body)) - 1); 595: #else 596: return 0; 597: #endif 598: } 599: else 600: length = insn_default_length (insn); 601: break; 602: 603: case INSN: 604: body = PATTERN (insn); 605: if (GET_CODE (body) == USE || GET_CODE (body) == CLOBBER) 606: return 0; 607: 608: else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0) 1.1.1.6 ! root 609: length = asm_insn_count (body) * insn_default_length (insn); 1.1 root 610: else if (GET_CODE (body) == SEQUENCE) 611: for (i = 0; i < XVECLEN (body, 0); i++) 612: length += get_attr_length (XVECEXP (body, 0, i)); 613: else 614: length = insn_default_length (insn); 615: } 616: 617: #ifdef ADJUST_INSN_LENGTH 618: ADJUST_INSN_LENGTH (insn, length); 619: #endif 620: return length; 621: #else /* not HAVE_ATTR_length */ 622: return 0; 623: #endif /* not HAVE_ATTR_length */ 624: } 625: 626: /* Make a pass over all insns and compute their actual lengths by shortening 627: any branches of variable length if possible. */ 628: 629: /* Give a default value for the lowest address in a function. */ 630: 631: #ifndef FIRST_INSN_ADDRESS 632: #define FIRST_INSN_ADDRESS 0 633: #endif 634: 635: void 636: shorten_branches (first) 637: rtx first; 638: { 639: #ifdef HAVE_ATTR_length 640: rtx insn; 641: int something_changed = 1; 642: int max_uid = 0; 643: char *varying_length; 644: rtx body; 645: int uid; 646: 647: /* Compute maximum UID and allocate arrays. */ 648: for (insn = first; insn; insn = NEXT_INSN (insn)) 649: if (INSN_UID (insn) > max_uid) 650: max_uid = INSN_UID (insn); 651: 652: max_uid++; 653: insn_lengths = (short *) oballoc (max_uid * sizeof (short)); 654: insn_addresses = (int *) oballoc (max_uid * sizeof (int)); 655: varying_length = (char *) oballoc (max_uid * sizeof (char)); 656: 657: /* Compute initial lengths, addresses, and varying flags for each insn. */ 658: for (insn_current_address = FIRST_INSN_ADDRESS, insn = first; 659: insn != 0; 660: insn_current_address += insn_lengths[uid], insn = NEXT_INSN (insn)) 661: { 662: uid = INSN_UID (insn); 663: insn_addresses[uid] = insn_current_address; 664: insn_lengths[uid] = 0; 665: varying_length[uid] = 0; 666: 667: if (GET_CODE (insn) == NOTE || GET_CODE (insn) == BARRIER 668: || GET_CODE (insn) == CODE_LABEL) 669: continue; 670: 671: body = PATTERN (insn); 672: if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC) 673: { 674: /* This only takes room if read-only data goes into the text 675: section. */ 676: #if !defined(READONLY_DATA_SECTION) || defined(JUMP_TABLES_IN_TEXT_SECTION) 677: int unitsize = GET_MODE_SIZE (GET_MODE (body)); 678: 679: insn_lengths[uid] = (XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC) 680: * GET_MODE_SIZE (GET_MODE (body))); 681: 682: /* Account for possible alignment. */ 683: insn_lengths[uid] 684: += unitsize - (insn_current_address & (unitsize - 1)); 685: #else 686: ; 687: #endif 688: } 689: else if (asm_noperands (body) >= 0) 690: insn_lengths[uid] = asm_insn_count (body) * insn_default_length (insn); 691: else if (GET_CODE (body) == SEQUENCE) 692: { 693: int i; 1.1.1.4 root 694: int const_delay_slots; 695: #ifdef DELAY_SLOTS 696: const_delay_slots = const_num_delay_slots (XVECEXP (body, 0, 0)); 697: #else 698: const_delay_slots = 0; 699: #endif 1.1 root 700: /* Inside a delay slot sequence, we do not do any branch shortening 1.1.1.4 root 701: if the shortening could change the number of delay slots 702: of the branch. */ 1.1 root 703: for (i = 0; i < XVECLEN (body, 0); i++) 704: { 705: rtx inner_insn = XVECEXP (body, 0, i); 706: int inner_uid = INSN_UID (inner_insn); 707: int inner_length; 708: 709: if (asm_noperands (PATTERN (XVECEXP (body, 0, i))) >= 0) 710: inner_length = (asm_insn_count (PATTERN (inner_insn)) 711: * insn_default_length (inner_insn)); 712: else 713: inner_length = insn_default_length (inner_insn); 714: 715: insn_lengths[inner_uid] = inner_length; 1.1.1.4 root 716: if (const_delay_slots) 717: { 718: if ((varying_length[inner_uid] 719: = insn_variable_length_p (inner_insn)) != 0) 720: varying_length[uid] = 1; 721: insn_addresses[inner_uid] = (insn_current_address + 722: insn_lengths[uid]); 723: } 724: else 725: varying_length[inner_uid] = 0; 1.1 root 726: insn_lengths[uid] += inner_length; 727: } 728: } 729: else if (GET_CODE (body) != USE && GET_CODE (body) != CLOBBER) 730: { 731: insn_lengths[uid] = insn_default_length (insn); 732: varying_length[uid] = insn_variable_length_p (insn); 733: } 734: 735: /* If needed, do any adjustment. */ 736: #ifdef ADJUST_INSN_LENGTH 737: ADJUST_INSN_LENGTH (insn, insn_lengths[uid]); 738: #endif 739: } 740: 741: /* Now loop over all the insns finding varying length insns. For each, 742: get the current insn length. If it has changed, reflect the change. 743: When nothing changes for a full pass, we are done. */ 744: 745: while (something_changed) 746: { 747: something_changed = 0; 748: for (insn_current_address = FIRST_INSN_ADDRESS, insn = first; 749: insn != 0; 1.1.1.4 root 750: insn = NEXT_INSN (insn)) 1.1 root 751: { 752: int new_length; 1.1.1.5 root 753: int tmp_length; 1.1 root 754: 755: uid = INSN_UID (insn); 756: insn_addresses[uid] = insn_current_address; 757: if (! varying_length[uid]) 1.1.1.4 root 758: { 759: insn_current_address += insn_lengths[uid]; 760: continue; 761: } 762: if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE) 763: { 764: int i; 765: 766: body = PATTERN (insn); 767: new_length = 0; 768: for (i = 0; i < XVECLEN (body, 0); i++) 769: { 770: rtx inner_insn = XVECEXP (body, 0, i); 771: int inner_uid = INSN_UID (inner_insn); 772: int inner_length; 773: 774: insn_addresses[inner_uid] = insn_current_address; 1.1.1.5 root 775: 776: /* insn_current_length returns 0 for insns with a 777: non-varying length. */ 778: if (! varying_length[inner_uid]) 779: inner_length = insn_lengths[inner_uid]; 780: else 781: inner_length = insn_current_length (inner_insn); 782: 1.1.1.4 root 783: if (inner_length != insn_lengths[inner_uid]) 784: { 785: insn_lengths[inner_uid] = inner_length; 786: something_changed = 1; 787: } 788: insn_current_address += insn_lengths[inner_uid]; 789: new_length += inner_length; 790: } 791: } 792: else 793: { 794: new_length = insn_current_length (insn); 795: insn_current_address += new_length; 796: } 1.1.1.5 root 797: 798: #ifdef SHORTEN_WITH_ADJUST_INSN_LENGTH 799: #ifdef ADJUST_INSN_LENGTH 800: /* If needed, do any adjustment. */ 801: tmp_length = new_length; 802: ADJUST_INSN_LENGTH (insn, new_length); 803: insn_current_address += (new_length - tmp_length); 804: #endif 805: #endif 806: 1.1 root 807: if (new_length != insn_lengths[uid]) 808: { 809: insn_lengths[uid] = new_length; 810: something_changed = 1; 811: } 812: } 813: } 814: #endif /* HAVE_ATTR_length */ 815: } 816: 817: #ifdef HAVE_ATTR_length 818: /* Given the body of an INSN known to be generated by an ASM statement, return 819: the number of machine instructions likely to be generated for this insn. 820: This is used to compute its length. */ 821: 822: static int 823: asm_insn_count (body) 824: rtx body; 825: { 826: char *template; 827: int count = 1; 828: 1.1.1.4 root 829: for (template = decode_asm_operands (body, NULL_PTR, NULL_PTR, 830: NULL_PTR, NULL_PTR); 1.1 root 831: *template; template++) 832: if (*template == ';' || *template == '\n') 833: count++; 834: 835: return count; 836: } 837: #endif 838: 839: /* Output assembler code for the start of a function, 840: and initialize some of the variables in this file 841: for the new function. The label for the function and associated 842: assembler pseudo-ops have already been output in `assemble_start_function'. 843: 844: FIRST is the first insn of the rtl for the function being compiled. 845: FILE is the file to write assembler code to. 846: OPTIMIZE is nonzero if we should eliminate redundant 847: test and compare insns. */ 848: 849: void 850: final_start_function (first, file, optimize) 851: rtx first; 852: FILE *file; 853: int optimize; 854: { 855: block_depth = 0; 856: 857: this_is_asm_operands = 0; 858: 859: #ifdef NON_SAVING_SETJMP 860: /* A function that calls setjmp should save and restore all the 861: call-saved registers on a system where longjmp clobbers them. */ 862: if (NON_SAVING_SETJMP && current_function_calls_setjmp) 863: { 864: int i; 865: 866: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 867: if (!call_used_regs[i] && !call_fixed_regs[i]) 868: regs_ever_live[i] = 1; 869: } 870: #endif 871: 872: /* Initial line number is supposed to be output 873: before the function's prologue and label 874: so that the function's address will not appear to be 875: in the last statement of the preceding function. */ 876: if (NOTE_LINE_NUMBER (first) != NOTE_INSN_DELETED) 877: { 878: if (write_symbols == SDB_DEBUG) 879: /* For sdb, let's not, but say we did. 880: We need to set last_linenum for sdbout_function_begin, 881: but we can't have an actual line number before the .bf symbol. 882: (sdb_begin_function_line is not set, 883: and other compilers don't do it.) */ 884: last_linenum = NOTE_LINE_NUMBER (first); 1.1.1.2 root 885: #ifdef XCOFF_DEBUGGING_INFO 886: else if (write_symbols == XCOFF_DEBUG) 887: { 888: last_linenum = NOTE_LINE_NUMBER (first); 889: xcoffout_output_first_source_line (file, last_linenum); 890: } 891: #endif 1.1 root 892: else 893: output_source_line (file, first); 894: } 895: 896: #ifdef LEAF_REG_REMAP 897: if (leaf_function) 898: leaf_renumber_regs (first); 899: #endif 900: 901: /* The Sun386i and perhaps other machines don't work right 902: if the profiling code comes after the prologue. */ 903: #ifdef PROFILE_BEFORE_PROLOGUE 904: if (profile_flag) 905: profile_function (file); 906: #endif /* PROFILE_BEFORE_PROLOGUE */ 907: 908: #ifdef FUNCTION_PROLOGUE 909: /* First output the function prologue: code to set up the stack frame. */ 910: FUNCTION_PROLOGUE (file, get_frame_size ()); 911: #endif 912: 1.1.1.2 root 913: #if defined (SDB_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO) 914: if (write_symbols == SDB_DEBUG || write_symbols == XCOFF_DEBUG) 1.1 root 915: next_block_index = 1; 916: #endif 917: 1.1.1.4 root 918: /* If the machine represents the prologue as RTL, the profiling code must 919: be emitted when NOTE_INSN_PROLOGUE_END is scanned. */ 920: #ifdef HAVE_prologue 921: if (! HAVE_prologue) 922: #endif 923: profile_after_prologue (file); 924: 925: profile_label_no++; 1.1.1.6 ! root 926: ! 927: /* If we are doing basic block profiling, remember a printable version ! 928: of the function name. */ ! 929: if (profile_block_flag) ! 930: { ! 931: char *junk = "function"; ! 932: bb_func_label_num = ! 933: add_bb_string ((*decl_printable_name) (current_function_decl, &junk), FALSE); ! 934: } 1.1.1.4 root 935: } 936: 937: static void 938: profile_after_prologue (file) 939: FILE *file; 940: { 1.1 root 941: #ifdef FUNCTION_BLOCK_PROFILER 942: if (profile_block_flag) 943: { 944: FUNCTION_BLOCK_PROFILER (file, profile_label_no); 945: } 946: #endif /* FUNCTION_BLOCK_PROFILER */ 947: 948: #ifndef PROFILE_BEFORE_PROLOGUE 949: if (profile_flag) 950: profile_function (file); 951: #endif /* not PROFILE_BEFORE_PROLOGUE */ 952: } 953: 954: void 955: profile_function (file) 956: FILE *file; 957: { 958: int align = MIN (BIGGEST_ALIGNMENT, INT_TYPE_SIZE); 959: int sval = current_function_returns_struct; 960: int cxt = current_function_needs_context; 961: 962: data_section (); 963: ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT)); 964: ASM_OUTPUT_INTERNAL_LABEL (file, "LP", profile_label_no); 965: assemble_integer (const0_rtx, UNITS_PER_WORD, 1); 966: 967: text_section (); 968: 969: #ifdef STRUCT_VALUE_INCOMING_REGNUM 970: if (sval) 971: ASM_OUTPUT_REG_PUSH (file, STRUCT_VALUE_INCOMING_REGNUM); 972: #else 973: #ifdef STRUCT_VALUE_REGNUM 974: if (sval) 975: ASM_OUTPUT_REG_PUSH (file, STRUCT_VALUE_REGNUM); 976: #endif 977: #endif 978: 979: #if 0 980: #ifdef STATIC_CHAIN_INCOMING_REGNUM 981: if (cxt) 982: ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_INCOMING_REGNUM); 983: #else 984: #ifdef STATIC_CHAIN_REGNUM 985: if (cxt) 986: ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_REGNUM); 987: #endif 988: #endif 989: #endif /* 0 */ 990: 991: FUNCTION_PROFILER (file, profile_label_no); 992: 993: #if 0 994: #ifdef STATIC_CHAIN_INCOMING_REGNUM 995: if (cxt) 996: ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_INCOMING_REGNUM); 997: #else 998: #ifdef STATIC_CHAIN_REGNUM 999: if (cxt) 1000: ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_REGNUM); 1001: #endif 1002: #endif 1003: #endif /* 0 */ 1004: 1005: #ifdef STRUCT_VALUE_INCOMING_REGNUM 1006: if (sval) 1007: ASM_OUTPUT_REG_POP (file, STRUCT_VALUE_INCOMING_REGNUM); 1008: #else 1009: #ifdef STRUCT_VALUE_REGNUM 1010: if (sval) 1011: ASM_OUTPUT_REG_POP (file, STRUCT_VALUE_REGNUM); 1012: #endif 1013: #endif 1014: } 1015: 1016: /* Output assembler code for the end of a function. 1017: For clarity, args are same as those of `final_start_function' 1018: even though not all of them are needed. */ 1019: 1020: void 1021: final_end_function (first, file, optimize) 1022: rtx first; 1023: FILE *file; 1024: int optimize; 1025: { 1026: if (app_on) 1027: { 1028: fprintf (file, ASM_APP_OFF); 1029: app_on = 0; 1030: } 1031: 1032: #ifdef SDB_DEBUGGING_INFO 1033: if (write_symbols == SDB_DEBUG) 1034: sdbout_end_function (last_linenum); 1035: #endif 1036: 1.1.1.4 root 1037: #ifdef DWARF_DEBUGGING_INFO 1038: if (write_symbols == DWARF_DEBUG) 1039: dwarfout_end_function (); 1040: #endif 1041: 1.1.1.2 root 1042: #ifdef XCOFF_DEBUGGING_INFO 1043: if (write_symbols == XCOFF_DEBUG) 1044: xcoffout_end_function (file, last_linenum); 1045: #endif 1046: 1.1 root 1047: #ifdef FUNCTION_EPILOGUE 1048: /* Finally, output the function epilogue: 1049: code to restore the stack frame and return to the caller. */ 1050: FUNCTION_EPILOGUE (file, get_frame_size ()); 1051: #endif 1052: 1053: #ifdef SDB_DEBUGGING_INFO 1054: if (write_symbols == SDB_DEBUG) 1055: sdbout_end_epilogue (); 1056: #endif 1057: 1058: #ifdef DWARF_DEBUGGING_INFO 1059: if (write_symbols == DWARF_DEBUG) 1060: dwarfout_end_epilogue (); 1061: #endif 1062: 1.1.1.2 root 1063: #ifdef XCOFF_DEBUGGING_INFO 1064: if (write_symbols == XCOFF_DEBUG) 1065: xcoffout_end_epilogue (file); 1066: #endif 1067: 1.1.1.6 ! root 1068: bb_func_label_num = -1; /* not in function, nuke label # */ ! 1069: 1.1 root 1070: /* If FUNCTION_EPILOGUE is not defined, then the function body 1071: itself contains return instructions wherever needed. */ 1072: } 1073: 1.1.1.6 ! root 1074: /* Add a block to the linked list that remembers the current line/file/function ! 1075: for basic block profiling. Emit the label in front of the basic block and ! 1076: the instructions that increment the count field. */ ! 1077: ! 1078: static void ! 1079: add_bb (file) ! 1080: FILE *file; ! 1081: { ! 1082: struct bb_list *ptr = (struct bb_list *) permalloc (sizeof (struct bb_list)); ! 1083: ! 1084: /* Add basic block to linked list. */ ! 1085: ptr->next = 0; ! 1086: ptr->line_num = last_linenum; ! 1087: ptr->file_label_num = bb_file_label_num; ! 1088: ptr->func_label_num = bb_func_label_num; ! 1089: *bb_tail = ptr; ! 1090: bb_tail = &ptr->next; ! 1091: ! 1092: /* Enable the table of basic-block use counts ! 1093: to point at the code it applies to. */ ! 1094: ASM_OUTPUT_INTERNAL_LABEL (file, "LPB", count_basic_blocks); ! 1095: ! 1096: /* Before first insn of this basic block, increment the ! 1097: count of times it was entered. */ ! 1098: #ifdef BLOCK_PROFILER ! 1099: BLOCK_PROFILER (file, count_basic_blocks); ! 1100: CC_STATUS_INIT; ! 1101: #endif ! 1102: ! 1103: new_block = 0; ! 1104: count_basic_blocks++; ! 1105: } ! 1106: ! 1107: /* Add a string to be used for basic block profiling. */ ! 1108: ! 1109: static int ! 1110: add_bb_string (string, perm_p) ! 1111: char *string; ! 1112: int perm_p; ! 1113: { ! 1114: int len; ! 1115: struct bb_str *ptr = 0; ! 1116: ! 1117: if (!string) ! 1118: { ! 1119: string = "<unknown>"; ! 1120: perm_p = TRUE; ! 1121: } ! 1122: ! 1123: /* Allocate a new string if the current string isn't permanent. If ! 1124: the string is permanent search for the same string in other ! 1125: allocations. */ ! 1126: ! 1127: len = strlen (string) + 1; ! 1128: if (!perm_p) ! 1129: { ! 1130: char *p = (char *) permalloc (len); ! 1131: bcopy (string, p, len); ! 1132: string = p; ! 1133: } ! 1134: else ! 1135: for (ptr = sbb_head; ptr != (struct bb_str *)0; ptr = ptr->next) ! 1136: if (ptr->string == string) ! 1137: break; ! 1138: ! 1139: /* Allocate a new string block if we need to. */ ! 1140: if (!ptr) ! 1141: { ! 1142: ptr = (struct bb_str *) permalloc (sizeof (*ptr)); ! 1143: ptr->next = 0; ! 1144: ptr->length = len; ! 1145: ptr->label_num = sbb_label_num++; ! 1146: ptr->string = string; ! 1147: *sbb_tail = ptr; ! 1148: sbb_tail = &ptr->next; ! 1149: } ! 1150: ! 1151: return ptr->label_num; ! 1152: } ! 1153: ! 1154: 1.1 root 1155: /* Output assembler code for some insns: all or part of a function. 1156: For description of args, see `final_start_function', above. 1157: 1158: PRESCAN is 1 if we are not really outputting, 1159: just scanning as if we were outputting. 1160: Prescanning deletes and rearranges insns just like ordinary output. 1161: PRESCAN is -2 if we are outputting after having prescanned. 1162: In this case, don't try to delete or rearrange insns 1163: because that has already been done. 1164: Prescanning is done only on certain machines. */ 1165: 1166: void 1167: final (first, file, optimize, prescan) 1168: rtx first; 1169: FILE *file; 1170: int optimize; 1171: int prescan; 1172: { 1173: register rtx insn; 1174: int max_line = 0; 1175: 1176: last_ignored_compare = 0; 1177: new_block = 1; 1178: 1.1.1.4 root 1179: /* Make a map indicating which line numbers appear in this function. 1180: When producing SDB debugging info, delete troublesome line number 1181: notes from inlined functions in other files as well as duplicate 1182: line number notes. */ 1183: #ifdef SDB_DEBUGGING_INFO 1184: if (write_symbols == SDB_DEBUG) 1185: { 1186: rtx last = 0; 1187: for (insn = first; insn; insn = NEXT_INSN (insn)) 1188: if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0) 1189: { 1190: if ((RTX_INTEGRATED_P (insn) 1191: && strcmp (NOTE_SOURCE_FILE (insn), main_input_filename) != 0) 1192: || (last != 0 1193: && NOTE_LINE_NUMBER (insn) == NOTE_LINE_NUMBER (last) 1194: && NOTE_SOURCE_FILE (insn) == NOTE_SOURCE_FILE (last))) 1195: { 1196: NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; 1197: NOTE_SOURCE_FILE (insn) = 0; 1198: continue; 1199: } 1200: last = insn; 1201: if (NOTE_LINE_NUMBER (insn) > max_line) 1202: max_line = NOTE_LINE_NUMBER (insn); 1203: } 1204: } 1205: else 1206: #endif 1207: { 1208: for (insn = first; insn; insn = NEXT_INSN (insn)) 1209: if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > max_line) 1210: max_line = NOTE_LINE_NUMBER (insn); 1211: } 1.1 root 1212: 1213: line_note_exists = (char *) oballoc (max_line + 1); 1214: bzero (line_note_exists, max_line + 1); 1215: 1216: for (insn = first; insn; insn = NEXT_INSN (insn)) 1217: if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0) 1218: line_note_exists[NOTE_LINE_NUMBER (insn)] = 1; 1219: 1220: init_recog (); 1221: 1222: CC_STATUS_INIT; 1223: 1224: /* Output the insns. */ 1225: for (insn = NEXT_INSN (first); insn;) 1226: insn = final_scan_insn (insn, file, optimize, prescan, 0); 1227: 1228: /* Do basic-block profiling here 1229: if the last insn was a conditional branch. */ 1230: if (profile_block_flag && new_block) 1.1.1.6 ! root 1231: add_bb (file); 1.1 root 1232: } 1233: 1234: /* The final scan for one insn, INSN. 1235: Args are same as in `final', except that INSN 1236: is the insn being scanned. 1237: Value returned is the next insn to be scanned. 1238: 1239: NOPEEPHOLES is the flag to disallow peephole processing (currently 1240: used for within delayed branch sequence output). */ 1241: 1242: rtx 1243: final_scan_insn (insn, file, optimize, prescan, nopeepholes) 1244: rtx insn; 1245: FILE *file; 1246: int optimize; 1247: int prescan; 1248: int nopeepholes; 1249: { 1250: register int i; 1251: insn_counter++; 1252: 1253: /* Ignore deleted insns. These can occur when we split insns (due to a 1254: template of "#") while not optimizing. */ 1255: if (INSN_DELETED_P (insn)) 1256: return NEXT_INSN (insn); 1257: 1258: switch (GET_CODE (insn)) 1259: { 1260: case NOTE: 1261: if (prescan > 0) 1262: break; 1263: 1264: /* Align the beginning of a loop, for higher speed 1265: on certain machines. */ 1266: 1267: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG && optimize > 0) 1268: { 1269: #ifdef ASM_OUTPUT_LOOP_ALIGN 1270: rtx next = next_nonnote_insn (insn); 1271: if (next && GET_CODE (next) == CODE_LABEL) 1272: { 1273: ASM_OUTPUT_LOOP_ALIGN (asm_out_file); 1274: } 1275: #endif 1276: break; 1277: } 1278: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END) 1279: break; 1280: 1.1.1.4 root 1281: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_PROLOGUE_END) 1282: { 1283: #ifdef FUNCTION_END_PROLOGUE 1284: FUNCTION_END_PROLOGUE (file); 1285: #endif 1286: profile_after_prologue (file); 1287: break; 1288: } 1289: 1290: #ifdef FUNCTION_BEGIN_EPILOGUE 1291: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EPILOGUE_BEG) 1292: { 1293: FUNCTION_BEGIN_EPILOGUE (file); 1294: break; 1295: } 1296: #endif 1297: 1.1 root 1298: if (write_symbols == NO_DEBUG) 1299: break; 1300: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG) 1301: { 1302: #ifdef SDB_DEBUGGING_INFO 1303: if (write_symbols == SDB_DEBUG) 1304: sdbout_begin_function (last_linenum); 1305: #endif 1.1.1.2 root 1306: #ifdef XCOFF_DEBUGGING_INFO 1307: if (write_symbols == XCOFF_DEBUG) 1308: xcoffout_begin_function (file, last_linenum); 1309: #endif 1.1.1.4 root 1310: #ifdef DWARF_DEBUGGING_INFO 1311: if (write_symbols == DWARF_DEBUG) 1312: dwarfout_begin_function (); 1313: #endif 1.1 root 1314: break; 1315: } 1316: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED) 1317: break; /* An insn that was "deleted" */ 1318: if (app_on) 1319: { 1320: fprintf (file, ASM_APP_OFF); 1321: app_on = 0; 1322: } 1323: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG 1324: && (debug_info_level == DINFO_LEVEL_NORMAL 1.1.1.4 root 1325: || debug_info_level == DINFO_LEVEL_VERBOSE 1326: #ifdef DWARF_DEBUGGING_INFO 1327: || write_symbols == DWARF_DEBUG 1328: #endif 1329: ) 1330: ) 1.1 root 1331: { 1332: /* Beginning of a symbol-block. Assign it a sequence number 1333: and push the number onto the stack PENDING_BLOCKS. */ 1334: 1335: if (block_depth == max_block_depth) 1336: { 1337: /* PENDING_BLOCKS is full; make it longer. */ 1338: max_block_depth *= 2; 1339: pending_blocks 1340: = (int *) xrealloc (pending_blocks, 1341: max_block_depth * sizeof (int)); 1342: } 1343: pending_blocks[block_depth++] = next_block_index; 1344: 1345: /* Output debugging info about the symbol-block beginning. */ 1346: 1347: #ifdef SDB_DEBUGGING_INFO 1348: if (write_symbols == SDB_DEBUG) 1349: sdbout_begin_block (file, last_linenum, next_block_index); 1350: #endif 1.1.1.2 root 1351: #ifdef XCOFF_DEBUGGING_INFO 1352: if (write_symbols == XCOFF_DEBUG) 1353: xcoffout_begin_block (file, last_linenum, next_block_index); 1354: #endif 1.1 root 1355: #ifdef DBX_DEBUGGING_INFO 1356: if (write_symbols == DBX_DEBUG) 1357: ASM_OUTPUT_INTERNAL_LABEL (file, "LBB", next_block_index); 1358: #endif 1359: #ifdef DWARF_DEBUGGING_INFO 1360: if (write_symbols == DWARF_DEBUG && block_depth > 1) 1361: dwarfout_begin_block (next_block_index); 1362: #endif 1363: 1364: next_block_index++; 1365: } 1366: else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END 1367: && (debug_info_level == DINFO_LEVEL_NORMAL 1.1.1.4 root 1368: || debug_info_level == DINFO_LEVEL_VERBOSE 1369: #ifdef DWARF_DEBUGGING_INFO 1370: || write_symbols == DWARF_DEBUG 1371: #endif 1372: ) 1373: ) 1.1 root 1374: { 1375: /* End of a symbol-block. Pop its sequence number off 1376: PENDING_BLOCKS and output debugging info based on that. */ 1377: 1378: --block_depth; 1379: 1.1.1.2 root 1380: #ifdef XCOFF_DEBUGGING_INFO 1381: if (write_symbols == XCOFF_DEBUG && block_depth >= 0) 1382: xcoffout_end_block (file, last_linenum, pending_blocks[block_depth]); 1383: #endif 1.1 root 1384: #ifdef DBX_DEBUGGING_INFO 1385: if (write_symbols == DBX_DEBUG && block_depth >= 0) 1386: ASM_OUTPUT_INTERNAL_LABEL (file, "LBE", 1387: pending_blocks[block_depth]); 1388: #endif 1389: #ifdef SDB_DEBUGGING_INFO 1390: if (write_symbols == SDB_DEBUG && block_depth >= 0) 1391: sdbout_end_block (file, last_linenum); 1392: #endif 1393: #ifdef DWARF_DEBUGGING_INFO 1394: if (write_symbols == DWARF_DEBUG && block_depth >= 1) 1395: dwarfout_end_block (pending_blocks[block_depth]); 1396: #endif 1397: } 1.1.1.4 root 1398: else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL 1399: && (debug_info_level == DINFO_LEVEL_NORMAL 1400: || debug_info_level == DINFO_LEVEL_VERBOSE)) 1401: { 1402: #ifdef DWARF_DEBUGGING_INFO 1403: if (write_symbols == DWARF_DEBUG) 1404: dwarfout_label (insn); 1405: #endif 1406: } 1.1 root 1407: else if (NOTE_LINE_NUMBER (insn) > 0) 1408: /* This note is a line-number. */ 1409: { 1410: register rtx note; 1411: 1412: #if 0 /* This is what we used to do. */ 1413: output_source_line (file, insn); 1414: #endif 1415: int note_after = 0; 1416: 1417: /* If there is anything real after this note, 1418: output it. If another line note follows, omit this one. */ 1419: for (note = NEXT_INSN (insn); note; note = NEXT_INSN (note)) 1420: { 1421: if (GET_CODE (note) != NOTE && GET_CODE (note) != CODE_LABEL) 1422: break; 1.1.1.3 root 1423: /* These types of notes can be significant 1.1.1.4 root 1424: so make sure the preceding line number stays. */ 1.1.1.3 root 1425: else if (GET_CODE (note) == NOTE 1426: && (NOTE_LINE_NUMBER (note) == NOTE_INSN_BLOCK_BEG 1427: || NOTE_LINE_NUMBER (note) == NOTE_INSN_BLOCK_END 1428: || NOTE_LINE_NUMBER (note) == NOTE_INSN_FUNCTION_BEG)) 1429: break; 1.1 root 1430: else if (GET_CODE (note) == NOTE && NOTE_LINE_NUMBER (note) > 0) 1431: { 1.1.1.3 root 1432: /* Another line note follows; we can delete this note 1433: if no intervening line numbers have notes elsewhere. */ 1.1 root 1434: int num; 1435: for (num = NOTE_LINE_NUMBER (insn) + 1; 1436: num < NOTE_LINE_NUMBER (note); 1437: num++) 1438: if (line_note_exists[num]) 1439: break; 1440: 1.1.1.4 root 1441: if (num >= NOTE_LINE_NUMBER (note)) 1.1 root 1442: note_after = 1; 1443: break; 1444: } 1445: } 1446: 1447: /* Output this line note 1448: if it is the first or the last line note in a row. */ 1449: if (!note_after) 1450: output_source_line (file, insn); 1451: } 1452: break; 1453: 1454: case BARRIER: 1455: #ifdef ASM_OUTPUT_ALIGN_CODE 1.1.1.4 root 1456: /* Don't litter the assembler output with needless alignments. A 1457: BARRIER will be placed at the end of every function if HAVE_epilogue 1458: is true. */ 1459: if (NEXT_INSN (insn)) 1460: ASM_OUTPUT_ALIGN_CODE (file); 1.1 root 1461: #endif 1462: break; 1463: 1464: case CODE_LABEL: 1465: CC_STATUS_INIT; 1466: if (prescan > 0) 1467: break; 1468: new_block = 1; 1469: #ifdef SDB_DEBUGGING_INFO 1470: if (write_symbols == SDB_DEBUG && LABEL_NAME (insn)) 1471: sdbout_label (insn); 1472: #endif 1473: #ifdef DWARF_DEBUGGING_INFO 1474: if (write_symbols == DWARF_DEBUG && LABEL_NAME (insn)) 1475: dwarfout_label (insn); 1476: #endif 1477: if (app_on) 1478: { 1479: fprintf (file, ASM_APP_OFF); 1480: app_on = 0; 1481: } 1482: if (NEXT_INSN (insn) != 0 1483: && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN) 1484: { 1485: rtx nextbody = PATTERN (NEXT_INSN (insn)); 1486: 1487: /* If this label is followed by a jump-table, 1488: make sure we put the label in the read-only section. Also 1489: possibly write the label and jump table together. */ 1490: 1491: if (GET_CODE (nextbody) == ADDR_VEC 1492: || GET_CODE (nextbody) == ADDR_DIFF_VEC) 1493: { 1494: #ifndef JUMP_TABLES_IN_TEXT_SECTION 1495: readonly_data_section (); 1.1.1.4 root 1496: #ifdef READONLY_DATA_SECTION 1497: ASM_OUTPUT_ALIGN (file, 1498: exact_log2 (BIGGEST_ALIGNMENT 1499: / BITS_PER_UNIT)); 1500: #endif /* READONLY_DATA_SECTION */ 1501: #else /* JUMP_TABLES_IN_TEXT_SECTION */ 1.1 root 1502: text_section (); 1.1.1.4 root 1503: #endif /* JUMP_TABLES_IN_TEXT_SECTION */ 1.1 root 1504: #ifdef ASM_OUTPUT_CASE_LABEL 1505: ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn), 1506: NEXT_INSN (insn)); 1507: #else 1508: ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn)); 1509: #endif 1510: break; 1511: } 1512: } 1513: 1514: ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn)); 1515: break; 1516: 1517: default: 1518: { 1519: register rtx body = PATTERN (insn); 1520: int insn_code_number; 1521: char *template; 1522: rtx note; 1523: 1524: /* An INSN, JUMP_INSN or CALL_INSN. 1525: First check for special kinds that recog doesn't recognize. */ 1526: 1527: if (GET_CODE (body) == USE /* These are just declarations */ 1528: || GET_CODE (body) == CLOBBER) 1529: break; 1530: 1531: #ifdef HAVE_cc0 1532: /* If there is a REG_CC_SETTER note on this insn, it means that 1533: the setting of the condition code was done in the delay slot 1534: of the insn that branched here. So recover the cc status 1535: from the insn that set it. */ 1536: 1.1.1.4 root 1537: note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX); 1.1 root 1538: if (note) 1539: { 1540: NOTICE_UPDATE_CC (PATTERN (XEXP (note, 0)), XEXP (note, 0)); 1541: cc_prev_status = cc_status; 1542: } 1543: #endif 1544: 1545: /* Detect insns that are really jump-tables 1546: and output them as such. */ 1547: 1548: if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC) 1549: { 1550: register int vlen, idx; 1551: 1552: if (prescan > 0) 1553: break; 1554: 1555: if (app_on) 1556: { 1557: fprintf (file, ASM_APP_OFF); 1558: app_on = 0; 1559: } 1560: 1561: vlen = XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC); 1562: for (idx = 0; idx < vlen; idx++) 1563: { 1564: if (GET_CODE (body) == ADDR_VEC) 1.1.1.4 root 1565: { 1566: #ifdef ASM_OUTPUT_ADDR_VEC_ELT 1567: ASM_OUTPUT_ADDR_VEC_ELT 1568: (file, CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0))); 1569: #else 1570: abort (); 1571: #endif 1572: } 1.1 root 1573: else 1.1.1.4 root 1574: { 1575: #ifdef ASM_OUTPUT_ADDR_DIFF_ELT 1576: ASM_OUTPUT_ADDR_DIFF_ELT 1577: (file, 1578: CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 1, idx), 0)), 1579: CODE_LABEL_NUMBER (XEXP (XEXP (body, 0), 0))); 1580: #else 1581: abort (); 1582: #endif 1583: } 1.1 root 1584: } 1585: #ifdef ASM_OUTPUT_CASE_END 1586: ASM_OUTPUT_CASE_END (file, 1587: CODE_LABEL_NUMBER (PREV_INSN (insn)), 1588: insn); 1589: #endif 1590: 1591: text_section (); 1592: 1593: break; 1594: } 1595: 1596: /* Do basic-block profiling when we reach a new block. 1597: Done here to avoid jump tables. */ 1598: if (profile_block_flag && new_block) 1.1.1.6 ! root 1599: add_bb (file); 1.1 root 1600: 1601: if (GET_CODE (body) == ASM_INPUT) 1602: { 1603: /* There's no telling what that did to the condition codes. */ 1604: CC_STATUS_INIT; 1605: if (prescan > 0) 1606: break; 1607: if (! app_on) 1608: { 1609: fprintf (file, ASM_APP_ON); 1610: app_on = 1; 1611: } 1612: fprintf (asm_out_file, "\t%s\n", XSTR (body, 0)); 1613: break; 1614: } 1615: 1616: /* Detect `asm' construct with operands. */ 1617: if (asm_noperands (body) >= 0) 1618: { 1619: int noperands = asm_noperands (body); 1620: rtx *ops; 1621: char *string; 1622: 1623: /* There's no telling what that did to the condition codes. */ 1624: CC_STATUS_INIT; 1625: if (prescan > 0) 1626: break; 1627: 1628: /* alloca won't do here, since only return from `final' 1629: would free it. */ 1630: if (noperands > 0) 1631: ops = (rtx *) xmalloc (noperands * sizeof (rtx)); 1632: 1633: if (! app_on) 1634: { 1635: fprintf (file, ASM_APP_ON); 1636: app_on = 1; 1637: } 1638: 1639: /* Get out the operand values. */ 1.1.1.4 root 1640: string = decode_asm_operands (body, ops, NULL_PTR, 1641: NULL_PTR, NULL_PTR); 1.1 root 1642: /* Inhibit aborts on what would otherwise be compiler bugs. */ 1643: insn_noperands = noperands; 1644: this_is_asm_operands = insn; 1645: /* Output the insn using them. */ 1646: output_asm_insn (string, ops); 1647: this_is_asm_operands = 0; 1648: if (noperands > 0) 1649: free (ops); 1650: break; 1651: } 1652: 1653: if (prescan <= 0 && app_on) 1654: { 1655: fprintf (file, ASM_APP_OFF); 1656: app_on = 0; 1657: } 1658: 1659: if (GET_CODE (body) == SEQUENCE) 1660: { 1661: /* A delayed-branch sequence */ 1662: register int i; 1663: rtx next; 1664: 1665: if (prescan > 0) 1666: break; 1667: final_sequence = body; 1668: 1669: /* The first insn in this SEQUENCE might be a JUMP_INSN that will 1670: force the restoration of a comparison that was previously 1671: thought unnecessary. If that happens, cancel this sequence 1672: and cause that insn to be restored. */ 1673: 1674: next = final_scan_insn (XVECEXP (body, 0, 0), file, 0, prescan, 1); 1675: if (next != XVECEXP (body, 0, 1)) 1676: { 1677: final_sequence = 0; 1678: return next; 1679: } 1680: 1681: for (i = 1; i < XVECLEN (body, 0); i++) 1682: final_scan_insn (XVECEXP (body, 0, i), file, 0, prescan, 1); 1683: #ifdef DBR_OUTPUT_SEQEND 1684: DBR_OUTPUT_SEQEND (file); 1685: #endif 1686: final_sequence = 0; 1687: 1688: /* If the insn requiring the delay slot was a CALL_INSN, the 1689: insns in the delay slot are actually executed before the 1690: called function. Hence we don't preserve any CC-setting 1691: actions in these insns and the CC must be marked as being 1692: clobbered by the function. */ 1693: if (GET_CODE (XVECEXP (body, 0, 0)) == CALL_INSN) 1694: CC_STATUS_INIT; 1.1.1.3 root 1695: 1696: /* Following a conditional branch sequence, we have a new basic 1697: block. */ 1698: if (profile_block_flag) 1699: { 1700: rtx insn = XVECEXP (body, 0, 0); 1701: rtx body = PATTERN (insn); 1702: 1703: if ((GET_CODE (insn) == JUMP_INSN && GET_CODE (body) == SET 1704: && GET_CODE (SET_SRC (body)) != LABEL_REF) 1705: || (GET_CODE (insn) == JUMP_INSN 1706: && GET_CODE (body) == PARALLEL 1707: && GET_CODE (XVECEXP (body, 0, 0)) == SET 1708: && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) != LABEL_REF)) 1709: new_block = 1; 1710: } 1.1 root 1711: break; 1712: } 1713: 1714: /* We have a real machine instruction as rtl. */ 1715: 1716: body = PATTERN (insn); 1717: 1718: #ifdef HAVE_cc0 1719: /* Check for redundant test and compare instructions 1720: (when the condition codes are already set up as desired). 1721: This is done only when optimizing; if not optimizing, 1722: it should be possible for the user to alter a variable 1723: with the debugger in between statements 1724: and the next statement should reexamine the variable 1725: to compute the condition codes. */ 1726: 1727: if (optimize 1728: && GET_CODE (body) == SET 1729: && GET_CODE (SET_DEST (body)) == CC0 1730: && insn != last_ignored_compare) 1731: { 1732: if (GET_CODE (SET_SRC (body)) == SUBREG) 1733: SET_SRC (body) = alter_subreg (SET_SRC (body)); 1734: else if (GET_CODE (SET_SRC (body)) == COMPARE) 1735: { 1736: if (GET_CODE (XEXP (SET_SRC (body), 0)) == SUBREG) 1737: XEXP (SET_SRC (body), 0) 1738: = alter_subreg (XEXP (SET_SRC (body), 0)); 1739: if (GET_CODE (XEXP (SET_SRC (body), 1)) == SUBREG) 1740: XEXP (SET_SRC (body), 1) 1741: = alter_subreg (XEXP (SET_SRC (body), 1)); 1742: } 1743: if ((cc_status.value1 != 0 1744: && rtx_equal_p (SET_SRC (body), cc_status.value1)) 1745: || (cc_status.value2 != 0 1746: && rtx_equal_p (SET_SRC (body), cc_status.value2))) 1747: { 1748: /* Don't delete insn if it has an addressing side-effect. */ 1749: if (! FIND_REG_INC_NOTE (insn, 0) 1750: /* or if anything in it is volatile. */ 1751: && ! volatile_refs_p (PATTERN (insn))) 1752: { 1753: /* We don't really delete the insn; just ignore it. */ 1754: last_ignored_compare = insn; 1755: break; 1756: } 1757: } 1758: } 1759: #endif 1760: 1.1.1.3 root 1761: /* Following a conditional branch, we have a new basic block. 1762: But if we are inside a sequence, the new block starts after the 1763: last insn of the sequence. */ 1764: if (profile_block_flag && final_sequence == 0 1765: && ((GET_CODE (insn) == JUMP_INSN && GET_CODE (body) == SET 1766: && GET_CODE (SET_SRC (body)) != LABEL_REF) 1767: || (GET_CODE (insn) == JUMP_INSN && GET_CODE (body) == PARALLEL 1768: && GET_CODE (XVECEXP (body, 0, 0)) == SET 1769: && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) != LABEL_REF))) 1.1 root 1770: new_block = 1; 1771: 1772: #ifndef STACK_REGS 1773: /* Don't bother outputting obvious no-ops, even without -O. 1774: This optimization is fast and doesn't interfere with debugging. 1775: Don't do this if the insn is in a delay slot, since this 1776: will cause an improper number of delay insns to be written. */ 1777: if (final_sequence == 0 1778: && prescan >= 0 1779: && GET_CODE (insn) == INSN && GET_CODE (body) == SET 1780: && GET_CODE (SET_SRC (body)) == REG 1781: && GET_CODE (SET_DEST (body)) == REG 1782: && REGNO (SET_SRC (body)) == REGNO (SET_DEST (body))) 1783: break; 1784: #endif 1785: 1786: #ifdef HAVE_cc0 1787: /* If this is a conditional branch, maybe modify it 1788: if the cc's are in a nonstandard state 1789: so that it accomplishes the same thing that it would 1790: do straightforwardly if the cc's were set up normally. */ 1791: 1792: if (cc_status.flags != 0 1793: && GET_CODE (insn) == JUMP_INSN 1794: && GET_CODE (body) == SET 1795: && SET_DEST (body) == pc_rtx 1796: && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE 1797: /* This is done during prescan; it is not done again 1798: in final scan when prescan has been done. */ 1799: && prescan >= 0) 1800: { 1801: /* This function may alter the contents of its argument 1802: and clear some of the cc_status.flags bits. 1803: It may also return 1 meaning condition now always true 1804: or -1 meaning condition now always false 1805: or 2 meaning condition nontrivial but altered. */ 1806: register int result = alter_cond (XEXP (SET_SRC (body), 0)); 1807: /* If condition now has fixed value, replace the IF_THEN_ELSE 1808: with its then-operand or its else-operand. */ 1809: if (result == 1) 1810: SET_SRC (body) = XEXP (SET_SRC (body), 1); 1811: if (result == -1) 1812: SET_SRC (body) = XEXP (SET_SRC (body), 2); 1813: 1814: /* The jump is now either unconditional or a no-op. 1815: If it has become a no-op, don't try to output it. 1816: (It would not be recognized.) */ 1817: if (SET_SRC (body) == pc_rtx) 1818: { 1819: PUT_CODE (insn, NOTE); 1820: NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; 1821: NOTE_SOURCE_FILE (insn) = 0; 1822: break; 1823: } 1824: else if (GET_CODE (SET_SRC (body)) == RETURN) 1825: /* Replace (set (pc) (return)) with (return). */ 1826: PATTERN (insn) = body = SET_SRC (body); 1827: 1828: /* Rerecognize the instruction if it has changed. */ 1829: if (result != 0) 1830: INSN_CODE (insn) = -1; 1831: } 1832: 1833: /* Make same adjustments to instructions that examine the 1834: condition codes without jumping (if this machine has them). */ 1835: 1836: if (cc_status.flags != 0 1837: && GET_CODE (body) == SET) 1838: { 1839: switch (GET_CODE (SET_SRC (body))) 1840: { 1841: case GTU: 1842: case GT: 1843: case LTU: 1844: case LT: 1845: case GEU: 1846: case GE: 1847: case LEU: 1848: case LE: 1849: case EQ: 1850: case NE: 1851: { 1852: register int result; 1853: if (XEXP (SET_SRC (body), 0) != cc0_rtx) 1854: break; 1855: result = alter_cond (SET_SRC (body)); 1856: if (result == 1) 1857: validate_change (insn, &SET_SRC (body), const_true_rtx, 0); 1858: else if (result == -1) 1859: validate_change (insn, &SET_SRC (body), const0_rtx, 0); 1860: else if (result == 2) 1861: INSN_CODE (insn) = -1; 1862: } 1863: } 1864: } 1865: #endif 1866: 1867: /* Do machine-specific peephole optimizations if desired. */ 1868: 1869: if (optimize && !flag_no_peephole && !nopeepholes) 1870: { 1871: rtx next = peephole (insn); 1872: /* When peepholing, if there were notes within the peephole, 1873: emit them before the peephole. */ 1874: if (next != 0 && next != NEXT_INSN (insn)) 1875: { 1876: rtx prev = PREV_INSN (insn); 1877: rtx note; 1878: 1879: for (note = NEXT_INSN (insn); note != next; 1880: note = NEXT_INSN (note)) 1881: final_scan_insn (note, file, optimize, prescan, nopeepholes); 1882: 1883: /* In case this is prescan, put the notes 1884: in proper position for later rescan. */ 1885: note = NEXT_INSN (insn); 1886: PREV_INSN (note) = prev; 1887: NEXT_INSN (prev) = note; 1888: NEXT_INSN (PREV_INSN (next)) = insn; 1889: PREV_INSN (insn) = PREV_INSN (next); 1890: NEXT_INSN (insn) = next; 1891: PREV_INSN (next) = insn; 1892: } 1893: 1894: /* PEEPHOLE might have changed this. */ 1895: body = PATTERN (insn); 1896: } 1897: 1898: /* Try to recognize the instruction. 1899: If successful, verify that the operands satisfy the 1900: constraints for the instruction. Crash if they don't, 1901: since `reload' should have changed them so that they do. */ 1902: 1903: insn_code_number = recog_memoized (insn); 1904: insn_extract (insn); 1905: for (i = 0; i < insn_n_operands[insn_code_number]; i++) 1906: { 1907: if (GET_CODE (recog_operand[i]) == SUBREG) 1908: recog_operand[i] = alter_subreg (recog_operand[i]); 1.1.1.6 ! root 1909: else if (GET_CODE (recog_operand[i]) == PLUS ! 1910: || GET_CODE (recog_operand[i]) == MULT) ! 1911: recog_operand[i] = walk_alter_subreg (recog_operand[i]); 1.1 root 1912: } 1913: 1.1.1.5 root 1914: for (i = 0; i < insn_n_dups[insn_code_number]; i++) 1915: { 1916: if (GET_CODE (*recog_dup_loc[i]) == SUBREG) 1917: *recog_dup_loc[i] = alter_subreg (*recog_dup_loc[i]); 1.1.1.6 ! root 1918: else if (GET_CODE (*recog_dup_loc[i]) == PLUS ! 1919: || GET_CODE (*recog_dup_loc[i]) == MULT) ! 1920: *recog_dup_loc[i] = walk_alter_subreg (*recog_dup_loc[i]); 1.1.1.5 root 1921: } 1922: 1.1 root 1923: #ifdef REGISTER_CONSTRAINTS 1924: if (! constrain_operands (insn_code_number, 1)) 1925: fatal_insn_not_found (insn); 1926: #endif 1927: 1928: /* Some target machines need to prescan each insn before 1929: it is output. */ 1930: 1931: #ifdef FINAL_PRESCAN_INSN 1932: FINAL_PRESCAN_INSN (insn, recog_operand, 1933: insn_n_operands[insn_code_number]); 1934: #endif 1935: 1936: #ifdef HAVE_cc0 1937: cc_prev_status = cc_status; 1938: 1939: /* Update `cc_status' for this instruction. 1940: The instruction's output routine may change it further. 1941: If the output routine for a jump insn needs to depend 1942: on the cc status, it should look at cc_prev_status. */ 1943: 1944: NOTICE_UPDATE_CC (body, insn); 1945: #endif 1946: 1947: debug_insn = insn; 1948: 1949: /* If the proper template needs to be chosen by some C code, 1950: run that code and get the real template. */ 1951: 1952: template = insn_template[insn_code_number]; 1953: if (template == 0) 1954: { 1955: template = (*insn_outfun[insn_code_number]) (recog_operand, insn); 1956: 1957: /* If the C code returns 0, it means that it is a jump insn 1958: which follows a deleted test insn, and that test insn 1959: needs to be reinserted. */ 1960: if (template == 0) 1961: { 1962: if (prev_nonnote_insn (insn) != last_ignored_compare) 1963: abort (); 1964: new_block = 0; 1965: return prev_nonnote_insn (insn); 1966: } 1967: } 1968: 1969: /* If the template is the string "#", it means that this insn must 1970: be split. */ 1971: if (template[0] == '#' && template[1] == '\0') 1972: { 1973: rtx new = try_split (body, insn, 0); 1974: 1975: /* If we didn't split the insn, go away. */ 1976: if (new == insn && PATTERN (new) == body) 1977: abort (); 1978: 1979: new_block = 0; 1980: return new; 1981: } 1982: 1983: if (prescan > 0) 1984: break; 1985: 1986: /* Output assembler code from the template. */ 1987: 1988: output_asm_insn (template, recog_operand); 1989: 1990: #if 0 1991: /* It's not at all clear why we did this and doing so interferes 1992: with tests we'd like to do to use REG_WAS_0 notes, so let's try 1993: with this out. */ 1994: 1995: /* Mark this insn as having been output. */ 1996: INSN_DELETED_P (insn) = 1; 1997: #endif 1998: 1999: debug_insn = 0; 2000: } 2001: } 2002: return NEXT_INSN (insn); 2003: } 2004: 2005: /* Output debugging info to the assembler file FILE 2006: based on the NOTE-insn INSN, assumed to be a line number. */ 2007: 2008: static void 2009: output_source_line (file, insn) 2010: FILE *file; 2011: rtx insn; 2012: { 2013: char ltext_label_name[100]; 2014: register char *filename = NOTE_SOURCE_FILE (insn); 2015: 1.1.1.6 ! root 2016: /* Remember filename for basic block profiling. ! 2017: Filenames are allocated on the permanent obstack ! 2018: or are passed in ARGV, so we don't have to save ! 2019: the string. */ ! 2020: ! 2021: if (profile_block_flag && last_filename != filename) ! 2022: bb_file_label_num = add_bb_string (filename, TRUE); ! 2023: ! 2024: last_filename = filename; 1.1 root 2025: last_linenum = NOTE_LINE_NUMBER (insn); 2026: 2027: if (write_symbols != NO_DEBUG) 2028: { 2029: #ifdef SDB_DEBUGGING_INFO 2030: if (write_symbols == SDB_DEBUG 2031: #if 0 /* People like having line numbers even in wrong file! */ 2032: /* COFF can't handle multiple source files--lose, lose. */ 2033: && !strcmp (filename, main_input_filename) 2034: #endif 2035: /* COFF relative line numbers must be positive. */ 2036: && last_linenum > sdb_begin_function_line) 2037: { 2038: #ifdef ASM_OUTPUT_SOURCE_LINE 2039: ASM_OUTPUT_SOURCE_LINE (file, last_linenum); 2040: #else 2041: fprintf (file, "\t.ln\t%d\n", 2042: ((sdb_begin_function_line > -1) 2043: ? last_linenum - sdb_begin_function_line : 1)); 2044: #endif 2045: } 2046: #endif 2047: 1.1.1.2 root 2048: #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO) 2049: if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG) 1.1.1.4 root 2050: dbxout_source_line (file, filename, NOTE_LINE_NUMBER (insn)); 1.1.1.2 root 2051: #endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */ 1.1 root 2052: 2053: #ifdef DWARF_DEBUGGING_INFO 2054: if (write_symbols == DWARF_DEBUG) 2055: dwarfout_line (filename, NOTE_LINE_NUMBER (insn)); 2056: #endif 2057: } 2058: } 2059: 2060: /* If X is a SUBREG, replace it with a REG or a MEM, 2061: based on the thing it is a subreg of. */ 2062: 2063: rtx 2064: alter_subreg (x) 2065: register rtx x; 2066: { 2067: register rtx y = SUBREG_REG (x); 2068: if (GET_CODE (y) == SUBREG) 2069: y = alter_subreg (y); 2070: 2071: if (GET_CODE (y) == REG) 2072: { 2073: /* If the containing reg really gets a hard reg, so do we. */ 2074: PUT_CODE (x, REG); 2075: REGNO (x) = REGNO (y) + SUBREG_WORD (x); 2076: } 2077: else if (GET_CODE (y) == MEM) 2078: { 2079: register int offset = SUBREG_WORD (x) * UNITS_PER_WORD; 2080: #if BYTES_BIG_ENDIAN 2081: offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))) 2082: - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (y)))); 2083: #endif 2084: PUT_CODE (x, MEM); 2085: MEM_VOLATILE_P (x) = MEM_VOLATILE_P (y); 2086: XEXP (x, 0) = plus_constant (XEXP (y, 0), offset); 2087: } 2088: 2089: return x; 2090: } 2091: 2092: /* Do alter_subreg on all the SUBREGs contained in X. */ 2093: 2094: static rtx 2095: walk_alter_subreg (x) 2096: rtx x; 2097: { 2098: switch (GET_CODE (x)) 2099: { 2100: case PLUS: 2101: case MULT: 2102: XEXP (x, 0) = walk_alter_subreg (XEXP (x, 0)); 2103: XEXP (x, 1) = walk_alter_subreg (XEXP (x, 1)); 2104: break; 2105: 2106: case MEM: 2107: XEXP (x, 0) = walk_alter_subreg (XEXP (x, 0)); 2108: break; 2109: 2110: case SUBREG: 2111: return alter_subreg (x); 2112: } 2113: 2114: return x; 2115: } 2116: 2117: #ifdef HAVE_cc0 2118: 2119: /* Given BODY, the body of a jump instruction, alter the jump condition 2120: as required by the bits that are set in cc_status.flags. 2121: Not all of the bits there can be handled at this level in all cases. 2122: 2123: The value is normally 0. 2124: 1 means that the condition has become always true. 2125: -1 means that the condition has become always false. 2126: 2 means that COND has been altered. */ 2127: 2128: static int 2129: alter_cond (cond) 2130: register rtx cond; 2131: { 2132: int value = 0; 2133: 2134: if (cc_status.flags & CC_REVERSED) 2135: { 2136: value = 2; 2137: PUT_CODE (cond, swap_condition (GET_CODE (cond))); 2138: } 2139: 2140: if (cc_status.flags & CC_INVERTED) 2141: { 2142: value = 2; 2143: PUT_CODE (cond, reverse_condition (GET_CODE (cond))); 2144: } 2145: 2146: if (cc_status.flags & CC_NOT_POSITIVE) 2147: switch (GET_CODE (cond)) 2148: { 2149: case LE: 2150: case LEU: 2151: case GEU: 2152: /* Jump becomes unconditional. */ 2153: return 1; 2154: 2155: case GT: 2156: case GTU: 2157: case LTU: 2158: /* Jump becomes no-op. */ 2159: return -1; 2160: 2161: case GE: 2162: PUT_CODE (cond, EQ); 2163: value = 2; 2164: break; 2165: 2166: case LT: 2167: PUT_CODE (cond, NE); 2168: value = 2; 2169: break; 2170: } 2171: 2172: if (cc_status.flags & CC_NOT_NEGATIVE) 2173: switch (GET_CODE (cond)) 2174: { 2175: case GE: 2176: case GEU: 2177: /* Jump becomes unconditional. */ 2178: return 1; 2179: 2180: case LT: 2181: case LTU: 2182: /* Jump becomes no-op. */ 2183: return -1; 2184: 2185: case LE: 2186: case LEU: 2187: PUT_CODE (cond, EQ); 2188: value = 2; 2189: break; 2190: 2191: case GT: 2192: case GTU: 2193: PUT_CODE (cond, NE); 2194: value = 2; 2195: break; 2196: } 2197: 2198: if (cc_status.flags & CC_NO_OVERFLOW) 2199: switch (GET_CODE (cond)) 2200: { 2201: case GEU: 2202: /* Jump becomes unconditional. */ 2203: return 1; 2204: 2205: case LEU: 2206: PUT_CODE (cond, EQ); 2207: value = 2; 2208: break; 2209: 2210: case GTU: 2211: PUT_CODE (cond, NE); 2212: value = 2; 2213: break; 2214: 2215: case LTU: 2216: /* Jump becomes no-op. */ 2217: return -1; 2218: } 2219: 2220: if (cc_status.flags & (CC_Z_IN_NOT_N | CC_Z_IN_N)) 2221: switch (GET_CODE (cond)) 2222: { 2223: case LE: 2224: case LEU: 2225: case GE: 2226: case GEU: 2227: case LT: 2228: case LTU: 2229: case GT: 2230: case GTU: 2231: abort (); 2232: 2233: case NE: 2234: PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? GE : LT); 2235: value = 2; 2236: break; 2237: 2238: case EQ: 2239: PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? LT : GE); 2240: value = 2; 2241: break; 2242: } 1.1.1.4 root 2243: 2244: if (cc_status.flags & CC_NOT_SIGNED) 2245: /* The flags are valid if signed condition operators are converted 2246: to unsigned. */ 2247: switch (GET_CODE (cond)) 2248: { 2249: case LE: 2250: PUT_CODE (cond, LEU); 2251: value = 2; 2252: break; 2253: 2254: case LT: 2255: PUT_CODE (cond, LTU); 2256: value = 2; 2257: break; 2258: 2259: case GT: 2260: PUT_CODE (cond, GTU); 2261: value = 2; 2262: break; 2263: 2264: case GE: 2265: PUT_CODE (cond, GEU); 2266: value = 2; 2267: break; 2268: } 2269: 1.1 root 2270: return value; 2271: } 2272: #endif 2273: 2274: /* Report inconsistency between the assembler template and the operands. 2275: In an `asm', it's the user's fault; otherwise, the compiler's fault. */ 2276: 2277: void 2278: output_operand_lossage (str) 2279: char *str; 2280: { 2281: if (this_is_asm_operands) 2282: error_for_asm (this_is_asm_operands, "invalid `asm': %s", str); 2283: else 2284: abort (); 2285: } 2286: 2287: /* Output of assembler code from a template, and its subroutines. */ 2288: 2289: /* Output text from TEMPLATE to the assembler output file, 2290: obeying %-directions to substitute operands taken from 2291: the vector OPERANDS. 2292: 2293: %N (for N a digit) means print operand N in usual manner. 2294: %lN means require operand N to be a CODE_LABEL or LABEL_REF 2295: and print the label name with no punctuation. 2296: %cN means require operand N to be a constant 2297: and print the constant expression with no punctuation. 2298: %aN means expect operand N to be a memory address 2299: (not a memory reference!) and print a reference 2300: to that address. 2301: %nN means expect operand N to be a constant 2302: and print a constant expression for minus the value 2303: of the operand, with no other punctuation. */ 2304: 2305: void 2306: output_asm_insn (template, operands) 2307: char *template; 2308: rtx *operands; 2309: { 2310: register char *p; 1.1.1.6 ! root 2311: register int c, i; 1.1 root 2312: 2313: /* An insn may return a null string template 2314: in a case where no assembler code is needed. */ 2315: if (*template == 0) 2316: return; 2317: 2318: p = template; 2319: putc ('\t', asm_out_file); 2320: 2321: #ifdef ASM_OUTPUT_OPCODE 2322: ASM_OUTPUT_OPCODE (asm_out_file, p); 2323: #endif 2324: 2325: while (c = *p++) 1.1.1.6 ! root 2326: switch (c) ! 2327: { 1.1 root 2328: #ifdef ASM_OUTPUT_OPCODE 1.1.1.6 ! root 2329: case '\n': 1.1 root 2330: putc (c, asm_out_file); 1.1.1.6 ! root 2331: while ((c = *p) == '\t') ! 2332: { ! 2333: putc (c, asm_out_file); ! 2334: p++; ! 2335: } ! 2336: ASM_OUTPUT_OPCODE (asm_out_file, p); ! 2337: break; ! 2338: #endif ! 2339: ! 2340: #ifdef ASSEMBLER_DIALECT ! 2341: case '{': ! 2342: /* If we want the first dialect, do nothing. Otherwise, skip ! 2343: DIALECT_NUMBER of strings ending with '|'. */ ! 2344: for (i = 0; i < dialect_number; i++) ! 2345: { ! 2346: while (*p && *p++ != '|') ! 2347: ; ! 2348: ! 2349: if (*p == '|') 1.1.1.4 root 2350: p++; 1.1.1.6 ! root 2351: } ! 2352: break; 1.1 root 2353: 1.1.1.6 ! root 2354: case '|': ! 2355: /* Skip to close brace. */ ! 2356: while (*p && *p++ != '}') ! 2357: ; ! 2358: break; ! 2359: ! 2360: case '}': ! 2361: break; ! 2362: #endif ! 2363: ! 2364: case '%': ! 2365: /* %% outputs a single %. */ ! 2366: if (*p == '%') ! 2367: { ! 2368: p++; ! 2369: putc (c, asm_out_file); ! 2370: } ! 2371: /* %= outputs a number which is unique to each insn in the entire ! 2372: compilation. This is useful for making local labels that are ! 2373: referred to more than once in a given insn. */ ! 2374: else if (*p == '=') ! 2375: { ! 2376: p++; ! 2377: fprintf (asm_out_file, "%d", insn_counter); ! 2378: } ! 2379: /* % followed by a letter and some digits ! 2380: outputs an operand in a special way depending on the letter. ! 2381: Letters `acln' are implemented directly. ! 2382: Other letters are passed to `output_operand' so that ! 2383: the PRINT_OPERAND macro can define them. */ ! 2384: else if ((*p >= 'a' && *p <= 'z') ! 2385: || (*p >= 'A' && *p <= 'Z')) ! 2386: { ! 2387: int letter = *p++; ! 2388: c = atoi (p); ! 2389: ! 2390: if (! (*p >= '0' && *p <= '9')) ! 2391: output_operand_lossage ("operand number missing after %-letter"); ! 2392: else if (this_is_asm_operands && c >= (unsigned) insn_noperands) ! 2393: output_operand_lossage ("operand number out of range"); ! 2394: else if (letter == 'l') ! 2395: output_asm_label (operands[c]); ! 2396: else if (letter == 'a') ! 2397: output_address (operands[c]); ! 2398: else if (letter == 'c') ! 2399: { ! 2400: if (CONSTANT_ADDRESS_P (operands[c])) ! 2401: output_addr_const (asm_out_file, operands[c]); ! 2402: else ! 2403: output_operand (operands[c], 'c'); ! 2404: } ! 2405: else if (letter == 'n') ! 2406: { ! 2407: if (GET_CODE (operands[c]) == CONST_INT) ! 2408: fprintf (asm_out_file, 1.1.1.4 root 2409: #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT 1.1.1.6 ! root 2410: "%d", 1.1.1.4 root 2411: #else 1.1.1.6 ! root 2412: "%ld", 1.1.1.4 root 2413: #endif 1.1.1.6 ! root 2414: - INTVAL (operands[c])); ! 2415: else ! 2416: { ! 2417: putc ('-', asm_out_file); ! 2418: output_addr_const (asm_out_file, operands[c]); ! 2419: } ! 2420: } ! 2421: else ! 2422: output_operand (operands[c], letter); ! 2423: ! 2424: while ((c = *p) >= '0' && c <= '9') p++; ! 2425: } ! 2426: /* % followed by a digit outputs an operand the default way. */ ! 2427: else if (*p >= '0' && *p <= '9') ! 2428: { ! 2429: c = atoi (p); ! 2430: if (this_is_asm_operands && c >= (unsigned) insn_noperands) ! 2431: output_operand_lossage ("operand number out of range"); ! 2432: else ! 2433: output_operand (operands[c], 0); ! 2434: while ((c = *p) >= '0' && c <= '9') p++; ! 2435: } ! 2436: /* % followed by punctuation: output something for that ! 2437: punctuation character alone, with no operand. ! 2438: The PRINT_OPERAND macro decides what is actually done. */ 1.1 root 2439: #ifdef PRINT_OPERAND_PUNCT_VALID_P 1.1.1.6 ! root 2440: else if (PRINT_OPERAND_PUNCT_VALID_P (*p)) ! 2441: output_operand (NULL_RTX, *p++); 1.1 root 2442: #endif 1.1.1.6 ! root 2443: else ! 2444: output_operand_lossage ("invalid %%-code"); ! 2445: break; ! 2446: ! 2447: default: ! 2448: putc (c, asm_out_file); ! 2449: } 1.1 root 2450: 2451: if (flag_print_asm_name) 2452: { 2453: /* Annotate the assembly with a comment describing the pattern and 2454: alternative used. */ 2455: if (debug_insn) 2456: { 2457: register int num = INSN_CODE (debug_insn); 2458: fprintf (asm_out_file, " %s %d %s", 2459: ASM_COMMENT_START, INSN_UID (debug_insn), insn_name[num]); 2460: if (insn_n_alternatives[num] > 1) 2461: fprintf (asm_out_file, "/%d", which_alternative + 1); 2462: 2463: /* Clear this so only the first assembler insn 2464: of any rtl insn will get the special comment for -dp. */ 2465: debug_insn = 0; 2466: } 2467: } 2468: 2469: putc ('\n', asm_out_file); 2470: } 2471: 2472: /* Output a LABEL_REF, or a bare CODE_LABEL, as an assembler symbol. */ 2473: 2474: void 2475: output_asm_label (x) 2476: rtx x; 2477: { 2478: char buf[256]; 2479: 2480: if (GET_CODE (x) == LABEL_REF) 2481: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0))); 2482: else if (GET_CODE (x) == CODE_LABEL) 2483: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x)); 2484: else 2485: output_operand_lossage ("`%l' operand isn't a label"); 2486: 2487: assemble_name (asm_out_file, buf); 2488: } 2489: 2490: /* Print operand X using machine-dependent assembler syntax. 2491: The macro PRINT_OPERAND is defined just to control this function. 2492: CODE is a non-digit that preceded the operand-number in the % spec, 2493: such as 'z' if the spec was `%z3'. CODE is 0 if there was no char 2494: between the % and the digits. 2495: When CODE is a non-letter, X is 0. 2496: 2497: The meanings of the letters are machine-dependent and controlled 2498: by PRINT_OPERAND. */ 2499: 2500: static void 2501: output_operand (x, code) 2502: rtx x; 2503: int code; 2504: { 2505: if (x && GET_CODE (x) == SUBREG) 2506: x = alter_subreg (x); 1.1.1.4 root 2507: 2508: /* If X is a pseudo-register, abort now rather than writing trash to the 2509: assembler file. */ 2510: 2511: if (x && GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER) 2512: abort (); 2513: 1.1 root 2514: PRINT_OPERAND (asm_out_file, x, code); 2515: } 2516: 2517: /* Print a memory reference operand for address X 2518: using machine-dependent assembler syntax. 2519: The macro PRINT_OPERAND_ADDRESS exists just to control this function. */ 2520: 2521: void 2522: output_address (x) 2523: rtx x; 2524: { 2525: walk_alter_subreg (x); 2526: PRINT_OPERAND_ADDRESS (asm_out_file, x); 2527: } 2528: 2529: /* Print an integer constant expression in assembler syntax. 2530: Addition and subtraction are the only arithmetic 2531: that may appear in these expressions. */ 2532: 2533: void 2534: output_addr_const (file, x) 2535: FILE *file; 2536: rtx x; 2537: { 2538: char buf[256]; 2539: 2540: restart: 2541: switch (GET_CODE (x)) 2542: { 2543: case PC: 2544: if (flag_pic) 2545: putc ('.', file); 2546: else 2547: abort (); 2548: break; 2549: 2550: case SYMBOL_REF: 2551: assemble_name (file, XSTR (x, 0)); 2552: break; 2553: 2554: case LABEL_REF: 2555: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0))); 1.1.1.4 root 2556: assemble_name (file, buf); 1.1 root 2557: break; 2558: 2559: case CODE_LABEL: 2560: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x)); 1.1.1.4 root 2561: assemble_name (file, buf); 1.1 root 2562: break; 2563: 2564: case CONST_INT: 1.1.1.4 root 2565: fprintf (file, 2566: #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT 2567: "%d", 2568: #else 2569: "%ld", 2570: #endif 2571: INTVAL (x)); 1.1 root 2572: break; 2573: 2574: case CONST: 2575: /* This used to output parentheses around the expression, 2576: but that does not work on the 386 (either ATT or BSD assembler). */ 2577: output_addr_const (file, XEXP (x, 0)); 2578: break; 2579: 2580: case CONST_DOUBLE: 2581: if (GET_MODE (x) == VOIDmode) 2582: { 1.1.1.4 root 2583: /* We can use %d if the number is one word and positive. */ 1.1.1.5 root 2584: if (CONST_DOUBLE_HIGH (x)) 1.1.1.4 root 2585: fprintf (file, 2586: #if HOST_BITS_PER_WIDE_INT == 64 2587: #if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT 1.1.1.5 root 2588: "0x%lx%016lx", 1.1.1.4 root 2589: #else 1.1.1.5 root 2590: "0x%x%016x", 1.1.1.4 root 2591: #endif 2592: #else 2593: #if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT 1.1.1.5 root 2594: "0x%lx%08lx", 1.1.1.4 root 2595: #else 1.1.1.5 root 2596: "0x%x%08x", 1.1.1.4 root 2597: #endif 2598: #endif 1.1 root 2599: CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x)); 1.1.1.5 root 2600: else if (CONST_DOUBLE_LOW (x) < 0) 2601: fprintf (file, 2602: #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT 2603: "0x%x", 2604: #else 2605: "0x%lx", 2606: #endif 2607: CONST_DOUBLE_LOW (x)); 1.1 root 2608: else 1.1.1.4 root 2609: fprintf (file, 2610: #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT 2611: "%d", 2612: #else 2613: "%ld", 2614: #endif 2615: CONST_DOUBLE_LOW (x)); 1.1 root 2616: } 2617: else 2618: /* We can't handle floating point constants; 2619: PRINT_OPERAND must handle them. */ 2620: output_operand_lossage ("floating constant misused"); 2621: break; 2622: 2623: case PLUS: 2624: /* Some assemblers need integer constants to appear last (eg masm). */ 2625: if (GET_CODE (XEXP (x, 0)) == CONST_INT) 2626: { 2627: output_addr_const (file, XEXP (x, 1)); 2628: if (INTVAL (XEXP (x, 0)) >= 0) 2629: fprintf (file, "+"); 2630: output_addr_const (file, XEXP (x, 0)); 2631: } 2632: else 2633: { 2634: output_addr_const (file, XEXP (x, 0)); 2635: if (INTVAL (XEXP (x, 1)) >= 0) 2636: fprintf (file, "+"); 2637: output_addr_const (file, XEXP (x, 1)); 2638: } 2639: break; 2640: 2641: case MINUS: 1.1.1.4 root 2642: /* Avoid outputting things like x-x or x+5-x, 2643: since some assemblers can't handle that. */ 2644: x = simplify_subtraction (x); 2645: if (GET_CODE (x) != MINUS) 2646: goto restart; 2647: 1.1 root 2648: output_addr_const (file, XEXP (x, 0)); 2649: fprintf (file, "-"); 1.1.1.4 root 2650: if (GET_CODE (XEXP (x, 1)) == CONST_INT 2651: && INTVAL (XEXP (x, 1)) < 0) 2652: { 2653: fprintf (file, ASM_OPEN_PAREN); 2654: output_addr_const (file, XEXP (x, 1)); 2655: fprintf (file, ASM_CLOSE_PAREN); 2656: } 2657: else 2658: output_addr_const (file, XEXP (x, 1)); 2659: break; 2660: 2661: case ZERO_EXTEND: 2662: case SIGN_EXTEND: 2663: output_addr_const (file, XEXP (x, 0)); 1.1 root 2664: break; 2665: 2666: default: 2667: output_operand_lossage ("invalid expression as operand"); 2668: } 2669: } 2670: 2671: /* A poor man's fprintf, with the added features of %I, %R, %L, and %U. 2672: %R prints the value of REGISTER_PREFIX. 2673: %L prints the value of LOCAL_LABEL_PREFIX. 2674: %U prints the value of USER_LABEL_PREFIX. 2675: %I prints the value of IMMEDIATE_PREFIX. 1.1.1.2 root 2676: %O runs ASM_OUTPUT_OPCODE to transform what follows in the string. 1.1.1.6 ! root 2677: Also supported are %d, %x, %s, %e, %f, %g and %%. ! 2678: ! 2679: We handle alternate assembler dialects here, just like output_asm_insn. */ 1.1 root 2680: 2681: void 2682: asm_fprintf (va_alist) 2683: va_dcl 2684: { 2685: va_list argptr; 2686: FILE *file; 2687: char buf[10]; 2688: char *p, *q, c; 1.1.1.6 ! root 2689: int i; 1.1 root 2690: 2691: va_start (argptr); 2692: 2693: file = va_arg (argptr, FILE *); 2694: p = va_arg (argptr, char *); 2695: buf[0] = '%'; 2696: 2697: while (c = *p++) 2698: switch (c) 2699: { 1.1.1.6 ! root 2700: #ifdef ASSEMBLER_DIALECT ! 2701: case '{': ! 2702: /* If we want the first dialect, do nothing. Otherwise, skip ! 2703: DIALECT_NUMBER of strings ending with '|'. */ ! 2704: for (i = 0; i < dialect_number; i++) ! 2705: { ! 2706: while (*p && *p++ != '|') ! 2707: ; ! 2708: ! 2709: if (*p == '|') ! 2710: p++; ! 2711: } ! 2712: break; ! 2713: ! 2714: case '|': ! 2715: /* Skip to close brace. */ ! 2716: while (*p && *p++ != '}') ! 2717: ; ! 2718: break; ! 2719: ! 2720: case '}': ! 2721: break; ! 2722: #endif ! 2723: 1.1 root 2724: case '%': 2725: c = *p++; 2726: q = &buf[1]; 2727: while ((c >= '0' && c <= '9') || c == '.') 2728: { 2729: *q++ = c; 2730: c = *p++; 2731: } 2732: switch (c) 2733: { 2734: case '%': 2735: fprintf (file, "%%"); 2736: break; 2737: 2738: case 'd': case 'i': case 'u': 2739: case 'x': case 'p': case 'X': 2740: case 'o': 2741: *q++ = c; 2742: *q = 0; 2743: fprintf (file, buf, va_arg (argptr, int)); 2744: break; 2745: 1.1.1.6 ! root 2746: case 'w': ! 2747: /* This is a prefix to the 'd', 'i', 'u', 'x', 'p', and 'X' cases, ! 2748: but we do not check for those cases. It means that the value ! 2749: is a HOST_WIDE_INT, which may be either `int' or `long'. */ ! 2750: ! 2751: #if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT ! 2752: *q++ = 'l'; ! 2753: #endif ! 2754: ! 2755: *q++ = *p++; ! 2756: *q = 0; ! 2757: fprintf (file, buf, va_arg (argptr, HOST_WIDE_INT)); ! 2758: break; ! 2759: ! 2760: case 'l': ! 2761: *q++ = c; ! 2762: *q++ = *p++; ! 2763: *q = 0; ! 2764: fprintf (file, buf, va_arg (argptr, long)); ! 2765: break; ! 2766: 1.1 root 2767: case 'e': 2768: case 'f': 2769: case 'g': 2770: *q++ = c; 2771: *q = 0; 2772: fprintf (file, buf, va_arg (argptr, double)); 2773: break; 2774: 2775: case 's': 2776: *q++ = c; 2777: *q = 0; 2778: fprintf (file, buf, va_arg (argptr, char *)); 2779: break; 2780: 1.1.1.2 root 2781: case 'O': 2782: #ifdef ASM_OUTPUT_OPCODE 2783: ASM_OUTPUT_OPCODE (asm_out_file, p); 2784: #endif 2785: break; 2786: 1.1 root 2787: case 'R': 2788: #ifdef REGISTER_PREFIX 2789: fprintf (file, "%s", REGISTER_PREFIX); 2790: #endif 2791: break; 2792: 2793: case 'I': 2794: #ifdef IMMEDIATE_PREFIX 2795: fprintf (file, "%s", IMMEDIATE_PREFIX); 2796: #endif 2797: break; 2798: 2799: case 'L': 2800: #ifdef LOCAL_LABEL_PREFIX 2801: fprintf (file, "%s", LOCAL_LABEL_PREFIX); 2802: #endif 2803: break; 2804: 2805: case 'U': 2806: #ifdef USER_LABEL_PREFIX 2807: fprintf (file, "%s", USER_LABEL_PREFIX); 2808: #endif 2809: break; 2810: 2811: default: 2812: abort (); 2813: } 2814: break; 2815: 2816: default: 2817: fputc (c, file); 2818: } 2819: } 2820: 2821: /* Split up a CONST_DOUBLE or integer constant rtx 2822: into two rtx's for single words, 2823: storing in *FIRST the word that comes first in memory in the target 2824: and in *SECOND the other. */ 2825: 2826: void 2827: split_double (value, first, second) 2828: rtx value; 2829: rtx *first, *second; 2830: { 2831: if (GET_CODE (value) == CONST_INT) 2832: { 2833: /* The rule for using CONST_INT for a wider mode 2834: is that we regard the value as signed. 2835: So sign-extend it. */ 2836: rtx high = (INTVAL (value) < 0 ? constm1_rtx : const0_rtx); 2837: #if WORDS_BIG_ENDIAN 2838: *first = high; 2839: *second = value; 2840: #else 2841: *first = value; 2842: *second = high; 2843: #endif 2844: } 2845: else if (GET_CODE (value) != CONST_DOUBLE) 2846: { 2847: #if WORDS_BIG_ENDIAN 2848: *first = const0_rtx; 2849: *second = value; 2850: #else 2851: *first = value; 2852: *second = const0_rtx; 2853: #endif 2854: } 2855: else if (GET_MODE (value) == VOIDmode 2856: /* This is the old way we did CONST_DOUBLE integers. */ 2857: || GET_MODE_CLASS (GET_MODE (value)) == MODE_INT) 2858: { 2859: /* In an integer, the words are defined as most and least significant. 2860: So order them by the target's convention. */ 2861: #if WORDS_BIG_ENDIAN 1.1.1.4 root 2862: *first = GEN_INT (CONST_DOUBLE_HIGH (value)); 2863: *second = GEN_INT (CONST_DOUBLE_LOW (value)); 1.1 root 2864: #else 1.1.1.4 root 2865: *first = GEN_INT (CONST_DOUBLE_LOW (value)); 2866: *second = GEN_INT (CONST_DOUBLE_HIGH (value)); 1.1 root 2867: #endif 2868: } 2869: else 2870: { 1.1.1.5 root 2871: #ifdef REAL_ARITHMETIC 2872: REAL_VALUE_TYPE r; HOST_WIDE_INT l[2]; 2873: REAL_VALUE_FROM_CONST_DOUBLE (r, value); 2874: REAL_VALUE_TO_TARGET_DOUBLE (r, l); 2875: *first = GEN_INT (l[0]); 2876: *second = GEN_INT (l[1]); 2877: #else 1.1 root 2878: if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT 1.1.1.4 root 2879: || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD) 1.1 root 2880: && ! flag_pretend_float) 2881: abort (); 2882: 2883: #if defined (HOST_WORDS_BIG_ENDIAN) == WORDS_BIG_ENDIAN 2884: /* Host and target agree => no need to swap. */ 1.1.1.4 root 2885: *first = GEN_INT (CONST_DOUBLE_LOW (value)); 2886: *second = GEN_INT (CONST_DOUBLE_HIGH (value)); 1.1 root 2887: #else 1.1.1.4 root 2888: *second = GEN_INT (CONST_DOUBLE_LOW (value)); 2889: *first = GEN_INT (CONST_DOUBLE_HIGH (value)); 1.1 root 2890: #endif 1.1.1.5 root 2891: #endif /* no REAL_ARITHMETIC */ 1.1 root 2892: } 2893: } 2894: 2895: /* Return nonzero if this function has no function calls. */ 2896: 2897: int 2898: leaf_function_p () 2899: { 2900: rtx insn; 2901: 2902: if (profile_flag || profile_block_flag) 2903: return 0; 2904: 2905: for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) 2906: { 2907: if (GET_CODE (insn) == CALL_INSN) 2908: return 0; 2909: if (GET_CODE (insn) == INSN 2910: && GET_CODE (PATTERN (insn)) == SEQUENCE 2911: && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == CALL_INSN) 2912: return 0; 2913: } 2914: for (insn = current_function_epilogue_delay_list; insn; insn = XEXP (insn, 1)) 2915: { 2916: if (GET_CODE (XEXP (insn, 0)) == CALL_INSN) 2917: return 0; 2918: if (GET_CODE (XEXP (insn, 0)) == INSN 2919: && GET_CODE (PATTERN (XEXP (insn, 0))) == SEQUENCE 2920: && GET_CODE (XVECEXP (PATTERN (XEXP (insn, 0)), 0, 0)) == CALL_INSN) 2921: return 0; 2922: } 2923: 2924: return 1; 2925: } 2926: 2927: /* On some machines, a function with no call insns 2928: can run faster if it doesn't create its own register window. 2929: When output, the leaf function should use only the "output" 2930: registers. Ordinarily, the function would be compiled to use 2931: the "input" registers to find its arguments; it is a candidate 2932: for leaf treatment if it uses only the "input" registers. 2933: Leaf function treatment means renumbering so the function 2934: uses the "output" registers instead. */ 2935: 2936: #ifdef LEAF_REGISTERS 2937: 2938: static char permitted_reg_in_leaf_functions[] = LEAF_REGISTERS; 2939: 2940: /* Return 1 if this function uses only the registers that can be 2941: safely renumbered. */ 2942: 2943: int 2944: only_leaf_regs_used () 2945: { 2946: int i; 2947: 2948: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 2949: { 1.1.1.4 root 2950: if ((regs_ever_live[i] || global_regs[i]) 2951: && ! permitted_reg_in_leaf_functions[i]) 1.1 root 2952: return 0; 2953: } 2954: return 1; 2955: } 2956: 2957: /* Scan all instructions and renumber all registers into those 2958: available in leaf functions. */ 2959: 2960: static void 2961: leaf_renumber_regs (first) 2962: rtx first; 2963: { 2964: rtx insn; 2965: 2966: /* Renumber only the actual patterns. 2967: The reg-notes can contain frame pointer refs, 2968: and renumbering them could crash, and should not be needed. */ 2969: for (insn = first; insn; insn = NEXT_INSN (insn)) 2970: if (GET_RTX_CLASS (GET_CODE (insn)) == 'i') 2971: leaf_renumber_regs_insn (PATTERN (insn)); 2972: for (insn = current_function_epilogue_delay_list; insn; insn = XEXP (insn, 1)) 2973: if (GET_RTX_CLASS (GET_CODE (XEXP (insn, 0))) == 'i') 2974: leaf_renumber_regs_insn (PATTERN (XEXP (insn, 0))); 2975: } 2976: 2977: /* Scan IN_RTX and its subexpressions, and renumber all regs into those 2978: available in leaf functions. */ 2979: 2980: void 2981: leaf_renumber_regs_insn (in_rtx) 2982: register rtx in_rtx; 2983: { 2984: register int i, j; 2985: register char *format_ptr; 2986: 2987: if (in_rtx == 0) 2988: return; 2989: 2990: /* Renumber all input-registers into output-registers. 2991: renumbered_regs would be 1 for an output-register; 2992: they */ 2993: 2994: if (GET_CODE (in_rtx) == REG) 2995: { 2996: int newreg; 2997: 2998: /* Don't renumber the same reg twice. */ 2999: if (in_rtx->used) 3000: return; 3001: 3002: newreg = REGNO (in_rtx); 1.1.1.2 root 3003: /* Don't try to renumber pseudo regs. It is possible for a pseudo reg 1.1 root 3004: to reach here as part of a REG_NOTE. */ 3005: if (newreg >= FIRST_PSEUDO_REGISTER) 3006: { 3007: in_rtx->used = 1; 3008: return; 3009: } 3010: newreg = LEAF_REG_REMAP (newreg); 3011: if (newreg < 0) 3012: abort (); 3013: regs_ever_live[REGNO (in_rtx)] = 0; 3014: regs_ever_live[newreg] = 1; 3015: REGNO (in_rtx) = newreg; 3016: in_rtx->used = 1; 3017: } 3018: 3019: if (GET_RTX_CLASS (GET_CODE (in_rtx)) == 'i') 3020: { 3021: /* Inside a SEQUENCE, we find insns. 3022: Renumber just the patterns of these insns, 3023: just as we do for the top-level insns. */ 3024: leaf_renumber_regs_insn (PATTERN (in_rtx)); 3025: return; 3026: } 3027: 3028: format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx)); 3029: 3030: for (i = 0; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++) 3031: switch (*format_ptr++) 3032: { 3033: case 'e': 3034: leaf_renumber_regs_insn (XEXP (in_rtx, i)); 3035: break; 3036: 3037: case 'E': 3038: if (NULL != XVEC (in_rtx, i)) 3039: { 3040: for (j = 0; j < XVECLEN (in_rtx, i); j++) 3041: leaf_renumber_regs_insn (XVECEXP (in_rtx, i, j)); 3042: } 3043: break; 3044: 3045: case 'S': 3046: case 's': 3047: case '0': 3048: case 'i': 1.1.1.4 root 3049: case 'w': 1.1 root 3050: case 'n': 3051: case 'u': 3052: break; 3053: 3054: default: 3055: abort (); 3056: } 3057: } 3058: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.