|
|
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
531: ASM_OUTPUT_CASE_END (file, CODE_LABEL_NUMBER (PREV_INSN (insn)));
532: #endif
1.1 root 533: break;
534: }
535:
536: /* We have a real machine instruction as rtl. */
537:
538: body = PATTERN (insn);
539:
1.1.1.2 root 540: /* Check for redundant move insns moving a reg into itself.
541: This takes little time and does not affect the semantics
542: so we do it even when `optimize' is 0.
543: It is not safe to do this for memory references;
544: we would not know if they were volatile. */
1.1 root 545: if (GET_CODE (body) == SET
1.1.1.2 root 546: && SET_DEST (body) == SET_SRC (body)
547: && GET_CODE (SET_DEST (body)) == REG)
1.1 root 548: break;
1.1.1.4 root 549:
550: /* Check for redundant test and compare instructions
1.1 root 551: (when the condition codes are already set up as desired).
552: This is done only when optimizing; if not optimizing,
553: it should be possible for the user to alter a variable
554: with the debugger in between statements
555: and the next statement should reexamine the variable
556: to compute the condition codes. */
557:
558: if (optimize
559: && GET_CODE (body) == SET
560: && GET_CODE (SET_DEST (body)) == CC0)
561: {
562: if (GET_CODE (SET_SRC (body)) == SUBREG)
1.1.1.6 ! root 563: SET_SRC (body) = alter_subreg (SET_SRC (body));
1.1 root 564: if ((cc_status.value1 != 0
565: && rtx_equal_p (SET_SRC (body), cc_status.value1))
566: || (cc_status.value2 != 0
567: && rtx_equal_p (SET_SRC (body), cc_status.value2)))
1.1.1.2 root 568: {
569: /* Don't delete insn if has an addressing side-effect */
1.1.1.6 ! root 570: if (! find_reg_note (insn, REG_INC, 0)
! 571: /* or if anything in it is volatile. */
! 572: && ! volatile_refs_p (PATTERN (insn)))
1.1.1.2 root 573: break;
574: }
1.1 root 575: }
576:
577: /* If this is a conditional branch, maybe modify it
578: if the cc's are in a nonstandard state
579: so that it accomplishes the same thing that it would
580: do straightforwardly if the cc's were set up normally. */
581:
582: if (cc_status.flags != 0
583: && GET_CODE (insn) == JUMP_INSN
584: && GET_CODE (body) == SET
585: && SET_DEST (body) == pc_rtx
586: && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE)
587: {
588: /* This function may alter the contents of its argument
589: and clear some of the cc_status.flags bits.
590: It may also return 1 meaning condition now always true
591: or -1 meaning condition now always false
592: or 2 meaning condition nontrivial but altered. */
593: register int result = alter_cond (XEXP (SET_SRC (body), 0));
594: /* If condition now has fixed value, replace the IF_THEN_ELSE
595: with its then-operand or its else-operand. */
596: if (result == 1)
597: SET_SRC (body) = XEXP (SET_SRC (body), 1);
598: if (result == -1)
599: SET_SRC (body) = XEXP (SET_SRC (body), 2);
600: /* The jump is now either unconditional or a no-op.
601: If it has become a no-op, don't try to output it.
602: (It would not be recognized.) */
603: if (SET_SRC (body) == pc_rtx)
604: continue;
605: /* Rerecognize the instruction if it has changed. */
606: if (result != 0)
607: INSN_CODE (insn) = -1;
608: }
609:
610: /* Make same adjustments to instructions that examine the
611: condition codes without jumping. */
612:
613: if (cc_status.flags != 0
614: && GET_CODE (body) == SET)
615: switch (GET_CODE (SET_SRC (body)))
616: {
617: case GTU:
618: case GT:
619: case LTU:
620: case LT:
621: case GEU:
622: case GE:
623: case LEU:
624: case LE:
625: case EQ:
626: case NE:
627: {
628: register int result = alter_cond (SET_SRC (body));
629: if (result == 1)
630: SET_SRC (body) = gen_rtx (CONST_INT, VOIDmode, -1);
631: if (result == -1)
632: SET_SRC (body) = const0_rtx;
633: if (result != 0)
634: INSN_CODE (insn) = -1;
635: }
636: }
637:
638: /* Try to recognize the instruction.
639: If successful, verify that the operands satisfy the
640: constraints for the instruction. Crash if they don't,
641: since `reload' should have changed them so that they do. */
642:
643: insn_code_number = recog_memoized (insn);
644: insn_extract (insn);
645: for (i = 0; i < insn_n_operands[insn_code_number]; i++)
646: if (GET_CODE (recog_operand[i]) == SUBREG)
1.1.1.6 ! root 647: recog_operand[i] = alter_subreg (recog_operand[i]);
1.1 root 648:
649: #ifdef REGISTER_CONSTRAINTS
650: if (! constrain_operands (insn_code_number))
651: abort ();
652: #endif
653:
1.1.1.4 root 654: /* Some target machines need to prescan each insn before
655: it is output. */
656:
657: #ifdef FINAL_PRESCAN_INSN
658: FINAL_PRESCAN_INSN (insn, recog_operand,
659: insn_n_operands[insn_code_number]);
660: #endif
661:
1.1.1.2 root 662: cc_prev_status = cc_status;
663:
1.1 root 664: /* Update `cc_status' for this instruction.
665: The instruction's output routine may change it further.
666: This should be a no-op for jump instructions
667: because their output routines may need to examine `cc_status',
668: below. That's ok since jump insns don't normally alter
669: the condition codes. */
670:
671: NOTICE_UPDATE_CC (body);
672:
673: /* If the proper template needs to be chosen by some C code,
1.1.1.2 root 674: run that code and get the real template. */
1.1 root 675:
676: template = insn_template[insn_code_number];
677: if (template == 0)
1.1.1.5 root 678: template = (*insn_outfun[insn_code_number]) (recog_operand, insn);
1.1 root 679:
680: /* Output assembler code from the template. */
681:
682: output_asm_insn (template, recog_operand);
683: }
684: }
685: }
1.1.1.2 root 686: }
687:
688: /* Set up FILENAME as the current file for GDB line-number output. */
1.1 root 689:
1.1.1.2 root 690: void
691: set_current_gdbfile (filename)
692: char *filename;
693: {
694: register struct gdbfile *f;
695: for (f = gdbfiles; f; f = f->next)
696: if (!strcmp (f->name, filename))
697: break;
1.1 root 698:
1.1.1.2 root 699: if (!f)
700: {
701: f = (struct gdbfile *) permalloc (sizeof (struct gdbfile));
702: f->next = gdbfiles;
703: gdbfiles = f;
704: f->name = filename;
705: f->filenum = next_gdb_filenum++;
706: f->nlines = 0;
707: }
708: current_gdbfile = f;
709: lastfile = filename;
1.1 root 710: }
711:
1.1.1.2 root 712: /* Output debugging info to the assembler file FILE
713: based on the NOTE-insn INSN, assumed to be a line number. */
1.1 root 714:
1.1.1.2 root 715: static void
716: output_source_line (file, insn, write_symbols)
1.1 root 717: FILE *file;
718: rtx insn;
1.1.1.4 root 719: enum debugger write_symbols;
1.1 root 720: {
721: register char *filename = NOTE_SOURCE_FILE (insn);
1.1.1.4 root 722:
723: last_linenum = NOTE_LINE_NUMBER (insn);
724:
725: if (write_symbols == GDB_DEBUG)
1.1.1.2 root 726: {
727: /* Output GDB-format line number info. */
1.1 root 728:
1.1.1.2 root 729: /* If this is not the same source file as last time,
730: find or assign a GDB-file-number to this file. */
731: if (filename && (lastfile == 0 || strcmp (filename, lastfile)
732: || current_gdbfile == 0))
733: set_current_gdbfile (filename);
734:
735: ++current_gdbfile->nlines;
736: fprintf (file, "\t.gdbline %d,%d\n",
737: current_gdbfile->filenum, NOTE_LINE_NUMBER (insn));
738: }
1.1.1.4 root 739:
1.1.1.6 ! root 740: if (write_symbols == SDB_DEBUG || write_symbols == DBX_DEBUG)
1.1.1.4 root 741: {
1.1.1.6 ! root 742: #ifdef SDB_DEBUGGING_INFO
! 743: if (write_symbols == SDB_DEBUG
! 744: /* COFF can't handle multiple source files--lose, lose. */
! 745: && !strcmp (filename, main_input_filename))
! 746: {
1.1.1.4 root 747: #ifdef ASM_OUTPUT_SOURCE_LINE
1.1.1.6 ! root 748: ASM_OUTPUT_SOURCE_LINE (file, last_linenum);
1.1.1.4 root 749: #else
1.1.1.6 ! root 750: fprintf (file, "\t.ln\t%d\n",
! 751: (sdb_begin_function_line
! 752: ? last_linenum - sdb_begin_function_line : 1));
1.1.1.4 root 753: #endif
1.1.1.6 ! root 754: }
1.1.1.4 root 755: #endif
756:
757: #ifdef DBX_DEBUGGING_INFO
1.1.1.6 ! root 758: if (write_symbols == DBX_DEBUG)
1.1.1.4 root 759: {
1.1.1.6 ! root 760: /* Write DBX line number data. */
! 761:
! 762: if (filename && (lastfile == 0 || strcmp (filename, lastfile)))
! 763: {
1.1.1.2 root 764: #ifdef ASM_OUTPUT_SOURCE_FILENAME
1.1.1.6 ! root 765: ASM_OUTPUT_SOURCE_FILENAME (file, filename);
1.1.1.2 root 766: #else
1.1.1.6 ! root 767: fprintf (file, "\t.stabs \"%s\",%d,0,0,Ltext\n",
! 768: filename, N_SOL);
1.1.1.2 root 769: #endif
1.1.1.6 ! root 770: lastfile = filename;
! 771: }
1.1.1.4 root 772: }
1.1.1.2 root 773:
774: #ifdef ASM_OUTPUT_SOURCE_LINE
775: ASM_OUTPUT_SOURCE_LINE (file, NOTE_LINE_NUMBER (insn));
776: #else
777: fprintf (file, "\t.stabd %d,0,%d\n",
778: N_SLINE, NOTE_LINE_NUMBER (insn));
779: #endif
1.1.1.4 root 780: #endif /* DBX_DEBUGGING_INFO */
1.1.1.2 root 781: }
1.1 root 782: }
783:
1.1.1.2 root 784: /* If X is a SUBREG, replace it with a REG or a MEM,
785: based on the thing it is a subreg of. */
1.1 root 786:
1.1.1.6 ! root 787: static rtx
1.1 root 788: alter_subreg (x)
789: register rtx x;
790: {
791: register rtx y = SUBREG_REG (x);
792: if (GET_CODE (y) == SUBREG)
1.1.1.6 ! root 793: y = alter_subreg (y);
1.1 root 794:
795: if (GET_CODE (y) == REG)
796: {
797: /* If the containing reg really gets a hard reg, so do we. */
798: PUT_CODE (x, REG);
799: REGNO (x) = REGNO (y) + SUBREG_WORD (x);
800: }
801: else if (GET_CODE (y) == MEM)
802: {
1.1.1.2 root 803: register int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
1.1 root 804: #ifdef BYTES_BIG_ENDIAN
1.1.1.2 root 805: offset -= (min (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x)))
806: - min (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (y))));
1.1 root 807: #endif
808: PUT_CODE (x, MEM);
809: XEXP (x, 0) = plus_constant (XEXP (y, 0), offset);
810: }
1.1.1.6 ! root 811: else if (GET_CODE (y) == CONST_DOUBLE)
! 812: return y;
! 813:
! 814: return x;
1.1 root 815: }
816:
1.1.1.2 root 817: /* Do alter_subreg on all the SUBREGs contained in X. */
1.1 root 818:
1.1.1.2 root 819: static rtx
820: walk_alter_subreg (x)
821: rtx x;
822: {
823: switch (GET_CODE (x))
1.1 root 824: {
1.1.1.2 root 825: case PLUS:
826: case MULT:
827: XEXP (x, 0) = walk_alter_subreg (XEXP (x, 0));
828: XEXP (x, 1) = walk_alter_subreg (XEXP (x, 1));
829: break;
830:
831: case MEM:
832: XEXP (x, 0) = walk_alter_subreg (XEXP (x, 0));
833: break;
834:
835: case SUBREG:
1.1.1.6 ! root 836: return alter_subreg (x);
1.1 root 837: }
838:
1.1.1.2 root 839: return x;
1.1 root 840: }
841:
842: /* Given BODY, the body of a jump instruction, alter the jump condition
843: as required by the bits that are set in cc_status.flags.
844: Not all of the bits there can be handled at this level in all cases.
845: The bits that are taken care of here are cleared.
846:
847: The value is normally 0.
848: In this case, COND itself has usually been altered.
849: 1 means that the condition has become always true.
850: -1 means that the condition has become always false. */
851:
852: static int
853: alter_cond (cond)
854: register rtx cond;
855: {
856: int value = 0;
857:
858: if (cc_status.flags & CC_REVERSED)
859: {
860: value = 2;
861: switch (GET_CODE (cond))
862: {
863: case LE:
864: PUT_CODE (cond, GE);
865: break;
866: case GE:
867: PUT_CODE (cond, LE);
868: break;
869: case LT:
870: PUT_CODE (cond, GT);
871: break;
872: case GT:
873: PUT_CODE (cond, LT);
874: break;
875: case LEU:
876: PUT_CODE (cond, GEU);
877: break;
878: case GEU:
879: PUT_CODE (cond, LEU);
880: break;
881: case LTU:
882: PUT_CODE (cond, GTU);
883: break;
884: case GTU:
885: PUT_CODE (cond, LTU);
886: break;
887: }
888: }
889:
890: if (cond != 0 && cc_status.flags & CC_NOT_POSITIVE)
891: switch (GET_CODE (cond))
892: {
893: case LE:
894: case LEU:
895: case GEU:
896: /* Jump becomes unconditional. */
897: return 1;
898:
899: case GT:
900: case GTU:
901: case LTU:
902: /* Jump becomes no-op. */
903: return -1;
904:
905: case GE:
906: PUT_CODE (cond, EQ);
907: value = 2;
908: break;
909:
910: case LT:
911: PUT_CODE (cond, NE);
912: value = 2;
913: break;
914: }
915:
916: if (cond != 0 && cc_status.flags & CC_NOT_NEGATIVE)
917: switch (GET_CODE (cond))
918: {
919: case GE:
920: case GEU:
921: /* Jump becomes unconditional. */
922: return 1;
923:
924: case LT:
925: case LTU:
926: /* Jump becomes no-op. */
927: return -1;
928:
929: case LE:
930: case LEU:
931: PUT_CODE (cond, EQ);
932: value = 2;
933: break;
934:
935: case GT:
936: case GTU:
937: PUT_CODE (cond, NE);
938: value = 2;
939: break;
940: }
941:
942: if (cond != 0 && cc_status.flags & CC_NO_OVERFLOW)
943: switch (GET_CODE (cond))
944: {
945: case GEU:
946: /* Jump becomes unconditional. */
947: return 1;
948:
949: case LEU:
950: PUT_CODE (cond, EQ);
951: value = 2;
952: break;
953:
954: case GTU:
955: PUT_CODE (cond, NE);
956: value = 2;
957: break;
958:
959: case LTU:
960: /* Jump becomes no-op. */
961: return -1;
962: }
963:
964: return value;
965: }
966:
967: /* Output of assembler code from a template, and its subroutines. */
968:
969: /* Output text from TEMPLATE to the assembler output file,
970: obeying %-directions to substitute operands taken from
971: the vector OPERANDS.
972:
973: %N (for N a digit) means print operand N in usual manner.
974: %lN means require operand N to be a CODE_LABEL or LABEL_REF
975: and print the label name with no punctuation.
976: %cN means require operand N to be a constant
977: and print the constant expression with no punctuation.
978: %aN means expect operand N to be a memory address
979: (not a memory reference!) and print a reference
980: to that address.
981: %nN means expect operand N to be a constant
982: and print a constant expression for minus the value
983: of the operand, with no other punctuation. */
984:
985: void
986: output_asm_insn (template, operands)
987: char *template;
988: rtx *operands;
989: {
990: register char *p;
991: register int c;
992:
1.1.1.2 root 993: /* An insn may return a null string template
994: in a case where no assembler code is needed. */
995: if (*template == 0)
996: return;
997:
1.1 root 998: p = template;
1.1.1.2 root 999: putc ('\t', asm_out_file);
1000:
1001: #ifdef ASM_OUTPUT_OPCODE
1002: ASM_OUTPUT_OPCODE (asm_out_file, p);
1003: #endif
1004:
1.1 root 1005: while (c = *p++)
1006: {
1.1.1.2 root 1007: #ifdef ASM_OUTPUT_OPCODE
1008: if (c == '\n')
1.1 root 1009: {
1.1.1.2 root 1010: putc (c, asm_out_file);
1011: while ((c = *p) == '\t')
1.1 root 1012: {
1.1.1.2 root 1013: putc (c, asm_out_file);
1014: p++;
1.1 root 1015: }
1.1.1.2 root 1016: ASM_OUTPUT_OPCODE (asm_out_file, p);
1017: }
1018: else
1019: #endif
1020: if (c != '%')
1021: putc (c, asm_out_file);
1022: else
1023: {
1024: /* %% outputs a single %. */
1025: if (*p == '%')
1.1 root 1026: {
1.1.1.2 root 1027: p++;
1028: putc (c, asm_out_file);
1.1 root 1029: }
1.1.1.2 root 1030: /* % followed by a letter and some digits
1031: outputs an operand in a special way depending on the letter.
1032: Letters `acln' are implemented here.
1033: Other letters are passed to `output_operand' so that
1034: the PRINT_OPERAND macro can define them. */
1035: else if ((*p >= 'a' && *p <= 'z')
1036: || (*p >= 'A' && *p <= 'Z'))
1.1 root 1037: {
1.1.1.2 root 1038: int letter = *p++;
1039: c = atoi (p);
1040:
1041: if (letter == 'l')
1042: output_asm_label (operands[c]);
1043: else if (letter == 'a')
1044: output_address (operands[c]);
1045: else if (letter == 'c')
1046: {
1047: if (CONSTANT_ADDRESS_P (operands[c]))
1048: output_addr_const (asm_out_file, operands[c]);
1049: else
1050: output_operand (operands[c], 'c');
1051: }
1052: else if (letter == 'n')
1.1 root 1053: {
1.1.1.2 root 1054: if (GET_CODE (operands[c]) == CONST_INT)
1055: fprintf (asm_out_file, "%d", - INTVAL (operands[c]));
1056: else
1057: {
1058: putc ('-', asm_out_file);
1059: output_addr_const (asm_out_file, operands[c]);
1060: }
1.1 root 1061: }
1.1.1.2 root 1062: else if (*p >= '0' && *p <= '9')
1063: output_operand (operands[c], letter);
1064: else
1065: /* No operand-number follows the letter. */
1066: output_operand (0, letter);
1067:
1068: while ((c = *p) >= '0' && c <= '9') p++;
1.1 root 1069: }
1.1.1.2 root 1070: /* % followed by a digit outputs an operand the default way. */
1071: else if (*p >= '0' && *p <= '9')
1.1 root 1072: {
1073: c = atoi (p);
1.1.1.2 root 1074: output_operand (operands[c], 0);
1075: while ((c = *p) >= '0' && c <= '9') p++;
1.1 root 1076: }
1.1.1.2 root 1077: /* % followed by punctuation: output something for that
1078: punctuation character alone, with no operand.
1079: The PRINT_OPERAND macro decides what is actually done. */
1080: else
1081: output_operand (0, *p++);
1.1 root 1082: }
1083: }
1084:
1.1.1.2 root 1085: putc ('\n', asm_out_file);
1.1 root 1086: }
1087:
1.1.1.3 root 1088: /* Output a LABEL_REF, or a bare CODE_LABEL, as an assembler symbol. */
1089:
1090: void
1.1 root 1091: output_asm_label (x)
1092: rtx x;
1093: {
1.1.1.2 root 1094: char buf[20];
1095:
1.1 root 1096: if (GET_CODE (x) == LABEL_REF)
1.1.1.2 root 1097: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
1.1 root 1098: else if (GET_CODE (x) == CODE_LABEL)
1.1.1.2 root 1099: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
1.1 root 1100: else
1101: abort ();
1.1.1.2 root 1102:
1103: assemble_name (asm_out_file, buf);
1.1 root 1104: }
1105:
1106: /* Print operand X using machine-dependent assembler syntax.
1.1.1.2 root 1107: The macro PRINT_OPERAND is defined just to control this function.
1108: CODE is a non-digit that preceded the operand-number in the % spec,
1109: such as 'z' if the spec was `%z3'. CODE is 0 if there was no char
1110: between the % and the digits.
1111: When CODE is a non-letter, X is 0.
1112:
1113: The meanings of the letters are machine-dependent and controlled
1114: by PRINT_OPERAND. */
1.1 root 1115:
1116: static void
1.1.1.2 root 1117: output_operand (x, code)
1.1 root 1118: rtx x;
1.1.1.2 root 1119: int code;
1.1 root 1120: {
1.1.1.2 root 1121: if (x && GET_CODE (x) == SUBREG)
1.1.1.6 ! root 1122: x = alter_subreg (x);
1.1.1.2 root 1123: PRINT_OPERAND (asm_out_file, x, code);
1.1 root 1124: }
1125:
1126: /* Print a memory reference operand for address X
1127: using machine-dependent assembler syntax.
1128: The macro PRINT_OPERAND_ADDRESS exists just to control this function. */
1129:
1.1.1.2 root 1130: void
1.1 root 1131: output_address (x)
1132: rtx x;
1133: {
1.1.1.2 root 1134: walk_alter_subreg (x);
1135: PRINT_OPERAND_ADDRESS (asm_out_file, x);
1.1 root 1136: }
1137:
1138: /* Print an integer constant expression in assembler syntax.
1139: Addition and subtraction are the only arithmetic
1140: that may appear in these expressions. */
1141:
1142: void
1143: output_addr_const (file, x)
1144: FILE *file;
1145: rtx x;
1146: {
1.1.1.2 root 1147: char buf[20];
1148:
1.1 root 1149: restart:
1150: switch (GET_CODE (x))
1151: {
1152: case SYMBOL_REF:
1.1.1.2 root 1153: assemble_name (file, XSTR (x, 0));
1.1 root 1154: break;
1155:
1156: case LABEL_REF:
1.1.1.2 root 1157: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
1158: assemble_name (asm_out_file, buf);
1.1 root 1159: break;
1160:
1161: case CODE_LABEL:
1.1.1.2 root 1162: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
1163: assemble_name (asm_out_file, buf);
1.1 root 1164: break;
1165:
1166: case CONST_INT:
1167: fprintf (file, "%d", INTVAL (x));
1168: break;
1169:
1170: case CONST:
1171: x = XEXP (x, 0);
1172: goto restart;
1173:
1174: case PLUS:
1.1.1.4 root 1175: /* Some assemblers need integer constants to appear last (eg masm). */
1176: if (GET_CODE (XEXP (x, 0)) == CONST_INT)
1177: {
1178: output_addr_const (file, XEXP (x, 1));
1179: fprintf (file, "+");
1180: output_addr_const (file, XEXP (x, 0));
1181: }
1182: else
1183: {
1184: output_addr_const (file, XEXP (x, 0));
1185: fprintf (file, "+");
1186: output_addr_const (file, XEXP (x, 1));
1187: }
1.1 root 1188: break;
1189:
1190: case MINUS:
1191: output_addr_const (file, XEXP (x, 0));
1192: fprintf (file, "-");
1193: output_addr_const (file, XEXP (x, 1));
1194: break;
1195:
1196: default:
1197: abort ();
1198: }
1199: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.