|
|
1.1 root 1: /* Subroutines for insn-output.c for Convex.
2: Copyright (C) 1989,1991 Free Software Foundation, Inc.
3:
4: This file is part of GNU CC.
5:
6: GNU CC is free software; you can redistribute it and/or modify
7: it under the terms of the GNU General Public License as published by
8: the Free Software Foundation; either version 1, or (at your option)
9: any later version.
10:
11: GNU CC is distributed in the hope that it will be useful,
12: but WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14: GNU General Public License for more details.
15:
16: You should have received a copy of the GNU General Public License
17: along with GNU CC; see the file COPYING. If not, write to
18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19:
20: #include "config.h"
21: #include "rtl.h"
22: #include "regs.h"
23: #include "hard-reg-set.h"
24: #include "real.h"
25: #include "insn-config.h"
26: #include "conditions.h"
27: #include "insn-flags.h"
28: #include "output.h"
29: #include "insn-attr.h"
30:
31: /* Boolean to keep track of whether the current section is .text or not.
32: Used by .align handler in convex.h. */
33:
34: int current_section_is_text;
35:
36: /* set_cmp saves the operands of a "cmp" insn, along with the type character
37: * to be used in the compare instruction.
38: *
39: * gen_cmp finds out what comparison is to be performed and outputs the
40: * necessary instructions, e.g.
41: * "eq.w a1,a2\;jbra.t L5"
42: * for (cmpsi a1 a2) (beq L5) */
43:
44: static rtx xop0, xop1;
45: static char typech, regch;
46:
47: char *
48: set_cmp (op0, op1, typechr)
49: rtx op0, op1;
50: char typechr;
51: {
52: xop0 = op0;
53: xop1 = op1;
54: typech = typechr;
55: if (GET_CODE (op0) == REG)
56: regch = A_REGNO_P (REGNO (op0)) ? 'a' : 's';
57: else if (GET_CODE (op1) == REG)
58: regch = A_REGNO_P (REGNO (op1)) ? 'a' : 's';
59: else abort ();
60: return "";
61: }
62:
63: char *
64: gen_cmp (label, cmpop, tf)
65: rtx label;
66: char *cmpop;
67: char tf;
68: {
69: char buf[80];
70: char revop[4];
71: rtx ops[3];
72:
73: ops[2] = label;
74:
75: /* Constant must be first; swap operands if necessary.
76: If lt, le, ltu, leu are swapped, change to le, lt, leu, ltu
77: and reverse the sense of the jump. */
78:
79: if (CONSTANT_P (xop1))
80: {
81: ops[0] = xop1;
82: ops[1] = xop0;
83: if (cmpop[0] == 'l')
84: {
85: bcopy (cmpop, revop, sizeof revop);
86: revop[1] ^= 'e' ^ 't';
87: tf ^= 't' ^ 'f';
88: cmpop = revop;
89: }
90: }
91: else
92: {
93: ops[0] = xop0;
94: ops[1] = xop1;
95: }
96:
97: sprintf (buf, "%s.%c %%0,%%1\n\tjbr%c.%c %%l2", cmpop, typech, regch, tf);
98: output_asm_insn (buf, ops);
99: return "";
100: }
101:
102: /* Routines to separate CONST_DOUBLEs into component parts. */
103:
104: int
105: const_double_high_int (x)
106: rtx x;
107: {
108: if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
109: return CONST_DOUBLE_LOW (x);
110: else
111: return CONST_DOUBLE_HIGH (x);
112: }
113:
114: int
115: const_double_low_int (x)
116: rtx x;
117: {
118: if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
119: return CONST_DOUBLE_HIGH (x);
120: else
121: return CONST_DOUBLE_LOW (x);
122: }
123:
124: /* Return the number of args in the call insn X. */
125:
126: static int
127: call_num_args (x)
128: rtx x;
129: {
130: if (GET_CODE (x) == CALL)
131: return INTVAL (x->fld[1].rtx);
132: if (GET_CODE (x) == SET)
133: return call_num_args (SET_SRC (x));
134: abort ();
135: }
136:
137: /* Scan forward from a call to decide whether we need to reload AP
138: from 12(FP) after it. We need to if there can be a reference to
139: arg_pointer_rtx before the next call, which will clobber AP.
140: Look forward in the instruction list until encountering a call
141: (don't need the load), or a reference to AP (do need it), or
142: a jump (don't know, do the load). */
143:
144: static int
145: ap_reload_needed (insn)
146: rtx insn;
147: {
148: for (;;)
149: {
150: insn = NEXT_INSN (insn);
151: switch (GET_CODE (insn))
152: {
153: case JUMP_INSN:
154: /* Basic block ends. If return, no AP needed, else assume it is. */
155: return GET_CODE (PATTERN (insn)) != RETURN;
156: case CALL_INSN:
157: /* A subsequent call. AP isn't needed unless the call itself
158: requires it. But zero-arg calls don't clobber AP, so
159: don't terminate the search in that case. */
160: if (reg_mentioned_p (arg_pointer_rtx, PATTERN (insn)))
161: return 1;
162: if (! TARGET_ARGCOUNT && call_num_args (PATTERN (insn)) == 0)
163: break;
164: return 0;
165: case BARRIER:
166: /* Barrier, don't need AP. */
167: return 0;
168: case INSN:
169: /* Other insn may need AP; if not, keep looking. */
170: if (reg_mentioned_p (arg_pointer_rtx, PATTERN (insn)))
171: return 1;
172: }
173: }
174: }
175:
176: /* Output the insns needed to do a call. */
177:
178: char *
179: output_call (insn, address, argcount)
180: rtx insn, address, argcount;
181: {
182: int set_ap = TARGET_ARGCOUNT || argcount != const0_rtx;
183:
184: /* If AP is used by the call address, evaluate the address into a temp. */
185: if (reg_mentioned_p (arg_pointer_rtx, address))
186: if (set_ap)
187: {
188: address = XEXP (address, 0);
189: output_asm_insn ("ld.w %0,a1", &address);
190: address = gen_rtx (MEM, QImode, gen_rtx (REG, Pmode, 9));
191: }
192:
193: /* If there are args, point AP to them. */
194: if (set_ap)
195: output_asm_insn ("mov sp,ap");
196:
197: /* If we are passing an arg count, convert it to words and push it. */
198: if (TARGET_ARGCOUNT)
199: {
200: argcount = gen_rtx (CONST_INT, VOIDmode, (INTVAL (argcount) + 3) / 4);
201: output_asm_insn ("pshea %a0", &argcount);
202: }
203:
204: /* The call. */
205: output_asm_insn ("calls %0", &address);
206:
207: /* If we clobbered AP, reload it if it is live. */
208: if (set_ap)
209: if (ap_reload_needed (insn))
210: output_asm_insn ("ld.w 12(fp),ap");
211:
212: /* If we pushed an arg count, pop it and the args. */
213: if (TARGET_ARGCOUNT)
214: {
215: argcount = gen_rtx (CONST_INT, VOIDmode, INTVAL (argcount) * 4 + 4);
216: output_asm_insn ("add.w %0,sp", &argcount);
217: }
218:
219: return "";
220: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.