|
|
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 ();
1.1.1.6 root 75: static rtx alter_subreg ();
1.1 root 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);
1.1.1.6 root 276: data_section ();
1.1.1.2 root 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 ();
1.1.1.6 root 280: text_section ();
1.1.1.2 root 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:
1.1.1.6 root 319: #ifdef SDB_DEBUGGING_INFO
320: if (write_symbols == SDB_DEBUG)
321: sdbout_end_epilogue ();
322: #endif
323:
1.1.1.2 root 324: /* If FUNCTION_EPILOGUE is not defined, then the function body
325: itself contains return instructions wherever needed. */
326: }
327:
328: /* Output assembler code for some insns: all or part of a function.
329: For description of args, see `final_start_function', above. */
330:
331: void
332: final (first, file, write_symbols, optimize)
333: rtx first;
334: FILE *file;
1.1.1.4 root 335: enum debugger write_symbols;
1.1.1.2 root 336: int optimize;
337: {
338: register rtx insn;
339: register int i;
1.1 root 340:
341: for (insn = NEXT_INSN (first); insn; insn = NEXT_INSN (insn))
342: {
343: switch (GET_CODE (insn))
344: {
345: case NOTE:
1.1.1.4 root 346: if (write_symbols == NO_DEBUG)
1.1 root 347: break;
348: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG)
349: abort (); /* Obsolete; shouldn't appear */
350: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
351: || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
352: break;
353: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED)
354: break; /* An insn that was "deleted" */
1.1.1.2 root 355: if (app_on)
356: {
357: fprintf (file, ASM_APP_OFF);
358: app_on = 0;
359: }
1.1 root 360: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG)
361: {
362: /* Beginning of a symbol-block. Assign it a sequence number
363: and push the number onto the stack PENDING_BLOCKS. */
364:
1.1.1.2 root 365: if (block_depth == max_block_depth)
1.1 root 366: {
367: /* PENDING_BLOCKS is full; make it longer. */
1.1.1.2 root 368: max_block_depth *= 2;
369: pending_blocks
370: = (int *) xrealloc (pending_blocks,
371: max_block_depth * sizeof (int));
1.1 root 372: }
1.1.1.2 root 373: pending_blocks[block_depth++] = next_block_index;
1.1 root 374:
375: /* Output debugging info about the symbol-block beginning. */
376:
1.1.1.4 root 377: #ifdef SDB_DEBUGGING_INFO
378: if (write_symbols == SDB_DEBUG)
379: sdbout_begin_block (file, last_linenum, next_block_index);
380: #endif
381: #ifdef DBX_DEBUGGING_INFO
382: if (write_symbols == DBX_DEBUG)
1.1.1.2 root 383: ASM_OUTPUT_INTERNAL_LABEL (file, "LBB", next_block_index);
1.1.1.4 root 384: #endif
385: if (write_symbols == GDB_DEBUG)
1.1.1.2 root 386: fprintf (file, "\t.gdbbeg %d\n", next_block_index);
1.1.1.4 root 387:
1.1.1.2 root 388: next_block_index++;
1.1 root 389: }
390: else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
391: {
392: /* End of a symbol-block. Pop its sequence number off
393: PENDING_BLOCKS and output debugging info based on that. */
394:
1.1.1.4 root 395: --block_depth;
396:
397: #ifdef DBX_DEBUGGING_INFO
398: if (write_symbols == DBX_DEBUG && block_depth >= 0)
399: ASM_OUTPUT_INTERNAL_LABEL (file, "LBE",
400: pending_blocks[block_depth]);
401: #endif
402:
403: #ifdef SDB_DEBUGGING_INFO
404: if (write_symbols == SDB_DEBUG && block_depth >= 0)
405: sdbout_end_block (file, last_linenum);
406: #endif
407:
408: if (write_symbols == GDB_DEBUG)
409: fprintf (file, "\t.gdbend %d\n", pending_blocks[block_depth]);
1.1 root 410: }
1.1.1.2 root 411: else if (NOTE_LINE_NUMBER (insn) > 0)
1.1 root 412: /* This note is a line-number. */
1.1.1.2 root 413: output_source_line (file, insn, write_symbols);
1.1 root 414: break;
415:
416: case BARRIER:
417: break;
418:
419: case CODE_LABEL:
1.1.1.2 root 420: if (app_on)
421: {
422: fprintf (file, ASM_APP_OFF);
423: app_on = 0;
424: }
425: #ifdef ASM_OUTPUT_CASE_LABEL
426: if (NEXT_INSN (insn) != 0
427: && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN)
428: {
429: rtx nextbody = PATTERN (NEXT_INSN (insn));
430:
431: /* If this label is followed by a jump-table,
432: output the two of them together in a special way. */
433:
434: if (GET_CODE (nextbody) == ADDR_VEC
435: || GET_CODE (nextbody) == ADDR_DIFF_VEC)
436: {
437: ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn),
438: NEXT_INSN (insn));
439: break;
440: }
441: }
442: #endif
443:
444: ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
1.1 root 445: CC_STATUS_INIT;
446: break;
447:
448: default:
449: {
450: register rtx body = PATTERN (insn);
451: int insn_code_number;
452: char *template;
453:
454: /* An INSN, JUMP_INSN or CALL_INSN.
1.1.1.2 root 455: First check for special kinds that recog doesn't recognize. */
1.1.1.4 root 456:
1.1 root 457: if (GET_CODE (body) == USE /* These are just declarations */
458: || GET_CODE (body) == CLOBBER)
459: break;
460: if (GET_CODE (body) == ASM_INPUT)
461: {
1.1.1.2 root 462: if (! app_on)
463: {
464: fprintf (file, ASM_APP_ON);
465: app_on = 1;
466: }
467: fprintf (asm_out_file, "\t%s\n", XSTR (body, 0));
468:
469: /* There's no telling what that did to the condition codes. */
470: CC_STATUS_INIT;
1.1 root 471: break;
472: }
473:
1.1.1.2 root 474: /* Detect `asm' construct with operands. */
475: if (asm_noperands (body) > 0)
476: {
477: int noperands = asm_noperands (body);
478: rtx *ops = (rtx *) malloc (noperands * sizeof (rtx));
479: char *string;
480:
481: if (! app_on)
482: {
483: fprintf (file, ASM_APP_ON);
484: app_on = 1;
485: }
486:
487: /* Get out the operand values. */
488: string = decode_asm_operands (body, ops, 0, 0, 0);
489: /* Output the insn using them. */
490: output_asm_insn (string, ops);
491:
492: /* There's no telling what that did to the condition codes. */
493: CC_STATUS_INIT;
494: break;
495: }
496:
497: if (app_on)
498: {
499: fprintf (file, ASM_APP_OFF);
500: app_on = 0;
501: }
502:
1.1 root 503: /* Detect insns that are really jump-tables
504: and output them as such. */
505:
506: if (GET_CODE (body) == ADDR_VEC)
507: {
508: enum machine_mode mode = GET_MODE (body);
509: register int vlen, idx;
510: vlen = XVECLEN (body, 0);
511: for (idx = 0; idx < vlen; idx++)
1.1.1.4 root 512: ASM_OUTPUT_ADDR_VEC_ELT (file,
1.1 root 513: CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0)));
1.1.1.4 root 514: #ifdef ASM_OUTPUT_CASE_END
515: ASM_OUTPUT_CASE_END (file,
516: CODE_LABEL_NUMBER (PREV_INSN (insn)),
517: insn);
518: #endif
1.1 root 519: break;
520: }
521: if (GET_CODE (body) == ADDR_DIFF_VEC)
522: {
523: enum machine_mode mode = GET_MODE (body);
524: register int vlen, idx;
525: vlen = XVECLEN (body, 1);
526: for (idx = 0; idx < vlen; idx++)
1.1.1.4 root 527: ASM_OUTPUT_ADDR_DIFF_ELT (file,
1.1 root 528: CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 1, idx), 0)),
529: CODE_LABEL_NUMBER (XEXP (XEXP (body, 0), 0)));
1.1.1.4 root 530: #ifdef ASM_OUTPUT_CASE_END
1.1.1.7 ! root 531: ASM_OUTPUT_CASE_END (file,
! 532: CODE_LABEL_NUMBER (PREV_INSN (insn)),
! 533: insn);
1.1.1.4 root 534: #endif
1.1 root 535: break;
536: }
537:
538: /* We have a real machine instruction as rtl. */
539:
540: body = PATTERN (insn);
541:
1.1.1.2 root 542: /* Check for redundant move insns moving a reg into itself.
543: This takes little time and does not affect the semantics
544: so we do it even when `optimize' is 0.
545: It is not safe to do this for memory references;
546: we would not know if they were volatile. */
1.1 root 547: if (GET_CODE (body) == SET
1.1.1.2 root 548: && SET_DEST (body) == SET_SRC (body)
549: && GET_CODE (SET_DEST (body)) == REG)
1.1 root 550: break;
1.1.1.4 root 551:
552: /* Check for redundant test and compare instructions
1.1 root 553: (when the condition codes are already set up as desired).
554: This is done only when optimizing; if not optimizing,
555: it should be possible for the user to alter a variable
556: with the debugger in between statements
557: and the next statement should reexamine the variable
558: to compute the condition codes. */
559:
560: if (optimize
561: && GET_CODE (body) == SET
562: && GET_CODE (SET_DEST (body)) == CC0)
563: {
564: if (GET_CODE (SET_SRC (body)) == SUBREG)
1.1.1.6 root 565: SET_SRC (body) = alter_subreg (SET_SRC (body));
1.1 root 566: if ((cc_status.value1 != 0
567: && rtx_equal_p (SET_SRC (body), cc_status.value1))
568: || (cc_status.value2 != 0
569: && rtx_equal_p (SET_SRC (body), cc_status.value2)))
1.1.1.2 root 570: {
571: /* Don't delete insn if has an addressing side-effect */
1.1.1.6 root 572: if (! find_reg_note (insn, REG_INC, 0)
573: /* or if anything in it is volatile. */
574: && ! volatile_refs_p (PATTERN (insn)))
1.1.1.2 root 575: break;
576: }
1.1 root 577: }
578:
579: /* If this is a conditional branch, maybe modify it
580: if the cc's are in a nonstandard state
581: so that it accomplishes the same thing that it would
582: do straightforwardly if the cc's were set up normally. */
583:
584: if (cc_status.flags != 0
585: && GET_CODE (insn) == JUMP_INSN
586: && GET_CODE (body) == SET
587: && SET_DEST (body) == pc_rtx
588: && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE)
589: {
590: /* This function may alter the contents of its argument
591: and clear some of the cc_status.flags bits.
592: It may also return 1 meaning condition now always true
593: or -1 meaning condition now always false
594: or 2 meaning condition nontrivial but altered. */
595: register int result = alter_cond (XEXP (SET_SRC (body), 0));
596: /* If condition now has fixed value, replace the IF_THEN_ELSE
597: with its then-operand or its else-operand. */
598: if (result == 1)
599: SET_SRC (body) = XEXP (SET_SRC (body), 1);
600: if (result == -1)
601: SET_SRC (body) = XEXP (SET_SRC (body), 2);
602: /* The jump is now either unconditional or a no-op.
603: If it has become a no-op, don't try to output it.
604: (It would not be recognized.) */
605: if (SET_SRC (body) == pc_rtx)
606: continue;
607: /* Rerecognize the instruction if it has changed. */
608: if (result != 0)
609: INSN_CODE (insn) = -1;
610: }
611:
612: /* Make same adjustments to instructions that examine the
613: condition codes without jumping. */
614:
615: if (cc_status.flags != 0
616: && GET_CODE (body) == SET)
617: switch (GET_CODE (SET_SRC (body)))
618: {
619: case GTU:
620: case GT:
621: case LTU:
622: case LT:
623: case GEU:
624: case GE:
625: case LEU:
626: case LE:
627: case EQ:
628: case NE:
629: {
630: register int result = alter_cond (SET_SRC (body));
631: if (result == 1)
632: SET_SRC (body) = gen_rtx (CONST_INT, VOIDmode, -1);
633: if (result == -1)
634: SET_SRC (body) = const0_rtx;
635: if (result != 0)
636: INSN_CODE (insn) = -1;
637: }
638: }
639:
640: /* Try to recognize the instruction.
641: If successful, verify that the operands satisfy the
642: constraints for the instruction. Crash if they don't,
643: since `reload' should have changed them so that they do. */
644:
645: insn_code_number = recog_memoized (insn);
646: insn_extract (insn);
647: for (i = 0; i < insn_n_operands[insn_code_number]; i++)
648: if (GET_CODE (recog_operand[i]) == SUBREG)
1.1.1.6 root 649: recog_operand[i] = alter_subreg (recog_operand[i]);
1.1 root 650:
651: #ifdef REGISTER_CONSTRAINTS
652: if (! constrain_operands (insn_code_number))
653: abort ();
654: #endif
655:
1.1.1.4 root 656: /* Some target machines need to prescan each insn before
657: it is output. */
658:
659: #ifdef FINAL_PRESCAN_INSN
660: FINAL_PRESCAN_INSN (insn, recog_operand,
661: insn_n_operands[insn_code_number]);
662: #endif
663:
1.1.1.2 root 664: cc_prev_status = cc_status;
665:
1.1 root 666: /* Update `cc_status' for this instruction.
667: The instruction's output routine may change it further.
668: This should be a no-op for jump instructions
669: because their output routines may need to examine `cc_status',
670: below. That's ok since jump insns don't normally alter
671: the condition codes. */
672:
673: NOTICE_UPDATE_CC (body);
674:
675: /* If the proper template needs to be chosen by some C code,
1.1.1.2 root 676: run that code and get the real template. */
1.1 root 677:
678: template = insn_template[insn_code_number];
679: if (template == 0)
1.1.1.5 root 680: template = (*insn_outfun[insn_code_number]) (recog_operand, insn);
1.1 root 681:
682: /* Output assembler code from the template. */
683:
684: output_asm_insn (template, recog_operand);
685: }
686: }
687: }
1.1.1.2 root 688: }
689:
690: /* Set up FILENAME as the current file for GDB line-number output. */
1.1 root 691:
1.1.1.2 root 692: void
693: set_current_gdbfile (filename)
694: char *filename;
695: {
696: register struct gdbfile *f;
697: for (f = gdbfiles; f; f = f->next)
698: if (!strcmp (f->name, filename))
699: break;
1.1 root 700:
1.1.1.2 root 701: if (!f)
702: {
703: f = (struct gdbfile *) permalloc (sizeof (struct gdbfile));
704: f->next = gdbfiles;
705: gdbfiles = f;
706: f->name = filename;
707: f->filenum = next_gdb_filenum++;
708: f->nlines = 0;
709: }
710: current_gdbfile = f;
711: lastfile = filename;
1.1 root 712: }
713:
1.1.1.2 root 714: /* Output debugging info to the assembler file FILE
715: based on the NOTE-insn INSN, assumed to be a line number. */
1.1 root 716:
1.1.1.2 root 717: static void
718: output_source_line (file, insn, write_symbols)
1.1 root 719: FILE *file;
720: rtx insn;
1.1.1.4 root 721: enum debugger write_symbols;
1.1 root 722: {
723: register char *filename = NOTE_SOURCE_FILE (insn);
1.1.1.4 root 724:
725: last_linenum = NOTE_LINE_NUMBER (insn);
726:
727: if (write_symbols == GDB_DEBUG)
1.1.1.2 root 728: {
729: /* Output GDB-format line number info. */
1.1 root 730:
1.1.1.2 root 731: /* If this is not the same source file as last time,
732: find or assign a GDB-file-number to this file. */
733: if (filename && (lastfile == 0 || strcmp (filename, lastfile)
734: || current_gdbfile == 0))
735: set_current_gdbfile (filename);
736:
737: ++current_gdbfile->nlines;
738: fprintf (file, "\t.gdbline %d,%d\n",
739: current_gdbfile->filenum, NOTE_LINE_NUMBER (insn));
740: }
1.1.1.4 root 741:
1.1.1.6 root 742: if (write_symbols == SDB_DEBUG || write_symbols == DBX_DEBUG)
1.1.1.4 root 743: {
1.1.1.6 root 744: #ifdef SDB_DEBUGGING_INFO
745: if (write_symbols == SDB_DEBUG
746: /* COFF can't handle multiple source files--lose, lose. */
747: && !strcmp (filename, main_input_filename))
748: {
1.1.1.4 root 749: #ifdef ASM_OUTPUT_SOURCE_LINE
1.1.1.6 root 750: ASM_OUTPUT_SOURCE_LINE (file, last_linenum);
1.1.1.4 root 751: #else
1.1.1.6 root 752: fprintf (file, "\t.ln\t%d\n",
753: (sdb_begin_function_line
754: ? last_linenum - sdb_begin_function_line : 1));
1.1.1.4 root 755: #endif
1.1.1.6 root 756: }
1.1.1.4 root 757: #endif
758:
759: #ifdef DBX_DEBUGGING_INFO
1.1.1.6 root 760: if (write_symbols == DBX_DEBUG)
1.1.1.4 root 761: {
1.1.1.6 root 762: /* Write DBX line number data. */
763:
764: if (filename && (lastfile == 0 || strcmp (filename, lastfile)))
765: {
1.1.1.2 root 766: #ifdef ASM_OUTPUT_SOURCE_FILENAME
1.1.1.6 root 767: ASM_OUTPUT_SOURCE_FILENAME (file, filename);
1.1.1.2 root 768: #else
1.1.1.6 root 769: fprintf (file, "\t.stabs \"%s\",%d,0,0,Ltext\n",
770: filename, N_SOL);
1.1.1.2 root 771: #endif
1.1.1.6 root 772: lastfile = filename;
773: }
1.1.1.4 root 774: }
1.1.1.2 root 775:
776: #ifdef ASM_OUTPUT_SOURCE_LINE
777: ASM_OUTPUT_SOURCE_LINE (file, NOTE_LINE_NUMBER (insn));
778: #else
779: fprintf (file, "\t.stabd %d,0,%d\n",
780: N_SLINE, NOTE_LINE_NUMBER (insn));
781: #endif
1.1.1.4 root 782: #endif /* DBX_DEBUGGING_INFO */
1.1.1.2 root 783: }
1.1 root 784: }
785:
1.1.1.2 root 786: /* If X is a SUBREG, replace it with a REG or a MEM,
787: based on the thing it is a subreg of. */
1.1 root 788:
1.1.1.6 root 789: static rtx
1.1 root 790: alter_subreg (x)
791: register rtx x;
792: {
793: register rtx y = SUBREG_REG (x);
794: if (GET_CODE (y) == SUBREG)
1.1.1.6 root 795: y = alter_subreg (y);
1.1 root 796:
797: if (GET_CODE (y) == REG)
798: {
799: /* If the containing reg really gets a hard reg, so do we. */
800: PUT_CODE (x, REG);
801: REGNO (x) = REGNO (y) + SUBREG_WORD (x);
802: }
803: else if (GET_CODE (y) == MEM)
804: {
1.1.1.2 root 805: register int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
1.1 root 806: #ifdef BYTES_BIG_ENDIAN
1.1.1.2 root 807: offset -= (min (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x)))
808: - min (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (y))));
1.1 root 809: #endif
810: PUT_CODE (x, MEM);
811: XEXP (x, 0) = plus_constant (XEXP (y, 0), offset);
812: }
1.1.1.6 root 813: else if (GET_CODE (y) == CONST_DOUBLE)
814: return y;
815:
816: return x;
1.1 root 817: }
818:
1.1.1.2 root 819: /* Do alter_subreg on all the SUBREGs contained in X. */
1.1 root 820:
1.1.1.2 root 821: static rtx
822: walk_alter_subreg (x)
823: rtx x;
824: {
825: switch (GET_CODE (x))
1.1 root 826: {
1.1.1.2 root 827: case PLUS:
828: case MULT:
829: XEXP (x, 0) = walk_alter_subreg (XEXP (x, 0));
830: XEXP (x, 1) = walk_alter_subreg (XEXP (x, 1));
831: break;
832:
833: case MEM:
834: XEXP (x, 0) = walk_alter_subreg (XEXP (x, 0));
835: break;
836:
837: case SUBREG:
1.1.1.6 root 838: return alter_subreg (x);
1.1 root 839: }
840:
1.1.1.2 root 841: return x;
1.1 root 842: }
843:
844: /* Given BODY, the body of a jump instruction, alter the jump condition
845: as required by the bits that are set in cc_status.flags.
846: Not all of the bits there can be handled at this level in all cases.
847: The bits that are taken care of here are cleared.
848:
849: The value is normally 0.
850: In this case, COND itself has usually been altered.
851: 1 means that the condition has become always true.
852: -1 means that the condition has become always false. */
853:
854: static int
855: alter_cond (cond)
856: register rtx cond;
857: {
858: int value = 0;
859:
860: if (cc_status.flags & CC_REVERSED)
861: {
862: value = 2;
863: switch (GET_CODE (cond))
864: {
865: case LE:
866: PUT_CODE (cond, GE);
867: break;
868: case GE:
869: PUT_CODE (cond, LE);
870: break;
871: case LT:
872: PUT_CODE (cond, GT);
873: break;
874: case GT:
875: PUT_CODE (cond, LT);
876: break;
877: case LEU:
878: PUT_CODE (cond, GEU);
879: break;
880: case GEU:
881: PUT_CODE (cond, LEU);
882: break;
883: case LTU:
884: PUT_CODE (cond, GTU);
885: break;
886: case GTU:
887: PUT_CODE (cond, LTU);
888: break;
889: }
890: }
891:
892: if (cond != 0 && cc_status.flags & CC_NOT_POSITIVE)
893: switch (GET_CODE (cond))
894: {
895: case LE:
896: case LEU:
897: case GEU:
898: /* Jump becomes unconditional. */
899: return 1;
900:
901: case GT:
902: case GTU:
903: case LTU:
904: /* Jump becomes no-op. */
905: return -1;
906:
907: case GE:
908: PUT_CODE (cond, EQ);
909: value = 2;
910: break;
911:
912: case LT:
913: PUT_CODE (cond, NE);
914: value = 2;
915: break;
916: }
917:
918: if (cond != 0 && cc_status.flags & CC_NOT_NEGATIVE)
919: switch (GET_CODE (cond))
920: {
921: case GE:
922: case GEU:
923: /* Jump becomes unconditional. */
924: return 1;
925:
926: case LT:
927: case LTU:
928: /* Jump becomes no-op. */
929: return -1;
930:
931: case LE:
932: case LEU:
933: PUT_CODE (cond, EQ);
934: value = 2;
935: break;
936:
937: case GT:
938: case GTU:
939: PUT_CODE (cond, NE);
940: value = 2;
941: break;
942: }
943:
944: if (cond != 0 && cc_status.flags & CC_NO_OVERFLOW)
945: switch (GET_CODE (cond))
946: {
947: case GEU:
948: /* Jump becomes unconditional. */
949: return 1;
950:
951: case LEU:
952: PUT_CODE (cond, EQ);
953: value = 2;
954: break;
955:
956: case GTU:
957: PUT_CODE (cond, NE);
958: value = 2;
959: break;
960:
961: case LTU:
962: /* Jump becomes no-op. */
963: return -1;
964: }
965:
966: return value;
967: }
968:
969: /* Output of assembler code from a template, and its subroutines. */
970:
971: /* Output text from TEMPLATE to the assembler output file,
972: obeying %-directions to substitute operands taken from
973: the vector OPERANDS.
974:
975: %N (for N a digit) means print operand N in usual manner.
976: %lN means require operand N to be a CODE_LABEL or LABEL_REF
977: and print the label name with no punctuation.
978: %cN means require operand N to be a constant
979: and print the constant expression with no punctuation.
980: %aN means expect operand N to be a memory address
981: (not a memory reference!) and print a reference
982: to that address.
983: %nN means expect operand N to be a constant
984: and print a constant expression for minus the value
985: of the operand, with no other punctuation. */
986:
987: void
988: output_asm_insn (template, operands)
989: char *template;
990: rtx *operands;
991: {
992: register char *p;
993: register int c;
994:
1.1.1.2 root 995: /* An insn may return a null string template
996: in a case where no assembler code is needed. */
997: if (*template == 0)
998: return;
999:
1.1 root 1000: p = template;
1.1.1.2 root 1001: putc ('\t', asm_out_file);
1002:
1003: #ifdef ASM_OUTPUT_OPCODE
1004: ASM_OUTPUT_OPCODE (asm_out_file, p);
1005: #endif
1006:
1.1 root 1007: while (c = *p++)
1008: {
1.1.1.2 root 1009: #ifdef ASM_OUTPUT_OPCODE
1010: if (c == '\n')
1.1 root 1011: {
1.1.1.2 root 1012: putc (c, asm_out_file);
1013: while ((c = *p) == '\t')
1.1 root 1014: {
1.1.1.2 root 1015: putc (c, asm_out_file);
1016: p++;
1.1 root 1017: }
1.1.1.2 root 1018: ASM_OUTPUT_OPCODE (asm_out_file, p);
1019: }
1020: else
1021: #endif
1022: if (c != '%')
1023: putc (c, asm_out_file);
1024: else
1025: {
1026: /* %% outputs a single %. */
1027: if (*p == '%')
1.1 root 1028: {
1.1.1.2 root 1029: p++;
1030: putc (c, asm_out_file);
1.1 root 1031: }
1.1.1.2 root 1032: /* % followed by a letter and some digits
1033: outputs an operand in a special way depending on the letter.
1034: Letters `acln' are implemented here.
1035: Other letters are passed to `output_operand' so that
1036: the PRINT_OPERAND macro can define them. */
1037: else if ((*p >= 'a' && *p <= 'z')
1038: || (*p >= 'A' && *p <= 'Z'))
1.1 root 1039: {
1.1.1.2 root 1040: int letter = *p++;
1041: c = atoi (p);
1042:
1043: if (letter == 'l')
1044: output_asm_label (operands[c]);
1045: else if (letter == 'a')
1046: output_address (operands[c]);
1047: else if (letter == 'c')
1048: {
1049: if (CONSTANT_ADDRESS_P (operands[c]))
1050: output_addr_const (asm_out_file, operands[c]);
1051: else
1052: output_operand (operands[c], 'c');
1053: }
1054: else if (letter == 'n')
1.1 root 1055: {
1.1.1.2 root 1056: if (GET_CODE (operands[c]) == CONST_INT)
1057: fprintf (asm_out_file, "%d", - INTVAL (operands[c]));
1058: else
1059: {
1060: putc ('-', asm_out_file);
1061: output_addr_const (asm_out_file, operands[c]);
1062: }
1.1 root 1063: }
1.1.1.2 root 1064: else if (*p >= '0' && *p <= '9')
1065: output_operand (operands[c], letter);
1066: else
1067: /* No operand-number follows the letter. */
1068: output_operand (0, letter);
1069:
1070: while ((c = *p) >= '0' && c <= '9') p++;
1.1 root 1071: }
1.1.1.2 root 1072: /* % followed by a digit outputs an operand the default way. */
1073: else if (*p >= '0' && *p <= '9')
1.1 root 1074: {
1075: c = atoi (p);
1.1.1.2 root 1076: output_operand (operands[c], 0);
1077: while ((c = *p) >= '0' && c <= '9') p++;
1.1 root 1078: }
1.1.1.2 root 1079: /* % followed by punctuation: output something for that
1080: punctuation character alone, with no operand.
1081: The PRINT_OPERAND macro decides what is actually done. */
1082: else
1083: output_operand (0, *p++);
1.1 root 1084: }
1085: }
1086:
1.1.1.2 root 1087: putc ('\n', asm_out_file);
1.1 root 1088: }
1089:
1.1.1.3 root 1090: /* Output a LABEL_REF, or a bare CODE_LABEL, as an assembler symbol. */
1091:
1092: void
1.1 root 1093: output_asm_label (x)
1094: rtx x;
1095: {
1.1.1.2 root 1096: char buf[20];
1097:
1.1 root 1098: if (GET_CODE (x) == LABEL_REF)
1.1.1.2 root 1099: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
1.1 root 1100: else if (GET_CODE (x) == CODE_LABEL)
1.1.1.2 root 1101: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
1.1 root 1102: else
1103: abort ();
1.1.1.2 root 1104:
1105: assemble_name (asm_out_file, buf);
1.1 root 1106: }
1107:
1108: /* Print operand X using machine-dependent assembler syntax.
1.1.1.2 root 1109: The macro PRINT_OPERAND is defined just to control this function.
1110: CODE is a non-digit that preceded the operand-number in the % spec,
1111: such as 'z' if the spec was `%z3'. CODE is 0 if there was no char
1112: between the % and the digits.
1113: When CODE is a non-letter, X is 0.
1114:
1115: The meanings of the letters are machine-dependent and controlled
1116: by PRINT_OPERAND. */
1.1 root 1117:
1118: static void
1.1.1.2 root 1119: output_operand (x, code)
1.1 root 1120: rtx x;
1.1.1.2 root 1121: int code;
1.1 root 1122: {
1.1.1.2 root 1123: if (x && GET_CODE (x) == SUBREG)
1.1.1.6 root 1124: x = alter_subreg (x);
1.1.1.2 root 1125: PRINT_OPERAND (asm_out_file, x, code);
1.1 root 1126: }
1127:
1128: /* Print a memory reference operand for address X
1129: using machine-dependent assembler syntax.
1130: The macro PRINT_OPERAND_ADDRESS exists just to control this function. */
1131:
1.1.1.2 root 1132: void
1.1 root 1133: output_address (x)
1134: rtx x;
1135: {
1.1.1.2 root 1136: walk_alter_subreg (x);
1137: PRINT_OPERAND_ADDRESS (asm_out_file, x);
1.1 root 1138: }
1139:
1140: /* Print an integer constant expression in assembler syntax.
1141: Addition and subtraction are the only arithmetic
1142: that may appear in these expressions. */
1143:
1144: void
1145: output_addr_const (file, x)
1146: FILE *file;
1147: rtx x;
1148: {
1.1.1.2 root 1149: char buf[20];
1150:
1.1 root 1151: restart:
1152: switch (GET_CODE (x))
1153: {
1154: case SYMBOL_REF:
1.1.1.2 root 1155: assemble_name (file, XSTR (x, 0));
1.1 root 1156: break;
1157:
1158: case LABEL_REF:
1.1.1.2 root 1159: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
1160: assemble_name (asm_out_file, buf);
1.1 root 1161: break;
1162:
1163: case CODE_LABEL:
1.1.1.2 root 1164: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
1165: assemble_name (asm_out_file, buf);
1.1 root 1166: break;
1167:
1168: case CONST_INT:
1169: fprintf (file, "%d", INTVAL (x));
1170: break;
1171:
1172: case CONST:
1173: x = XEXP (x, 0);
1174: goto restart;
1175:
1176: case PLUS:
1.1.1.4 root 1177: /* Some assemblers need integer constants to appear last (eg masm). */
1178: if (GET_CODE (XEXP (x, 0)) == CONST_INT)
1179: {
1180: output_addr_const (file, XEXP (x, 1));
1181: fprintf (file, "+");
1182: output_addr_const (file, XEXP (x, 0));
1183: }
1184: else
1185: {
1186: output_addr_const (file, XEXP (x, 0));
1187: fprintf (file, "+");
1188: output_addr_const (file, XEXP (x, 1));
1189: }
1.1 root 1190: break;
1191:
1192: case MINUS:
1193: output_addr_const (file, XEXP (x, 0));
1194: fprintf (file, "-");
1195: output_addr_const (file, XEXP (x, 1));
1196: break;
1197:
1198: default:
1199: abort ();
1200: }
1201: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.