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