|
|
1.1 root 1: /* Subroutines for insn-output.c for MIPS
2: Contributed by A. Lichnewsky, [email protected].
3: Copyright (C) 1989 Free Software Foundation, Inc.
4:
5: This file is part of GNU CC.
6:
7: GNU CC is free software; you can redistribute it and/or modify
8: it under the terms of the GNU General Public License as published by
9: the Free Software Foundation; either version 1, or (at your option)
10: any later version.
11:
12: GNU CC is distributed in the hope that it will be useful,
13: but WITHOUT ANY WARRANTY; without even the implied warranty of
14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: GNU General Public License for more details.
16:
17: You should have received a copy of the GNU General Public License
18: along with GNU CC; see the file COPYING. If not, write to
19: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20:
21:
22: #include <stdio.h>
23: extern void my_print_rtx ();
24: extern void abort_with_insn ();
25:
26:
27: /* Global variables for machine-dependent things. */
28:
29: char *reg_numchar[] = REGISTER_NUMCHAR;
30:
31:
32: /* Return truth value of whether OP can be used as an operands
33: where a 16 bit integer is needed */
34:
35: int
36: arith_operand (op, mode)
37: rtx op;
38: enum machine_mode mode;
39: {
40: return (register_operand (op, mode)
41: || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
42: }
43:
44: /* Return truth value of whether OP can be used as an operand in a two
45: address arithmetic insn (such as set 123456,%o4) of mode MODE. */
46:
47: int
48: arith32_operand (op, mode)
49: rtx op;
50: enum machine_mode mode;
51: {
52: return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
53: }
54:
55: /* Return truth value of whether OP is a integer which fits in 16 bits */
56:
57: int
58: small_int (op, mode)
59: rtx op;
60: enum machine_mode mode;
61: {
62: return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
63: }
64:
65:
66: #if 0
67: /* Used to allow constant expression known
68: ** only at assembly time
69: */
70: int
71: legitimize_constant_expr(expr)
72: rtx expr;
73: {
74: if (GET_CODE (expr) == PLUS
75: ||
76: GET_CODE (expr) == MINUS)
77: return (BASIC_CONSTANT_P (XEXP (expr, 0))
78: && BASIC_CONSTANT_P (XEXP (expr, 1)));
79: return 0;
80: }
81: #endif
82:
83: char *
84: output_load_immediate (operands)
85: rtx *operands;
86: {
87: rtx xops[3];
88: xops[0] = operands[0];
89: xops[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]));
90:
91: if ((INTVAL (operands[1]) >> 16)
92: && (INTVAL (operands[1]) & 0xffff))
93: {
94: if (!((-INTVAL (operands[1])) >> 16))
95: {
96: xops[1] = gen_rtx (CONST_INT, VOIDmode,
97: (INTVAL (operands[1])) & 0xffff);
98: output_asm_insn ("addi%:\t%0,$0,%x1\t#movsi low part of %2",
99: xops);
100: }
101: else
102: {
103: xops[1] = gen_rtx (CONST_INT, VOIDmode,
104: (INTVAL (operands[1]))>>16);
105: output_asm_insn ("lui\t%0,%x1\t#movsi high part of %2", xops);
106: xops[1] = gen_rtx (CONST_INT, VOIDmode,
107: (INTVAL (operands[1])) & 0xffff);
108: output_asm_insn ("ori\t%0,%x1\t#movsi low part of %2", xops);
109: }
110: }
111: else if (INTVAL (operands[1]) >> 16)
112: {
113: xops[1] = gen_rtx (CONST_INT, VOIDmode,
114: (INTVAL (operands[1]))>>16);
115: output_asm_insn ("lui\t%0,%x1\t#movsi high part of %2", xops);
116: xops[1] = gen_rtx (CONST_INT, VOIDmode,
117: (INTVAL (operands[1])) & 0xffff);
118: }
119: else
120: {
121: xops[1] = gen_rtx (CONST_INT, VOIDmode,
122: (INTVAL (operands[1])) & 0xffff);
123: output_asm_insn ("ori\t%0,$0,%x1\t#movsi low part of %2",
124: xops);
125: }
126: return "";
127: }
128:
129: /* Used to obtain address of subregs */
130: /* when in memory. This takes mode and */
131: /* subreg number into account */
132:
133: rtx
134: addr_compensate (addr, submode, origmode, subnum)
135: rtx addr;
136: enum machine_mode submode;
137: enum machine_mode origmode;
138: int subnum;
139: {
140: extern rtx change_address ();
141: extern rtx plus_constant ();
142:
143: if (submode == QImode && origmode == SImode)
144: {
145: #ifdef BYTES_BIG_ENDIAN
146: return change_address (addr, QImode,
147: plus_constant (XEXP (addr, 0), 3 - subnum));
148: #else
149: return change_address (addr, QImode,
150: plus_constant (XEXP (addr, 0), subnum));
151: #endif
152: }
153: else if (submode == HImode && origmode == SImode)
154: {
155: #ifdef BYTES_BIG_ENDIAN
156: return change_address (addr, HImode,
157: plus_constant (XEXP (addr, 0), 2 - 2*subnum));
158: #else
159: return change_address (addr, HImode,
160: plus_constant (XEXP (addr, 0), subnum));
161: #endif
162: }
163: else
164: abort_with_insn (addr, "addr_compensate does not support mode");
165: }
166:
167:
168:
169:
170: /* VARARGS */
171: int function_suspect;
172: int varargs_suspect = 0;
173: int this_varargs_suspect;
174:
175: /* PARAMETER LIST CONSTRUCTION */
176:
177:
178: static struct
179: {
180: enum arg_state nxs_if_f, nxs_if_g;
181: short reg_if_f, reg_if_g;
182: }
183: arg_state_table[(int) (ARG_STA_GGGG + 1)] = ARG_STA_AUTOMA;
184:
185:
186:
187: /* For use in Frame/ Stack pointer management*/
188: char * current_function_name;
189: int current_function_total_framesize;
190:
191:
192: enum arg_state
193: function_arg_advance (cum, mode, type)
194: CUMULATIVE_ARGS *cum;
195: enum machine_mode mode;
196: int type;
197: {
198: cum->arg_rec_state
199: = (FP_REGS == PREFERRED_RELOAD_CLASS_FM (mode, GR_REGS)
200: ? arg_state_table[(int)((cum->arg_rec_state))].nxs_if_f
201: : arg_state_table[(int)((cum->arg_rec_state))].nxs_if_g);
202:
203: (cum->arg_num)++;
204: }
205:
206: rtx
207: function_arg (cum, mode, type, named)
208: CUMULATIVE_ARGS *cum;
209: enum machine_mode mode;
210: int type;
211: int named;
212: {
213: int regnum;
214:
215: regnum
216: = (FP_REGS == PREFERRED_RELOAD_CLASS_FM (mode, GR_REGS)
217: ? arg_state_table[(int)((cum->arg_rec_state))].reg_if_f
218: : arg_state_table[(int)((cum->arg_rec_state))].reg_if_g);
219:
220: if (mode == BLKmode)
221: return 0;
222: else
223: return (regnum >= 0 ? gen_rtx (REG, mode, regnum)
224: : regnum == -2 ? gen_rtx (REG, DFmode, 6)
225: : 0);
226: }
227:
228:
229:
230: static rtx branch_cmp_op[2];
231: static enum machine_mode branch_cmp_mode;
232:
233: compare_collect (mode, op0, op1)
234: enum machine_mode mode;
235: rtx op0;
236: rtx op1;
237: {
238: if (TARGET_DEBUGD_MODE)
239: {
240: fprintf (stderr, "compare_collect mode = %d, operands::", mode);
241: my_print_rtx (op0);
242: my_print_rtx (op1);
243: }
244: branch_cmp_op[0] = op0;
245: branch_cmp_op[1] = op1;
246: branch_cmp_mode = mode;
247: }
248:
249:
250: compare_restore (operands, mode, insn)
251: rtx *operands;
252: enum machine_mode *mode;
253: rtx insn;
254: {
255: rtx previous;
256: rtx prev_par;
257: if (TARGET_DEBUGD_MODE)
258: {
259: fprintf (stderr, "compare_restore returning mode = %d, operands:%X,%X:",
260: branch_cmp_mode, branch_cmp_op[0], branch_cmp_op[1]);
261: my_print_rtx (branch_cmp_op[0]);
262: my_print_rtx (branch_cmp_op[1]);
263: }
264:
265: if ((! branch_cmp_op[0]) && (! branch_cmp_op[1]))
266: {
267: /* Signal that multiple branches following */
268: /* a comparison have been found */
269: if (TARGET_DEBUGD_MODE)
270: {
271: fprintf (stderr, "Not at ease in compare_restore\n");
272: my_print_rtx (insn);
273: my_print_rtx (PREV_INSN (insn));
274: }
275: /* Find the previous comparison */
276: while ((GET_CODE (PREV_INSN (insn))) == JUMP_INSN)
277: {
278: insn = PREV_INSN (insn);
279: if (TARGET_DEBUGD_MODE)
280: my_print_rtx (PREV_INSN (insn));
281: }
282:
283: previous = PATTERN (PREV_INSN (insn));
284:
285: if ((GET_CODE (previous)) == PARALLEL)
286: {
287: /* Signal that we have a very strange */
288: /* RTL construct,... usually generated */
289: /* by the optimizer, that seems to */
290: /* contradict the documentation */
291:
292: /* However, this construct holds the */
293: /* correct information in a very reliable */
294: /* way */
295:
296: branch_cmp_op[0] = XVECEXP (previous, 0, 0);
297: branch_cmp_op[1] = XVECEXP (previous, 0, 1);
298: /* warning ("Check branch optimization with -mdebugd");
299: */
300: }
301: else
302: if (((GET_CODE (previous)) == SET)
303: &&
304: ((GET_CODE (XEXP (previous, 0))) == CC0)
305: &&
306: ((GET_CODE (XEXP (previous, 1))) == COMPARE))
307: { /* Here we find the comparison info */
308: /* in a more classical format */
309:
310: previous = XEXP (previous, 1);
311: branch_cmp_op[0] = XEXP (previous, 0);
312: branch_cmp_op[1] = XEXP (previous, 1);
313: }
314: else
315: { /* Be prepared for other things popping out */
316: abort ();
317: }
318: }
319:
320:
321:
322: if (! branch_cmp_op[0])
323: operands[0] = gen_rtx (REG, VOIDmode, 0);
324: else
325: operands[0] = branch_cmp_op[0];
326: if (! branch_cmp_op[1])
327: operands[1] = gen_rtx (REG, VOIDmode, 0);
328: else
329: operands[1] = branch_cmp_op[1];
330: *mode = branch_cmp_mode;
331:
332: branch_cmp_op[0] = NULL;
333: branch_cmp_op[1] = NULL;
334:
335: }
336:
337: #if 0
338: /* See flags.h and toplev.c */
339: extern int optimize;
340: extern int flag_combine_regs;
341: extern int flag_strength_reduce;
342: extern int flag_no_peephole;
343: extern int flag_inline_functions;
344: extern int flag_omit_frame_pointer;
345: extern char *main_input_filename;
346: extern char *asm_file_name;
347: /* See c-tree.h and c-decl.c */
348: extern int flag_signed_char;
349:
350: #include <time.h>
351: #include <sys/types.h>
352: #include <sys/timeb.h>
353:
354: void
355: print_options (out)
356: FILE *out;
357: {
358: char *a_time;
359: long c_time;
360:
361: fprintf (out, " #OPTIONS:\t%s%s%s%s%s%s%s\n",
362: (TARGET_NOFIXED_OVFL ? " -dnofixed-ovfl":" -dfixed-ovfl"),
363: (optimize ? " optimize" : ""),
364: (flag_combine_regs ? " -fcombine-regs" : " !combine-regs"),
365: (flag_strength_reduce ? "" : " !strength_reduce"),
366: (flag_omit_frame_pointer ?"" :" !omit_frame_pointer"),
367: (flag_no_peephole ? "" : " peephole"),
368: (flag_inline_functions ?" inline-functions":""));
369: fprintf (out, " #OPTIONS:\t%s%s\n",
370: (flag_signed_char ? " signed-char" : " !signed-char"),
371: (TARGET_GP_OPT ? " gpOPT" : " !gpOPT"));
372: fprintf (out, " #Source:\t%s\n", main_input_filename);
373: fprintf (out, " #Destination:\t%s\n", asm_file_name);
374: c_time = time (0);
375: a_time = ctime (&c_time);
376: fprintf (out, " #Compiled:\t%s", a_time);
377: #ifdef __GNUC__
378: #ifndef __VERSION__
379: #define __VERSION__ "[unknown]"
380: #endif
381: fprintf (out, " # (META)compiled by GNU C version %s.\n", __VERSION__);
382: #else
383: fprintf (out, " # (META)compiled by CC.\n");
384: #endif
385: }
386:
387: /* DEBUGGING UTILITIES */
388: rtx al_log_insn_debug;
389:
390: abort_show_logged ()
391: {
392: if (al_log_insn_debug)
393: my_print_rtx (al_log_insn_debug);
394: abort ();
395: }
396:
397: extern FILE *outfile;
398:
399: void
400: my_print_rtx (in_rtx)
401: register rtx in_rtx;
402: {
403: FILE *old;
404: old = outfile;
405:
406: outfile = stderr;
407: print_rtx (in_rtx);
408: fprintf (outfile, "\n");
409:
410: outfile = old;
411: }
412:
413: void
414: my_print_insncode (insn)
415: rtx insn;
416: {
417: FILE *old;
418: old = outfile;
419:
420: outfile = stderr;
421: print_rtx (insn);
422: fprintf (outfile, "\n");
423: fprintf (outfile, "INSN_CODE (insn) = %X\n", INSN_CODE (insn));
424:
425: outfile = old;
426: }
427:
428: void
429: abort_with_insn (insn, reason)
430: rtx insn;
431: char *reason;
432: {
433: fprintf (stderr, "About to Abort::%s\n", reason);
434: my_print_rtx (insn);
435: abort ();
436: }
437: #endif
438:
439: void
440: abort_with_insn ()
441: {
442: abort ();
443: }
444:
445: void
446: my_print_rtx (in_rtx)
447: register rtx in_rtx;
448:
449: {
450: abort();
451: }
452:
453: #include "tree.h"
454: /* GET SECTION (DATA/SDATA) THRESHOLD */
455: int mips_section_threshold = -1;
456:
457: extern char *tree_code_name[];
458:
459: int
460: mips_section_get ()
461: {
462: register int i;
463: if (mips_section_threshold == -1)
464: {
465: i = TARGET_GVALUE;
466: if (i >= 6) i += 3;
467: if ((1 << i) != MIPS_GVALUE_DEFAULT)
468: warning ("G value this run == %d\n", 1 << i);
469: mips_section_threshold = 1 << i;
470: }
471:
472: return mips_section_threshold;
473: }
474:
475: int
476: mips_output_external (file, tree_exp, name)
477: FILE *file;
478: tree tree_exp;
479: char *name;
480: {
481: register int i;
482: if (TARGET_GP_OPT
483: && ((TREE_CODE (tree_exp)) != FUNCTION_DECL)
484: &&
485: ((i = int_size_in_bytes (TREE_TYPE (tree_exp))) > 0))
486: {
487: fputs ("\n#ifndef _gccx__", file);
488: assemble_name (file, name);
489: fputs ("\n.extern\t", (file));
490: assemble_name ((file), (name));
491: fprintf ((file), ", %d", i, (TREE_TYPE (tree_exp)));
492: fputs ("\n#define _gccx__", file);
493: assemble_name (file, name);
494: fputs ("\n#endif\n ", file);
495: }
496: return 0;
497: }
498:
499: extern char *asm_file_name;
500:
501: int
502: mips_asm_file_end (file)
503: FILE *file;
504: {
505: if (TARGET_GP_OPT)
506: {
507: fprintf (file, "\n#else\n#ifndef %sRESCAN_GCC", "__x_");
508: fprintf (file, "\n#define %sRESCAN_GCC\n#include \"%s\"", "__x_",
509: asm_file_name);
510: fprintf (file, "\n#endif\n#endif\n");
511: }
512: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.