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