|
|
1.1 root 1: /* Convert RTL to assembler code and output it, for GNU compiler. 1.1.1.2 ! root 2: Copyright (C) 1987, 1988 Free Software Foundation, Inc. 1.1 root 3: 4: This file is part of GNU CC. 5: 6: GNU CC is distributed in the hope that it will be useful, 7: but WITHOUT ANY WARRANTY. No author or distributor 8: accepts responsibility to anyone for the consequences of using it 9: or for whether it serves any particular purpose or works at all, 10: unless he says so in writing. Refer to the GNU CC General Public 11: License for full details. 12: 13: Everyone is granted permission to copy, modify and redistribute 14: GNU CC, but only under the conditions described in the 15: GNU CC General Public License. A copy of this license is 16: supposed to have been given to you along with GNU CC so you 17: can know your rights and responsibilities. It should be in a 18: file named COPYING. Among other things, the copyright notice 19: and this notice must be preserved on all copies. */ 20: 21: 22: /* This is the final pass of the compiler. 23: It looks at the rtl code for a function and outputs assembler code. 24: 1.1.1.2 ! root 25: Call `final_start_function' to output the assembler code for function entry, ! 26: `final' to output assembler code for some RTL code, ! 27: `final_end_function' to output assembler code for function exit. ! 28: If a function is compiled in several pieces, each piece is ! 29: output separately with `final'. 1.1 root 30: 31: Some optimizations are also done at this level. 32: Move instructions that were made unnecessary by good register allocation 1.1.1.2 ! root 33: are detected and omitted from the output. (Though most of these ! 34: are removed by the last jump pass.) ! 35: 1.1 root 36: Instructions to set the condition codes are omitted when it can be 37: seen that the condition codes already had the desired values. 1.1.1.2 ! root 38: 1.1 root 39: In some cases it is sufficient if the inherited condition codes 40: have related values, but this may require the following insn 41: (the one that tests the condition codes) to be modified. 42: 43: The code for the function prologue and epilogue are generated 44: directly as assembler code by the macros FUNCTION_PROLOGUE and 45: FUNCTION_EPILOGUE. Those instructions never exist as rtl. */ 46: 47: #include <stdio.h> 48: #include "config.h" 49: #include "rtl.h" 50: #include "regs.h" 51: #include "insn-config.h" 52: #include "recog.h" 53: #include "conditions.h" 1.1.1.2 ! root 54: #include "gdbfiles.h" ! 55: ! 56: /* .stabd code for line number. */ ! 57: #ifndef N_SLINE ! 58: #define N_SLINE 0x44 ! 59: #endif ! 60: ! 61: /* .stabs code for included file name. */ ! 62: #ifndef N_SOL ! 63: #define N_SOL 0x84 ! 64: #endif 1.1 root 65: 66: #define min(A,B) ((A) < (B) ? (A) : (B)) 67: 68: void output_asm_insn (); 69: static void alter_subreg (); 70: static int alter_cond (); 71: static void output_asm_label (); 72: static void output_operand (); 1.1.1.2 ! root 73: void output_address (); 1.1 root 74: void output_addr_const (); 1.1.1.2 ! root 75: static void output_source_line (); 1.1 root 76: 77: static char *reg_name[] = REGISTER_NAMES; 78: 79: /* File in which assembler code is being written. */ 80: 1.1.1.2 ! root 81: extern FILE *asm_out_file; 1.1 root 82: 83: /* All the symbol-blocks (levels of scoping) in the compilation 84: are assigned sequence numbers in order of appearance of the 85: beginnings of the symbol-blocks. Both final and dbxout do this, 86: and assume that they will both give the same number to each block. 87: Final uses these sequence numbers to generate assembler label names 88: LBBnnn and LBEnnn for the beginning and end of the symbol-block. 89: Dbxout uses the sequence nunbers to generate references to the same labels 90: from the dbx debugging information. */ 91: 92: static next_block_index; 93: 1.1.1.2 ! root 94: /* Chain of all `struct gdbfile's. */ ! 95: ! 96: struct gdbfile *gdbfiles; ! 97: ! 98: /* `struct gdbfile' for the last file we wrote a line number for. */ ! 99: ! 100: static struct gdbfile *current_gdbfile; ! 101: ! 102: /* Filenum to assign to the next distinct source file encountered. */ ! 103: ! 104: static int next_gdb_filenum; ! 105: 1.1 root 106: /* This variable contains machine-dependent flags (defined in tm-...h) 107: set and examined by output routines 108: that describe how to interpret the condition codes properly. */ 109: 110: CC_STATUS cc_status; 111: 1.1.1.2 ! root 112: /* During output of an insn, this contains a copy of cc_status ! 113: from before the insn. */ ! 114: ! 115: CC_STATUS cc_prev_status; ! 116: 1.1 root 117: /* Last source file name mentioned in a NOTE insn. */ 118: 119: static char *lastfile; 120: 121: /* Indexed by hardware reg number, is 1 if that register is ever 122: used in the current function. 123: 124: In life_analysis, or in stupid_life_analysis, this is set 125: up to record the hard regs used explicitly. Reload adds 126: in the hard regs used for holding pseudo regs. Final uses 127: it to generate the code in the function prologue and epilogue 128: to save and restore registers as needed. */ 129: 130: char regs_ever_live[FIRST_PSEUDO_REGISTER]; 131: 1.1.1.2 ! root 132: /* Nonzero means current function must be given a frame pointer. ! 133: Set in stmt.c if anything is allocated on the stack there. ! 134: Set in reload1.c if anything is allocated on the stack there. */ ! 135: ! 136: int frame_pointer_needed; ! 137: ! 138: /* Assign unique numbers to labels generated for profiling. */ ! 139: ! 140: int profile_label_no; ! 141: ! 142: /* Length so far allocated in PENDING_BLOCKS. */ ! 143: ! 144: static int max_block_depth; ! 145: ! 146: /* Stack of sequence numbers of symbol-blocks of which we have seen the ! 147: beginning but not yet the end. Sequence numbers are assigned at ! 148: the beginning; this stack allows us to find the sequence number ! 149: of a block that is ending. */ 1.1 root 150: 1.1.1.2 ! root 151: static int *pending_blocks; ! 152: ! 153: /* Number of elements currently in use in PENDING_BLOCKS. */ ! 154: ! 155: static int block_depth; ! 156: ! 157: /* Nonzero if have enabled APP processing of our assembler output. */ ! 158: ! 159: static int app_on; 1.1 root 160: 161: /* Initialize data in final at the beginning of a compilation. */ 162: 163: void 164: init_final (filename) 165: char *filename; 166: { 167: next_block_index = 2; 168: lastfile = filename; 1.1.1.2 ! root 169: app_on = 0; ! 170: max_block_depth = 20; ! 171: pending_blocks = (int *) xmalloc (20 * sizeof *pending_blocks); ! 172: gdbfiles = 0; ! 173: next_gdb_filenum = 0; 1.1 root 174: } 175: 1.1.1.2 ! root 176: /* Enable APP processing of subsequent output. ! 177: Used before the output from an `asm' statement. */ ! 178: ! 179: void ! 180: app_enable () ! 181: { ! 182: if (! app_on) ! 183: { ! 184: fprintf (asm_out_file, ASM_APP_ON); ! 185: app_on = 1; ! 186: } ! 187: } ! 188: ! 189: /* Enable APP processing of subsequent output. ! 190: Called from varasm.c before most kinds of output. */ ! 191: ! 192: void ! 193: app_disable () ! 194: { ! 195: if (app_on) ! 196: { ! 197: fprintf (asm_out_file, ASM_APP_OFF); ! 198: app_on = 0; ! 199: } ! 200: } ! 201: ! 202: /* Output assembler code for the start of a function, ! 203: and initialize some of the variables in this file ! 204: for the new function. The label for the function and associated ! 205: assembler pseudo-ops have already been output in `assemble_function'. ! 206: 1.1 root 207: FIRST is the first insn of the rtl for the function being compiled. 208: FILE is the file to write assembler code to. 209: WRITE_SYMBOLS is 1 for gdb symbols, 2 for dbx symbols. 210: OPTIMIZE is nonzero if we should eliminate redundant 211: test and compare insns. */ 212: 213: void 1.1.1.2 ! root 214: final_start_function (first, file, write_symbols, optimize) 1.1 root 215: rtx first; 216: FILE *file; 217: int write_symbols; 218: int optimize; 219: { 1.1.1.2 ! root 220: extern int profile_flag; 1.1 root 221: 222: init_recog (); 223: 1.1.1.2 ! root 224: block_depth = 0; 1.1 root 225: 226: /* Record beginning of the symbol-block that's the entire function. */ 227: 228: if (write_symbols == 1) 229: { 1.1.1.2 ! root 230: pending_blocks[block_depth++] = next_block_index; 1.1 root 231: fprintf (file, "\t.gdbbeg %d\n", next_block_index++); 232: } 233: 234: /* Initial line number is supposed to be output 235: before the function's prologue and label 236: so that the function's address will not appear to be 237: in the last statement of the preceding function. */ 238: if (NOTE_LINE_NUMBER (first) != NOTE_INSN_DELETED) 1.1.1.2 ! root 239: output_source_line (file, first, write_symbols); 1.1 root 240: 241: #ifdef FUNCTION_PROLOGUE 242: /* First output the function prologue: code to set up the stack frame. */ 243: FUNCTION_PROLOGUE (file, get_frame_size ()); 244: #endif 245: 1.1.1.2 ! root 246: if (profile_flag) ! 247: { ! 248: int align = min (BIGGEST_ALIGNMENT, BITS_PER_WORD); ! 249: fprintf (file, "\t%s\n", DATA_SECTION_ASM_OP); ! 250: ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT)); ! 251: ASM_OUTPUT_INTERNAL_LABEL (file, "LP", profile_label_no); ! 252: assemble_integer_zero (); ! 253: fprintf (file, "\t%s\n", TEXT_SECTION_ASM_OP); ! 254: FUNCTION_PROFILER (file, profile_label_no); ! 255: profile_label_no++; ! 256: } ! 257: 1.1 root 258: CC_STATUS_INIT; 1.1.1.2 ! root 259: } ! 260: ! 261: /* Output assembler code for the end of a function. ! 262: For clarity, args are same as those of `final_start_function' ! 263: even though not all of them are needed. */ ! 264: ! 265: void ! 266: final_end_function (first, file, write_symbols, optimize) ! 267: rtx first; ! 268: FILE *file; ! 269: int write_symbols; ! 270: int optimize; ! 271: { ! 272: if (app_on) ! 273: { ! 274: fprintf (file, ASM_APP_OFF); ! 275: app_on = 0; ! 276: } ! 277: ! 278: if (write_symbols == 1) ! 279: fprintf (file, "\t.gdbend %d\n", pending_blocks[0]); ! 280: ! 281: #ifdef FUNCTION_EPILOGUE ! 282: /* Finally, output the function epilogue: ! 283: code to restore the stack frame and return to the caller. */ ! 284: FUNCTION_EPILOGUE (file, get_frame_size ()); ! 285: #endif ! 286: ! 287: /* If FUNCTION_EPILOGUE is not defined, then the function body ! 288: itself contains return instructions wherever needed. */ ! 289: } ! 290: ! 291: /* Output assembler code for some insns: all or part of a function. ! 292: For description of args, see `final_start_function', above. */ ! 293: ! 294: void ! 295: final (first, file, write_symbols, optimize) ! 296: rtx first; ! 297: FILE *file; ! 298: int write_symbols; ! 299: int optimize; ! 300: { ! 301: register rtx insn; ! 302: register int i; 1.1 root 303: 304: for (insn = NEXT_INSN (first); insn; insn = NEXT_INSN (insn)) 305: { 306: switch (GET_CODE (insn)) 307: { 308: case NOTE: 309: if (! write_symbols) 310: break; 311: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG) 312: abort (); /* Obsolete; shouldn't appear */ 313: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG 314: || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END) 315: break; 316: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED) 317: break; /* An insn that was "deleted" */ 1.1.1.2 ! root 318: if (app_on) ! 319: { ! 320: fprintf (file, ASM_APP_OFF); ! 321: app_on = 0; ! 322: } 1.1 root 323: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG) 324: { 325: /* Beginning of a symbol-block. Assign it a sequence number 326: and push the number onto the stack PENDING_BLOCKS. */ 327: 1.1.1.2 ! root 328: if (block_depth == max_block_depth) 1.1 root 329: { 330: /* PENDING_BLOCKS is full; make it longer. */ 1.1.1.2 ! root 331: max_block_depth *= 2; ! 332: pending_blocks ! 333: = (int *) xrealloc (pending_blocks, ! 334: max_block_depth * sizeof (int)); 1.1 root 335: } 1.1.1.2 ! root 336: pending_blocks[block_depth++] = next_block_index; 1.1 root 337: 338: /* Output debugging info about the symbol-block beginning. */ 339: 340: if (write_symbols == 2) 1.1.1.2 ! root 341: ASM_OUTPUT_INTERNAL_LABEL (file, "LBB", next_block_index); 1.1 root 342: else 1.1.1.2 ! root 343: fprintf (file, "\t.gdbbeg %d\n", next_block_index); ! 344: next_block_index++; 1.1 root 345: } 346: else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END) 347: { 348: /* End of a symbol-block. Pop its sequence number off 349: PENDING_BLOCKS and output debugging info based on that. */ 350: 351: if (write_symbols == 2) 352: { 1.1.1.2 ! root 353: if (block_depth > 0) ! 354: ASM_OUTPUT_INTERNAL_LABEL (file, "LBE", ! 355: pending_blocks[--block_depth]); 1.1 root 356: } 357: else 1.1.1.2 ! root 358: fprintf (file, "\t.gdbend %d\n", pending_blocks[--block_depth]); 1.1 root 359: } 1.1.1.2 ! root 360: else if (NOTE_LINE_NUMBER (insn) > 0) 1.1 root 361: /* This note is a line-number. */ 1.1.1.2 ! root 362: output_source_line (file, insn, write_symbols); 1.1 root 363: break; 364: 365: case BARRIER: 366: break; 367: 368: case CODE_LABEL: 1.1.1.2 ! root 369: if (app_on) ! 370: { ! 371: fprintf (file, ASM_APP_OFF); ! 372: app_on = 0; ! 373: } ! 374: #ifdef ASM_OUTPUT_CASE_LABEL ! 375: if (NEXT_INSN (insn) != 0 ! 376: && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN) ! 377: { ! 378: rtx nextbody = PATTERN (NEXT_INSN (insn)); ! 379: ! 380: /* If this label is followed by a jump-table, ! 381: output the two of them together in a special way. */ ! 382: ! 383: if (GET_CODE (nextbody) == ADDR_VEC ! 384: || GET_CODE (nextbody) == ADDR_DIFF_VEC) ! 385: { ! 386: ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn), ! 387: NEXT_INSN (insn)); ! 388: break; ! 389: } ! 390: } ! 391: #endif ! 392: ! 393: ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn)); 1.1 root 394: CC_STATUS_INIT; 395: break; 396: 397: default: 398: { 399: register rtx body = PATTERN (insn); 400: int insn_code_number; 401: char *template; 402: 403: /* An INSN, JUMP_INSN or CALL_INSN. 1.1.1.2 ! root 404: First check for special kinds that recog doesn't recognize. */ 1.1 root 405: 406: if (GET_CODE (body) == USE /* These are just declarations */ 407: || GET_CODE (body) == CLOBBER) 408: break; 409: if (GET_CODE (body) == ASM_INPUT) 410: { 1.1.1.2 ! root 411: if (! app_on) ! 412: { ! 413: fprintf (file, ASM_APP_ON); ! 414: app_on = 1; ! 415: } ! 416: fprintf (asm_out_file, "\t%s\n", XSTR (body, 0)); ! 417: ! 418: /* There's no telling what that did to the condition codes. */ ! 419: CC_STATUS_INIT; 1.1 root 420: break; 421: } 422: 1.1.1.2 ! root 423: /* Detect `asm' construct with operands. */ ! 424: if (asm_noperands (body) > 0) ! 425: { ! 426: int noperands = asm_noperands (body); ! 427: rtx *ops = (rtx *) malloc (noperands * sizeof (rtx)); ! 428: char *string; ! 429: ! 430: if (! app_on) ! 431: { ! 432: fprintf (file, ASM_APP_ON); ! 433: app_on = 1; ! 434: } ! 435: ! 436: /* Get out the operand values. */ ! 437: string = decode_asm_operands (body, ops, 0, 0, 0); ! 438: /* Output the insn using them. */ ! 439: output_asm_insn (string, ops); ! 440: ! 441: /* There's no telling what that did to the condition codes. */ ! 442: CC_STATUS_INIT; ! 443: break; ! 444: } ! 445: ! 446: if (app_on) ! 447: { ! 448: fprintf (file, ASM_APP_OFF); ! 449: app_on = 0; ! 450: } ! 451: 1.1 root 452: /* Detect insns that are really jump-tables 453: and output them as such. */ 454: 455: if (GET_CODE (body) == ADDR_VEC) 456: { 457: enum machine_mode mode = GET_MODE (body); 458: register int vlen, idx; 459: vlen = XVECLEN (body, 0); 460: for (idx = 0; idx < vlen; idx++) 1.1.1.2 ! root 461: ASM_OUTPUT_ADDR_VEC_ELT (file, 1.1 root 462: CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0))); 463: break; 464: } 465: if (GET_CODE (body) == ADDR_DIFF_VEC) 466: { 467: enum machine_mode mode = GET_MODE (body); 468: register int vlen, idx; 469: vlen = XVECLEN (body, 1); 470: for (idx = 0; idx < vlen; idx++) 1.1.1.2 ! root 471: ASM_OUTPUT_ADDR_DIFF_ELT (file, 1.1 root 472: CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 1, idx), 0)), 473: CODE_LABEL_NUMBER (XEXP (XEXP (body, 0), 0))); 474: break; 475: } 476: 477: /* We have a real machine instruction as rtl. */ 478: 479: body = PATTERN (insn); 480: 1.1.1.2 ! root 481: /* Check for redundant move insns moving a reg into itself. ! 482: This takes little time and does not affect the semantics ! 483: so we do it even when `optimize' is 0. ! 484: It is not safe to do this for memory references; ! 485: we would not know if they were volatile. */ 1.1 root 486: if (GET_CODE (body) == SET 1.1.1.2 ! root 487: && SET_DEST (body) == SET_SRC (body) ! 488: && GET_CODE (SET_DEST (body)) == REG) 1.1 root 489: break; 1.1.1.2 ! root 490: 1.1 root 491: /* Check for redundant test and compare instructions 492: (when the condition codes are already set up as desired). 493: This is done only when optimizing; if not optimizing, 494: it should be possible for the user to alter a variable 495: with the debugger in between statements 496: and the next statement should reexamine the variable 497: to compute the condition codes. */ 498: 499: if (optimize 500: && GET_CODE (body) == SET 501: && GET_CODE (SET_DEST (body)) == CC0) 502: { 503: if (GET_CODE (SET_SRC (body)) == SUBREG) 504: alter_subreg (SET_SRC (body)); 505: if ((cc_status.value1 != 0 506: && rtx_equal_p (SET_SRC (body), cc_status.value1)) 507: || (cc_status.value2 != 0 508: && rtx_equal_p (SET_SRC (body), cc_status.value2))) 1.1.1.2 ! root 509: { ! 510: /* Don't delete insn if has an addressing side-effect */ ! 511: if (! find_reg_note (insn, REG_INC, 0)) ! 512: break; ! 513: } 1.1 root 514: } 515: 516: /* If this is a conditional branch, maybe modify it 517: if the cc's are in a nonstandard state 518: so that it accomplishes the same thing that it would 519: do straightforwardly if the cc's were set up normally. */ 520: 521: if (cc_status.flags != 0 522: && GET_CODE (insn) == JUMP_INSN 523: && GET_CODE (body) == SET 524: && SET_DEST (body) == pc_rtx 525: && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE) 526: { 527: /* This function may alter the contents of its argument 528: and clear some of the cc_status.flags bits. 529: It may also return 1 meaning condition now always true 530: or -1 meaning condition now always false 531: or 2 meaning condition nontrivial but altered. */ 532: register int result = alter_cond (XEXP (SET_SRC (body), 0)); 533: /* If condition now has fixed value, replace the IF_THEN_ELSE 534: with its then-operand or its else-operand. */ 535: if (result == 1) 536: SET_SRC (body) = XEXP (SET_SRC (body), 1); 537: if (result == -1) 538: SET_SRC (body) = XEXP (SET_SRC (body), 2); 539: /* The jump is now either unconditional or a no-op. 540: If it has become a no-op, don't try to output it. 541: (It would not be recognized.) */ 542: if (SET_SRC (body) == pc_rtx) 543: continue; 544: /* Rerecognize the instruction if it has changed. */ 545: if (result != 0) 546: INSN_CODE (insn) = -1; 547: } 548: 549: /* Make same adjustments to instructions that examine the 550: condition codes without jumping. */ 551: 552: if (cc_status.flags != 0 553: && GET_CODE (body) == SET) 554: switch (GET_CODE (SET_SRC (body))) 555: { 556: case GTU: 557: case GT: 558: case LTU: 559: case LT: 560: case GEU: 561: case GE: 562: case LEU: 563: case LE: 564: case EQ: 565: case NE: 566: { 567: register int result = alter_cond (SET_SRC (body)); 568: if (result == 1) 569: SET_SRC (body) = gen_rtx (CONST_INT, VOIDmode, -1); 570: if (result == -1) 571: SET_SRC (body) = const0_rtx; 572: if (result != 0) 573: INSN_CODE (insn) = -1; 574: } 575: } 576: 577: /* Try to recognize the instruction. 578: If successful, verify that the operands satisfy the 579: constraints for the instruction. Crash if they don't, 580: since `reload' should have changed them so that they do. */ 581: 582: insn_code_number = recog_memoized (insn); 583: insn_extract (insn); 584: for (i = 0; i < insn_n_operands[insn_code_number]; i++) 585: if (GET_CODE (recog_operand[i]) == SUBREG) 586: alter_subreg (recog_operand[i]); 587: 588: #ifdef REGISTER_CONSTRAINTS 589: if (! constrain_operands (insn_code_number)) 590: abort (); 591: #endif 592: 1.1.1.2 ! root 593: cc_prev_status = cc_status; ! 594: 1.1 root 595: /* Update `cc_status' for this instruction. 596: The instruction's output routine may change it further. 597: This should be a no-op for jump instructions 598: because their output routines may need to examine `cc_status', 599: below. That's ok since jump insns don't normally alter 600: the condition codes. */ 601: 602: NOTICE_UPDATE_CC (body); 603: 604: /* If the proper template needs to be chosen by some C code, 1.1.1.2 ! root 605: run that code and get the real template. */ 1.1 root 606: 607: template = insn_template[insn_code_number]; 608: if (template == 0) 1.1.1.2 ! root 609: template = insn_outfun[insn_code_number] (recog_operand, insn); 1.1 root 610: 611: /* Output assembler code from the template. */ 612: 613: output_asm_insn (template, recog_operand); 614: } 615: } 616: } 1.1.1.2 ! root 617: } ! 618: ! 619: /* Set up FILENAME as the current file for GDB line-number output. */ 1.1 root 620: 1.1.1.2 ! root 621: void ! 622: set_current_gdbfile (filename) ! 623: char *filename; ! 624: { ! 625: register struct gdbfile *f; ! 626: for (f = gdbfiles; f; f = f->next) ! 627: if (!strcmp (f->name, filename)) ! 628: break; 1.1 root 629: 1.1.1.2 ! root 630: if (!f) ! 631: { ! 632: f = (struct gdbfile *) permalloc (sizeof (struct gdbfile)); ! 633: f->next = gdbfiles; ! 634: gdbfiles = f; ! 635: f->name = filename; ! 636: f->filenum = next_gdb_filenum++; ! 637: f->nlines = 0; ! 638: } ! 639: current_gdbfile = f; ! 640: lastfile = filename; 1.1 root 641: } 642: 1.1.1.2 ! root 643: /* Output debugging info to the assembler file FILE ! 644: based on the NOTE-insn INSN, assumed to be a line number. */ 1.1 root 645: 1.1.1.2 ! root 646: static void ! 647: output_source_line (file, insn, write_symbols) 1.1 root 648: FILE *file; 649: rtx insn; 1.1.1.2 ! root 650: int write_symbols; 1.1 root 651: { 652: register char *filename = NOTE_SOURCE_FILE (insn); 1.1.1.2 ! root 653: if (write_symbols == 1) ! 654: { ! 655: /* Output GDB-format line number info. */ 1.1 root 656: 1.1.1.2 ! root 657: /* If this is not the same source file as last time, ! 658: find or assign a GDB-file-number to this file. */ ! 659: if (filename && (lastfile == 0 || strcmp (filename, lastfile) ! 660: || current_gdbfile == 0)) ! 661: set_current_gdbfile (filename); ! 662: ! 663: ++current_gdbfile->nlines; ! 664: fprintf (file, "\t.gdbline %d,%d\n", ! 665: current_gdbfile->filenum, NOTE_LINE_NUMBER (insn)); ! 666: } ! 667: else ! 668: { ! 669: /* Write DBX line number data. */ ! 670: ! 671: if (filename && (lastfile == 0 || strcmp (filename, lastfile))) ! 672: #ifdef ASM_OUTPUT_SOURCE_FILENAME ! 673: ASM_OUTPUT_SOURCE_FILENAME (file, filename); ! 674: #else ! 675: fprintf (file, "\t.stabs \"%s\",%d,0,0,Ltext\n", ! 676: filename, N_SOL); ! 677: #endif ! 678: lastfile = filename; ! 679: ! 680: #ifdef ASM_OUTPUT_SOURCE_LINE ! 681: ASM_OUTPUT_SOURCE_LINE (file, NOTE_LINE_NUMBER (insn)); ! 682: #else ! 683: fprintf (file, "\t.stabd %d,0,%d\n", ! 684: N_SLINE, NOTE_LINE_NUMBER (insn)); ! 685: #endif ! 686: } 1.1 root 687: } 688: 1.1.1.2 ! root 689: /* If X is a SUBREG, replace it with a REG or a MEM, ! 690: based on the thing it is a subreg of. */ 1.1 root 691: 692: static void 693: alter_subreg (x) 694: register rtx x; 695: { 696: register rtx y = SUBREG_REG (x); 697: if (GET_CODE (y) == SUBREG) 698: alter_subreg (y); 699: 700: if (GET_CODE (y) == REG) 701: { 702: /* If the containing reg really gets a hard reg, so do we. */ 703: PUT_CODE (x, REG); 704: REGNO (x) = REGNO (y) + SUBREG_WORD (x); 705: } 706: else if (GET_CODE (y) == MEM) 707: { 1.1.1.2 ! root 708: register int offset = SUBREG_WORD (x) * UNITS_PER_WORD; 1.1 root 709: #ifdef BYTES_BIG_ENDIAN 1.1.1.2 ! root 710: offset -= (min (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))) ! 711: - min (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (y)))); 1.1 root 712: #endif 713: PUT_CODE (x, MEM); 714: XEXP (x, 0) = plus_constant (XEXP (y, 0), offset); 715: } 716: } 717: 1.1.1.2 ! root 718: /* Do alter_subreg on all the SUBREGs contained in X. */ 1.1 root 719: 1.1.1.2 ! root 720: static rtx ! 721: walk_alter_subreg (x) ! 722: rtx x; ! 723: { ! 724: switch (GET_CODE (x)) 1.1 root 725: { 1.1.1.2 ! root 726: case PLUS: ! 727: case MULT: ! 728: XEXP (x, 0) = walk_alter_subreg (XEXP (x, 0)); ! 729: XEXP (x, 1) = walk_alter_subreg (XEXP (x, 1)); ! 730: break; ! 731: ! 732: case MEM: ! 733: XEXP (x, 0) = walk_alter_subreg (XEXP (x, 0)); ! 734: break; ! 735: ! 736: case SUBREG: ! 737: alter_subreg (x); 1.1 root 738: } 739: 1.1.1.2 ! root 740: return x; 1.1 root 741: } 742: 743: /* Given BODY, the body of a jump instruction, alter the jump condition 744: as required by the bits that are set in cc_status.flags. 745: Not all of the bits there can be handled at this level in all cases. 746: The bits that are taken care of here are cleared. 747: 748: The value is normally 0. 749: In this case, COND itself has usually been altered. 750: 1 means that the condition has become always true. 751: -1 means that the condition has become always false. */ 752: 753: static int 754: alter_cond (cond) 755: register rtx cond; 756: { 757: int value = 0; 758: 759: if (cc_status.flags & CC_REVERSED) 760: { 761: value = 2; 762: switch (GET_CODE (cond)) 763: { 764: case LE: 765: PUT_CODE (cond, GE); 766: break; 767: case GE: 768: PUT_CODE (cond, LE); 769: break; 770: case LT: 771: PUT_CODE (cond, GT); 772: break; 773: case GT: 774: PUT_CODE (cond, LT); 775: break; 776: case LEU: 777: PUT_CODE (cond, GEU); 778: break; 779: case GEU: 780: PUT_CODE (cond, LEU); 781: break; 782: case LTU: 783: PUT_CODE (cond, GTU); 784: break; 785: case GTU: 786: PUT_CODE (cond, LTU); 787: break; 788: } 789: } 790: 791: if (cond != 0 && cc_status.flags & CC_NOT_POSITIVE) 792: switch (GET_CODE (cond)) 793: { 794: case LE: 795: case LEU: 796: case GEU: 797: /* Jump becomes unconditional. */ 798: return 1; 799: 800: case GT: 801: case GTU: 802: case LTU: 803: /* Jump becomes no-op. */ 804: return -1; 805: 806: case GE: 807: PUT_CODE (cond, EQ); 808: value = 2; 809: break; 810: 811: case LT: 812: PUT_CODE (cond, NE); 813: value = 2; 814: break; 815: } 816: 817: if (cond != 0 && cc_status.flags & CC_NOT_NEGATIVE) 818: switch (GET_CODE (cond)) 819: { 820: case GE: 821: case GEU: 822: /* Jump becomes unconditional. */ 823: return 1; 824: 825: case LT: 826: case LTU: 827: /* Jump becomes no-op. */ 828: return -1; 829: 830: case LE: 831: case LEU: 832: PUT_CODE (cond, EQ); 833: value = 2; 834: break; 835: 836: case GT: 837: case GTU: 838: PUT_CODE (cond, NE); 839: value = 2; 840: break; 841: } 842: 843: if (cond != 0 && cc_status.flags & CC_NO_OVERFLOW) 844: switch (GET_CODE (cond)) 845: { 846: case GEU: 847: /* Jump becomes unconditional. */ 848: return 1; 849: 850: case LEU: 851: PUT_CODE (cond, EQ); 852: value = 2; 853: break; 854: 855: case GTU: 856: PUT_CODE (cond, NE); 857: value = 2; 858: break; 859: 860: case LTU: 861: /* Jump becomes no-op. */ 862: return -1; 863: } 864: 865: return value; 866: } 867: 868: /* Output of assembler code from a template, and its subroutines. */ 869: 870: /* Output text from TEMPLATE to the assembler output file, 871: obeying %-directions to substitute operands taken from 872: the vector OPERANDS. 873: 874: %N (for N a digit) means print operand N in usual manner. 875: %lN means require operand N to be a CODE_LABEL or LABEL_REF 876: and print the label name with no punctuation. 877: %cN means require operand N to be a constant 878: and print the constant expression with no punctuation. 879: %aN means expect operand N to be a memory address 880: (not a memory reference!) and print a reference 881: to that address. 882: %nN means expect operand N to be a constant 883: and print a constant expression for minus the value 884: of the operand, with no other punctuation. */ 885: 886: void 887: output_asm_insn (template, operands) 888: char *template; 889: rtx *operands; 890: { 891: register char *p; 892: register int c; 893: 1.1.1.2 ! root 894: /* An insn may return a null string template ! 895: in a case where no assembler code is needed. */ ! 896: if (*template == 0) ! 897: return; ! 898: 1.1 root 899: p = template; 1.1.1.2 ! root 900: putc ('\t', asm_out_file); ! 901: ! 902: #ifdef ASM_OUTPUT_OPCODE ! 903: ASM_OUTPUT_OPCODE (asm_out_file, p); ! 904: #endif ! 905: 1.1 root 906: while (c = *p++) 907: { 1.1.1.2 ! root 908: #ifdef ASM_OUTPUT_OPCODE ! 909: if (c == '\n') 1.1 root 910: { 1.1.1.2 ! root 911: putc (c, asm_out_file); ! 912: while ((c = *p) == '\t') 1.1 root 913: { 1.1.1.2 ! root 914: putc (c, asm_out_file); ! 915: p++; 1.1 root 916: } 1.1.1.2 ! root 917: ASM_OUTPUT_OPCODE (asm_out_file, p); ! 918: } ! 919: else ! 920: #endif ! 921: if (c != '%') ! 922: putc (c, asm_out_file); ! 923: else ! 924: { ! 925: /* %% outputs a single %. */ ! 926: if (*p == '%') 1.1 root 927: { 1.1.1.2 ! root 928: p++; ! 929: putc (c, asm_out_file); 1.1 root 930: } 1.1.1.2 ! root 931: /* % followed by a letter and some digits ! 932: outputs an operand in a special way depending on the letter. ! 933: Letters `acln' are implemented here. ! 934: Other letters are passed to `output_operand' so that ! 935: the PRINT_OPERAND macro can define them. */ ! 936: else if ((*p >= 'a' && *p <= 'z') ! 937: || (*p >= 'A' && *p <= 'Z')) 1.1 root 938: { 1.1.1.2 ! root 939: int letter = *p++; ! 940: c = atoi (p); ! 941: ! 942: if (letter == 'l') ! 943: output_asm_label (operands[c]); ! 944: else if (letter == 'a') ! 945: output_address (operands[c]); ! 946: else if (letter == 'c') ! 947: { ! 948: if (CONSTANT_ADDRESS_P (operands[c])) ! 949: output_addr_const (asm_out_file, operands[c]); ! 950: else ! 951: output_operand (operands[c], 'c'); ! 952: } ! 953: else if (letter == 'n') 1.1 root 954: { 1.1.1.2 ! root 955: if (GET_CODE (operands[c]) == CONST_INT) ! 956: fprintf (asm_out_file, "%d", - INTVAL (operands[c])); ! 957: else ! 958: { ! 959: putc ('-', asm_out_file); ! 960: output_addr_const (asm_out_file, operands[c]); ! 961: } 1.1 root 962: } 1.1.1.2 ! root 963: else if (*p >= '0' && *p <= '9') ! 964: output_operand (operands[c], letter); ! 965: else ! 966: /* No operand-number follows the letter. */ ! 967: output_operand (0, letter); ! 968: ! 969: while ((c = *p) >= '0' && c <= '9') p++; 1.1 root 970: } 1.1.1.2 ! root 971: /* % followed by a digit outputs an operand the default way. */ ! 972: else if (*p >= '0' && *p <= '9') 1.1 root 973: { 974: c = atoi (p); 1.1.1.2 ! root 975: output_operand (operands[c], 0); ! 976: while ((c = *p) >= '0' && c <= '9') p++; 1.1 root 977: } 1.1.1.2 ! root 978: /* % followed by punctuation: output something for that ! 979: punctuation character alone, with no operand. ! 980: The PRINT_OPERAND macro decides what is actually done. */ ! 981: else ! 982: output_operand (0, *p++); 1.1 root 983: } 984: } 985: 1.1.1.2 ! root 986: putc ('\n', asm_out_file); 1.1 root 987: } 988: 989: static void 990: output_asm_label (x) 991: rtx x; 992: { 1.1.1.2 ! root 993: char buf[20]; ! 994: 1.1 root 995: if (GET_CODE (x) == LABEL_REF) 1.1.1.2 ! root 996: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0))); 1.1 root 997: else if (GET_CODE (x) == CODE_LABEL) 1.1.1.2 ! root 998: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x)); 1.1 root 999: else 1000: abort (); 1.1.1.2 ! root 1001: ! 1002: assemble_name (asm_out_file, buf); 1.1 root 1003: } 1004: 1005: /* Print operand X using machine-dependent assembler syntax. 1.1.1.2 ! root 1006: The macro PRINT_OPERAND is defined just to control this function. ! 1007: CODE is a non-digit that preceded the operand-number in the % spec, ! 1008: such as 'z' if the spec was `%z3'. CODE is 0 if there was no char ! 1009: between the % and the digits. ! 1010: When CODE is a non-letter, X is 0. ! 1011: ! 1012: The meanings of the letters are machine-dependent and controlled ! 1013: by PRINT_OPERAND. */ 1.1 root 1014: 1015: static void 1.1.1.2 ! root 1016: output_operand (x, code) 1.1 root 1017: rtx x; 1.1.1.2 ! root 1018: int code; 1.1 root 1019: { 1.1.1.2 ! root 1020: if (x && GET_CODE (x) == SUBREG) 1.1 root 1021: alter_subreg (x); 1.1.1.2 ! root 1022: PRINT_OPERAND (asm_out_file, x, code); 1.1 root 1023: } 1024: 1025: /* Print a memory reference operand for address X 1026: using machine-dependent assembler syntax. 1027: The macro PRINT_OPERAND_ADDRESS exists just to control this function. */ 1028: 1.1.1.2 ! root 1029: void 1.1 root 1030: output_address (x) 1031: rtx x; 1032: { 1.1.1.2 ! root 1033: walk_alter_subreg (x); ! 1034: PRINT_OPERAND_ADDRESS (asm_out_file, x); 1.1 root 1035: } 1036: 1037: /* Print an integer constant expression in assembler syntax. 1038: Addition and subtraction are the only arithmetic 1039: that may appear in these expressions. */ 1040: 1041: void 1042: output_addr_const (file, x) 1043: FILE *file; 1044: rtx x; 1045: { 1.1.1.2 ! root 1046: char buf[20]; ! 1047: 1.1 root 1048: restart: 1049: switch (GET_CODE (x)) 1050: { 1051: case SYMBOL_REF: 1.1.1.2 ! root 1052: assemble_name (file, XSTR (x, 0)); 1.1 root 1053: break; 1054: 1055: case LABEL_REF: 1.1.1.2 ! root 1056: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0))); ! 1057: assemble_name (asm_out_file, buf); 1.1 root 1058: break; 1059: 1060: case CODE_LABEL: 1.1.1.2 ! root 1061: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x)); ! 1062: assemble_name (asm_out_file, buf); 1.1 root 1063: break; 1064: 1065: case CONST_INT: 1066: fprintf (file, "%d", INTVAL (x)); 1067: break; 1068: 1069: case CONST: 1070: x = XEXP (x, 0); 1071: goto restart; 1072: 1073: case PLUS: 1074: output_addr_const (file, XEXP (x, 0)); 1075: fprintf (file, "+"); 1076: output_addr_const (file, XEXP (x, 1)); 1077: break; 1078: 1079: case MINUS: 1080: output_addr_const (file, XEXP (x, 0)); 1081: fprintf (file, "-"); 1082: output_addr_const (file, XEXP (x, 1)); 1083: break; 1084: 1085: default: 1086: abort (); 1087: } 1088: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.