|
|
1.1 root 1: /* Convert RTL to assembler code and output it, for GNU compiler. 1.1.1.13! root 2: Copyright (C) 1987, 1988, 1989 Free Software Foundation, Inc. 1.1 root 3: 4: This file is part of GNU CC. 5: 1.1.1.13! root 6: GNU CC is free software; you can redistribute it and/or modify ! 7: it under the terms of the GNU General Public License as published by ! 8: the Free Software Foundation; either version 1, or (at your option) ! 9: any later version. ! 10: 1.1 root 11: GNU CC is distributed in the hope that it will be useful, 1.1.1.13! root 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. */ 1.1 root 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: 1.1.1.2 root 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'. 1.1 root 29: 30: Some optimizations are also done at this level. 31: Move instructions that were made unnecessary by good register allocation 1.1.1.2 root 32: are detected and omitted from the output. (Though most of these 33: are removed by the last jump pass.) 34: 1.1 root 35: Instructions to set the condition codes are omitted when it can be 36: seen that the condition codes already had the desired values. 1.1.1.2 root 37: 1.1 root 38: In some cases it is sufficient if the inherited condition codes 39: have related values, but this may require the following insn 40: (the one that tests the condition codes) to be modified. 41: 42: The code for the function prologue and epilogue are generated 43: directly as assembler code by the macros FUNCTION_PROLOGUE and 44: FUNCTION_EPILOGUE. Those instructions never exist as rtl. */ 45: 46: #include <stdio.h> 47: #include "config.h" 48: #include "rtl.h" 49: #include "regs.h" 50: #include "insn-config.h" 51: #include "recog.h" 52: #include "conditions.h" 1.1.1.2 root 53: #include "gdbfiles.h" 1.1.1.4 root 54: #include "flags.h" 1.1.1.12 root 55: #include "real.h" 1.1.1.2 root 56: 1.1.1.3 root 57: /* Get N_SLINE and N_SOL from stab.h if we can expect the file to exist. */ 1.1.1.4 root 58: #ifdef DBX_DEBUGGING_INFO 1.1.1.12 root 59: #ifdef USG 60: #include "stab.h" /* If doing DBX on sysV, use our own stab.h. */ 61: #else 62: #include <stab.h> /* On BSD, use the system's stab.h. */ 63: #endif /* not USG */ 64: #endif /* DBX_DEBUGGING_INFO */ 1.1.1.3 root 65: 1.1.1.2 root 66: /* .stabd code for line number. */ 67: #ifndef N_SLINE 68: #define N_SLINE 0x44 69: #endif 70: 71: /* .stabs code for included file name. */ 72: #ifndef N_SOL 73: #define N_SOL 0x84 74: #endif 1.1 root 75: 76: #define min(A,B) ((A) < (B) ? (A) : (B)) 77: 78: void output_asm_insn (); 1.1.1.10 root 79: rtx alter_subreg (); 1.1 root 80: static int alter_cond (); 1.1.1.3 root 81: void output_asm_label (); 1.1 root 82: static void output_operand (); 1.1.1.2 root 83: void output_address (); 1.1 root 84: void output_addr_const (); 1.1.1.2 root 85: static void output_source_line (); 1.1 root 86: 1.1.1.4 root 87: /* the sdb debugger needs the line given as an offset from the beginning 88: of the current function -wfs*/ 89: 90: extern int sdb_begin_function_line; 91: 92: /* Line number of last NOTE. */ 93: static int last_linenum; 94: 1.1.1.13! root 95: /* Number of basic blocks seen so far; ! 96: used if profile_block_flag is set. */ ! 97: static int count_basic_blocks; ! 98: 1.1.1.9 root 99: /* Nonzero while outputting an `asm' with operands. 1.1.1.10 root 100: This means that inconsistencies are the user's fault, so don't abort. 101: The precise value is the insn being output, to pass to error_for_asm. */ 102: static rtx this_is_asm_operands; 1.1.1.9 root 103: 104: /* Number of operands of this insn, for an `asm' with operands. */ 105: static int insn_noperands; 106: 1.1.1.4 root 107: /* Indexed by hard register, the name of the register for assembler code. */ 108: 1.1 root 109: static char *reg_name[] = REGISTER_NAMES; 110: 111: /* File in which assembler code is being written. */ 112: 1.1.1.2 root 113: extern FILE *asm_out_file; 1.1 root 114: 115: /* All the symbol-blocks (levels of scoping) in the compilation 116: are assigned sequence numbers in order of appearance of the 117: beginnings of the symbol-blocks. Both final and dbxout do this, 118: and assume that they will both give the same number to each block. 119: Final uses these sequence numbers to generate assembler label names 120: LBBnnn and LBEnnn for the beginning and end of the symbol-block. 121: Dbxout uses the sequence nunbers to generate references to the same labels 1.1.1.4 root 122: from the dbx debugging information. 123: 124: Sdb records this level at the beginning 125: of each function, so that when it recurses down the declarations, it may 126: find the current level, since it outputs the block beginning and endings 127: at the point in the asm file, where the blocks would begin and end. */ 1.1 root 128: 1.1.1.4 root 129: int next_block_index; 1.1 root 130: 1.1.1.2 root 131: /* Chain of all `struct gdbfile's. */ 132: 133: struct gdbfile *gdbfiles; 134: 135: /* `struct gdbfile' for the last file we wrote a line number for. */ 136: 137: static struct gdbfile *current_gdbfile; 138: 139: /* Filenum to assign to the next distinct source file encountered. */ 140: 141: static int next_gdb_filenum; 142: 1.1 root 143: /* This variable contains machine-dependent flags (defined in tm-...h) 144: set and examined by output routines 145: that describe how to interpret the condition codes properly. */ 146: 147: CC_STATUS cc_status; 148: 1.1.1.2 root 149: /* During output of an insn, this contains a copy of cc_status 150: from before the insn. */ 151: 152: CC_STATUS cc_prev_status; 153: 1.1 root 154: /* Last source file name mentioned in a NOTE insn. */ 155: 156: static char *lastfile; 157: 158: /* Indexed by hardware reg number, is 1 if that register is ever 159: used in the current function. 160: 161: In life_analysis, or in stupid_life_analysis, this is set 162: up to record the hard regs used explicitly. Reload adds 163: in the hard regs used for holding pseudo regs. Final uses 164: it to generate the code in the function prologue and epilogue 165: to save and restore registers as needed. */ 166: 167: char regs_ever_live[FIRST_PSEUDO_REGISTER]; 168: 1.1.1.2 root 169: /* Nonzero means current function must be given a frame pointer. 170: Set in stmt.c if anything is allocated on the stack there. 171: Set in reload1.c if anything is allocated on the stack there. */ 172: 173: int frame_pointer_needed; 174: 175: /* Assign unique numbers to labels generated for profiling. */ 176: 177: int profile_label_no; 178: 179: /* Length so far allocated in PENDING_BLOCKS. */ 180: 181: static int max_block_depth; 182: 183: /* Stack of sequence numbers of symbol-blocks of which we have seen the 184: beginning but not yet the end. Sequence numbers are assigned at 185: the beginning; this stack allows us to find the sequence number 186: of a block that is ending. */ 1.1 root 187: 1.1.1.2 root 188: static int *pending_blocks; 189: 190: /* Number of elements currently in use in PENDING_BLOCKS. */ 191: 192: static int block_depth; 193: 194: /* Nonzero if have enabled APP processing of our assembler output. */ 195: 196: static int app_on; 1.1 root 197: 198: /* Initialize data in final at the beginning of a compilation. */ 199: 200: void 201: init_final (filename) 202: char *filename; 203: { 204: next_block_index = 2; 205: lastfile = filename; 1.1.1.2 root 206: app_on = 0; 207: max_block_depth = 20; 208: pending_blocks = (int *) xmalloc (20 * sizeof *pending_blocks); 209: gdbfiles = 0; 210: next_gdb_filenum = 0; 1.1 root 211: } 212: 1.1.1.13! root 213: /* Called at end of source file, ! 214: to output the block-profiling table for this entire compilation. */ ! 215: ! 216: void ! 217: end_final (filename) ! 218: char *filename; ! 219: { ! 220: int i; ! 221: ! 222: if (profile_block_flag) ! 223: { ! 224: char name[12]; ! 225: ! 226: data_section (); ! 227: ! 228: /* Output the main header, of 6 words: ! 229: 0: 1 if this file's initialized, else 0. ! 230: 1: address of file name. ! 231: 2: address of table of counts. ! 232: 4: number of counts in the table. ! 233: 5: always 0, for compatibility with Sun. ! 234: 6: extra word added by GNU: address of address table ! 235: which contains addresses of basic blocks, ! 236: in parallel with the table of counts. */ ! 237: ASM_OUTPUT_ALIGN (asm_out_file, ! 238: exact_log2 (min (UNITS_PER_WORD, ! 239: BIGGEST_ALIGNMENT / BITS_PER_UNIT))); ! 240: ! 241: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 0); ! 242: assemble_integer_zero (); ! 243: ! 244: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 1); ! 245: ASM_OUTPUT_INT (asm_out_file, gen_rtx (SYMBOL_REF, Pmode, name)); ! 246: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2); ! 247: ASM_OUTPUT_INT (asm_out_file, gen_rtx (SYMBOL_REF, Pmode, name)); ! 248: ASM_OUTPUT_INT (asm_out_file, gen_rtx (CONST_INT, VOIDmode, ! 249: count_basic_blocks)); ! 250: assemble_integer_zero (); ! 251: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 3); ! 252: ASM_OUTPUT_INT (asm_out_file, gen_rtx (SYMBOL_REF, Pmode, name)); ! 253: ! 254: /* Output the file name. */ ! 255: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 1); ! 256: assemble_string (filename, strlen (filename) + 1); ! 257: ! 258: /* Make space for the table of counts. */ ! 259: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 2); ! 260: ASM_OUTPUT_SKIP (asm_out_file, UNITS_PER_WORD * count_basic_blocks); ! 261: ! 262: /* Output the table of addresses. */ ! 263: text_section (); ! 264: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 3); ! 265: for (i = 0; i < count_basic_blocks; i++) ! 266: { ! 267: char name[12]; ! 268: ASM_GENERATE_INTERNAL_LABEL (name, "LPB", i); ! 269: ASM_OUTPUT_INT (asm_out_file, gen_rtx (SYMBOL_REF, Pmode, name)); ! 270: } ! 271: ! 272: /* End with the address of the table of addresses, ! 273: so we can find it easily, as the last word in the file's text. */ ! 274: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 3); ! 275: ASM_OUTPUT_INT (asm_out_file, gen_rtx (SYMBOL_REF, Pmode, name)); ! 276: } ! 277: } ! 278: 1.1.1.2 root 279: /* Enable APP processing of subsequent output. 280: Used before the output from an `asm' statement. */ 281: 282: void 283: app_enable () 284: { 285: if (! app_on) 286: { 287: fprintf (asm_out_file, ASM_APP_ON); 288: app_on = 1; 289: } 290: } 291: 292: /* Enable APP processing of subsequent output. 293: Called from varasm.c before most kinds of output. */ 294: 295: void 296: app_disable () 297: { 298: if (app_on) 299: { 300: fprintf (asm_out_file, ASM_APP_OFF); 301: app_on = 0; 302: } 303: } 304: 305: /* Output assembler code for the start of a function, 306: and initialize some of the variables in this file 307: for the new function. The label for the function and associated 308: assembler pseudo-ops have already been output in `assemble_function'. 309: 1.1 root 310: FIRST is the first insn of the rtl for the function being compiled. 311: FILE is the file to write assembler code to. 1.1.1.4 root 312: WRITE_SYMBOLS says which kind of debugging info to write (or none). 1.1 root 313: OPTIMIZE is nonzero if we should eliminate redundant 314: test and compare insns. */ 315: 316: void 1.1.1.2 root 317: final_start_function (first, file, write_symbols, optimize) 1.1 root 318: rtx first; 319: FILE *file; 1.1.1.4 root 320: enum debugger write_symbols; 1.1 root 321: int optimize; 322: { 1.1.1.2 root 323: block_depth = 0; 1.1 root 324: 1.1.1.9 root 325: this_is_asm_operands = 0; 326: 1.1 root 327: /* Record beginning of the symbol-block that's the entire function. */ 328: 1.1.1.4 root 329: if (write_symbols == GDB_DEBUG) 1.1 root 330: { 1.1.1.2 root 331: pending_blocks[block_depth++] = next_block_index; 1.1 root 332: fprintf (file, "\t.gdbbeg %d\n", next_block_index++); 333: } 334: 335: /* Initial line number is supposed to be output 336: before the function's prologue and label 337: so that the function's address will not appear to be 338: in the last statement of the preceding function. */ 339: if (NOTE_LINE_NUMBER (first) != NOTE_INSN_DELETED) 1.1.1.2 root 340: output_source_line (file, first, write_symbols); 1.1 root 341: 342: #ifdef FUNCTION_PROLOGUE 343: /* First output the function prologue: code to set up the stack frame. */ 344: FUNCTION_PROLOGUE (file, get_frame_size ()); 345: #endif 346: 1.1.1.4 root 347: #ifdef SDB_DEBUGGING_INFO 348: next_block_index = 1; 349: if (write_symbols == SDB_DEBUG) 350: sdbout_begin_function (last_linenum); 351: #endif 352: 1.1.1.13! root 353: #ifdef FUNCTION_BLOCK_PROFILER ! 354: if (profile_block_flag) ! 355: { ! 356: FUNCTION_BLOCK_PROFILER (file, profile_label_no); ! 357: } ! 358: #endif /* FUNCTION_BLOCK_PROFILER */ ! 359: 1.1.1.2 root 360: if (profile_flag) 1.1.1.4 root 361: { 1.1.1.2 root 362: int align = min (BIGGEST_ALIGNMENT, BITS_PER_WORD); 1.1.1.8 root 363: extern int current_function_returns_struct; 364: extern int current_function_needs_context; 365: int sval = current_function_returns_struct; 366: int cxt = current_function_needs_context; 1.1.1.13! root 367: 1.1.1.6 root 368: data_section (); 1.1.1.2 root 369: ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT)); 370: ASM_OUTPUT_INTERNAL_LABEL (file, "LP", profile_label_no); 371: assemble_integer_zero (); 1.1.1.13! root 372: 1.1.1.6 root 373: text_section (); 1.1.1.8 root 374: 375: #ifdef STRUCT_VALUE_INCOMING_REGNUM 376: if (sval) 377: ASM_OUTPUT_REG_PUSH (file, STRUCT_VALUE_INCOMING_REGNUM); 378: #else 379: #ifdef STRUCT_VALUE_REGNUM 380: if (sval) 381: ASM_OUTPUT_REG_PUSH (file, STRUCT_VALUE_REGNUM); 382: #endif 383: #endif 384: 385: #if 0 386: #ifdef STATIC_CHAIN_INCOMING_REGNUM 387: if (cxt) 388: ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_INCOMING_REGNUM); 389: #else 390: #ifdef STATIC_CHAIN_REGNUM 391: if (cxt) 392: ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_REGNUM); 393: #endif 394: #endif 395: #endif /* 0 */ 396: 1.1.1.2 root 397: FUNCTION_PROFILER (file, profile_label_no); 398: 1.1.1.8 root 399: #if 0 400: #ifdef STATIC_CHAIN_INCOMING_REGNUM 401: if (cxt) 402: ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_INCOMING_REGNUM); 403: #else 404: #ifdef STATIC_CHAIN_REGNUM 405: if (cxt) 406: ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_REGNUM); 407: #endif 408: #endif 409: #endif /* 0 */ 410: 411: #ifdef STRUCT_VALUE_INCOMING_REGNUM 412: if (sval) 413: ASM_OUTPUT_REG_POP (file, STRUCT_VALUE_INCOMING_REGNUM); 414: #else 415: #ifdef STRUCT_VALUE_REGNUM 416: if (sval) 417: ASM_OUTPUT_REG_POP (file, STRUCT_VALUE_REGNUM); 418: #endif 419: #endif 420: } 1.1.1.13! root 421: ! 422: profile_label_no++; 1.1.1.2 root 423: } 424: 425: /* Output assembler code for the end of a function. 426: For clarity, args are same as those of `final_start_function' 427: even though not all of them are needed. */ 428: 429: void 430: final_end_function (first, file, write_symbols, optimize) 431: rtx first; 432: FILE *file; 1.1.1.4 root 433: enum debugger write_symbols; 1.1.1.2 root 434: int optimize; 435: { 436: if (app_on) 437: { 438: fprintf (file, ASM_APP_OFF); 439: app_on = 0; 440: } 441: 1.1.1.4 root 442: if (write_symbols == GDB_DEBUG) 1.1.1.2 root 443: fprintf (file, "\t.gdbend %d\n", pending_blocks[0]); 444: 1.1.1.4 root 445: #ifdef SDB_DEBUGGING_INFO 446: if (write_symbols == SDB_DEBUG) 447: sdbout_end_function (last_linenum); 448: #endif 449: 1.1.1.2 root 450: #ifdef FUNCTION_EPILOGUE 451: /* Finally, output the function epilogue: 452: code to restore the stack frame and return to the caller. */ 453: FUNCTION_EPILOGUE (file, get_frame_size ()); 454: #endif 455: 1.1.1.6 root 456: #ifdef SDB_DEBUGGING_INFO 457: if (write_symbols == SDB_DEBUG) 458: sdbout_end_epilogue (); 459: #endif 460: 1.1.1.2 root 461: /* If FUNCTION_EPILOGUE is not defined, then the function body 462: itself contains return instructions wherever needed. */ 463: } 464: 465: /* Output assembler code for some insns: all or part of a function. 1.1.1.8 root 466: For description of args, see `final_start_function', above. 467: 468: PRESCAN is 1 if we are not really outputting, 469: just scanning as if we were outputting. 470: Prescanning deletes and rearranges insns just like ordinary output. 471: PRESCAN is -2 if we are outputting after having prescanned. 472: In this case, don't try to delete or rearrange insns 473: because that has already been done. 474: Prescanning is done only on certain machines. */ 1.1.1.2 root 475: 476: void 1.1.1.8 root 477: final (first, file, write_symbols, optimize, prescan) 1.1.1.2 root 478: rtx first; 479: FILE *file; 1.1.1.4 root 480: enum debugger write_symbols; 1.1.1.2 root 481: int optimize; 1.1.1.8 root 482: int prescan; 1.1.1.2 root 483: { 484: register rtx insn; 485: register int i; 1.1.1.12 root 486: rtx last_ignored_compare = 0; 1.1.1.13! root 487: int new_block = 1; 1.1 root 488: 1.1.1.8 root 489: init_recog (); 490: 491: CC_STATUS_INIT; 492: 1.1 root 493: for (insn = NEXT_INSN (first); insn; insn = NEXT_INSN (insn)) 494: { 495: switch (GET_CODE (insn)) 496: { 497: case NOTE: 1.1.1.8 root 498: if (prescan > 0) 499: break; 1.1.1.4 root 500: if (write_symbols == NO_DEBUG) 1.1 root 501: break; 502: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG) 503: abort (); /* Obsolete; shouldn't appear */ 504: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG 505: || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END) 506: break; 507: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED) 508: break; /* An insn that was "deleted" */ 1.1.1.2 root 509: if (app_on) 510: { 511: fprintf (file, ASM_APP_OFF); 512: app_on = 0; 513: } 1.1 root 514: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG) 515: { 516: /* Beginning of a symbol-block. Assign it a sequence number 517: and push the number onto the stack PENDING_BLOCKS. */ 518: 1.1.1.2 root 519: if (block_depth == max_block_depth) 1.1 root 520: { 521: /* PENDING_BLOCKS is full; make it longer. */ 1.1.1.2 root 522: max_block_depth *= 2; 523: pending_blocks 524: = (int *) xrealloc (pending_blocks, 525: max_block_depth * sizeof (int)); 1.1 root 526: } 1.1.1.2 root 527: pending_blocks[block_depth++] = next_block_index; 1.1 root 528: 529: /* Output debugging info about the symbol-block beginning. */ 530: 1.1.1.4 root 531: #ifdef SDB_DEBUGGING_INFO 532: if (write_symbols == SDB_DEBUG) 533: sdbout_begin_block (file, last_linenum, next_block_index); 534: #endif 535: #ifdef DBX_DEBUGGING_INFO 536: if (write_symbols == DBX_DEBUG) 1.1.1.2 root 537: ASM_OUTPUT_INTERNAL_LABEL (file, "LBB", next_block_index); 1.1.1.4 root 538: #endif 539: if (write_symbols == GDB_DEBUG) 1.1.1.2 root 540: fprintf (file, "\t.gdbbeg %d\n", next_block_index); 1.1.1.4 root 541: 1.1.1.2 root 542: next_block_index++; 1.1 root 543: } 544: else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END) 545: { 546: /* End of a symbol-block. Pop its sequence number off 547: PENDING_BLOCKS and output debugging info based on that. */ 548: 1.1.1.4 root 549: --block_depth; 550: 551: #ifdef DBX_DEBUGGING_INFO 552: if (write_symbols == DBX_DEBUG && block_depth >= 0) 553: ASM_OUTPUT_INTERNAL_LABEL (file, "LBE", 554: pending_blocks[block_depth]); 555: #endif 556: 557: #ifdef SDB_DEBUGGING_INFO 558: if (write_symbols == SDB_DEBUG && block_depth >= 0) 559: sdbout_end_block (file, last_linenum); 560: #endif 561: 562: if (write_symbols == GDB_DEBUG) 563: fprintf (file, "\t.gdbend %d\n", pending_blocks[block_depth]); 1.1 root 564: } 1.1.1.2 root 565: else if (NOTE_LINE_NUMBER (insn) > 0) 1.1 root 566: /* This note is a line-number. */ 1.1.1.2 root 567: output_source_line (file, insn, write_symbols); 1.1 root 568: break; 569: 570: case BARRIER: 1.1.1.11 root 571: #ifdef ASM_OUTPUT_ALIGN_CODE 572: ASM_OUTPUT_ALIGN_CODE (file); 573: #endif 1.1 root 574: break; 575: 576: case CODE_LABEL: 1.1.1.8 root 577: CC_STATUS_INIT; 578: if (prescan > 0) 579: break; 1.1.1.13! root 580: new_block = 1; 1.1.1.2 root 581: if (app_on) 582: { 583: fprintf (file, ASM_APP_OFF); 584: app_on = 0; 585: } 586: #ifdef ASM_OUTPUT_CASE_LABEL 587: if (NEXT_INSN (insn) != 0 588: && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN) 589: { 590: rtx nextbody = PATTERN (NEXT_INSN (insn)); 591: 592: /* If this label is followed by a jump-table, 593: output the two of them together in a special way. */ 594: 595: if (GET_CODE (nextbody) == ADDR_VEC 596: || GET_CODE (nextbody) == ADDR_DIFF_VEC) 597: { 598: ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn), 599: NEXT_INSN (insn)); 600: break; 601: } 602: } 603: #endif 604: 605: ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn)); 1.1 root 606: break; 607: 608: default: 609: { 610: register rtx body = PATTERN (insn); 611: int insn_code_number; 612: char *template; 613: 614: /* An INSN, JUMP_INSN or CALL_INSN. 1.1.1.2 root 615: First check for special kinds that recog doesn't recognize. */ 1.1.1.4 root 616: 1.1 root 617: if (GET_CODE (body) == USE /* These are just declarations */ 618: || GET_CODE (body) == CLOBBER) 619: break; 1.1.1.13! root 620: ! 621: if (profile_block_flag && new_block) ! 622: { ! 623: new_block = 0; ! 624: /* Enable the table of basic-block use counts ! 625: to point at the code it applies to. */ ! 626: ASM_OUTPUT_INTERNAL_LABEL (file, "LPB", count_basic_blocks); ! 627: /* Before first insn of this basic block, increment the ! 628: count of times it was entered. */ ! 629: #ifdef BLOCK_PROFILER ! 630: BLOCK_PROFILER (file, count_basic_blocks); ! 631: #endif ! 632: count_basic_blocks++; ! 633: } ! 634: 1.1 root 635: if (GET_CODE (body) == ASM_INPUT) 636: { 1.1.1.8 root 637: /* There's no telling what that did to the condition codes. */ 638: CC_STATUS_INIT; 639: if (prescan > 0) 640: break; 1.1.1.2 root 641: if (! app_on) 642: { 643: fprintf (file, ASM_APP_ON); 644: app_on = 1; 645: } 646: fprintf (asm_out_file, "\t%s\n", XSTR (body, 0)); 1.1 root 647: break; 648: } 649: 1.1.1.2 root 650: /* Detect `asm' construct with operands. */ 1.1.1.11 root 651: if (asm_noperands (body) >= 0) 1.1.1.2 root 652: { 653: int noperands = asm_noperands (body); 1.1.1.8 root 654: rtx *ops; 1.1.1.2 root 655: char *string; 656: 1.1.1.8 root 657: /* There's no telling what that did to the condition codes. */ 658: CC_STATUS_INIT; 659: if (prescan > 0) 660: break; 661: 662: /* alloca won't do here, since only return from `final' 663: would free it. */ 1.1.1.11 root 664: if (noperands > 0) 665: ops = (rtx *) xmalloc (noperands * sizeof (rtx)); 1.1.1.8 root 666: 1.1.1.2 root 667: if (! app_on) 668: { 669: fprintf (file, ASM_APP_ON); 670: app_on = 1; 671: } 672: 673: /* Get out the operand values. */ 674: string = decode_asm_operands (body, ops, 0, 0, 0); 1.1.1.9 root 675: /* Inhibit aborts on what would otherwise be compiler bugs. */ 676: insn_noperands = noperands; 1.1.1.10 root 677: this_is_asm_operands = insn; 1.1.1.2 root 678: /* Output the insn using them. */ 679: output_asm_insn (string, ops); 1.1.1.9 root 680: this_is_asm_operands = 0; 1.1.1.11 root 681: if (noperands > 0) 682: free (ops); 1.1.1.2 root 683: break; 684: } 685: 1.1.1.8 root 686: if (prescan <= 0 && app_on) 1.1.1.2 root 687: { 688: fprintf (file, ASM_APP_OFF); 689: app_on = 0; 690: } 691: 1.1 root 692: /* Detect insns that are really jump-tables 693: and output them as such. */ 694: 695: if (GET_CODE (body) == ADDR_VEC) 696: { 697: register int vlen, idx; 1.1.1.8 root 698: 699: if (prescan > 0) 700: break; 701: 1.1 root 702: vlen = XVECLEN (body, 0); 703: for (idx = 0; idx < vlen; idx++) 1.1.1.4 root 704: ASM_OUTPUT_ADDR_VEC_ELT (file, 1.1 root 705: CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0))); 1.1.1.4 root 706: #ifdef ASM_OUTPUT_CASE_END 707: ASM_OUTPUT_CASE_END (file, 708: CODE_LABEL_NUMBER (PREV_INSN (insn)), 709: insn); 710: #endif 1.1 root 711: break; 712: } 713: if (GET_CODE (body) == ADDR_DIFF_VEC) 714: { 715: register int vlen, idx; 1.1.1.8 root 716: 717: if (prescan > 0) 718: break; 719: 1.1 root 720: vlen = XVECLEN (body, 1); 721: for (idx = 0; idx < vlen; idx++) 1.1.1.4 root 722: ASM_OUTPUT_ADDR_DIFF_ELT (file, 1.1 root 723: CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 1, idx), 0)), 724: CODE_LABEL_NUMBER (XEXP (XEXP (body, 0), 0))); 1.1.1.4 root 725: #ifdef ASM_OUTPUT_CASE_END 1.1.1.7 root 726: ASM_OUTPUT_CASE_END (file, 727: CODE_LABEL_NUMBER (PREV_INSN (insn)), 728: insn); 1.1.1.4 root 729: #endif 1.1 root 730: break; 731: } 732: 733: /* We have a real machine instruction as rtl. */ 734: 735: body = PATTERN (insn); 736: 1.1.1.4 root 737: /* Check for redundant test and compare instructions 1.1 root 738: (when the condition codes are already set up as desired). 739: This is done only when optimizing; if not optimizing, 740: it should be possible for the user to alter a variable 741: with the debugger in between statements 742: and the next statement should reexamine the variable 743: to compute the condition codes. */ 744: 745: if (optimize 746: && GET_CODE (body) == SET 747: && GET_CODE (SET_DEST (body)) == CC0) 748: { 749: if (GET_CODE (SET_SRC (body)) == SUBREG) 1.1.1.6 root 750: SET_SRC (body) = alter_subreg (SET_SRC (body)); 1.1 root 751: if ((cc_status.value1 != 0 752: && rtx_equal_p (SET_SRC (body), cc_status.value1)) 753: || (cc_status.value2 != 0 754: && rtx_equal_p (SET_SRC (body), cc_status.value2))) 1.1.1.2 root 755: { 756: /* Don't delete insn if has an addressing side-effect */ 1.1.1.6 root 757: if (! find_reg_note (insn, REG_INC, 0) 758: /* or if anything in it is volatile. */ 759: && ! volatile_refs_p (PATTERN (insn))) 1.1.1.12 root 760: { 761: /* We don't really delete the insn; just ignore it. */ 762: last_ignored_compare = insn; 763: break; 764: } 1.1.1.2 root 765: } 1.1 root 766: } 767: 1.1.1.12 root 768: reinsert_compare: 769: 1.1.1.13! root 770: /* Following a conditional branch, we have a new basic block. */ ! 771: if (GET_CODE (insn) == JUMP_INSN && GET_CODE (body) == SET ! 772: && GET_CODE (SET_SRC (body)) != LABEL_REF) ! 773: new_block = 1; ! 774: 1.1 root 775: /* If this is a conditional branch, maybe modify it 776: if the cc's are in a nonstandard state 777: so that it accomplishes the same thing that it would 778: do straightforwardly if the cc's were set up normally. */ 779: 780: if (cc_status.flags != 0 781: && GET_CODE (insn) == JUMP_INSN 782: && GET_CODE (body) == SET 783: && SET_DEST (body) == pc_rtx 1.1.1.8 root 784: && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE 785: /* This is done during prescan; it is not done again 786: in final scan when prescan has been done. */ 787: && prescan >= 0) 1.1 root 788: { 789: /* This function may alter the contents of its argument 790: and clear some of the cc_status.flags bits. 791: It may also return 1 meaning condition now always true 792: or -1 meaning condition now always false 793: or 2 meaning condition nontrivial but altered. */ 794: register int result = alter_cond (XEXP (SET_SRC (body), 0)); 795: /* If condition now has fixed value, replace the IF_THEN_ELSE 796: with its then-operand or its else-operand. */ 797: if (result == 1) 798: SET_SRC (body) = XEXP (SET_SRC (body), 1); 799: if (result == -1) 800: SET_SRC (body) = XEXP (SET_SRC (body), 2); 801: /* The jump is now either unconditional or a no-op. 802: If it has become a no-op, don't try to output it. 803: (It would not be recognized.) */ 804: if (SET_SRC (body) == pc_rtx) 1.1.1.8 root 805: { 806: PUT_CODE (insn, NOTE); 807: NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; 808: NOTE_SOURCE_FILE (insn) = 0; 809: break; 810: } 1.1 root 811: /* Rerecognize the instruction if it has changed. */ 812: if (result != 0) 813: INSN_CODE (insn) = -1; 814: } 815: 1.1.1.8 root 816: #ifdef STORE_FLAG_VALUE 1.1 root 817: /* Make same adjustments to instructions that examine the 1.1.1.8 root 818: condition codes without jumping (if this machine has them). */ 1.1 root 819: 820: if (cc_status.flags != 0 821: && GET_CODE (body) == SET) 822: switch (GET_CODE (SET_SRC (body))) 823: { 824: case GTU: 825: case GT: 826: case LTU: 827: case LT: 828: case GEU: 829: case GE: 830: case LEU: 831: case LE: 832: case EQ: 833: case NE: 834: { 1.1.1.8 root 835: register int result; 836: if (GET_CODE (XEXP (SET_SRC (body), 0)) != CC0) 837: break; 838: result = alter_cond (SET_SRC (body)); 1.1 root 839: if (result == 1) 1.1.1.8 root 840: SET_SRC (body) = gen_rtx (CONST_INT, VOIDmode, 841: STORE_FLAG_VALUE); 1.1 root 842: if (result == -1) 843: SET_SRC (body) = const0_rtx; 844: if (result != 0) 845: INSN_CODE (insn) = -1; 846: } 847: } 1.1.1.8 root 848: #endif /* STORE_FLAG_VALUE */ 1.1 root 849: 1.1.1.12 root 850: /* Do machine-specific peephole optimizations if desired. */ 851: 852: if (optimize && !flag_no_peephole) 853: { 854: peephole (insn); 855: 856: /* PEEPHOLE might have changed this. */ 857: body = PATTERN (insn); 858: } 859: 1.1 root 860: /* Try to recognize the instruction. 861: If successful, verify that the operands satisfy the 862: constraints for the instruction. Crash if they don't, 863: since `reload' should have changed them so that they do. */ 864: 865: insn_code_number = recog_memoized (insn); 866: insn_extract (insn); 867: for (i = 0; i < insn_n_operands[insn_code_number]; i++) 1.1.1.11 root 868: { 869: if (GET_CODE (recog_operand[i]) == SUBREG) 870: recog_operand[i] = alter_subreg (recog_operand[i]); 871: } 1.1 root 872: 873: #ifdef REGISTER_CONSTRAINTS 874: if (! constrain_operands (insn_code_number)) 875: abort (); 876: #endif 877: 1.1.1.4 root 878: /* Some target machines need to prescan each insn before 879: it is output. */ 880: 881: #ifdef FINAL_PRESCAN_INSN 882: FINAL_PRESCAN_INSN (insn, recog_operand, 883: insn_n_operands[insn_code_number]); 884: #endif 885: 1.1.1.2 root 886: cc_prev_status = cc_status; 887: 1.1 root 888: /* Update `cc_status' for this instruction. 889: The instruction's output routine may change it further. 1.1.1.11 root 890: If the output routine for a jump insn needs to depend 891: on the cc status, it should look at cc_prev_status. */ 1.1 root 892: 1.1.1.8 root 893: NOTICE_UPDATE_CC (body, insn); 1.1 root 894: 895: /* If the proper template needs to be chosen by some C code, 1.1.1.2 root 896: run that code and get the real template. */ 1.1 root 897: 898: template = insn_template[insn_code_number]; 899: if (template == 0) 1.1.1.12 root 900: { 901: template = (*insn_outfun[insn_code_number]) (recog_operand, insn); 902: 903: /* If the C code returns 0, it means that it is a jump insn 904: which follows a deleted test insn, and that test insn 905: needs to be reinserted. */ 906: if (template == 0) 907: { 908: if (PREV_INSN (insn) != last_ignored_compare) 909: abort (); 910: insn = PREV_INSN (insn); 911: body = PATTERN (insn); 1.1.1.13! root 912: new_block = 0; 1.1.1.12 root 913: goto reinsert_compare; 914: } 915: } 1.1 root 916: 1.1.1.8 root 917: if (prescan > 0) 918: break; 919: 1.1 root 920: /* Output assembler code from the template. */ 921: 922: output_asm_insn (template, recog_operand); 1.1.1.12 root 923: 924: /* Mark this insn as having been output. */ 925: INSN_DELETED_P (insn) = 1; 1.1 root 926: } 927: } 928: } 1.1.1.2 root 929: } 930: 931: /* Set up FILENAME as the current file for GDB line-number output. */ 1.1 root 932: 1.1.1.2 root 933: void 934: set_current_gdbfile (filename) 935: char *filename; 936: { 937: register struct gdbfile *f; 938: for (f = gdbfiles; f; f = f->next) 939: if (!strcmp (f->name, filename)) 940: break; 1.1 root 941: 1.1.1.2 root 942: if (!f) 943: { 944: f = (struct gdbfile *) permalloc (sizeof (struct gdbfile)); 945: f->next = gdbfiles; 946: gdbfiles = f; 947: f->name = filename; 948: f->filenum = next_gdb_filenum++; 949: f->nlines = 0; 950: } 951: current_gdbfile = f; 952: lastfile = filename; 1.1 root 953: } 954: 1.1.1.2 root 955: /* Output debugging info to the assembler file FILE 956: based on the NOTE-insn INSN, assumed to be a line number. */ 1.1 root 957: 1.1.1.2 root 958: static void 959: output_source_line (file, insn, write_symbols) 1.1 root 960: FILE *file; 961: rtx insn; 1.1.1.4 root 962: enum debugger write_symbols; 1.1 root 963: { 964: register char *filename = NOTE_SOURCE_FILE (insn); 1.1.1.4 root 965: 966: last_linenum = NOTE_LINE_NUMBER (insn); 967: 968: if (write_symbols == GDB_DEBUG) 1.1.1.2 root 969: { 970: /* Output GDB-format line number info. */ 1.1 root 971: 1.1.1.2 root 972: /* If this is not the same source file as last time, 973: find or assign a GDB-file-number to this file. */ 974: if (filename && (lastfile == 0 || strcmp (filename, lastfile) 975: || current_gdbfile == 0)) 976: set_current_gdbfile (filename); 977: 978: ++current_gdbfile->nlines; 979: fprintf (file, "\t.gdbline %d,%d\n", 980: current_gdbfile->filenum, NOTE_LINE_NUMBER (insn)); 981: } 1.1.1.4 root 982: 1.1.1.6 root 983: if (write_symbols == SDB_DEBUG || write_symbols == DBX_DEBUG) 1.1.1.4 root 984: { 1.1.1.6 root 985: #ifdef SDB_DEBUGGING_INFO 986: if (write_symbols == SDB_DEBUG 987: /* COFF can't handle multiple source files--lose, lose. */ 1.1.1.10 root 988: && !strcmp (filename, main_input_filename) 989: /* COFF can't handle line #s before start-line of this function. */ 990: && last_linenum >= sdb_begin_function_line) 1.1.1.6 root 991: { 1.1.1.4 root 992: #ifdef ASM_OUTPUT_SOURCE_LINE 1.1.1.6 root 993: ASM_OUTPUT_SOURCE_LINE (file, last_linenum); 1.1.1.4 root 994: #else 1.1.1.6 root 995: fprintf (file, "\t.ln\t%d\n", 996: (sdb_begin_function_line 997: ? last_linenum - sdb_begin_function_line : 1)); 1.1.1.4 root 998: #endif 1.1.1.6 root 999: } 1.1.1.4 root 1000: #endif 1001: 1002: #ifdef DBX_DEBUGGING_INFO 1.1.1.6 root 1003: if (write_symbols == DBX_DEBUG) 1.1.1.4 root 1004: { 1.1.1.6 root 1005: /* Write DBX line number data. */ 1006: 1007: if (filename && (lastfile == 0 || strcmp (filename, lastfile))) 1008: { 1.1.1.2 root 1009: #ifdef ASM_OUTPUT_SOURCE_FILENAME 1.1.1.6 root 1010: ASM_OUTPUT_SOURCE_FILENAME (file, filename); 1.1.1.2 root 1011: #else 1.1.1.6 root 1012: fprintf (file, "\t.stabs \"%s\",%d,0,0,Ltext\n", 1013: filename, N_SOL); 1.1.1.2 root 1014: #endif 1.1.1.6 root 1015: lastfile = filename; 1016: } 1.1.1.4 root 1017: } 1.1.1.2 root 1018: 1019: #ifdef ASM_OUTPUT_SOURCE_LINE 1020: ASM_OUTPUT_SOURCE_LINE (file, NOTE_LINE_NUMBER (insn)); 1021: #else 1022: fprintf (file, "\t.stabd %d,0,%d\n", 1023: N_SLINE, NOTE_LINE_NUMBER (insn)); 1024: #endif 1.1.1.4 root 1025: #endif /* DBX_DEBUGGING_INFO */ 1.1.1.2 root 1026: } 1.1 root 1027: } 1028: 1.1.1.2 root 1029: /* If X is a SUBREG, replace it with a REG or a MEM, 1030: based on the thing it is a subreg of. */ 1.1 root 1031: 1.1.1.10 root 1032: rtx 1.1 root 1033: alter_subreg (x) 1034: register rtx x; 1035: { 1036: register rtx y = SUBREG_REG (x); 1037: if (GET_CODE (y) == SUBREG) 1.1.1.6 root 1038: y = alter_subreg (y); 1.1 root 1039: 1040: if (GET_CODE (y) == REG) 1041: { 1042: /* If the containing reg really gets a hard reg, so do we. */ 1043: PUT_CODE (x, REG); 1044: REGNO (x) = REGNO (y) + SUBREG_WORD (x); 1045: } 1046: else if (GET_CODE (y) == MEM) 1047: { 1.1.1.2 root 1048: register int offset = SUBREG_WORD (x) * UNITS_PER_WORD; 1.1 root 1049: #ifdef BYTES_BIG_ENDIAN 1.1.1.2 root 1050: offset -= (min (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))) 1051: - min (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (y)))); 1.1 root 1052: #endif 1053: PUT_CODE (x, MEM); 1054: XEXP (x, 0) = plus_constant (XEXP (y, 0), offset); 1055: } 1.1.1.6 root 1056: else if (GET_CODE (y) == CONST_DOUBLE) 1057: return y; 1058: 1059: return x; 1.1 root 1060: } 1061: 1.1.1.2 root 1062: /* Do alter_subreg on all the SUBREGs contained in X. */ 1.1 root 1063: 1.1.1.2 root 1064: static rtx 1065: walk_alter_subreg (x) 1066: rtx x; 1067: { 1068: switch (GET_CODE (x)) 1.1 root 1069: { 1.1.1.2 root 1070: case PLUS: 1071: case MULT: 1072: XEXP (x, 0) = walk_alter_subreg (XEXP (x, 0)); 1073: XEXP (x, 1) = walk_alter_subreg (XEXP (x, 1)); 1074: break; 1075: 1076: case MEM: 1077: XEXP (x, 0) = walk_alter_subreg (XEXP (x, 0)); 1078: break; 1079: 1080: case SUBREG: 1.1.1.6 root 1081: return alter_subreg (x); 1.1 root 1082: } 1083: 1.1.1.2 root 1084: return x; 1.1 root 1085: } 1086: 1087: /* Given BODY, the body of a jump instruction, alter the jump condition 1088: as required by the bits that are set in cc_status.flags. 1089: Not all of the bits there can be handled at this level in all cases. 1090: 1091: The value is normally 0. 1092: 1 means that the condition has become always true. 1.1.1.8 root 1093: -1 means that the condition has become always false. 1094: 2 means that COND has been altered. */ 1.1 root 1095: 1096: static int 1097: alter_cond (cond) 1098: register rtx cond; 1099: { 1100: int value = 0; 1101: 1102: if (cc_status.flags & CC_REVERSED) 1103: { 1104: value = 2; 1105: switch (GET_CODE (cond)) 1106: { 1107: case LE: 1108: PUT_CODE (cond, GE); 1109: break; 1110: case GE: 1111: PUT_CODE (cond, LE); 1112: break; 1113: case LT: 1114: PUT_CODE (cond, GT); 1115: break; 1116: case GT: 1117: PUT_CODE (cond, LT); 1118: break; 1119: case LEU: 1120: PUT_CODE (cond, GEU); 1121: break; 1122: case GEU: 1123: PUT_CODE (cond, LEU); 1124: break; 1125: case LTU: 1126: PUT_CODE (cond, GTU); 1127: break; 1128: case GTU: 1129: PUT_CODE (cond, LTU); 1130: break; 1131: } 1132: } 1133: 1.1.1.8 root 1134: if (cc_status.flags & CC_NOT_POSITIVE) 1.1 root 1135: switch (GET_CODE (cond)) 1136: { 1137: case LE: 1138: case LEU: 1139: case GEU: 1140: /* Jump becomes unconditional. */ 1141: return 1; 1142: 1143: case GT: 1144: case GTU: 1145: case LTU: 1146: /* Jump becomes no-op. */ 1147: return -1; 1148: 1149: case GE: 1150: PUT_CODE (cond, EQ); 1151: value = 2; 1152: break; 1153: 1154: case LT: 1155: PUT_CODE (cond, NE); 1156: value = 2; 1157: break; 1158: } 1159: 1.1.1.8 root 1160: if (cc_status.flags & CC_NOT_NEGATIVE) 1.1 root 1161: switch (GET_CODE (cond)) 1162: { 1163: case GE: 1164: case GEU: 1165: /* Jump becomes unconditional. */ 1166: return 1; 1167: 1168: case LT: 1169: case LTU: 1170: /* Jump becomes no-op. */ 1171: return -1; 1172: 1173: case LE: 1174: case LEU: 1175: PUT_CODE (cond, EQ); 1176: value = 2; 1177: break; 1178: 1179: case GT: 1180: case GTU: 1181: PUT_CODE (cond, NE); 1182: value = 2; 1183: break; 1184: } 1185: 1.1.1.8 root 1186: if (cc_status.flags & CC_NO_OVERFLOW) 1.1 root 1187: switch (GET_CODE (cond)) 1188: { 1189: case GEU: 1190: /* Jump becomes unconditional. */ 1191: return 1; 1192: 1193: case LEU: 1194: PUT_CODE (cond, EQ); 1195: value = 2; 1196: break; 1197: 1198: case GTU: 1199: PUT_CODE (cond, NE); 1200: value = 2; 1201: break; 1202: 1203: case LTU: 1204: /* Jump becomes no-op. */ 1205: return -1; 1206: } 1207: 1.1.1.8 root 1208: if (cc_status.flags & (CC_Z_IN_NOT_N | CC_Z_IN_N)) 1209: switch (GET_CODE (cond)) 1210: { 1211: case LE: 1212: case LEU: 1213: case GE: 1214: case GEU: 1215: case LT: 1216: case LTU: 1217: case GT: 1218: case GTU: 1219: abort (); 1220: 1221: case NE: 1222: PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? GE : LT); 1223: value = 2; 1224: break; 1225: 1226: case EQ: 1227: PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? LT : GE); 1228: value = 2; 1229: break; 1230: } 1231: 1.1 root 1232: return value; 1233: } 1234: 1.1.1.9 root 1235: /* Report inconsistency between the assembler template and the operands. 1236: In an `asm', it's the user's fault; otherwise, the compiler's fault. */ 1237: 1238: static void 1239: output_operand_lossage (str) 1240: char *str; 1241: { 1242: if (this_is_asm_operands) 1.1.1.11 root 1243: error_for_asm (this_is_asm_operands, "invalid `asm': %s", str); 1.1.1.9 root 1244: else 1245: abort (); 1246: } 1247: 1.1 root 1248: /* Output of assembler code from a template, and its subroutines. */ 1249: 1250: /* Output text from TEMPLATE to the assembler output file, 1251: obeying %-directions to substitute operands taken from 1252: the vector OPERANDS. 1253: 1254: %N (for N a digit) means print operand N in usual manner. 1255: %lN means require operand N to be a CODE_LABEL or LABEL_REF 1256: and print the label name with no punctuation. 1257: %cN means require operand N to be a constant 1258: and print the constant expression with no punctuation. 1259: %aN means expect operand N to be a memory address 1260: (not a memory reference!) and print a reference 1261: to that address. 1262: %nN means expect operand N to be a constant 1263: and print a constant expression for minus the value 1264: of the operand, with no other punctuation. */ 1265: 1266: void 1267: output_asm_insn (template, operands) 1268: char *template; 1269: rtx *operands; 1270: { 1271: register char *p; 1272: register int c; 1273: 1.1.1.2 root 1274: /* An insn may return a null string template 1275: in a case where no assembler code is needed. */ 1276: if (*template == 0) 1277: return; 1278: 1.1 root 1279: p = template; 1.1.1.2 root 1280: putc ('\t', asm_out_file); 1281: 1282: #ifdef ASM_OUTPUT_OPCODE 1283: ASM_OUTPUT_OPCODE (asm_out_file, p); 1284: #endif 1285: 1.1 root 1286: while (c = *p++) 1287: { 1.1.1.2 root 1288: #ifdef ASM_OUTPUT_OPCODE 1289: if (c == '\n') 1.1 root 1290: { 1.1.1.2 root 1291: putc (c, asm_out_file); 1292: while ((c = *p) == '\t') 1.1 root 1293: { 1.1.1.2 root 1294: putc (c, asm_out_file); 1295: p++; 1.1 root 1296: } 1.1.1.2 root 1297: ASM_OUTPUT_OPCODE (asm_out_file, p); 1298: } 1299: else 1300: #endif 1301: if (c != '%') 1302: putc (c, asm_out_file); 1303: else 1304: { 1305: /* %% outputs a single %. */ 1306: if (*p == '%') 1.1 root 1307: { 1.1.1.2 root 1308: p++; 1309: putc (c, asm_out_file); 1.1 root 1310: } 1.1.1.2 root 1311: /* % followed by a letter and some digits 1312: outputs an operand in a special way depending on the letter. 1313: Letters `acln' are implemented here. 1314: Other letters are passed to `output_operand' so that 1315: the PRINT_OPERAND macro can define them. */ 1316: else if ((*p >= 'a' && *p <= 'z') 1317: || (*p >= 'A' && *p <= 'Z')) 1.1 root 1318: { 1.1.1.2 root 1319: int letter = *p++; 1320: c = atoi (p); 1321: 1.1.1.9 root 1322: if (this_is_asm_operands 1323: && c >= (unsigned) insn_noperands && *p >= '0' && *p <= '9') 1324: output_operand_lossage ("operand number out of range"); 1325: else if (letter == 'l') 1.1.1.2 root 1326: output_asm_label (operands[c]); 1327: else if (letter == 'a') 1328: output_address (operands[c]); 1329: else if (letter == 'c') 1330: { 1331: if (CONSTANT_ADDRESS_P (operands[c])) 1332: output_addr_const (asm_out_file, operands[c]); 1333: else 1334: output_operand (operands[c], 'c'); 1335: } 1336: else if (letter == 'n') 1.1 root 1337: { 1.1.1.2 root 1338: if (GET_CODE (operands[c]) == CONST_INT) 1339: fprintf (asm_out_file, "%d", - INTVAL (operands[c])); 1340: else 1341: { 1342: putc ('-', asm_out_file); 1343: output_addr_const (asm_out_file, operands[c]); 1344: } 1.1 root 1345: } 1.1.1.2 root 1346: else if (*p >= '0' && *p <= '9') 1347: output_operand (operands[c], letter); 1348: else 1349: /* No operand-number follows the letter. */ 1350: output_operand (0, letter); 1351: 1352: while ((c = *p) >= '0' && c <= '9') p++; 1.1 root 1353: } 1.1.1.2 root 1354: /* % followed by a digit outputs an operand the default way. */ 1355: else if (*p >= '0' && *p <= '9') 1.1 root 1356: { 1357: c = atoi (p); 1.1.1.9 root 1358: if (this_is_asm_operands && c >= (unsigned) insn_noperands) 1359: output_operand_lossage ("operand number out of range"); 1360: else 1361: output_operand (operands[c], 0); 1.1.1.2 root 1362: while ((c = *p) >= '0' && c <= '9') p++; 1.1 root 1363: } 1.1.1.2 root 1364: /* % followed by punctuation: output something for that 1365: punctuation character alone, with no operand. 1366: The PRINT_OPERAND macro decides what is actually done. */ 1367: else 1368: output_operand (0, *p++); 1.1 root 1369: } 1370: } 1371: 1.1.1.2 root 1372: putc ('\n', asm_out_file); 1.1 root 1373: } 1.1.1.9 root 1374: 1.1.1.3 root 1375: /* Output a LABEL_REF, or a bare CODE_LABEL, as an assembler symbol. */ 1376: 1377: void 1.1 root 1378: output_asm_label (x) 1379: rtx x; 1380: { 1.1.1.2 root 1381: char buf[20]; 1382: 1.1 root 1383: if (GET_CODE (x) == LABEL_REF) 1.1.1.2 root 1384: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0))); 1.1 root 1385: else if (GET_CODE (x) == CODE_LABEL) 1.1.1.2 root 1386: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x)); 1.1 root 1387: else 1.1.1.9 root 1388: output_operand_lossage ("`%l' operand isn't a label"); 1.1.1.2 root 1389: 1390: assemble_name (asm_out_file, buf); 1.1 root 1391: } 1392: 1393: /* Print operand X using machine-dependent assembler syntax. 1.1.1.2 root 1394: The macro PRINT_OPERAND is defined just to control this function. 1395: CODE is a non-digit that preceded the operand-number in the % spec, 1396: such as 'z' if the spec was `%z3'. CODE is 0 if there was no char 1397: between the % and the digits. 1398: When CODE is a non-letter, X is 0. 1399: 1400: The meanings of the letters are machine-dependent and controlled 1401: by PRINT_OPERAND. */ 1.1 root 1402: 1403: static void 1.1.1.2 root 1404: output_operand (x, code) 1.1 root 1405: rtx x; 1.1.1.2 root 1406: int code; 1.1 root 1407: { 1.1.1.2 root 1408: if (x && GET_CODE (x) == SUBREG) 1.1.1.6 root 1409: x = alter_subreg (x); 1.1.1.2 root 1410: PRINT_OPERAND (asm_out_file, x, code); 1.1 root 1411: } 1412: 1413: /* Print a memory reference operand for address X 1414: using machine-dependent assembler syntax. 1415: The macro PRINT_OPERAND_ADDRESS exists just to control this function. */ 1416: 1.1.1.2 root 1417: void 1.1 root 1418: output_address (x) 1419: rtx x; 1420: { 1.1.1.2 root 1421: walk_alter_subreg (x); 1422: PRINT_OPERAND_ADDRESS (asm_out_file, x); 1.1 root 1423: } 1424: 1425: /* Print an integer constant expression in assembler syntax. 1426: Addition and subtraction are the only arithmetic 1427: that may appear in these expressions. */ 1428: 1429: void 1430: output_addr_const (file, x) 1431: FILE *file; 1432: rtx x; 1433: { 1.1.1.2 root 1434: char buf[20]; 1435: 1.1 root 1436: restart: 1437: switch (GET_CODE (x)) 1438: { 1439: case SYMBOL_REF: 1.1.1.2 root 1440: assemble_name (file, XSTR (x, 0)); 1.1 root 1441: break; 1442: 1443: case LABEL_REF: 1.1.1.2 root 1444: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0))); 1445: assemble_name (asm_out_file, buf); 1.1 root 1446: break; 1447: 1448: case CODE_LABEL: 1.1.1.2 root 1449: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x)); 1450: assemble_name (asm_out_file, buf); 1.1 root 1451: break; 1452: 1453: case CONST_INT: 1454: fprintf (file, "%d", INTVAL (x)); 1455: break; 1456: 1457: case CONST: 1458: x = XEXP (x, 0); 1459: goto restart; 1460: 1.1.1.8 root 1461: case CONST_DOUBLE: 1462: if (GET_MODE (x) == DImode) 1463: { 1464: /* We can use %d if the number is <32 bits and positive. */ 1.1.1.12 root 1465: if (CONST_DOUBLE_HIGH (x) || CONST_DOUBLE_LOW (x) < 0) 1466: fprintf (file, "0x%x%08x", 1467: CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x)); 1.1.1.8 root 1468: else 1.1.1.12 root 1469: fprintf (file, "%d", CONST_DOUBLE_LOW (x)); 1.1.1.8 root 1470: } 1471: else 1472: /* We can't handle floating point constants; 1473: PRINT_OPERAND must handle them. */ 1.1.1.9 root 1474: output_operand_lossage ("floating constant misused"); 1.1.1.8 root 1475: break; 1476: 1.1 root 1477: case PLUS: 1.1.1.4 root 1478: /* Some assemblers need integer constants to appear last (eg masm). */ 1479: if (GET_CODE (XEXP (x, 0)) == CONST_INT) 1480: { 1481: output_addr_const (file, XEXP (x, 1)); 1.1.1.11 root 1482: if (INTVAL (XEXP (x, 0)) >= 0) 1483: fprintf (file, "+"); 1.1.1.4 root 1484: output_addr_const (file, XEXP (x, 0)); 1485: } 1486: else 1487: { 1488: output_addr_const (file, XEXP (x, 0)); 1.1.1.11 root 1489: if (INTVAL (XEXP (x, 1)) >= 0) 1490: fprintf (file, "+"); 1.1.1.4 root 1491: output_addr_const (file, XEXP (x, 1)); 1492: } 1.1 root 1493: break; 1494: 1495: case MINUS: 1496: output_addr_const (file, XEXP (x, 0)); 1497: fprintf (file, "-"); 1498: output_addr_const (file, XEXP (x, 1)); 1499: break; 1500: 1501: default: 1.1.1.9 root 1502: output_operand_lossage ("invalid expression as operand"); 1.1 root 1503: } 1504: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.