|
|
1.1 root 1: /* Convert tree expression to rtl instructions, for GNU compiler.
1.1.1.2 root 2: Copyright (C) 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: #include "config.h"
23: #include "rtl.h"
24: #include "tree.h"
1.1.1.2 root 25: #include "flags.h"
1.1 root 26: #include "insn-flags.h"
27: #include "insn-codes.h"
28: #include "expr.h"
1.1.1.2 root 29: #include "insn-config.h"
30: #include "recog.h"
31: #include "varargs.h"
32:
33: /* Decide whether a function's arguments should be processed
34: from first to last or from last to first. */
35:
36: #ifdef STACK_GROWS_DOWNWARD
37: #ifdef PUSH_ROUNDING
38: #define PUSH_ARGS_REVERSED /* If it's last to first */
39: #endif
40: #endif
41:
42: /* Like STACK_BOUNDARY but in units of bytes, not bits. */
43: #define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT)
1.1 root 44:
45: /* If this is nonzero, we do not bother generating VOLATILE
46: around volatile memory references, and we are willing to
47: output indirect addresses. If cse is to follow, we reject
48: indirect addresses so a useful potential cse is generated;
49: if it is used only once, instruction combination will produce
50: the same indirect address eventually. */
51: int cse_not_expected;
52:
53: /* Nonzero to generate code for all the subroutines within an
54: expression before generating the upper levels of the expression.
55: Nowadays this is never zero. */
56: int do_preexpand_calls = 1;
57:
58: /* Number of units that we should eventually pop off the stack.
59: These are the arguments to function calls that have already returned. */
60: int pending_stack_adjust;
61:
62: /* Total size of arguments already pushed for function calls that
63: have not happened yet. Also counts 1 for each level of conditional
64: expression that we are inside. When this is nonzero,
65: args passed to function calls must be popped right away
66: to ensure contiguity of argument lists for future calls. */
1.1.1.2 root 67: static int current_args_size;
1.1 root 68:
1.1.1.2 root 69: /* Nonzero means current function may call alloca. */
70: int may_call_alloca;
71:
72: rtx store_expr ();
73: static void store_constructor ();
74: static rtx store_field ();
1.1 root 75: static rtx expand_call ();
1.1.1.2 root 76: static void emit_call_1 ();
77: static rtx prepare_call_address ();
78: static rtx expand_builtin ();
1.1 root 79: static rtx compare ();
1.1.1.2 root 80: static rtx compare_constants ();
1.1 root 81: static rtx compare1 ();
82: static rtx do_store_flag ();
83: static void preexpand_calls ();
1.1.1.2 root 84: static rtx expand_increment ();
85: static void move_by_pieces_1 ();
1.1.1.4 ! root 86: static int move_by_pieces_ninsns ();
1.1.1.2 root 87: static void init_queue ();
88:
89: void do_pending_stack_adjust ();
1.1 root 90:
91: /* MOVE_RATIO is the number of move instructions that is better than
92: a block move. */
93:
94: #if defined (HAVE_movstrhi) || defined (HAVE_movstrsi)
95: #define MOVE_RATIO 2
96: #else
97: #define MOVE_RATIO 6
98: #endif
99:
100: /* Table indexed by tree code giving 1 if the code is for a
101: comparison operation, or anything that is most easily
102: computed with a conditional branch.
103:
104: We include tree.def to give it the proper length.
105: The contents thus created are irrelevant.
106: The real contents are initialized in init_comparisons. */
107:
1.1.1.2 root 108: #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) 0,
1.1 root 109:
110: static char comparison_code[] = {
111: #include "tree.def"
112: };
113: #undef DEFTREECODE
114:
1.1.1.2 root 115: /* This is run once per compilation. */
116:
117: void
1.1 root 118: init_comparisons ()
119: {
120: comparison_code[(int) EQ_EXPR] = 1;
121: comparison_code[(int) NE_EXPR] = 1;
122: comparison_code[(int) LT_EXPR] = 1;
123: comparison_code[(int) GT_EXPR] = 1;
124: comparison_code[(int) LE_EXPR] = 1;
125: comparison_code[(int) GE_EXPR] = 1;
126: }
1.1.1.2 root 127:
128: /* This is run at the start of compiling a function. */
129:
130: void
131: init_expr ()
132: {
133: init_queue ();
134: may_call_alloca = 0;
135: }
1.1 root 136:
137: /* Manage the queue of increment instructions to be output
138: for POSTINCREMENT_EXPR expressions, etc. */
139:
140: static rtx pending_chain;
141:
142: /* Queue up to increment (or change) VAR later. BODY says how:
143: BODY should be the same thing you would pass to emit_insn
144: to increment right away. It will go to emit_insn later on.
145:
146: The value is a QUEUED expression to be used in place of VAR
1.1.1.2 root 147: where you want to guarantee the pre-incrementation value of VAR. */
1.1 root 148:
149: static rtx
150: enqueue_insn (var, body)
151: rtx var, body;
152: {
153: pending_chain = gen_rtx (QUEUED, GET_MODE (var),
154: var, 0, 0, body, pending_chain);
155: return pending_chain;
156: }
157:
158: /* Use protect_from_queue to convert a QUEUED expression
159: into something that you can put immediately into an instruction.
160: If the queued incrementation has not happened yet,
161: protect_from_queue returns the variable itself.
162: If the incrementation has happened, protect_from_queue returns a temp
163: that contains a copy of the old value of the variable.
164:
165: Any time an rtx which might possibly be a QUEUED is to be put
166: into an instruction, it must be passed through protect_from_queue first.
167: QUEUED expressions are not meaningful in instructions.
168:
169: Do not pass a value through protect_from_queue and then hold
170: on to it for a while before putting it in an instruction!
171: If the queue is flushed in between, incorrect code will result. */
172:
173: rtx
174: protect_from_queue (x, modify)
175: register rtx x;
176: int modify;
177: {
178: register RTX_CODE code = GET_CODE (x);
179: if (code != QUEUED)
180: {
181: /* A special hack for read access to (MEM (QUEUED ...))
182: to facilitate use of autoincrement.
183: Make a copy of the contents of the memory location
184: rather than a copy of the address. */
185: if (code == MEM && GET_CODE (XEXP (x, 0)) == QUEUED && !modify)
186: {
187: register rtx y = XEXP (x, 0);
188: XEXP (x, 0) = QUEUED_VAR (y);
189: if (QUEUED_INSN (y))
190: {
191: register rtx temp = gen_reg_rtx (GET_MODE (x));
192: emit_insn_before (gen_move_insn (temp, x),
193: QUEUED_INSN (y));
194: return temp;
195: }
196: return x;
197: }
198: /* Otherwise, recursively protect the subexpressions of all
199: the kinds of rtx's that can contain a QUEUED. */
200: if (code == MEM)
201: XEXP (x, 0) = protect_from_queue (XEXP (x, 0), 0);
202: else if (code == PLUS || code == MULT)
203: {
204: XEXP (x, 0) = protect_from_queue (XEXP (x, 0), 0);
205: XEXP (x, 1) = protect_from_queue (XEXP (x, 1), 0);
206: }
207: return x;
208: }
209: /* If the increment has not happened, use the variable itself. */
210: if (QUEUED_INSN (x) == 0)
211: return QUEUED_VAR (x);
212: /* If the increment has happened and a pre-increment copy exists,
213: use that copy. */
214: if (QUEUED_COPY (x) != 0)
215: return QUEUED_COPY (x);
216: /* The increment has happened but we haven't set up a pre-increment copy.
217: Set one up now, and use it. */
218: QUEUED_COPY (x) = gen_reg_rtx (GET_MODE (QUEUED_VAR (x)));
219: emit_insn_before (gen_move_insn (QUEUED_COPY (x), QUEUED_VAR (x)),
220: QUEUED_INSN (x));
221: return QUEUED_COPY (x);
222: }
223:
1.1.1.2 root 224: /* Return nonzero if X contains a QUEUED expression:
225: if it contains anything that will be altered by a queued increment. */
226:
227: static int
228: queued_subexp_p (x)
229: rtx x;
230: {
231: register enum rtx_code code = GET_CODE (x);
232: switch (code)
233: {
234: case QUEUED:
235: return 1;
236: case MEM:
237: return queued_subexp_p (XEXP (x, 0));
238: case MULT:
239: case PLUS:
240: case MINUS:
241: return queued_subexp_p (XEXP (x, 0))
242: || queued_subexp_p (XEXP (x, 1));
243: }
244: return 0;
245: }
246:
247: /* Perform all the pending incrementations. */
1.1 root 248:
249: void
250: emit_queue ()
251: {
252: register rtx p;
253: while (p = pending_chain)
254: {
255: QUEUED_INSN (p) = emit_insn (QUEUED_BODY (p));
256: pending_chain = QUEUED_NEXT (p);
257: }
258: }
259:
1.1.1.2 root 260: static void
1.1 root 261: init_queue ()
262: {
263: if (pending_chain)
264: abort ();
265: }
266:
267: /* Copy data from FROM to TO, where the machine modes are not the same.
268: Both modes may be integer, or both may be floating.
269: UNSIGNEDP should be nonzero if FROM is an unsigned type.
270: This causes zero-extension instead of sign-extension. */
271:
272: void
273: convert_move (to, from, unsignedp)
274: register rtx to, from;
275: int unsignedp;
276: {
277: enum machine_mode to_mode = GET_MODE (to);
278: enum machine_mode from_mode = GET_MODE (from);
279: int to_real = to_mode == SFmode || to_mode == DFmode;
280: int from_real = from_mode == SFmode || from_mode == DFmode;
281: int extending = (int) to_mode > (int) from_mode;
282:
283: to = protect_from_queue (to, 1);
284: from = protect_from_queue (from, 0);
285:
286: if (to_real != from_real)
287: abort ();
288:
1.1.1.2 root 289: if (to_mode == from_mode
290: || (from_mode == VOIDmode && CONSTANT_P (from)))
1.1 root 291: {
292: emit_move_insn (to, from);
293: return;
294: }
295:
296: if (to_real)
297: {
298: #ifdef HAVE_extendsfdf2
299: if (HAVE_extendsfdf2 && extending)
300: {
1.1.1.2 root 301: emit_unop_insn (CODE_FOR_extendsfdf2, to, from, UNKNOWN);
1.1 root 302: return;
303: }
304: #endif
305: #ifdef HAVE_truncdfsf2
306: if (HAVE_truncdfsf2 && ! extending)
307: {
1.1.1.2 root 308: emit_unop_insn (CODE_FOR_truncdfsf2, to, from, UNKNOWN);
1.1 root 309: return;
310: }
311: #endif
312: emit_library_call (gen_rtx (SYMBOL_REF, Pmode, (extending
1.1.1.2 root 313: ? "_extendsfdf2"
314: : "_truncdfsf2")),
315: GET_MODE (to), 1,
316: from, (extending ? SFmode : DFmode));
317: emit_move_insn (to, hard_libcall_value (GET_MODE (to)));
1.1 root 318: return;
319: }
320:
1.1.1.2 root 321: /* Now both modes are integers. */
322:
1.1 root 323: if (to_mode == DImode)
324: {
325: emit_insn (gen_rtx (CLOBBER, VOIDmode, to));
326:
327: if (unsignedp)
328: {
329: convert_move (gen_lowpart (SImode, to), from, unsignedp);
330: emit_clr_insn (gen_highpart (SImode, to));
331: }
1.1.1.2 root 332: #ifdef HAVE_slt
333: else if (HAVE_slt && insn_operand_mode[(int) CODE_FOR_slt][0] == SImode)
1.1 root 334: {
335: convert_move (gen_lowpart (SImode, to), from, unsignedp);
1.1.1.2 root 336: emit_insn (gen_slt (gen_highpart (SImode, to)));
1.1 root 337: }
338: #endif
339: else
340: {
341: register rtx label = gen_label_rtx ();
342:
343: emit_clr_insn (gen_highpart (SImode, to));
344: convert_move (gen_lowpart (SImode, to), from, unsignedp);
345: emit_cmp_insn (gen_lowpart (SImode, to),
346: gen_rtx (CONST_INT, VOIDmode, 0),
347: 0, 0);
348: emit_jump_insn (gen_bge (label));
349: expand_unop (SImode, one_cmpl_optab,
350: gen_highpart (SImode, to), gen_highpart (SImode, to),
351: 1);
352: emit_label (label);
353: }
354: return;
355: }
356:
357: if (from_mode == DImode)
358: {
359: convert_move (to, gen_lowpart (SImode, from), 0);
360: return;
361: }
362:
363: /* Now follow all the conversions between integers
364: no more than a word long. */
365:
1.1.1.2 root 366: /* For truncation, usually we can just refer to FROM in a narrower mode. */
367: if (GET_MODE_BITSIZE (to_mode) < GET_MODE_BITSIZE (from_mode)
368: && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (to_mode),
369: GET_MODE_BITSIZE (from_mode))
370: && ((GET_CODE (from) == MEM
371: && ! mode_dependent_address_p (XEXP (from, 0)))
372: || GET_CODE (from) == REG))
373: {
374: emit_move_insn (to, gen_lowpart (to_mode, from));
375: return;
376: }
377:
1.1 root 378: if (to_mode == SImode && from_mode == HImode)
379: {
380: if (unsignedp)
381: {
382: #ifdef HAVE_zero_extendhisi2
383: if (HAVE_zero_extendhisi2)
1.1.1.2 root 384: emit_unop_insn (CODE_FOR_zero_extendhisi2, to, from, ZERO_EXTEND);
1.1 root 385: else
386: #endif
387: abort ();
388: }
389: else
390: {
391: #ifdef HAVE_extendhisi2
392: if (HAVE_extendhisi2)
1.1.1.2 root 393: emit_unop_insn (CODE_FOR_extendhisi2, to, from, SIGN_EXTEND);
1.1 root 394: else
395: #endif
396: abort ();
397: }
398: return;
399: }
400:
401: if (to_mode == SImode && from_mode == QImode)
402: {
403: if (unsignedp)
404: {
405: #ifdef HAVE_zero_extendqisi2
406: if (HAVE_zero_extendqisi2)
407: {
1.1.1.2 root 408: emit_unop_insn (CODE_FOR_zero_extendqisi2, to, from, ZERO_EXTEND);
1.1 root 409: return;
410: }
411: #endif
412: #if defined (HAVE_zero_extendqihi2) && defined (HAVE_extendhisi2)
413: if (HAVE_zero_extendqihi2 && HAVE_extendhisi2)
414: {
415: register rtx temp = gen_reg_rtx (HImode);
1.1.1.2 root 416: emit_unop_insn (CODE_FOR_zero_extendqihi2, temp, from, ZERO_EXTEND);
417: emit_unop_insn (CODE_FOR_extendhisi2, to, temp, SIGN_EXTEND);
1.1 root 418: return;
419: }
420: #endif
421: }
422: else
423: {
424: #ifdef HAVE_extendqisi2
425: if (HAVE_extendqisi2)
426: {
1.1.1.2 root 427: emit_unop_insn (CODE_FOR_extendqisi2, to, from, SIGN_EXTEND);
1.1 root 428: return;
429: }
430: #endif
431: #if defined (HAVE_extendqihi2) && defined (HAVE_extendhisi2)
432: if (HAVE_extendqihi2 && HAVE_extendhisi2)
433: {
434: register rtx temp = gen_reg_rtx (HImode);
1.1.1.2 root 435: emit_unop_insn (CODE_FOR_extendqihi2, temp, from, SIGN_EXTEND);
436: emit_unop_insn (CODE_FOR_extendhisi2, to, temp, SIGN_EXTEND);
1.1 root 437: return;
438: }
439: #endif
440: }
441: abort ();
442: }
443:
444: if (to_mode == HImode && from_mode == QImode)
445: {
446: if (unsignedp)
447: {
448: #ifdef HAVE_zero_extendqihi2
449: if (HAVE_zero_extendqihi2)
450: {
1.1.1.2 root 451: emit_unop_insn (CODE_FOR_zero_extendqihi2, to, from, ZERO_EXTEND);
1.1 root 452: return;
453: }
454: #endif
455: }
456: else
457: {
458: #ifdef HAVE_extendqihi2
459: if (HAVE_extendqihi2)
460: {
1.1.1.2 root 461: emit_unop_insn (CODE_FOR_extendqihi2, to, from, SIGN_EXTEND);
1.1 root 462: return;
463: }
464: #endif
465: }
466: abort ();
467: }
468:
469: /* Now we are truncating an integer to a smaller one.
470: If the result is a temporary, we might as well just copy it,
471: since only the low-order part of the result needs to be valid
472: and it is valid with no change. */
473:
474: if (GET_CODE (to) == REG)
475: {
476: if (GET_CODE (from) == REG)
477: {
478: emit_move_insn (to, gen_lowpart (GET_MODE (to), from));
479: return;
480: }
1.1.1.2 root 481: else if (GET_CODE (from) == SUBREG)
482: {
483: from = copy_rtx (from);
484: /* This is safe since FROM is not more than one word. */
485: PUT_MODE (from, GET_MODE (to));
486: emit_move_insn (to, from);
487: return;
488: }
1.1 root 489: #ifndef BYTES_BIG_ENDIAN
490: else if (GET_CODE (from) == MEM)
491: {
492: register rtx addr = XEXP (from, 0);
1.1.1.2 root 493: if (memory_address_p (GET_MODE (to), addr))
1.1 root 494: {
495: emit_move_insn (to, gen_rtx (MEM, GET_MODE (to), addr));
496: return;
497: }
498: }
499: #endif /* not BYTES_BIG_ENDIAN */
500: }
501:
502: if (from_mode == SImode && to_mode == HImode)
503: {
504: #ifdef HAVE_truncsihi2
505: if (HAVE_truncsihi2)
506: {
1.1.1.2 root 507: emit_unop_insn (CODE_FOR_truncsihi2, to, from, UNKNOWN);
1.1 root 508: return;
509: }
510: #endif
511: abort ();
512: }
513:
514: if (from_mode == SImode && to_mode == QImode)
515: {
516: #ifdef HAVE_truncsiqi2
517: if (HAVE_truncsiqi2)
518: {
1.1.1.2 root 519: emit_unop_insn (CODE_FOR_truncsiqi2, to, from, UNKNOWN);
1.1 root 520: return;
521: }
522: #endif
523: abort ();
524: }
525:
526: if (from_mode == HImode && to_mode == QImode)
527: {
528: #ifdef HAVE_trunchiqi2
529: if (HAVE_trunchiqi2)
530: {
1.1.1.2 root 531: emit_unop_insn (CODE_FOR_trunchiqi2, to, from, UNKNOWN);
1.1 root 532: return;
533: }
534: #endif
535: abort ();
536: }
1.1.1.2 root 537:
538: /* Mode combination is not recognized. */
539: abort ();
1.1 root 540: }
541:
542: /* Return an rtx for a value that would result
543: from converting X to mode MODE.
544: Both X and MODE may be floating, or both integer.
545: UNSIGNEDP is nonzero if X is an unsigned value.
546: This can be done by referring to a part of X in place
547: or by copying to a new temporary with conversion. */
548:
549: rtx
550: convert_to_mode (mode, x, unsignedp)
551: enum machine_mode mode;
552: rtx x;
553: int unsignedp;
554: {
555: register rtx temp;
556: if (mode == GET_MODE (x))
557: return x;
1.1.1.2 root 558: if (integer_mode_p (mode)
559: && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (x)))
1.1 root 560: return gen_lowpart (mode, x);
561: temp = gen_reg_rtx (mode);
562: convert_move (temp, x, unsignedp);
563: return temp;
564: }
1.1.1.2 root 565:
566: int
567: integer_mode_p (mode)
568: enum machine_mode mode;
569: {
570: return (int) mode > (int) VOIDmode && (int) mode <= (int) TImode;
571: }
1.1 root 572:
573: /* Generate several move instructions to copy LEN bytes
1.1.1.2 root 574: from block FROM to block TO. (These are MEM rtx's with BLKmode).
575: The caller must pass FROM and TO
1.1 root 576: through protect_from_queue before calling.
577: ALIGN (in bytes) is maximum alignment we can assume. */
578:
579: struct move_by_pieces
580: {
581: rtx to;
1.1.1.2 root 582: rtx to_addr;
1.1 root 583: int autinc_to;
584: int explicit_inc_to;
585: rtx from;
1.1.1.2 root 586: rtx from_addr;
1.1 root 587: int autinc_from;
588: int explicit_inc_from;
589: int len;
590: int offset;
591: int reverse;
592: };
593:
594: static void
1.1.1.2 root 595: move_by_pieces (to, from, len, align)
1.1 root 596: rtx to, from;
597: int len, align;
598: {
599: struct move_by_pieces data;
1.1.1.2 root 600: rtx to_addr = XEXP (to, 0), from_addr = XEXP (from, 0);
1.1 root 601:
602: data.offset = 0;
1.1.1.2 root 603: data.to_addr = to_addr;
604: data.from_addr = from_addr;
1.1 root 605: data.to = to;
606: data.from = from;
1.1.1.2 root 607: data.autinc_to
608: = (GET_CODE (to_addr) == PRE_INC || GET_CODE (to_addr) == PRE_DEC
609: || GET_CODE (to_addr) == POST_INC || GET_CODE (to_addr) == POST_DEC);
610: data.autinc_from
611: = (GET_CODE (from_addr) == PRE_INC || GET_CODE (from_addr) == PRE_DEC
612: || GET_CODE (from_addr) == POST_INC
613: || GET_CODE (from_addr) == POST_DEC);
1.1 root 614:
615: data.explicit_inc_from = 0;
616: data.explicit_inc_to = 0;
1.1.1.2 root 617: data.reverse
618: = (GET_CODE (to_addr) == PRE_DEC || GET_CODE (to_addr) == POST_DEC);
1.1 root 619: if (data.reverse) data.offset = len;
620: data.len = len;
621:
622: /* If copying requires more than two move insns,
623: copy addresses to registers (to make displacements shorter)
624: and use post-increment if available. */
625: if (!(data.autinc_from && data.autinc_to)
626: && move_by_pieces_ninsns (len, align) > 2)
627: {
628: #ifdef HAVE_PRE_DECREMENT
629: if (data.reverse && ! data.autinc_from)
630: {
1.1.1.2 root 631: data.from_addr = copy_addr_to_reg (plus_constant (from_addr, len));
1.1 root 632: data.autinc_from = 1;
633: data.explicit_inc_from = -1;
634: }
635: #endif
636: #ifdef HAVE_POST_INCREMENT
637: if (! data.autinc_from)
638: {
1.1.1.2 root 639: data.from_addr = copy_addr_to_reg (from_addr);
1.1 root 640: data.autinc_from = 1;
641: data.explicit_inc_from = 1;
642: }
643: #endif
1.1.1.2 root 644: if (!data.autinc_from && CONSTANT_P (from_addr))
645: data.from_addr = copy_addr_to_reg (from_addr);
1.1 root 646: #ifdef HAVE_PRE_DECREMENT
647: if (data.reverse && ! data.autinc_to)
648: {
1.1.1.2 root 649: data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len));
1.1 root 650: data.autinc_to = 1;
651: data.explicit_inc_to = -1;
652: }
653: #endif
654: #ifdef HAVE_POST_INCREMENT
655: if (! data.reverse && ! data.autinc_to)
656: {
1.1.1.2 root 657: data.to_addr = copy_addr_to_reg (to_addr);
1.1 root 658: data.autinc_to = 1;
659: data.explicit_inc_to = 1;
660: }
661: #endif
1.1.1.2 root 662: if (!data.autinc_to && CONSTANT_P (to_addr))
663: data.to_addr = copy_addr_to_reg (to_addr);
1.1 root 664: }
665:
666: #ifdef STRICT_ALIGNMENT
1.1.1.2 root 667: if (align > MOVE_MAX || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT)
1.1 root 668: align = MOVE_MAX;
669: #else
670: align = MOVE_MAX;
671: #endif
672:
673: #ifdef HAVE_movti
674: if (HAVE_movti && align >= GET_MODE_SIZE (TImode))
675: move_by_pieces_1 (gen_movti, TImode, &data);
676: #endif
677: #ifdef HAVE_movdi
678: if (HAVE_movdi && align >= GET_MODE_SIZE (DImode))
679: move_by_pieces_1 (gen_movdi, DImode, &data);
680: #endif
1.1.1.2 root 681: #ifdef HAVE_movsi
1.1 root 682: if (align >= GET_MODE_SIZE (SImode))
683: move_by_pieces_1 (gen_movsi, SImode, &data);
1.1.1.2 root 684: #endif
685: #ifdef HAVE_movhi
686: if (HAVE_movhi && align >= GET_MODE_SIZE (HImode))
1.1 root 687: move_by_pieces_1 (gen_movhi, HImode, &data);
1.1.1.2 root 688: #endif
689: #ifdef HAVE_movqi
1.1 root 690: move_by_pieces_1 (gen_movqi, QImode, &data);
1.1.1.2 root 691: #else
692: movqi instruction required in machine description
693: #endif
1.1 root 694: }
695:
696: /* Return number of insns required to move L bytes by pieces.
697: ALIGN (in bytes) is maximum alignment we can assume. */
698:
1.1.1.2 root 699: static int
1.1 root 700: move_by_pieces_ninsns (l, align)
701: unsigned int l;
702: int align;
703: {
704: register int n_insns = 0;
705:
706: #ifdef STRICT_ALIGNMENT
1.1.1.2 root 707: if (align > MOVE_MAX || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT)
1.1 root 708: align = MOVE_MAX;
709: #else
710: align = MOVE_MAX;
711: #endif
712:
713: #ifdef HAVE_movti
714: if (HAVE_movti && align >= GET_MODE_SIZE (TImode))
715: n_insns += l / GET_MODE_SIZE (TImode), l %= GET_MODE_SIZE (TImode);
716: #endif
717: #ifdef HAVE_movdi
718: if (HAVE_movdi && align >= GET_MODE_SIZE (DImode))
719: n_insns += l / GET_MODE_SIZE (DImode), l %= GET_MODE_SIZE (DImode);
720: #endif
1.1.1.2 root 721: #ifdef HAVE_movsi
1.1 root 722: if (HAVE_movsi && align >= GET_MODE_SIZE (SImode))
723: n_insns += l / GET_MODE_SIZE (SImode), l %= GET_MODE_SIZE (SImode);
1.1.1.2 root 724: #endif
725: #ifdef HAVE_movhi
1.1 root 726: if (HAVE_movhi && align >= GET_MODE_SIZE (HImode))
727: n_insns += l / GET_MODE_SIZE (HImode), l %= GET_MODE_SIZE (HImode);
1.1.1.2 root 728: #endif
1.1 root 729: n_insns += l;
730:
731: return n_insns;
732: }
733:
734: /* Subroutine of move_by_pieces. Move as many bytes as appropriate
735: with move instructions for mode MODE. GENFUN is the gen_... function
736: to make a move insn for that mode. DATA has all the other info. */
737:
1.1.1.2 root 738: static void
1.1 root 739: move_by_pieces_1 (genfun, mode, data)
740: rtx (*genfun) ();
741: enum machine_mode mode;
742: struct move_by_pieces *data;
743: {
744: register int size = GET_MODE_SIZE (mode);
745: register rtx to1, from1;
746:
1.1.1.2 root 747: #define add_offset(FLAG,X) \
748: (FLAG ? (X) : plus_constant ((X), data->offset))
1.1 root 749:
750: while (data->len >= size)
751: {
1.1.1.2 root 752: if (data->reverse) data->offset -= size;
1.1 root 753:
1.1.1.2 root 754: to1 = change_address (data->to, mode,
755: add_offset (data->autinc_to, data->to_addr));
756: from1 = change_address (data->from, mode,
757: add_offset (data->autinc_from, data->from_addr));
1.1 root 758:
759: #ifdef HAVE_PRE_DECREMENT
760: if (data->explicit_inc_to < 0)
1.1.1.2 root 761: emit_insn (gen_sub2_insn (data->to_addr,
1.1 root 762: gen_rtx (CONST_INT, VOIDmode, size)));
763: if (data->explicit_inc_from < 0)
1.1.1.2 root 764: emit_insn (gen_sub2_insn (data->from_addr,
1.1 root 765: gen_rtx (CONST_INT, VOIDmode, size)));
766: #endif
767:
768: emit_insn (genfun (to1, from1));
769: #ifdef HAVE_POST_INCREMENT
770: if (data->explicit_inc_to > 0)
1.1.1.2 root 771: emit_insn (gen_add2_insn (data->to_addr,
1.1 root 772: gen_rtx (CONST_INT, VOIDmode, size)));
773: if (data->explicit_inc_from > 0)
1.1.1.2 root 774: emit_insn (gen_add2_insn (data->from_addr,
1.1 root 775: gen_rtx (CONST_INT, VOIDmode, size)));
776: #endif
777:
778: if (! data->reverse) data->offset += size;
1.1.1.2 root 779:
1.1 root 780: data->len -= size;
781: }
782: }
783:
784: /* Emit code to move a block Y to a block X.
785: This may be done with string-move instructions,
786: with multiple scalar move instructions, or with a library call.
787:
788: Both X and Y must be MEM rtx's (perhaps inside VOLATILE)
789: with mode BLKmode.
790: SIZE is an rtx that says how long they are.
791: ALIGN is the maximum alignment we can assume they have,
792: measured in bytes. */
793:
794: static void
795: emit_block_move (x, y, size, align)
796: rtx x, y;
797: rtx size;
798: int align;
799: {
800: if (GET_MODE (x) != BLKmode)
801: abort ();
802:
803: if (GET_MODE (y) != BLKmode)
804: abort ();
805:
806: x = protect_from_queue (x, 1);
807: y = protect_from_queue (y, 0);
808:
1.1.1.2 root 809: if (GET_CODE (x) != MEM)
1.1 root 810: abort ();
1.1.1.2 root 811: if (GET_CODE (y) != MEM)
1.1 root 812: abort ();
813: if (size == 0)
814: abort ();
815:
816: if (GET_CODE (size) == CONST_INT
817: && (move_by_pieces_ninsns ((unsigned) INTVAL (size), align)
818: < MOVE_RATIO))
1.1.1.2 root 819: move_by_pieces (x, y, INTVAL (size), align);
1.1 root 820: else
821: {
822: #ifdef HAVE_movstrsi
823: if (HAVE_movstrsi)
824: {
825: emit_insn (gen_movstrsi (x, y, size));
826: return;
827: }
828: #endif
829: #ifdef HAVE_movstrhi
830: if (HAVE_movstrhi
831: && GET_CODE (size) == CONST_INT
832: && ((unsigned) INTVAL (size)
833: < (1 << (GET_MODE_SIZE (HImode) * BITS_PER_UNIT - 1))))
834: {
835: emit_insn (gen_movstrhi (x, y, size));
836: return;
837: }
838: #endif
1.1.1.2 root 839:
840: #ifdef TARGET_MEM_FUNCTIONS
841: emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "memcpy"),
842: VOIDmode, 3, XEXP (x, 0), Pmode,
843: XEXP (y, 0), Pmode,
844: size, Pmode);
845: #else
1.1 root 846: emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "bcopy"),
1.1.1.2 root 847: VOIDmode, 3, XEXP (y, 0), Pmode,
848: XEXP (x, 0), Pmode,
1.1 root 849: size, Pmode);
1.1.1.2 root 850: #endif
851: }
852: }
853:
854: /* Copy all or part of a BLKmode value X into registers starting at REGNO.
855: The number of registers to be filled is NREGS. */
856:
857: static void
858: move_block_to_reg (regno, x, nregs)
859: int regno;
860: rtx x;
861: int nregs;
862: {
863: int i;
864: if (GET_CODE (x) == CONST_DOUBLE && x != dconst0_rtx)
865: x = force_const_double_mem (x);
866: for (i = 0; i < nregs; i++)
867: {
868: if (GET_CODE (x) == REG)
869: emit_move_insn (gen_rtx (REG, SImode, regno + i),
870: gen_rtx (SUBREG, SImode, x, i));
871: else if (x == dconst0_rtx)
872: emit_move_insn (gen_rtx (REG, SImode, regno + i),
873: const0_rtx);
874: else
875: emit_move_insn (gen_rtx (REG, SImode, regno + i),
876: gen_rtx (MEM, SImode,
877: plus_constant (XEXP (x, 0),
878: i * GET_MODE_SIZE (SImode))));
879: }
880: }
881:
882: /* Copy all or part of a BLKmode value X out of registers starting at REGNO.
883: The number of registers to be filled is NREGS. */
884:
885: void
886: move_block_from_reg (regno, x, nregs)
887: int regno;
888: rtx x;
889: int nregs;
890: {
891: int i;
892: for (i = 0; i < nregs; i++)
893: {
894: if (GET_CODE (x) == REG)
895: emit_move_insn (gen_rtx (SUBREG, SImode, x, i),
896: gen_rtx (REG, SImode, regno + i));
897: else
898: emit_move_insn (gen_rtx (MEM, SImode,
899: plus_constant (XEXP (x, 0),
900: i * GET_MODE_SIZE (SImode))),
901: gen_rtx (REG, SImode, regno + i));
1.1 root 902: }
903: }
1.1.1.2 root 904:
905: /* Mark NREGS consecutive regs, starting at REGNO, as being live now. */
906:
907: static void
908: use_regs (regno, nregs)
909: int regno;
910: int nregs;
911: {
912: int i;
913: for (i = 0; i < nregs; i++)
914: emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, regno + i)));
915: }
1.1 root 916:
1.1.1.2 root 917: /* Write zeros through the storage of OBJECT.
918: If OBJECT has BLKmode, SIZE is its length in bytes. */
919:
920: void
921: clear_storage (object, size)
922: rtx object;
923: int size;
924: {
925: if (GET_MODE (object) == BLKmode)
926: {
927: #ifdef TARGET_MEM_FUNCTIONS
928: emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "memset"),
929: VOIDmode, 3,
930: XEXP (object, 0), Pmode, const0_rtx, Pmode,
931: gen_rtx (CONST_INT, VOIDmode, size), Pmode);
932: #else
933: emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "bzero"),
934: VOIDmode, 2,
935: XEXP (object, 0), Pmode,
936: gen_rtx (CONST_INT, VOIDmode, size), Pmode);
937: #endif
938: }
939: else
940: emit_move_insn (object, const0_rtx, 0);
941: }
942:
1.1 root 943: /* Generate code to copy Y into X.
944: Both Y and X must have the same mode, except that
945: Y can be a constant with VOIDmode.
1.1.1.2 root 946: This mode cannot be BLKmode; use emit_block_move for that.
1.1 root 947:
1.1.1.2 root 948: Return the last instruction emitted. */
949:
950: rtx
1.1 root 951: emit_move_insn (x, y)
952: rtx x, y;
953: {
954: enum machine_mode mode = GET_MODE (x);
955: x = protect_from_queue (x, 1);
956: y = protect_from_queue (y, 0);
957:
1.1.1.3 root 958: if ((CONSTANT_P (y) || GET_CODE (y) == CONST_DOUBLE)
959: && ! LEGITIMATE_CONSTANT_P (y))
1.1.1.2 root 960: y = force_const_mem (mode, y);
961:
1.1 root 962: if (mode == BLKmode)
963: abort ();
1.1.1.2 root 964: if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
965: return
966: emit_insn (GEN_FCN (mov_optab->handlers[(int) mode].insn_code) (x, y));
967: #if 0
968: /* It turns out you get much better optimization (in cse and flow)
969: if you define movdi and movdf instruction patterns
970: even if they must turn into multiple assembler instructions. */
1.1 root 971: else if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (SImode))
972: {
973: register int count = GET_MODE_SIZE (mode) / GET_MODE_SIZE (SImode);
974: register int i;
1.1.1.2 root 975: if (GET_CODE (y) == CONST_DOUBLE && y != dconst0_rtx)
976: y = force_const_double_mem (y);
1.1 root 977: for (i = 0; i < count; i++)
978: {
979: rtx x1, y1;
980: if (GET_CODE (x) == REG)
981: x1 = gen_rtx (SUBREG, SImode, x, i);
982: else
983: x1 = gen_rtx (MEM, SImode,
984: memory_address (SImode,
985: plus_constant (XEXP (x, 0),
986: i * GET_MODE_SIZE (SImode))));
987: if (GET_CODE (y) == REG)
988: y1 = gen_rtx (SUBREG, SImode, y, i);
1.1.1.2 root 989: else if (y == dconst0_rtx)
990: y1 = const0_rtx;
1.1 root 991: else
992: y1 = gen_rtx (MEM, SImode,
993: memory_address (SImode,
994: plus_constant (XEXP (y, 0),
995: i * GET_MODE_SIZE (SImode))));
996: emit_insn (gen_movsi (protect_from_queue (x1, 1), protect_from_queue (y1, 0)));
997: }
998: }
1.1.1.2 root 999: #endif
1.1 root 1000: else
1001: abort ();
1002: }
1003:
1004: /* Pushing data onto the stack. */
1005:
1006: /* Push a block of length SIZE (perhaps variable)
1007: and return an rtx to address the beginning of the block.
1.1.1.4 ! root 1008: Note that it is not possible for the value returned to be a QUEUED.
! 1009: The value may be stack_pointer_rtx.
! 1010:
! 1011: The value we return does not take account of STACK_POINTER_OFFSET,
! 1012: so the caller must do so when using the value. */
1.1 root 1013:
1014: static rtx
1015: push_block (size)
1016: rtx size;
1017: {
1018: register rtx temp;
1.1.1.2 root 1019: if (CONSTANT_P (size) || GET_CODE (size) == REG)
1020: anti_adjust_stack (size);
1021: else
1022: anti_adjust_stack (copy_to_mode_reg (Pmode, size));
1.1 root 1023:
1024: #ifdef STACK_GROWS_DOWNWARD
1.1.1.2 root 1025: temp = stack_pointer_rtx;
1.1 root 1026: #else
1027: temp = gen_rtx (PLUS, Pmode,
1.1.1.2 root 1028: stack_pointer_rtx,
1.1 root 1029: size);
1030: if (GET_CODE (size) != CONST_INT)
1031: temp = force_operand (temp, 0);
1032: #endif
1033: return memory_address (QImode, temp);
1034: }
1035:
1036: static rtx
1037: gen_push_operand ()
1038: {
1039: return gen_rtx (
1040: #ifdef STACK_GROWS_DOWNWARD
1041: PRE_DEC,
1042: #else
1043: PRE_INC,
1044: #endif
1045: Pmode,
1.1.1.2 root 1046: stack_pointer_rtx);
1.1 root 1047: }
1048:
1049: /* Generate code to push X onto the stack, assuming it has mode MODE.
1050: MODE is redundant except when X is a CONST_INT (since they don't
1051: carry mode info).
1052: SIZE is an rtx for the size of data to be copied (in bytes),
1053: needed only if X is BLKmode.
1.1.1.2 root 1054: ALIGN (in bytes) is maximum alignment we can assume.
1055:
1056: If PARTIAL is nonzero, then copy that many of the first words
1057: of X into registers starting with REG, and push the rest of X.
1058: The amount of space pushed is decreased by PARTIAL words,
1059: rounded *down* to a multiple of PARM_BOUNDARY.
1060: REG must be a hard register in this case.
1061:
1062: EXTRA is the amount in bytes of extra space to leave next to this arg.
1063:
1064: On a machine that lacks real push insns, ARGS_ADDR is the address of
1065: the bottom of the argument block for this call. We use indexing off there
1066: to store the arg. On machines with push insns, ARGS_ADDR is 0.
1067:
1068: ARGS_SO_FAR is the size of args previously pushed for this call. */
1.1 root 1069:
1070: static void
1.1.1.2 root 1071: emit_push_insn (x, mode, size, align, partial, reg, extra, args_addr, args_so_far)
1.1 root 1072: register rtx x;
1073: enum machine_mode mode;
1074: rtx size;
1075: int align;
1.1.1.2 root 1076: int partial;
1077: rtx reg;
1078: int extra;
1079: rtx args_addr;
1080: rtx args_so_far;
1.1 root 1081: {
1082: rtx xinner;
1083:
1084: xinner = x = protect_from_queue (x, 0);
1085:
1.1.1.2 root 1086: /* If part should go in registers, copy that part
1087: into the appropriate registers. */
1088: if (partial > 0)
1089: move_block_to_reg (REGNO (reg), x, partial);
1090:
1091: #ifdef STACK_GROWS_DOWNWARD
1092: if (extra && args_addr == 0)
1093: anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode, extra));
1094: #endif
1.1 root 1095:
1096: if (mode == BLKmode)
1097: {
1098: register rtx temp;
1.1.1.2 root 1099: int used = partial * UNITS_PER_WORD;
1100: int offset = used % (PARM_BOUNDARY / BITS_PER_UNIT);
1101:
1102: used -= used % (PARM_BOUNDARY / BITS_PER_UNIT);
1103:
1.1 root 1104: if (size == 0)
1105: abort ();
1106:
1.1.1.2 root 1107: if (partial != 0)
1108: xinner = change_address (xinner, BLKmode,
1109: plus_constant (XEXP (xinner, 0), used));
1110:
1111: #ifdef PUSH_ROUNDING
1112: /* Do it with several push insns if that doesn't take lots of insns
1113: and if there is no difficulty with push insns that skip bytes
1114: on the stack for alignment purposes. */
1115: if (args_addr == 0
1116: && GET_CODE (size) == CONST_INT
1117: && args_addr == 0
1118: && (move_by_pieces_ninsns ((unsigned) INTVAL (size) - used, align)
1119: < MOVE_RATIO)
1120: && PUSH_ROUNDING (INTVAL (size)) == INTVAL (size))
1121: move_by_pieces (gen_rtx (MEM, BLKmode, gen_push_operand ()), xinner,
1122: INTVAL (size) - used, align);
1.1 root 1123: else
1.1.1.2 root 1124: #endif /* PUSH_ROUNDING */
1.1 root 1125: {
1.1.1.2 root 1126: /* Otherwise make space on the stack and copy the data
1127: to the address of that space. */
1128:
1129: /* First deduct part put into registers from the size we need. */
1130: if (partial != 0)
1131: {
1132: if (GET_CODE (size) == CONST_INT)
1133: size = gen_rtx (CONST_INT, VOIDmode, INTVAL (size) - used);
1134: else
1135: size = expand_binop (GET_MODE (size), sub_optab, size,
1136: gen_rtx (CONST_INT, VOIDmode, used),
1137: 0, 0, OPTAB_LIB_WIDEN);
1138: }
1139:
1140: /* Get the address of the stack space. */
1141: if (! args_addr)
1142: temp = push_block (size);
1143: else if (GET_CODE (args_so_far) == CONST_INT)
1144: temp = memory_address (BLKmode,
1145: plus_constant (args_addr,
1146: offset + INTVAL (args_so_far)));
1147: else
1148: temp = memory_address (BLKmode,
1149: plus_constant (gen_rtx (PLUS, Pmode,
1150: args_addr, args_so_far),
1151: offset));
1152:
1153:
1154: /* TEMP is the address of the block. Copy the data there. */
1155: if (GET_CODE (size) == CONST_INT
1156: && (move_by_pieces_ninsns ((unsigned) INTVAL (size), align)
1157: < MOVE_RATIO))
1158: {
1159: move_by_pieces (gen_rtx (MEM, BLKmode, temp), xinner,
1160: INTVAL (size), align);
1161: return;
1162: }
1.1 root 1163: #ifdef HAVE_movstrsi
1164: if (HAVE_movstrsi)
1165: {
1166: emit_insn (gen_movstrsi (gen_rtx (MEM, BLKmode, temp), x, size));
1167: return;
1168: }
1169: #endif
1170: #ifdef HAVE_movstrhi
1171: if (HAVE_movstrhi
1172: && GET_CODE (size) == CONST_INT
1173: && ((unsigned) INTVAL (size)
1174: < (1 << (GET_MODE_SIZE (HImode) * BITS_PER_UNIT - 1))))
1175: {
1176: emit_insn (gen_movstrhi (gen_rtx (MEM, BLKmode, temp),
1177: x, size));
1178: return;
1179: }
1180: #endif
1.1.1.2 root 1181:
1182: if (reg_mentioned_p (stack_pointer_rtx, temp))
1183: {
1184: /* Correct TEMP so it holds what will be a description of
1185: the address to copy to, valid after one arg is pushed. */
1.1.1.4 ! root 1186: int xsize = ((PUSH_ROUNDING (GET_MODE_SIZE (Pmode))
! 1187: + PARM_BOUNDARY / BITS_PER_UNIT - 1)
! 1188: / (PARM_BOUNDARY / BITS_PER_UNIT)
! 1189: * (PARM_BOUNDARY / BITS_PER_UNIT));
1.1 root 1190: #ifdef STACK_GROWS_DOWNWARD
1.1.1.4 ! root 1191: temp = plus_constant (temp, xsize);
1.1 root 1192: #else
1.1.1.4 ! root 1193: temp = plus_constant (temp, xsize);
1.1 root 1194: #endif
1.1.1.2 root 1195: }
1196:
1197: /* Make current_args_size nonzero around the library call
1198: to force it to pop the bcopy-arguments right away. */
1199: current_args_size += 1;
1200: #ifdef TARGET_MEM_FUNCTIONS
1201: emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "memcpy"),
1202: VOIDmode, 3, temp, Pmode, XEXP (xinner, 0), Pmode,
1203: size, Pmode);
1204: #else
1.1 root 1205: emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "bcopy"),
1.1.1.2 root 1206: VOIDmode, 3, XEXP (xinner, 0), Pmode, temp, Pmode,
1.1 root 1207: size, Pmode);
1.1.1.2 root 1208: #endif
1209: current_args_size -= 1;
1.1 root 1210: }
1211: }
1.1.1.2 root 1212: else if (partial > 0)
1.1 root 1213: {
1.1.1.2 root 1214: int size = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
1215: int i;
1216: int used = partial * UNITS_PER_WORD;
1217: /* # words of start of argument
1218: that we must make space for but need not store. */
1219: int skip = partial % (PARM_BOUNDARY / BITS_PER_WORD);
1220: int args_offset = INTVAL (args_so_far);
1221:
1222: /* If we make space by pushing it, we might as well push
1223: the real data. Otherwise, we can leave SKIP nonzero
1224: and leave the space uninitialized. */
1225: if (args_addr == 0)
1226: skip = 0;
1227:
1228: /* Deduct all the rest of PARTIAL words from SIZE in any case.
1229: This is space that we don't even allocate in the stack. */
1230: used -= used % (PARM_BOUNDARY / BITS_PER_UNIT);
1231: size -= used / UNITS_PER_WORD;
1232:
1233: if (GET_CODE (x) == CONST_DOUBLE && x != dconst0_rtx)
1234: x = force_const_double_mem (x);
1235:
1236: #ifndef PUSH_ARGS_REVERSED
1237: for (i = skip; i < size; i++)
1238: #else
1239: for (i = size - 1; i >= skip; i--)
1240: #endif
1241: if (GET_CODE (x) == MEM)
1242: emit_push_insn (gen_rtx (MEM, SImode,
1243: plus_constant (XEXP (x, 0),
1244: i * UNITS_PER_WORD)),
1245: SImode, 0, align, 0, 0, 0, args_addr,
1246: gen_rtx (CONST_INT, VOIDmode,
1247: args_offset + i * UNITS_PER_WORD));
1248: else if (GET_CODE (x) == REG)
1249: emit_push_insn (gen_rtx (SUBREG, SImode, x, i),
1250: SImode, 0, align, 0, 0, 0, args_addr,
1251: gen_rtx (CONST_INT, VOIDmode,
1252: args_offset + i * UNITS_PER_WORD));
1253: else if (x == dconst0_rtx)
1254: emit_push_insn (const0_rtx,
1255: SImode, 0, align, 0, 0, 0, args_addr,
1256: gen_rtx (CONST_INT, VOIDmode,
1257: args_offset + i * UNITS_PER_WORD));
1258: else
1259: abort ();
1.1 root 1260: }
1261: else
1.1.1.2 root 1262: {
1263: rtx addr;
1264: #ifdef PUSH_ROUNDING
1265: if (args_addr == 0)
1266: addr = gen_push_operand ();
1267: else
1268: #endif
1269: if (GET_CODE (args_so_far) == CONST_INT)
1270: addr
1271: = memory_address (mode,
1272: plus_constant (args_addr, INTVAL (args_so_far)));
1273: else
1274: addr = memory_address (mode, gen_rtx (PLUS, Pmode, args_addr,
1275: args_so_far));
1276:
1277: emit_move_insn (gen_rtx (MEM, mode, addr), x);
1278: }
1279:
1280: #ifndef STACK_GROWS_DOWNWARD
1281: if (extra && args_addr == 0)
1282: anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode, extra));
1283: #endif
1.1 root 1284: }
1285:
1286: /* Output a library call to function FUN (a SYMBOL_REF rtx)
1.1.1.2 root 1287: for a value of mode OUTMODE
1.1 root 1288: with NARGS different arguments, passed as alternating rtx values
1289: and machine_modes to convert them to.
1290: The rtx values should have been passed through protect_from_queue already. */
1291:
1292: void
1.1.1.2 root 1293: emit_library_call (va_alist)
1294: va_dcl
1.1 root 1295: {
1.1.1.2 root 1296: register va_list p;
1.1 root 1297: register int args_size = 0;
1298: register int argnum;
1.1.1.2 root 1299: enum machine_mode outmode;
1300: int nargs;
1301: rtx fun;
1302: rtx orgfun;
1303: int inc;
1304: int count;
1305: rtx *regvec;
1306: rtx argblock = 0;
1307: CUMULATIVE_ARGS args_so_far;
1308: struct arg { rtx value; enum machine_mode mode; };
1309: struct arg *argvec;
1310: int old_args_size = current_args_size;
1311:
1312: va_start (p);
1313: orgfun = fun = va_arg (p, rtx);
1314: outmode = va_arg (p, enum machine_mode);
1315: nargs = va_arg (p, int);
1316:
1317: regvec = (rtx *) alloca (nargs * sizeof (rtx));
1318:
1319: /* Copy all the libcall-arguments out of the varargs data
1320: and into a vector ARGVEC. */
1321: argvec = (struct arg *) alloca (nargs * sizeof (struct arg));
1322: for (count = 0; count < nargs; count++)
1323: {
1324: argvec[count].value = va_arg (p, rtx);
1325: argvec[count].mode = va_arg (p, enum machine_mode);
1326: }
1327: va_end (p);
1328:
1329: /* If we have no actual push instructions, make space for all the args
1330: right now. */
1331: #ifndef PUSH_ROUNDING
1332: INIT_CUMULATIVE_ARGS (args_so_far, (tree)0);
1333: for (count = 0; count < nargs; count++)
1334: {
1335: register enum machine_mode mode = argvec[count].mode;
1336: register rtx reg;
1337: register int partial;
1338:
1339: reg = FUNCTION_ARG (args_so_far, mode, 0, 1);
1340: #ifdef FUNCTION_ARG_PARTIAL_NREGS
1341: partial = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode, 0, 1);
1342: #else
1343: partial = 0;
1344: #endif
1345: if (reg == 0 || partial != 0)
1346: args_size += GET_MODE_SIZE (mode);
1347: if (partial != 0)
1348: args_size -= partial * GET_MODE_SIZE (SImode);
1349: FUNCTION_ARG_ADVANCE (args_so_far, mode, 0, 1);
1350: }
1351:
1352: if (args_size != 0)
1353: argblock
1354: = push_block (round_push (gen_rtx (CONST_INT, VOIDmode, args_size)));
1355: #endif
1356:
1357: INIT_CUMULATIVE_ARGS (args_so_far, (tree)0);
1358:
1359: #ifdef PUSH_ARGS_REVERSED
1360: inc = -1;
1361: argnum = nargs - 1;
1.1 root 1362: #else
1.1.1.2 root 1363: inc = 1;
1364: argnum = 0;
1.1 root 1365: #endif
1.1.1.2 root 1366: args_size = 0;
1367:
1368: for (count = 0; count < nargs; count++, argnum += inc)
1.1 root 1369: {
1.1.1.2 root 1370: register enum machine_mode mode = argvec[argnum].mode;
1371: register rtx val = argvec[argnum].value;
1372: rtx reg;
1373: int partial;
1374: int arg_size;
1375:
1.1 root 1376: /* Convert the arg value to the mode the library wants. */
1377: /* ??? It is wrong to do it here; must do it earlier
1378: where we know the signedness of the arg. */
1379: if (GET_MODE (val) != mode && GET_MODE (val) != VOIDmode)
1380: {
1381: val = gen_reg_rtx (mode);
1.1.1.2 root 1382: convert_move (val, argvec[argnum].value, 0);
1.1 root 1383: }
1.1.1.2 root 1384: reg = FUNCTION_ARG (args_so_far, mode, 0, 1);
1385: regvec[argnum] = reg;
1386: #ifdef FUNCTION_ARG_PARTIAL_NREGS
1387: partial = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode, 0, 1);
1388: #else
1389: partial = 0;
1390: #endif
1391:
1392: if (reg != 0 && partial == 0)
1393: emit_move_insn (reg, val);
1394: else
1395: emit_push_insn (val, mode, 0, 0, partial, reg, 0, argblock,
1396: gen_rtx (CONST_INT, VOIDmode, args_size));
1397:
1398: /* Compute size of stack space used by this argument. */
1399: if (reg == 0 || partial != 0)
1400: arg_size = GET_MODE_SIZE (mode);
1401: else
1402: arg_size = 0;
1403: if (partial != 0)
1404: arg_size
1405: -= ((partial * UNITS_PER_WORD)
1406: / (PARM_BOUNDARY / BITS_PER_UNIT)
1407: * (PARM_BOUNDARY / BITS_PER_UNIT));
1408:
1409: args_size += arg_size;
1410: current_args_size += arg_size;
1411: FUNCTION_ARG_ADVANCE (args_so_far, mode, 0, 1);
1.1 root 1412: }
1413:
1414: emit_queue ();
1.1.1.2 root 1415:
1416: fun = prepare_call_address (fun, 0);
1417:
1418: /* Any regs containing parms remain in use through the call.
1419: ??? This is not quite correct, since it doesn't indicate
1420: that they are in use immediately before the call insn.
1421: Currently that doesn't matter since explicitly-used regs
1422: won't be used for reloading. But if the reloader becomes smarter,
1423: this will have to change somehow. */
1424: for (count = 0; count < nargs; count++)
1425: if (regvec[count] != 0)
1426: emit_insn (gen_rtx (USE, VOIDmode, regvec[count]));
1427:
1428: #ifdef STACK_BOUNDARY
1429: args_size = (args_size + STACK_BYTES - 1) / STACK_BYTES * STACK_BYTES;
1430: #endif
1431:
1.1.1.3 root 1432: /* Don't allow popping to be deferred, since then
1433: cse'ing of library calls could delete a call and leave the pop. */
1.1.1.2 root 1434: current_args_size += 1;
1435: emit_call_1 (fun, get_identifier (XSTR (orgfun, 0)), args_size,
1436: FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1),
1437: outmode != VOIDmode ? hard_libcall_value (outmode) : 0,
1.1.1.3 root 1438: old_args_size + 1);
1439: current_args_size -= 1;
1.1 root 1440: }
1441:
1442: /* Expand an assignment that stores the value of FROM into TO.
1.1.1.2 root 1443: If WANT_VALUE is nonzero, return an rtx for the value of TO.
1444: (This may contain a QUEUED rtx.)
1445: Otherwise, the returned value is not meaningful.
1446:
1447: SUGGEST_REG is no longer actually used.
1448: It used to mean, copy the value through a register
1449: and return that register, if that is possible.
1450: But now we do this if WANT_VALUE.
1451:
1452: If the value stored is a constant, we return the constant. */
1.1 root 1453:
1454: rtx
1.1.1.2 root 1455: expand_assignment (to, from, want_value, suggest_reg)
1.1 root 1456: tree to, from;
1.1.1.2 root 1457: int want_value;
1458: int suggest_reg;
1.1 root 1459: {
1460: register rtx to_rtx = 0;
1461:
1462: /* Don't crash if the lhs of the assignment was erroneous. */
1463:
1464: if (TREE_CODE (to) == ERROR_MARK)
1465: return expand_expr (from, 0, VOIDmode, 0);
1466:
1467: /* Assignment of a structure component needs special treatment
1.1.1.2 root 1468: if the structure component's rtx is not simply a MEM.
1469: Assignment of an array element at a constant index
1470: has the same problem. */
1471:
1472: if (TREE_CODE (to) == COMPONENT_REF
1473: || (TREE_CODE (to) == ARRAY_REF
1474: && TREE_CODE (TREE_OPERAND (to, 1)) == INTEGER_CST
1475: && TREE_CODE (TYPE_SIZE (TREE_TYPE (to))) == INTEGER_CST))
1.1 root 1476: {
1.1.1.2 root 1477: register enum machine_mode mode1;
1478: int bitsize;
1.1 root 1479: int volstruct = 0;
1.1.1.2 root 1480: tree tem = to;
1481: int bitpos = 0;
1482: int unsignedp;
1.1 root 1483:
1.1.1.2 root 1484: if (TREE_CODE (to) == COMPONENT_REF)
1.1 root 1485: {
1486: tree field = TREE_OPERAND (to, 1);
1.1.1.2 root 1487: bitsize = TREE_INT_CST_LOW (DECL_SIZE (field)) * DECL_SIZE_UNIT (field);
1488: mode1 = DECL_MODE (TREE_OPERAND (to, 1));
1489: unsignedp = TREE_UNSIGNED (field);
1.1 root 1490: }
1.1.1.2 root 1491: else
1.1 root 1492: {
1.1.1.2 root 1493: mode1 = TYPE_MODE (TREE_TYPE (to));
1494: bitsize = GET_MODE_BITSIZE (mode1);
1495: unsignedp = TREE_UNSIGNED (TREE_TYPE (to));
1.1 root 1496: }
1497:
1.1.1.2 root 1498: /* Compute cumulative bit-offset for nested component-refs
1499: and array-refs, and find the ultimate containing object. */
1.1 root 1500:
1.1.1.2 root 1501: while (1)
1.1 root 1502: {
1.1.1.2 root 1503: if (TREE_CODE (tem) == COMPONENT_REF)
1504: {
1505: bitpos += DECL_OFFSET (TREE_OPERAND (tem, 1));
1506: if (TREE_THIS_VOLATILE (tem))
1507: volstruct = 1;
1508: }
1509: else if (TREE_CODE (tem) == ARRAY_REF
1510: && TREE_CODE (TREE_OPERAND (tem, 1)) == INTEGER_CST
1511: && TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) == INTEGER_CST)
1512: {
1513: bitpos += (TREE_INT_CST_LOW (TREE_OPERAND (tem, 1))
1514: * TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (tem)))
1515: * TYPE_SIZE_UNIT (TREE_TYPE (tem)));
1516: }
1517: else
1518: break;
1519: tem = TREE_OPERAND (tem, 0);
1.1 root 1520: }
1521:
1.1.1.2 root 1522: /* If we are going to use store_bit_field and extract_bit_field,
1523: make sure to_rtx will be safe for multiple use. */
1524: if (mode1 == BImode && want_value)
1525: tem = stabilize_reference (tem);
1.1 root 1526:
1.1.1.2 root 1527: to_rtx = expand_expr (tem, 0, VOIDmode, 0);
1528:
1529: return store_field (to_rtx, bitsize, bitpos, mode1, from,
1530: want_value ? TYPE_MODE (TREE_TYPE (to)) : VOIDmode,
1531: unsignedp);
1.1 root 1532: }
1533:
1534: /* Ordinary treatment. Expand TO to get a REG or MEM rtx.
1535: Don't re-expand if it was expanded already (in COMPONENT_REF case). */
1536:
1537: if (to_rtx == 0)
1538: to_rtx = expand_expr (to, 0, VOIDmode, 0);
1539:
1540: /* Compute FROM and store the value in the rtx we got. */
1541:
1.1.1.2 root 1542: return store_expr (from, to_rtx, want_value);
1.1 root 1543: }
1544:
1545: /* Generate code for computing expression EXP,
1.1.1.2 root 1546: and storing the value into TARGET.
1547: Returns TARGET or an equivalent value.
1548: TARGET may contain a QUEUED rtx.
1.1 root 1549:
1.1.1.2 root 1550: If SUGGEST_REG is nonzero, copy the value through a register
1551: and return that register, if that is possible.
1552:
1553: If the value stored is a constant, we return the constant. */
1554:
1555: rtx
1556: store_expr (exp, target, suggest_reg)
1.1 root 1557: register tree exp;
1558: register rtx target;
1.1.1.2 root 1559: int suggest_reg;
1.1 root 1560: {
1.1.1.2 root 1561: register rtx temp;
1562: int dont_return_target = 0;
1563:
1564: /* Copying a non-constant CONSTRUCTOR needs special treatment. */
1565:
1566: if (TREE_CODE (exp) == CONSTRUCTOR && ! TREE_LITERAL (exp))
1567: {
1568: store_constructor (exp, target);
1569: return target;
1570: }
1571:
1572: if (suggest_reg && GET_CODE (target) == MEM && GET_MODE (target) != BLKmode)
1573: /* If target is in memory and caller wants value in a register instead,
1574: arrange that. Pass TARGET as target for expand_expr so that,
1575: if EXP is another assignment, SUGGEST_REG will be nonzero for it.
1576: We know expand_expr will not use the target in that case. */
1577: {
1578: temp = expand_expr (exp, cse_not_expected ? 0 : target,
1579: GET_MODE (target), 0);
1580: if (GET_MODE (temp) != BLKmode && GET_MODE (temp) != VOIDmode)
1581: temp = copy_to_reg (temp);
1582: dont_return_target = 1;
1583: }
1584: else if (queued_subexp_p (target))
1585: /* If target contains a postincrement, it is not safe
1586: to use as the returned value. It would access the wrong
1587: place by the time the queued increment gets output.
1588: So copy the value through a temporary and use that temp
1589: as the result. */
1590: {
1591: temp = expand_expr (exp, 0, GET_MODE (target), 0);
1592: if (GET_MODE (temp) != BLKmode && GET_MODE (temp) != VOIDmode)
1593: temp = copy_to_reg (temp);
1594: dont_return_target = 1;
1595: }
1596: else
1597: {
1598: temp = expand_expr (exp, target, GET_MODE (target), 0);
1599: /* DO return TARGET if it's a specified hardware register.
1600: expand_return relies on this. */
1601: if (!(target && GET_CODE (target) == REG
1602: && REGNO (target) < FIRST_PSEUDO_REGISTER)
1603: && (CONSTANT_P (temp) || GET_CODE (temp) == CONST_DOUBLE))
1604: dont_return_target = 1;
1605: }
1606:
1607: /* If value was not generated in the target, store it there. */
1608:
1.1 root 1609: if (temp != target && TREE_CODE (exp) != ERROR_MARK)
1610: {
1611: target = protect_from_queue (target, 1);
1612: if (GET_MODE (temp) != GET_MODE (target)
1613: && GET_MODE (temp) != VOIDmode)
1.1.1.2 root 1614: {
1615: int unsignedp = TREE_UNSIGNED (TREE_TYPE (exp));
1616: if (dont_return_target)
1617: temp = convert_to_mode (GET_MODE (target), temp, unsignedp);
1618: else
1619: convert_move (target, temp, unsignedp);
1620: }
1621:
1.1 root 1622: else if (GET_MODE (temp) == BLKmode)
1623: emit_block_move (target, temp, expr_size (exp),
1624: TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
1625: else
1626: emit_move_insn (target, temp);
1627: }
1.1.1.2 root 1628: if (dont_return_target)
1629: return temp;
1.1 root 1630: return target;
1631: }
1632:
1.1.1.2 root 1633: /* Store the value of constructor EXP into the rtx TARGET.
1634: TARGET is either a REG or a MEM. */
1.1 root 1635:
1.1.1.2 root 1636: static void
1637: store_constructor (exp, target)
1638: tree exp;
1639: rtx target;
1.1 root 1640: {
1.1.1.2 root 1641: if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
1.1 root 1642: {
1.1.1.2 root 1643: register tree elt;
1.1 root 1644:
1.1.1.2 root 1645: /* If the constructor has fewer fields than the structure,
1646: clear the whole structure first. */
1.1 root 1647:
1.1.1.2 root 1648: if (list_length (CONSTRUCTOR_ELTS (exp))
1649: != list_length (TYPE_FIELDS (TREE_TYPE (exp))))
1650: clear_storage (target, int_size_in_bytes (TREE_TYPE (exp)));
1651: else
1652: /* Inform later passes that the old value is dead. */
1653: emit_insn (gen_rtx (CLOBBER, VOIDmode, target));
1654:
1655: /* Store each element of the constructor into
1656: the corresponding field of TARGET. */
1657:
1658: for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
1659: {
1660: register tree field = TREE_PURPOSE (elt);
1661: register enum machine_mode mode;
1662: int bitsize;
1663: int bitpos;
1664: int unsignedp;
1665:
1666: bitsize = TREE_INT_CST_LOW (DECL_SIZE (field)) * DECL_SIZE_UNIT (field);
1667: mode = DECL_MODE (field);
1668: unsignedp = TREE_UNSIGNED (field);
1669:
1670: bitpos = DECL_OFFSET (field);
1671:
1672: store_field (target, bitsize, bitpos, mode, TREE_VALUE (elt),
1673: VOIDmode, 0);
1674: }
1675: }
1676: else if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
1677: {
1678: register tree elt;
1679: register int i;
1680: tree domain = TYPE_DOMAIN (TREE_TYPE (exp));
1681: int minelt = TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain));
1682: int maxelt = TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain));
1683: tree elttype = TREE_TYPE (TREE_TYPE (exp));
1684:
1685: /* If the constructor has fewer fields than the structure,
1686: clear the whole structure first. */
1687:
1688: if (list_length (CONSTRUCTOR_ELTS (exp)) < maxelt - minelt + 1)
1689: clear_storage (target, maxelt - minelt + 1);
1690: else
1691: /* Inform later passes that the old value is dead. */
1692: emit_insn (gen_rtx (CLOBBER, VOIDmode, target));
1693:
1694: /* Store each element of the constructor into
1695: the corresponding element of TARGET, determined
1696: by counting the elements. */
1697: for (elt = CONSTRUCTOR_ELTS (exp), i = 0;
1698: elt;
1699: elt = TREE_CHAIN (elt), i++)
1700: {
1701: register enum machine_mode mode;
1702: int bitsize;
1703: int bitpos;
1704: int unsignedp;
1705:
1706: mode = TYPE_MODE (elttype);
1707: bitsize = GET_MODE_BITSIZE (mode);
1708: unsignedp = TREE_UNSIGNED (elttype);
1709:
1710: bitpos = (i * TREE_INT_CST_LOW (TYPE_SIZE (elttype))
1711: * TYPE_SIZE_UNIT (elttype));
1712:
1713: store_field (target, bitsize, bitpos, mode, TREE_VALUE (elt),
1714: VOIDmode, 0);
1715: }
1716: }
1717: }
1718:
1719: /* Store the value of EXP (an expression tree)
1720: into a subfield of TARGET which has mode MODE and occupies
1721: BITSIZE bits, starting BITPOS bits from the start of TARGET.
1722:
1723: If VALUE_MODE is VOIDmode, return nothing in particular.
1724: UNSIGNEDP is not used in this case.
1725:
1726: Otherwise, return an rtx for the value stored. This rtx
1727: has mode VALUE_MODE if that is convenient to do.
1728: In this case, UNSIGNEDP must be nonzero if the value is an unsigned type. */
1729:
1730: static rtx
1731: store_field (target, bitsize, bitpos, mode, exp, value_mode, unsignedp)
1732: rtx target;
1733: int bitsize, bitpos;
1734: enum machine_mode mode;
1735: tree exp;
1736: enum machine_mode value_mode;
1737: int unsignedp;
1738: {
1739: /* If the structure is in a register or if the component
1740: is a bit field, we cannot use addressing to access it.
1741: Use bit-field techniques or SUBREG to store in it. */
1742:
1743: if (mode == BImode || GET_CODE (target) == REG
1744: || GET_CODE (target) == SUBREG)
1745: {
1746: store_bit_field (target, bitsize, bitpos,
1747: mode,
1748: expand_expr (exp, 0, VOIDmode, 0));
1749: if (value_mode != VOIDmode)
1750: return extract_bit_field (target, bitsize, bitpos, unsignedp,
1751: 0, value_mode, 0);
1752: return const0_rtx;
1753: }
1754: else
1755: {
1756: rtx addr = XEXP (target, 0);
1757: rtx to_rtx;
1758:
1759: /* If a value is wanted, it must be the lhs;
1760: so make the address stable for multiple use. */
1761:
1762: if (value_mode != VOIDmode && GET_CODE (addr) != REG
1763: && ! CONSTANT_ADDRESS_P (addr))
1764: addr = copy_to_reg (addr);
1765:
1766: /* Now build a reference to just the desired component. */
1767:
1768: to_rtx = change_address (target, mode,
1769: plus_constant (addr,
1770: (bitpos / BITS_PER_UNIT)));
1771: to_rtx->in_struct = 1;
1772:
1773: return store_expr (exp, to_rtx, value_mode != VOIDmode);
1774: }
1775: }
1776:
1777: /* Given an rtx VALUE that may contain additions and multiplications,
1778: return an equivalent value that just refers to a register or memory.
1779: This is done by generating instructions to perform the arithmetic
1780: and returning a pseudo-register containing the value. */
1781:
1782: rtx
1783: force_operand (value, target)
1784: rtx value, target;
1785: {
1786: register optab binoptab = 0;
1787: register rtx op2;
1788: /* Use subtarget as the target for operand 0 of a binary operation. */
1789: register rtx subtarget = (target != 0 && GET_CODE (target) == REG ? target : 0);
1790:
1791: if (GET_CODE (value) == PLUS)
1792: binoptab = add_optab;
1793: else if (GET_CODE (value) == MINUS)
1794: binoptab = sub_optab;
1795: else if (GET_CODE (value) == MULT)
1796: {
1797: op2 = XEXP (value, 1);
1798: if (!CONSTANT_P (op2)
1799: && !(GET_CODE (op2) == REG && op2 != subtarget))
1800: subtarget = 0;
1801: return expand_mult (GET_MODE (value),
1802: force_operand (XEXP (value, 0), subtarget),
1803: force_operand (op2, 0),
1804: target, 0);
1805: }
1806:
1807: if (binoptab)
1808: {
1809: op2 = XEXP (value, 1);
1810: if (!CONSTANT_P (op2)
1811: && !(GET_CODE (op2) == REG && op2 != subtarget))
1812: subtarget = 0;
1813: if (binoptab == sub_optab
1814: && GET_CODE (op2) == CONST_INT && INTVAL (op2) < 0)
1815: {
1816: binoptab = add_optab;
1817: op2 = gen_rtx (CONST_INT, VOIDmode, - INTVAL (op2));
1818: }
1819: return expand_binop (GET_MODE (value), binoptab,
1820: force_operand (XEXP (value, 0), subtarget),
1821: force_operand (op2, 0),
1822: target, 0, OPTAB_LIB_WIDEN);
1823: /* We give UNSIGNEP = 0 to expand_binop
1824: because the only operations we are expanding here are signed ones. */
1825: }
1826: return value;
1827: }
1828:
1829: /* expand_expr: generate code for computing expression EXP.
1830: An rtx for the computed value is returned.
1831:
1832: The value may be stored in TARGET if TARGET is nonzero.
1.1 root 1833: TARGET is just a suggestion; callers must assume that
1834: the rtx returned may not be the same as TARGET.
1835:
1.1.1.2 root 1836: If TARGET is CONST0_RTX, it means that the value will be ignored.
1837:
1.1 root 1838: If TMODE is not VOIDmode, it suggests generating the
1839: result in mode TMODE. But this is done only when convenient.
1840: Otherwise, TMODE is ignored and the value generated in its natural mode.
1841: TMODE is just a suggestion; callers must assume that
1842: the rtx returned may not have mode TMODE.
1843:
1.1.1.2 root 1844: If MODIFIER is EXPAND_SUM then when EXP is an addition
1.1 root 1845: we can return an rtx of the form (MULT (REG ...) (CONST_INT ...))
1846: or a nest of (PLUS ...) and (MINUS ...) where the terms are
1847: products as above, or REG or MEM, or constant.
1.1.1.2 root 1848: Ordinarily in such cases we would output mul or add instructions
1849: and then return a pseudo reg containing the sum.
1850:
1851: If MODIFIER is EXPAND_CONST_ADDRESS then it is ok to return
1852: a MEM rtx whose address is a constant that isn't a legitimate address. */
1.1 root 1853:
1854: /* Subroutine of expand_expr:
1855: return the target to use when recursively expanding
1856: the first operand of an arithmetic operation. */
1857:
1858: static rtx
1859: validate_subtarget (subtarget, otherop)
1860: rtx subtarget;
1861: tree otherop;
1862: {
1863: if (TREE_LITERAL (otherop))
1864: return subtarget;
1865: if (TREE_CODE (otherop) == VAR_DECL
1866: && DECL_RTL (otherop) != subtarget)
1867: return subtarget;
1868: return 0;
1869: }
1870:
1871: rtx
1.1.1.2 root 1872: expand_expr (exp, target, tmode, modifier)
1.1 root 1873: register tree exp;
1874: rtx target;
1875: enum machine_mode tmode;
1.1.1.2 root 1876: enum expand_modifier modifier;
1.1 root 1877: {
1878: register rtx op0, op1, temp;
1879: tree type = TREE_TYPE (exp);
1880: register enum machine_mode mode = TYPE_MODE (type);
1881: register enum tree_code code = TREE_CODE (exp);
1.1.1.2 root 1882: optab this_optab;
1.1 root 1883: int negate_1;
1884: /* Use subtarget as the target for operand 0 of a binary operation. */
1885: rtx subtarget = (target != 0 && GET_CODE (target) == REG ? target : 0);
1.1.1.2 root 1886: rtx original_target = target;
1887: int ignore = target == const0_rtx;
1888:
1889: if (ignore) target = 0, original_target = 0;
1.1 root 1890:
1891: /* If will do cse, generate all results into registers
1892: since 1) that allows cse to find more things
1893: and 2) otherwise cse could produce an insn the machine
1894: cannot support. */
1895:
1896: if (! cse_not_expected && mode != BLKmode)
1897: target = subtarget;
1898:
1.1.1.2 root 1899: /* No sense saving up arithmetic to be done
1900: if it's all in the wrong mode to form part of an address.
1901: And force_operand won't know whether to sign-extend or zero-extend. */
1902:
1903: if (mode != Pmode && modifier == EXPAND_SUM)
1904: modifier = (enum expand_modifier) 0;
1905:
1.1 root 1906: switch (code)
1907: {
1.1.1.4 ! root 1908: case PARM_DECL:
! 1909: if (DECL_RTL (exp) == 0)
! 1910: {
! 1911: error_with_decl (exp, "prior parameter's size depends on `%s'");
! 1912: return const0_rtx;
! 1913: }
! 1914:
1.1 root 1915: case FUNCTION_DECL:
1916: case VAR_DECL:
1917: case RESULT_DECL:
1918: if (DECL_RTL (exp) == 0)
1919: abort ();
1920: if (GET_CODE (DECL_RTL (exp)) == SYMBOL_REF)
1921: abort ();
1.1.1.2 root 1922: if (GET_CODE (DECL_RTL (exp)) == MEM
1923: && modifier != EXPAND_CONST_ADDRESS)
1924: {
1925: /* DECL_RTL probably contains a constant address.
1926: On RISC machines where a constant address isn't valid,
1927: make some insns to get that address into a register. */
1928: if (!memory_address_p (DECL_MODE (exp), XEXP (DECL_RTL (exp), 0)))
1929: return change_address (DECL_RTL (exp), VOIDmode,
1930: copy_rtx (XEXP (DECL_RTL (exp), 0)));
1931: }
1.1 root 1932: return DECL_RTL (exp);
1933:
1934: case INTEGER_CST:
1935: return gen_rtx (CONST_INT, VOIDmode, TREE_INT_CST_LOW (exp));
1936:
1937: case CONST_DECL:
1938: return expand_expr (DECL_INITIAL (exp), target, VOIDmode, 0);
1939:
1940: case REAL_CST:
1941: if (TREE_CST_RTL (exp))
1942: return TREE_CST_RTL (exp);
1943: /* If optimized, generate immediate float
1944: which will be turned into memory float if necessary. */
1945: if (!cse_not_expected)
1946: return immed_real_const (exp);
1947: output_constant_def (exp);
1948: return TREE_CST_RTL (exp);
1949:
1950: case COMPLEX_CST:
1951: case STRING_CST:
1952: if (TREE_CST_RTL (exp))
1953: return TREE_CST_RTL (exp);
1954: output_constant_def (exp);
1955: return TREE_CST_RTL (exp);
1956:
1957: case SAVE_EXPR:
1958: if (SAVE_EXPR_RTL (exp) == 0)
1959: {
1960: SAVE_EXPR_RTL (exp) = gen_reg_rtx (mode);
1.1.1.2 root 1961: store_expr (TREE_OPERAND (exp, 0), SAVE_EXPR_RTL (exp), 0);
1.1 root 1962: }
1.1.1.2 root 1963: /* Don't let the same rtl node appear in two places. */
1.1 root 1964: return SAVE_EXPR_RTL (exp);
1965:
1.1.1.2 root 1966: case RTL_EXPR:
1967: emit_insn (RTL_EXPR_SEQUENCE (exp));
1968: return RTL_EXPR_RTL (exp);
1969:
1970: case CONSTRUCTOR:
1971: /* All elts simple constants => refer to a constant in memory. */
1972: if (TREE_STATIC (exp))
1973: /* For aggregate types with non-BLKmode modes,
1974: this should ideally construct a CONST_INT. */
1975: return output_constant_def (exp);
1976:
1977: if (ignore)
1978: {
1979: tree elt;
1980: for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
1981: expand_expr (TREE_VALUE (elt), const0_rtx, VOIDmode, 0);
1982: return const0_rtx;
1983: }
1984: else
1985: {
1986: if (target == 0)
1987: target = gen_rtx (MEM, TYPE_MODE (TREE_TYPE (exp)),
1988: get_structure_value_addr (expr_size (exp)));
1989: store_expr (exp, target, 0);
1990: return target;
1991: }
1992:
1.1 root 1993: case INDIRECT_REF:
1994: {
1995: tree exp1 = TREE_OPERAND (exp, 0);
1996: tree exp2;
1997:
1998: /* A SAVE_EXPR as the address in an INDIRECT_EXPR is generated
1999: for *PTR += ANYTHING where PTR is put inside the SAVE_EXPR.
2000: This code has the same general effect as simply doing
2001: expand_expr on the save expr, except that the expression PTR
2002: is computed for use as a memory address. This means different
2003: code, suitable for indexing, may be generated. */
2004: if (TREE_CODE (exp1) == SAVE_EXPR
2005: && SAVE_EXPR_RTL (exp1) == 0
2006: && TREE_CODE (exp2 = TREE_OPERAND (exp1, 0)) != ERROR_MARK
2007: && TYPE_MODE (TREE_TYPE (exp1)) == Pmode
2008: && TYPE_MODE (TREE_TYPE (exp2)) == Pmode)
2009: {
1.1.1.2 root 2010: temp = expand_expr (TREE_OPERAND (exp1, 0), 0, VOIDmode, EXPAND_SUM);
1.1 root 2011: op0 = memory_address (mode, temp);
2012: op0 = copy_all_regs (op0);
2013: SAVE_EXPR_RTL (exp1) = op0;
2014: }
2015: else
2016: {
1.1.1.2 root 2017: op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, EXPAND_SUM);
1.1 root 2018: op0 = memory_address (mode, op0);
2019: }
2020: }
2021: temp = gen_rtx (MEM, mode, op0);
1.1.1.2 root 2022: /* If address was computed by addition,
2023: mark this as an element of an aggregate. */
2024: if (TREE_CODE (TREE_OPERAND (exp, 0)) == PLUS_EXPR
2025: || (TREE_CODE (TREE_OPERAND (exp, 0)) == SAVE_EXPR
2026: && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) == PLUS_EXPR))
2027: temp->in_struct = 1;
2028: temp->volatil = TREE_THIS_VOLATILE (exp) | flag_volatile;
2029: temp->unchanging = TREE_READONLY (exp);
2030: return temp;
2031:
2032: case ARRAY_REF:
2033: if (TREE_CODE (TREE_OPERAND (exp, 1)) != INTEGER_CST
2034: || TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) != INTEGER_CST)
2035: {
2036: /* Nonconstant array index or nonconstant element size.
2037: Generate the tree for *(&array+index) and expand that,
2038: except do it in a language-independent way
2039: and don't complain about non-lvalue arrays.
2040: `mark_addressable' should already have been called
2041: for any array for which this case will be reached. */
2042:
2043: tree array_adr = build (ADDR_EXPR, TYPE_POINTER_TO (type),
2044: TREE_OPERAND (exp, 0));
2045: tree index = TREE_OPERAND (exp, 1);
2046: tree elt;
2047:
2048: /* Convert the integer argument to a type the same size as a pointer
2049: so the multiply won't overflow spuriously. */
2050: if (TYPE_PRECISION (TREE_TYPE (index)) != POINTER_SIZE)
2051: index = convert (type_for_size (POINTER_SIZE, 0), index);
2052:
2053: /* The array address isn't volatile even if the array is. */
2054: TREE_VOLATILE (array_adr) = 0;
2055:
2056: elt = build (INDIRECT_REF, type,
2057: fold (build (PLUS_EXPR, TYPE_POINTER_TO (type),
2058: array_adr,
2059: fold (build (MULT_EXPR,
2060: TYPE_POINTER_TO (type),
2061: index, size_in_bytes (type))))));
2062:
2063: return expand_expr (elt, target, tmode, modifier);
2064: }
2065: /* Treat array-ref with constant index as a component-ref. */
1.1 root 2066:
2067: case COMPONENT_REF:
2068: {
1.1.1.2 root 2069: register enum machine_mode mode1;
1.1 root 2070: int volstruct = 0;
2071: tree dbg1 = TREE_OPERAND (exp, 0); /* For debugging */
1.1.1.2 root 2072: int bitsize;
2073: tree tem = exp;
2074: int bitpos = 0;
2075: int unsignedp;
1.1 root 2076:
1.1.1.2 root 2077: if (TREE_CODE (exp) == COMPONENT_REF)
1.1 root 2078: {
2079: tree field = TREE_OPERAND (exp, 1);
1.1.1.2 root 2080: bitsize = TREE_INT_CST_LOW (DECL_SIZE (field)) * DECL_SIZE_UNIT (field);
2081: mode1 = DECL_MODE (TREE_OPERAND (exp, 1));
2082: unsignedp = TREE_UNSIGNED (field);
1.1 root 2083: }
1.1.1.2 root 2084: else
1.1 root 2085: {
1.1.1.2 root 2086: mode1 = TYPE_MODE (TREE_TYPE (exp));
2087: bitsize = GET_MODE_BITSIZE (mode1);
2088: unsignedp = TREE_UNSIGNED (TREE_TYPE (exp));
1.1 root 2089: }
2090:
1.1.1.2 root 2091: /* Compute cumulative bit-offset for nested component-refs
2092: and array-refs, and find the ultimate containing object. */
2093:
2094: while (1)
1.1 root 2095: {
1.1.1.2 root 2096: if (TREE_CODE (tem) == COMPONENT_REF)
2097: {
2098: bitpos += DECL_OFFSET (TREE_OPERAND (tem, 1));
2099: if (TREE_THIS_VOLATILE (tem))
2100: volstruct = 1;
2101: }
2102: else if (TREE_CODE (tem) == ARRAY_REF
2103: && TREE_CODE (TREE_OPERAND (tem, 1)) == INTEGER_CST
2104: && TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) == INTEGER_CST)
2105: {
2106: bitpos += (TREE_INT_CST_LOW (TREE_OPERAND (tem, 1))
2107: * TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (tem)))
2108: * TYPE_SIZE_UNIT (TREE_TYPE (tem)));
2109: }
2110: else
2111: break;
2112: tem = TREE_OPERAND (tem, 0);
1.1 root 2113: }
2114:
1.1.1.2 root 2115: op0 = expand_expr (tem, 0, VOIDmode,
2116: (modifier == EXPAND_CONST_ADDRESS
2117: ? modifier : EXPAND_NORMAL));
1.1 root 2118:
1.1.1.2 root 2119: if (mode1 == BImode || GET_CODE (op0) == REG
2120: || GET_CODE (op0) == SUBREG)
2121: {
2122: return extract_bit_field (op0, bitsize, bitpos, unsignedp,
2123: target, mode, tmode);
2124: }
2125: /* Get a reference to just this component. */
2126: if (modifier == EXPAND_CONST_ADDRESS)
2127: op0 = gen_rtx (MEM, mode1, plus_constant (XEXP (op0, 0),
2128: (bitpos / BITS_PER_UNIT)));
2129: else
2130: op0 = change_address (op0, mode1,
2131: plus_constant (XEXP (op0, 0),
2132: (bitpos / BITS_PER_UNIT)));
2133: op0->in_struct = 1;
2134: op0->volatil = volstruct;
2135: /* If OP0 is in the shared structure-value stack slot,
2136: and it is not BLKmode, copy it into a register.
2137: The shared slot may be clobbered at any time by another call.
2138: BLKmode is safe because our caller will either copy the value away
2139: or take another component and come back here. */
2140: if (mode != BLKmode
2141: && TREE_CODE (TREE_OPERAND (exp, 0)) == CALL_EXPR
2142: && TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == BLKmode)
2143: op0 = copy_to_reg (op0);
2144: if (mode == mode1 || mode1 == BLKmode || mode1 == tmode)
2145: return op0;
2146: if (target == 0)
2147: target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode);
2148: convert_move (target, op0, unsignedp);
2149: return target;
1.1 root 2150: }
2151:
2152: /* Intended for a reference to a buffer of a file-object in Pascal.
2153: But it's not certain that a special tree code will really be
2154: necessary for these. INDIRECT_REF might work for them. */
2155: case BUFFER_REF:
2156: abort ();
2157:
2158: case CALL_EXPR:
1.1.1.2 root 2159: /* Check for a built-in function. */
2160: if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
2161: && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) == FUNCTION_DECL
2162: && DECL_FUNCTION_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
2163: return expand_builtin (exp, target, subtarget, tmode);
1.1 root 2164: /* If this call was expanded already by preexpand_calls,
2165: just return the result we got. */
2166: if (CALL_EXPR_RTL (exp) != 0)
2167: return CALL_EXPR_RTL (exp);
1.1.1.2 root 2168: return expand_call (exp, target, ignore);
1.1 root 2169:
2170: case NOP_EXPR:
2171: case CONVERT_EXPR:
1.1.1.2 root 2172: if (TREE_CODE (type) == VOID_TYPE || ignore)
1.1 root 2173: {
1.1.1.2 root 2174: expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, modifier);
1.1 root 2175: return const0_rtx;
2176: }
2177: if (mode == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
1.1.1.2 root 2178: return expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, modifier);
1.1 root 2179: op0 = expand_expr (TREE_OPERAND (exp, 0), 0, mode, 0);
1.1.1.2 root 2180: if (GET_MODE (op0) == mode || GET_MODE (op0) == VOIDmode)
1.1 root 2181: return op0;
1.1.1.2 root 2182: if (flag_force_mem && GET_CODE (op0) == MEM)
2183: op0 = copy_to_reg (op0);
1.1 root 2184: if (target == 0)
2185: target = gen_reg_rtx (mode);
1.1.1.2 root 2186: convert_move (target, op0, TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))));
1.1 root 2187: return target;
2188:
2189: case PLUS_EXPR:
2190: preexpand_calls (exp);
1.1.1.2 root 2191: if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST
2192: && modifier == EXPAND_SUM)
1.1 root 2193: {
1.1.1.2 root 2194: op1 = expand_expr (TREE_OPERAND (exp, 1), subtarget, VOIDmode, EXPAND_SUM);
1.1 root 2195: op1 = plus_constant (op1, TREE_INT_CST_LOW (TREE_OPERAND (exp, 0)));
1.1.1.2 root 2196: return op1;
1.1 root 2197: }
2198: negate_1 = 1;
2199: plus_minus:
1.1.1.2 root 2200: if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
2201: && modifier == EXPAND_SUM)
1.1 root 2202: {
1.1.1.2 root 2203: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, EXPAND_SUM);
1.1 root 2204: op0 = plus_constant (op0,
2205: negate_1 * TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)));
1.1.1.2 root 2206: return op0;
1.1 root 2207: }
2208: this_optab = add_optab;
1.1.1.2 root 2209: if (modifier != EXPAND_SUM) goto binop;
1.1 root 2210: subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
1.1.1.2 root 2211: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, EXPAND_SUM);
2212: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, EXPAND_SUM);
1.1 root 2213: /* Put a sum last, to simplify what follows. */
2214: #ifdef OLD_INDEXING
2215: if (GET_CODE (op1) == MULT)
2216: {
2217: temp = op0;
2218: op0 = op1;
2219: op1 = temp;
2220: }
2221: #endif
2222: #ifndef OLD_INDEXING
2223: /* Make sure any term that's a sum with a constant comes last. */
2224: if (GET_CODE (op0) == PLUS
1.1.1.2 root 2225: && CONSTANT_P (XEXP (op0, 1)))
1.1 root 2226: {
2227: temp = op0;
2228: op0 = op1;
2229: op1 = temp;
2230: }
2231: /* If adding to a sum including a constant,
2232: associate it to put the constant outside. */
2233: if (GET_CODE (op1) == PLUS
1.1.1.2 root 2234: && CONSTANT_P (XEXP (op1, 1)))
1.1 root 2235: {
2236: op0 = gen_rtx (PLUS, mode, XEXP (op1, 0), op0);
2237: if (GET_CODE (XEXP (op1, 1)) == CONST_INT)
2238: return plus_constant (op0, INTVAL (XEXP (op1, 1)));
2239: else
2240: return gen_rtx (PLUS, mode, op0, XEXP (op1, 1));
2241: }
2242: #endif
2243: return gen_rtx (PLUS, mode, op0, op1);
2244:
2245: case MINUS_EXPR:
2246: preexpand_calls (exp);
2247: if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
2248: {
1.1.1.2 root 2249: if (modifier == EXPAND_SUM)
2250: {
2251: negate_1 = -1;
2252: goto plus_minus;
2253: }
2254: subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
2255: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
2256: op1 = gen_rtx (CONST_INT, VOIDmode,
2257: - TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)));
2258: this_optab = add_optab;
2259: goto binop2;
1.1 root 2260: }
2261: this_optab = sub_optab;
2262: goto binop;
2263:
2264: case MULT_EXPR:
2265: preexpand_calls (exp);
2266: /* If first operand is constant, swap them.
2267: Thus the following special case checks need only
2268: check the second operand. */
2269: if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST)
2270: {
2271: register tree t1 = TREE_OPERAND (exp, 0);
2272: TREE_OPERAND (exp, 0) = TREE_OPERAND (exp, 1);
2273: TREE_OPERAND (exp, 1) = t1;
2274: }
2275:
2276: /* Attempt to return something suitable for generating an
2277: indexed address, for machines that support that. */
2278:
1.1.1.2 root 2279: if (modifier == EXPAND_SUM
2280: && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
1.1 root 2281: {
1.1.1.2 root 2282: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, EXPAND_SUM);
2283:
2284: /* Apply distributive law if OP0 is x+c. */
2285: if (GET_CODE (op0) == PLUS
2286: && GET_CODE (XEXP (op0, 1)) == CONST_INT)
2287: return gen_rtx (PLUS, mode,
2288: gen_rtx (MULT, mode, XEXP (op0, 0),
2289: gen_rtx (CONST_INT, VOIDmode,
2290: TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)))),
2291: gen_rtx (CONST_INT, VOIDmode,
2292: (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))
2293: * INTVAL (XEXP (op0, 1)))));
2294:
1.1 root 2295: if (GET_CODE (op0) != REG)
1.1.1.2 root 2296: op0 = force_operand (op0, 0);
2297: if (GET_CODE (op0) != REG)
2298: op0 = copy_to_mode_reg (mode, op0);
2299:
1.1 root 2300: return gen_rtx (MULT, mode, op0,
2301: gen_rtx (CONST_INT, VOIDmode,
2302: TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))));
2303: }
2304: subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
2305: /* Check for multiplying things that have been extended
2306: from a narrower type. If this machine supports multiplying
2307: in that narrower type with a result in the desired type,
2308: do it that way, and avoid the explicit type-conversion. */
2309: if (TREE_CODE (TREE_OPERAND (exp, 0)) == NOP_EXPR
2310: && TREE_CODE (TREE_TYPE (exp)) == INTEGER_TYPE
2311: && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
2312: < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0))))
2313: && ((TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
2314: && int_fits_type_p (TREE_OPERAND (exp, 1),
1.1.1.2 root 2315: TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
2316: /* Don't use a widening multiply if a shift will do. */
2317: && exact_log2 (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))) < 0)
1.1 root 2318: ||
2319: (TREE_CODE (TREE_OPERAND (exp, 1)) == NOP_EXPR
2320: && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 1), 0)))
2321: ==
1.1.1.2 root 2322: TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))))
2323: /* If both operands are extended, they must either both
2324: be zero-extended or both be sign-extended. */
2325: && (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 1), 0)))
2326: ==
2327: TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))))))
1.1 root 2328: {
2329: enum machine_mode innermode
2330: = TYPE_MODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)));
1.1.1.2 root 2331: this_optab = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
1.1 root 2332: ? umul_widen_optab : smul_widen_optab);
2333: if ((int) innermode + 1 == (int) mode
1.1.1.2 root 2334: && this_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1.1 root 2335: {
2336: op0 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
2337: 0, VOIDmode, 0);
2338: if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
2339: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
2340: else
2341: op1 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 1), 0),
2342: 0, VOIDmode, 0);
2343: goto binop2;
2344: }
2345: }
2346: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
2347: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
1.1.1.2 root 2348: return expand_mult (mode, op0, op1, target, TREE_UNSIGNED (type));
1.1 root 2349:
2350: case TRUNC_DIV_EXPR:
2351: case FLOOR_DIV_EXPR:
2352: case CEIL_DIV_EXPR:
2353: case ROUND_DIV_EXPR:
2354: preexpand_calls (exp);
2355: subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
1.1.1.2 root 2356: /* Possible optimization: compute the dividend with EXPAND_SUM
1.1 root 2357: then if the divisor is constant can optimize the case
2358: where some terms of the dividend have coeffs divisible by it. */
2359: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
2360: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
2361: return expand_divmod (0, code, mode, op0, op1, target,
1.1.1.2 root 2362: TREE_UNSIGNED (type));
1.1 root 2363:
2364: case RDIV_EXPR:
2365: preexpand_calls (exp);
2366: this_optab = flodiv_optab;
2367: goto binop;
2368:
2369: case TRUNC_MOD_EXPR:
2370: case FLOOR_MOD_EXPR:
2371: case CEIL_MOD_EXPR:
2372: case ROUND_MOD_EXPR:
2373: preexpand_calls (exp);
2374: subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
2375: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
2376: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
2377: return expand_divmod (1, code, mode, op0, op1, target,
1.1.1.2 root 2378: TREE_UNSIGNED (type));
1.1 root 2379: #if 0
2380: #ifdef HAVE_divmoddisi4
2381: if (GET_MODE (op0) != DImode)
2382: {
2383: temp = gen_reg_rtx (DImode);
2384: convert_move (temp, op0, 0);
2385: op0 = temp;
2386: if (GET_MODE (op1) != SImode && GET_CODE (op1) != CONST_INT)
2387: {
2388: temp = gen_reg_rtx (SImode);
2389: convert_move (temp, op1, 0);
2390: op1 = temp;
2391: }
2392: temp = gen_reg_rtx (SImode);
2393: if (target == 0)
2394: target = gen_reg_rtx (SImode);
2395: emit_insn (gen_divmoddisi4 (temp, protect_from_queue (op0, 0),
2396: protect_from_queue (op1, 0),
2397: protect_from_queue (target, 1)));
2398: return target;
2399: }
2400: #endif
2401: #endif
2402:
2403: case FIX_ROUND_EXPR:
2404: case FIX_FLOOR_EXPR:
2405: case FIX_CEIL_EXPR:
2406: abort (); /* Not used for C. */
2407:
2408: case FIX_TRUNC_EXPR:
2409: op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
2410: if (target == 0)
2411: target = gen_reg_rtx (mode);
1.1.1.2 root 2412: {
2413: int unsignedp = TREE_UNSIGNED (TREE_TYPE (exp));
2414: if (mode == HImode || mode == QImode)
2415: {
2416: register rtx temp = gen_reg_rtx (SImode);
1.1.1.4 ! root 2417: expand_fix (temp, op0, 1);
! 2418: convert_move (target, temp, 1);
1.1.1.2 root 2419: }
2420: else
2421: expand_fix (target, op0, unsignedp);
2422: }
1.1 root 2423: return target;
2424:
2425: case FLOAT_EXPR:
2426: op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
2427: if (target == 0)
2428: target = gen_reg_rtx (mode);
1.1.1.2 root 2429: {
2430: int unsignedp = TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)));
2431: if (GET_MODE (op0) == HImode
2432: || GET_MODE (op0) == QImode)
2433: {
2434: register rtx temp = gen_reg_rtx (SImode);
2435: convert_move (temp, op0, unsignedp);
2436: expand_float (target, temp, 0);
2437: }
2438: else
2439: expand_float (target, op0, unsignedp);
2440: }
1.1 root 2441: return target;
2442:
2443: case NEGATE_EXPR:
2444: op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0);
2445: temp = expand_unop (mode, neg_optab, op0, target, 0);
2446: if (temp == 0)
2447: abort ();
2448: return temp;
2449:
2450: case ABS_EXPR:
2451: /* First try to do it with a special abs instruction.
2452: If that does not win, use conditional jump and negate. */
1.1.1.2 root 2453: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
1.1 root 2454: temp = expand_unop (mode, abs_optab, op0, target, 0);
2455: if (temp != 0)
2456: return temp;
2457: temp = gen_label_rtx ();
2458: if (target == 0 || GET_CODE (target) != REG)
1.1.1.2 root 2459: target = gen_reg_rtx (mode);
1.1 root 2460: emit_move_insn (target, op0);
1.1.1.2 root 2461: emit_cmp_insn (target,
2462: expand_expr (convert (TREE_TYPE (exp), integer_zero_node),
2463: 0, VOIDmode, 0),
2464: 0, 0);
1.1 root 2465: emit_jump_insn (gen_bge (temp));
2466: op0 = expand_unop (mode, neg_optab, target, target, 0);
2467: if (op0 != target)
2468: emit_move_insn (target, op0);
2469: emit_label (temp);
2470: return target;
2471:
2472: case MAX_EXPR:
2473: case MIN_EXPR:
1.1.1.2 root 2474: mode = TYPE_MODE (TREE_OPERAND (exp, 1));
1.1 root 2475: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
2476: if (target == 0 || GET_CODE (target) != REG || target == op1)
1.1.1.2 root 2477: target = gen_reg_rtx (mode);
1.1 root 2478: op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0);
2479: if (target != op0)
2480: emit_move_insn (target, op0);
2481: op0 = gen_label_rtx ();
2482: if (code == MAX_EXPR)
1.1.1.2 root 2483: temp = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1)))
2484: ? compare1 (target, op1, GEU, LEU, 1, mode)
2485: : compare1 (target, op1, GE, LE, 0, mode));
2486: else
2487: temp = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1)))
2488: ? compare1 (target, op1, LEU, GEU, 1, mode)
2489: : compare1 (target, op1, LE, GE, 0, mode));
2490: if (temp == const0_rtx)
2491: emit_move_insn (target, op1);
2492: else if (temp != const1_rtx)
2493: {
2494: emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx,
2495: gen_rtx (IF_THEN_ELSE, VOIDmode,
2496: temp,
2497: gen_rtx (LABEL_REF, VOIDmode, op0),
2498: pc_rtx)));
2499: emit_move_insn (target, op1);
2500: }
2501: emit_label (op0);
1.1 root 2502: return target;
2503:
2504: /* ??? Can optimize when the operand of this is a bitwise operation,
2505: by using a different bitwise operation. */
2506: case BIT_NOT_EXPR:
2507: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
2508: temp = expand_unop (mode, one_cmpl_optab, op0, target, 1);
2509: if (temp == 0)
2510: abort ();
2511: return temp;
2512:
1.1.1.2 root 2513: case FFS_EXPR:
2514: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
2515: temp = expand_unop (mode, ffs_optab, op0, target, 1);
2516: if (temp == 0)
2517: abort ();
2518: return temp;
2519:
1.1 root 2520: /* ??? Can optimize bitwise operations with one arg constant.
2521: Pastel optimizes (a bitwise1 n) bitwise2 (a bitwise3 b)
2522: and (a bitwise1 b) bitwise2 b (etc)
2523: but that is probably not worth while. */
2524:
1.1.1.2 root 2525: /* BIT_AND_EXPR is for bitwise anding.
1.1 root 2526: TRUTH_AND_EXPR is for anding two boolean values
2527: when we want in all cases to compute both of them.
2528: In general it is fastest to do TRUTH_AND_EXPR by
2529: computing both operands as actual zero-or-1 values
2530: and then bitwise anding. In cases where there cannot
2531: be any side effects, better code would be made by
2532: treating TRUTH_AND_EXPR like TRUTH_ANDIF_EXPR;
2533: but the question is how to recognize those cases. */
2534:
2535: case TRUTH_AND_EXPR:
2536: case BIT_AND_EXPR:
2537: preexpand_calls (exp);
2538: subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
2539: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
2540: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
2541: return expand_bit_and (mode, op0, op1, target);
2542:
2543: /* See comment above about TRUTH_AND_EXPR; it applies here too. */
2544: case TRUTH_OR_EXPR:
2545: case BIT_IOR_EXPR:
2546: preexpand_calls (exp);
2547: this_optab = ior_optab;
2548: goto binop;
2549:
2550: case BIT_XOR_EXPR:
2551: preexpand_calls (exp);
2552: this_optab = xor_optab;
2553: goto binop;
2554:
2555: case LSHIFT_EXPR:
2556: case RSHIFT_EXPR:
2557: case LROTATE_EXPR:
2558: case RROTATE_EXPR:
2559: preexpand_calls (exp);
2560: subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
2561: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
2562: return expand_shift (code, mode, op0, TREE_OPERAND (exp, 1), target,
1.1.1.2 root 2563: TREE_UNSIGNED (type));
1.1 root 2564:
2565: /* ??? cv's were used to effect here to combine additive constants
2566: and to determine the answer when only additive constants differ.
2567: Also, the addition of one can be handled by changing the condition. */
2568: case LT_EXPR:
2569: case LE_EXPR:
2570: case GT_EXPR:
2571: case GE_EXPR:
2572: case EQ_EXPR:
2573: case NE_EXPR:
2574: preexpand_calls (exp);
1.1.1.2 root 2575: temp = do_store_flag (exp, target, mode);
1.1 root 2576: if (temp != 0)
2577: return temp;
1.1.1.2 root 2578: /* For foo != 0, load foo, and if it is nonzero load 1 instead. */
2579: if (code == NE_EXPR && integer_zerop (TREE_OPERAND (exp, 1))
2580: && subtarget
2581: && (GET_MODE (subtarget)
2582: == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
1.1 root 2583: {
2584: temp = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
2585: if (temp != subtarget)
2586: temp = copy_to_reg (temp);
2587: op1 = gen_label_rtx ();
1.1.1.2 root 2588: emit_cmp_insn (temp, const0_rtx, 0, TREE_UNSIGNED (type));
1.1 root 2589: emit_jump_insn (gen_beq (op1));
2590: emit_move_insn (temp, const1_rtx);
2591: emit_label (op1);
2592: return temp;
2593: }
2594: /* If no set-flag instruction, must generate a conditional
2595: store into a temporary variable. Drop through
2596: and handle this like && and ||. */
2597:
2598: case TRUTH_ANDIF_EXPR:
2599: case TRUTH_ORIF_EXPR:
2600: temp = gen_reg_rtx (mode);
2601: emit_clr_insn (temp);
2602: op1 = gen_label_rtx ();
2603: jumpifnot (exp, op1);
2604: emit_0_to_1_insn (temp);
2605: emit_label (op1);
2606: return temp;
2607:
2608: case TRUTH_NOT_EXPR:
2609: op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0);
2610: /* The parser is careful to generate TRUTH_NOT_EXPR
2611: only with operands that are always zero or one. */
2612: temp = expand_binop (mode, xor_optab, op0,
2613: gen_rtx (CONST_INT, mode, 1),
2614: target, 1, OPTAB_LIB_WIDEN);
2615: if (temp == 0)
2616: abort ();
2617: return temp;
2618:
2619: case COMPOUND_EXPR:
1.1.1.2 root 2620: expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
1.1 root 2621: emit_queue ();
2622: return expand_expr (TREE_OPERAND (exp, 1), target, VOIDmode, 0);
2623:
2624: case COND_EXPR:
2625: /* Note that COND_EXPRs whose type is a structure or union
2626: are required to be constructed to contain assignments of
2627: a temporary variable, so that we can evaluate them here
2628: for side effect only. If type is void, we must do likewise. */
2629: op0 = gen_label_rtx ();
2630: op1 = gen_label_rtx ();
2631:
1.1.1.2 root 2632: if (mode == VOIDmode || ignore)
1.1 root 2633: temp = 0;
2634: else if (target)
2635: temp = target;
1.1.1.2 root 2636: else if (mode == BLKmode)
2637: {
2638: if (TYPE_SIZE (type) == 0 || ! TREE_LITERAL (TYPE_SIZE (type)))
2639: abort ();
2640: temp = assign_stack_local (BLKmode,
2641: (TREE_INT_CST_LOW (TYPE_SIZE (type))
2642: * TYPE_SIZE_UNIT (type)
2643: + BITS_PER_UNIT - 1)
2644: / BITS_PER_UNIT);
2645: }
1.1 root 2646: else
2647: temp = gen_reg_rtx (mode);
2648:
2649: jumpifnot (TREE_OPERAND (exp, 0), op0);
2650: current_args_size += 1;
2651: if (temp != 0)
1.1.1.2 root 2652: store_expr (TREE_OPERAND (exp, 1), temp, 0);
1.1 root 2653: else
1.1.1.2 root 2654: expand_expr (TREE_OPERAND (exp, 1), ignore ? const0_rtx : 0,
2655: VOIDmode, 0);
1.1 root 2656: emit_queue ();
2657: emit_jump_insn (gen_jump (op1));
2658: emit_barrier ();
2659: emit_label (op0);
2660: if (temp != 0)
1.1.1.2 root 2661: store_expr (TREE_OPERAND (exp, 2), temp, 0);
1.1 root 2662: else
1.1.1.2 root 2663: expand_expr (TREE_OPERAND (exp, 2), ignore ? const0_rtx : 0,
2664: VOIDmode, 0);
1.1 root 2665: emit_queue ();
2666: emit_label (op1);
2667: current_args_size -= 1;
2668: return temp;
2669:
2670: case MODIFY_EXPR:
2671: /* If lhs is complex, expand calls in rhs before computing it.
2672: That's so we don't compute a pointer and save it over a call.
2673: If lhs is simple, compute it first so we can give it as a
2674: target if the rhs is just a call. This avoids an extra temp and copy
2675: and that prevents a partial-subsumption which makes bad code.
2676: Actually we could treat component_ref's of vars like vars. */
1.1.1.2 root 2677: if (TREE_CODE (TREE_OPERAND (exp, 0)) != VAR_DECL
2678: && TREE_CODE (TREE_OPERAND (exp, 0)) != RESULT_DECL
2679: && TREE_CODE (TREE_OPERAND (exp, 0)) != PARM_DECL)
1.1 root 2680: preexpand_calls (exp);
2681: temp = expand_assignment (TREE_OPERAND (exp, 0),
1.1.1.2 root 2682: TREE_OPERAND (exp, 1),
2683: ! ignore,
2684: original_target != 0);
1.1 root 2685: return temp;
2686:
2687: case PREINCREMENT_EXPR:
2688: case PREDECREMENT_EXPR:
1.1.1.2 root 2689: return expand_increment (exp, 0);
1.1 root 2690:
2691: case POSTINCREMENT_EXPR:
2692: case POSTDECREMENT_EXPR:
1.1.1.2 root 2693: return expand_increment (exp, 1);
1.1 root 2694:
2695: case ADDR_EXPR:
1.1.1.2 root 2696: op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode,
2697: EXPAND_CONST_ADDRESS);
1.1 root 2698: if (GET_CODE (op0) != MEM)
2699: abort ();
1.1.1.2 root 2700: if (modifier == EXPAND_SUM)
1.1 root 2701: return XEXP (op0, 0);
1.1.1.2 root 2702: op0 = force_operand (XEXP (op0, 0), target);
2703: if (flag_force_addr && GET_CODE (op0) != REG)
2704: return force_reg (Pmode, op0);
2705: return op0;
1.1 root 2706:
2707: case ENTRY_VALUE_EXPR:
2708: abort ();
2709:
2710: case ERROR_MARK:
1.1.1.2 root 2711: return const0_rtx;
1.1 root 2712:
2713: default:
2714: abort ();
2715: }
2716:
2717: /* Here to do an ordinary binary operator, generating an instruction
2718: from the optab already placed in `this_optab'. */
2719: binop:
2720: /* Detect things like x = y | (a == b)
2721: and do them as (x = y), (a == b ? x |= 1 : 0), x. */
2722: /* First, get the comparison or conditional into the second arg. */
2723: if (comparison_code[(int) TREE_CODE (TREE_OPERAND (exp, 0))]
2724: || (TREE_CODE (TREE_OPERAND (exp, 0)) == COND_EXPR
2725: && (integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 0), 1))
2726: || integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 0), 2)))))
2727: {
2728: if (this_optab == ior_optab || this_optab == add_optab
2729: || this_optab == xor_optab)
2730: {
2731: tree exch = TREE_OPERAND (exp, 1);
2732: TREE_OPERAND (exp, 1) = TREE_OPERAND (exp, 0);
2733: TREE_OPERAND (exp, 0) = exch;
2734: }
2735: }
1.1.1.3 root 2736: /* Optimize X + (Y ? Z : 0) by computing X and maybe adding Z. */
1.1 root 2737: if (comparison_code[(int) TREE_CODE (TREE_OPERAND (exp, 1))]
2738: || (TREE_CODE (TREE_OPERAND (exp, 1)) == COND_EXPR
2739: && (integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 1), 1))
2740: || integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 1), 2)))))
2741: {
2742: if (this_optab == ior_optab || this_optab == add_optab
2743: || this_optab == xor_optab || this_optab == sub_optab
2744: || this_optab == lshl_optab || this_optab == ashl_optab
2745: || this_optab == lshr_optab || this_optab == ashr_optab
2746: || this_optab == rotl_optab || this_optab == rotr_optab)
2747: {
1.1.1.2 root 2748: tree thenexp;
1.1 root 2749: rtx thenv = 0;
2750:
1.1.1.3 root 2751: /* Don't store intermediate results in a fixed register. */
2752: if (target != 0 && GET_CODE (target) == REG
2753: && REGNO (target) < FIRST_PSEUDO_REGISTER)
2754: target = 0;
1.1 root 2755: if (target == 0) target = gen_reg_rtx (mode);
1.1.1.3 root 2756:
2757: /* Compute X into the target. */
1.1.1.2 root 2758: store_expr (TREE_OPERAND (exp, 0), target, 0);
1.1 root 2759: op0 = gen_label_rtx ();
2760:
1.1.1.3 root 2761: /* If other operand is a comparison COMP, treat it as COMP ? 1 : 0 */
1.1 root 2762: if (TREE_CODE (TREE_OPERAND (exp, 1)) != COND_EXPR)
2763: {
2764: do_jump (TREE_OPERAND (exp, 1), op0, 0);
2765: thenv = const1_rtx;
2766: }
2767: else if (integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 1), 2)))
2768: {
2769: do_jump (TREE_OPERAND (TREE_OPERAND (exp, 1), 0), op0, 0);
2770: thenexp = TREE_OPERAND (TREE_OPERAND (exp, 1), 1);
2771: }
2772: else
2773: {
2774: do_jump (TREE_OPERAND (TREE_OPERAND (exp, 1), 0), 0, op0);
2775: thenexp = TREE_OPERAND (TREE_OPERAND (exp, 1), 2);
2776: }
2777:
2778: if (thenv == 0)
2779: thenv = expand_expr (thenexp, 0, VOIDmode, 0);
2780:
1.1.1.3 root 2781: /* THENV is now Z, the value to operate on, as an rtx.
2782: We have already tested that Y isn't zero, so do the operation. */
2783:
1.1 root 2784: if (this_optab == rotl_optab || this_optab == rotr_optab)
2785: temp = expand_binop (mode, this_optab, target, thenv, target,
2786: -1, OPTAB_LIB);
2787: else if (this_optab == lshl_optab || this_optab == lshr_optab)
2788: temp = expand_binop (mode, this_optab, target, thenv, target,
2789: 1, OPTAB_LIB_WIDEN);
2790: else
2791: temp = expand_binop (mode, this_optab, target, thenv, target,
2792: 0, OPTAB_LIB_WIDEN);
2793: if (target != temp)
2794: emit_move_insn (target, temp);
2795:
2796: emit_label (op0);
2797: return target;
2798: }
2799: }
2800: subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
2801: op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
2802: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
2803: binop2:
2804: temp = expand_binop (mode, this_optab, op0, op1, target,
1.1.1.2 root 2805: TREE_UNSIGNED (TREE_TYPE (exp)), OPTAB_LIB_WIDEN);
1.1 root 2806: binop1:
2807: if (temp == 0)
2808: abort ();
2809: return temp;
2810: }
2811:
1.1.1.2 root 2812: /* Expand an expression EXP that calls a built-in function,
2813: with result going to TARGET if that's convenient
2814: (and in mode MODE if that's convenient).
2815: SUBTARGET may be used as the target for computing one of EXP's operands. */
2816:
2817: static rtx
2818: expand_builtin (exp, target, subtarget, mode)
2819: tree exp;
2820: rtx target;
2821: rtx subtarget;
2822: enum machine_mode mode;
2823: {
2824: tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
2825: tree arglist = TREE_OPERAND (exp, 1);
2826: rtx op0;
2827: rtx temp;
2828:
2829: switch (DECL_FUNCTION_CODE (fndecl))
2830: {
2831: case BUILT_IN_ABS:
2832: case BUILT_IN_LABS:
2833: case BUILT_IN_FABS:
2834: /* build_function_call changes these into ABS_EXPR. */
2835: abort ();
2836:
2837: case BUILT_IN_ALLOCA:
2838: if (arglist == 0)
2839: return const0_rtx;
2840: frame_pointer_needed = 1;
2841: /* Compute the argument. */
2842: op0 = expand_expr (TREE_VALUE (arglist), 0, VOIDmode, 0);
2843: if (! CONSTANT_P (op0))
2844: {
2845: op0 = force_reg (GET_MODE (op0), op0);
2846: if (GET_MODE (op0) != Pmode)
2847: op0 = convert_to_mode (Pmode, op0);
2848: }
2849: /* Push that much space (rounding it up). */
1.1.1.3 root 2850: do_pending_stack_adjust ();
1.1.1.4 ! root 2851: #ifdef STACK_GROWS_DOWNWARD
1.1.1.2 root 2852: anti_adjust_stack (round_push (op0));
1.1.1.4 ! root 2853: #endif
1.1.1.2 root 2854: /* Return a copy of current stack ptr, in TARGET if possible. */
2855: if (target)
2856: emit_move_insn (target, stack_pointer_rtx);
2857: else
2858: target = copy_to_reg (stack_pointer_rtx);
1.1.1.4 ! root 2859: #ifdef STACK_POINTER_OFFSET
! 2860: /* If the contents of the stack pointer reg are offset from the
! 2861: actual top-of-stack address, add the offset here. */
! 2862: emit_insn (gen_add2_insn (target, gen_rtx (CONST_INT, VOIDmode,
! 2863: STACK_POINTER_OFFSET)));
! 2864: #endif
! 2865: #ifndef STACK_GROWS_DOWNWARD
! 2866: anti_adjust_stack (round_push (op0));
! 2867: #endif
1.1.1.2 root 2868: return target;
2869:
2870: case BUILT_IN_FFS:
2871: if (arglist == 0)
2872: return const0_rtx;
2873:
2874: /* Compute the argument. */
2875: op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
2876: /* Compute ffs, into TARGET if possible.
2877: Set TARGET to wherever the result comes back. */
2878: target = expand_unop (mode, ffs_optab, op0, target, 1);
2879: if (target == 0)
2880: abort ();
2881: return target;
2882:
2883: default:
2884: abort ();
2885: }
2886: }
2887:
2888: /* Expand code for a post- or pre- increment or decrement
2889: and return the RTX for the result.
2890: POST is 1 for postinc/decrements and 0 for preinc/decrements. */
2891:
2892: static rtx
2893: expand_increment (exp, post)
2894: register tree exp;
2895: int post;
2896: {
2897: register rtx op0, op1;
2898: register rtx temp;
2899: register tree incremented = TREE_OPERAND (exp, 0);
2900: optab this_optab = add_optab;
2901: int icode;
2902: enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
2903: int op0_is_copy = 0;
2904:
2905: /* Stabilize any component ref that might need to be
2906: evaluated more than once below. */
2907: if (TREE_CODE (incremented) == COMPONENT_REF
2908: && (TREE_CODE (TREE_OPERAND (incremented, 0)) != INDIRECT_REF
2909: || DECL_MODE (TREE_OPERAND (exp, 1)) == BImode))
2910: incremented = stabilize_reference (incremented);
2911:
2912: /* Compute the operands as RTX.
2913: Note whether OP0 is the actual lvalue or a copy of it:
2914: I believe it is a copy iff it is a register and insns were
2915: generated in computing it. */
2916: temp = get_last_insn ();
2917: op0 = expand_expr (incremented, 0, VOIDmode, 0);
2918: if (temp != get_last_insn ())
2919: op0_is_copy = (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG);
2920: op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
2921:
2922: /* Decide whether incrementing or decrementing. */
2923: if (TREE_CODE (exp) == POSTDECREMENT_EXPR
2924: || TREE_CODE (exp) == PREDECREMENT_EXPR)
2925: this_optab = sub_optab;
2926:
2927: /* If OP0 is not the actual lvalue, but rather a copy in a register,
2928: then we cannot just increment OP0. We must
2929: therefore contrive to increment the original value.
2930: Then we can return OP0 since it is a copy of the old value. */
2931: if (op0_is_copy)
2932: {
2933: /* This is the easiest way to increment the value wherever it is.
2934: Problems with multiple evaluation of INCREMENTED
2935: are prevented because either (1) it is a component_ref,
2936: in which case it was stabilized above, or (2) it is an array_ref
2937: with constant index in an array in a register, which is
2938: safe to reevaluate. */
2939: tree newexp = build ((this_optab == add_optab
2940: ? PLUS_EXPR : MINUS_EXPR),
2941: TREE_TYPE (exp),
2942: incremented,
2943: TREE_OPERAND (exp, 1));
2944: temp = expand_assignment (incremented, newexp, ! post, 0);
2945: return post ? op0 : temp;
2946: }
2947:
2948: /* Convert decrement by a constant into a negative increment. */
2949: if (this_optab == sub_optab
2950: && GET_CODE (op1) == CONST_INT)
2951: {
2952: op1 = gen_rtx (CONST_INT, VOIDmode, - INTVAL (op1));
2953: this_optab = add_optab;
2954: }
2955:
2956: if (post)
2957: {
2958: /* We have a true reference to the value in OP0.
2959: If there is an insn to add or subtract in this mode, queue it. */
2960:
2961: /* I'm not sure this is still necessary. */
2962: op0 = stabilize (op0);
2963:
2964: icode = (int) this_optab->handlers[(int) mode].insn_code;
2965: if (icode != (int) CODE_FOR_nothing
2966: /* Make sure that OP0 is valid for operands 0 and 1
2967: of the insn we want to queue. */
2968: && (*insn_operand_predicate[icode][0]) (op0, mode)
2969: && (*insn_operand_predicate[icode][1]) (op0, mode))
2970: {
2971: if (! (*insn_operand_predicate[icode][2]) (op1, mode))
2972: op1 = force_reg (mode, op1);
2973:
2974: return enqueue_insn (op0, GEN_FCN (icode) (op0, op0, op1));
2975: }
2976: }
2977:
2978: /* Preincrement, or we can't increment with one simple insn. */
2979: if (post)
2980: /* Save a copy of the value before inc or dec, to return it later. */
2981: temp = copy_to_reg (op0);
2982: else
2983: /* Arrange to return the incremented value. */
2984: temp = op0;
2985:
2986: /* Increment however we can. */
2987: op1 = expand_binop (mode, this_optab, op0, op1, op0,
2988: 0, OPTAB_LIB_WIDEN);
2989: /* Make sure the value is stored into OP0. */
2990: if (op1 != op0)
2991: emit_move_insn (op0, op1);
2992:
2993: return temp;
2994: }
2995:
1.1 root 2996: /* Expand all function calls contained within EXP, innermost ones first.
2997: But don't look within expressions that have sequence points.
2998: For each CALL_EXPR, record the rtx for its value
1.1.1.2 root 2999: in the CALL_EXPR_RTL field.
3000:
3001: Calls that return large structures for which a structure return
3002: stack slot is needed are not preexpanded. Preexpanding them loses
3003: because if more than one were preexpanded they would try to use the
3004: same stack slot. */
1.1 root 3005:
3006: static void
3007: preexpand_calls (exp)
3008: tree exp;
3009: {
3010: register int nops, i;
3011:
3012: if (! do_preexpand_calls)
3013: return;
3014:
1.1.1.2 root 3015: /* Only expressions and references can contain calls. */
3016:
3017: if (tree_code_type[(int) TREE_CODE (exp)][0] != 'e'
3018: && tree_code_type[(int) TREE_CODE (exp)][0] != 'r')
3019: return;
3020:
1.1 root 3021: switch (TREE_CODE (exp))
3022: {
3023: case CALL_EXPR:
1.1.1.2 root 3024: /* Do nothing to built-in functions. */
3025: if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
3026: && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) == FUNCTION_DECL
3027: && DECL_FUNCTION_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
3028: return;
3029: if (CALL_EXPR_RTL (exp) == 0
3030: && TYPE_MODE (TREE_TYPE (exp)) != BLKmode)
3031: CALL_EXPR_RTL (exp) = expand_call (exp, 0, 0);
1.1 root 3032: return;
3033:
3034: case COMPOUND_EXPR:
3035: case COND_EXPR:
3036: case TRUTH_ANDIF_EXPR:
3037: case TRUTH_ORIF_EXPR:
3038: /* If we find one of these, then we can be sure
3039: the adjust will be done for it (since it makes jumps).
3040: Do it now, so that if this is inside an argument
3041: of a function, we don't get the stack adjustment
3042: after some other args have already been pushed. */
3043: do_pending_stack_adjust ();
3044: return;
3045:
1.1.1.2 root 3046: case RTL_EXPR:
3047: return;
3048:
1.1 root 3049: case SAVE_EXPR:
3050: if (SAVE_EXPR_RTL (exp) != 0)
3051: return;
3052: }
3053:
3054: nops = tree_code_length[(int) TREE_CODE (exp)];
3055: for (i = 0; i < nops; i++)
3056: if (TREE_OPERAND (exp, i) != 0)
3057: {
3058: register int type = *tree_code_type[(int) TREE_CODE (TREE_OPERAND (exp, i))];
3059: if (type == 'e' || type == 'r')
3060: preexpand_calls (TREE_OPERAND (exp, i));
3061: }
3062: }
3063:
1.1.1.2 root 3064: /* Force FUNEXP into a form suitable for the address of a CALL,
3065: and return that as an rtx. Also load the static chain register
3066: from either FUNEXP or CONTEXT. */
1.1 root 3067:
1.1.1.2 root 3068: static rtx
3069: prepare_call_address (funexp, context)
1.1 root 3070: rtx funexp;
3071: rtx context;
3072: {
3073: funexp = protect_from_queue (funexp, 0);
1.1.1.2 root 3074: if (context != 0)
1.1 root 3075: context = protect_from_queue (context, 0);
3076:
3077: /* Function variable in language with nested functions. */
3078: if (GET_MODE (funexp) == EPmode)
3079: {
1.1.1.2 root 3080: emit_move_insn (static_chain_rtx, gen_highpart (Pmode, funexp));
3081: funexp = memory_address (FUNCTION_MODE, gen_lowpart (Pmode, funexp));
3082: emit_insn (gen_rtx (USE, VOIDmode, static_chain_rtx));
1.1 root 3083: }
3084: else
3085: {
3086: if (context != 0)
1.1.1.2 root 3087: /* Unless function variable in C, or top level function constant */
3088: emit_move_insn (static_chain_rtx, lookup_static_chain (context));
3089:
3090: /* Make a valid memory address and copy constants thru pseudo-regs,
3091: but not for a constant address if -fno-function-cse. */
3092: if (GET_CODE (funexp) != SYMBOL_REF)
3093: funexp = memory_address (FUNCTION_MODE, funexp);
3094: else
1.1 root 3095: {
1.1.1.2 root 3096: #ifndef NO_FUNCTION_CSE
3097: if (! flag_no_function_cse)
3098: funexp = copy_to_mode_reg (Pmode, funexp);
3099: #endif
3100: }
3101:
3102: if (context != 0)
3103: emit_insn (gen_rtx (USE, VOIDmode, static_chain_rtx));
1.1 root 3104: }
1.1.1.2 root 3105: return funexp;
3106: }
3107:
3108: /* Generate instructions to call function FUNEXP,
3109: and optionally pop the results.
3110: The CALL_INSN is the first insn generated.
3111:
3112: FUNTYPE is the data type of the function, or, for a library call,
3113: the identifier for the name of the call. This is given to the
3114: macro RETURN_POPS_ARGS to determine whether this function pops its own args.
3115:
3116: STACK_SIZE is the number of bytes of arguments on the stack,
3117: rounded up to STACK_BOUNDARY; zero if the size is variable.
3118: This is both to put into the call insn and
3119: to generate explicit popping code if necessary.
3120:
3121: NEXT_ARG_REG is the rtx that results from executing
3122: FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1)
3123: just after all the args have had their registers assigned.
3124: This could be whatever you like, but normally it is the first
3125: arg-register beyond those used for args in this call,
3126: or 0 if all the arg-registers are used in this call.
3127: It is passed on to `gen_call' so you can put this info in the call insn.
3128:
3129: VALREG is a hard register in which a value is returned,
3130: or 0 if the call does not return a value.
3131:
3132: OLD_ARGS_SIZE is the value that `current_args_size' had before
3133: the args to this call were processed.
3134: We restore `current_args_size' to that value. */
3135:
3136: static void
3137: emit_call_1 (funexp, funtype, stack_size, next_arg_reg, valreg, old_args_size)
3138: rtx funexp;
3139: tree funtype;
3140: int stack_size;
3141: rtx next_arg_reg;
3142: rtx valreg;
3143: int old_args_size;
3144: {
3145: rtx stack_size_rtx = gen_rtx (CONST_INT, VOIDmode, stack_size);
3146:
3147: if (valreg)
3148: emit_call_insn (gen_call_value (valreg,
3149: gen_rtx (MEM, FUNCTION_MODE, funexp),
3150: stack_size_rtx, next_arg_reg));
3151: else
3152: emit_call_insn (gen_call (gen_rtx (MEM, FUNCTION_MODE, funexp),
3153: stack_size_rtx, next_arg_reg));
3154:
3155: current_args_size = old_args_size;
3156:
1.1 root 3157: /* If returning from the subroutine does not automatically pop the args,
3158: we need an instruction to pop them sooner or later.
3159: Perhaps do it now; perhaps just record how much space to pop later. */
1.1.1.2 root 3160:
3161: if (! RETURN_POPS_ARGS (TREE_TYPE (funtype))
3162: && stack_size != 0)
1.1 root 3163: {
1.1.1.2 root 3164: if (flag_defer_pop && current_args_size == 0)
3165: pending_stack_adjust += stack_size;
1.1 root 3166: else
1.1.1.3 root 3167: adjust_stack (stack_size_rtx);
1.1 root 3168: }
3169: }
3170:
3171: /* At the start of a function, record that we have no previously-pushed
3172: arguments waiting to be popped. */
3173:
1.1.1.2 root 3174: void
3175: init_pending_stack_adjust ()
1.1 root 3176: {
3177: pending_stack_adjust = 0;
3178: }
3179:
1.1.1.2 root 3180: /* When exiting from function, if safe, clear out any pending stack adjust
3181: so the adjustment won't get done. */
3182:
3183: void
3184: clear_pending_stack_adjust ()
3185: {
3186: #ifdef EXIT_IGNORE_STACK
1.1.1.4 ! root 3187: if (!flag_omit_frame_pointer && EXIT_IGNORE_STACK
! 3188: && ! TREE_INLINE (current_function_decl))
1.1.1.2 root 3189: pending_stack_adjust = 0;
3190: #endif
3191: }
3192:
1.1 root 3193: /* At start of function, initialize. */
1.1.1.2 root 3194: void
1.1 root 3195: clear_current_args_size ()
3196: {
3197: current_args_size = 0;
3198: }
3199:
3200: /* Pop any previously-pushed arguments that have not been popped yet. */
3201:
1.1.1.2 root 3202: void
1.1 root 3203: do_pending_stack_adjust ()
3204: {
3205: if (current_args_size == 0)
3206: {
3207: if (pending_stack_adjust != 0)
3208: adjust_stack (gen_rtx (CONST_INT, VOIDmode, pending_stack_adjust));
3209: pending_stack_adjust = 0;
3210: }
3211: }
3212:
3213: /* Generate all the code for a function call
3214: and return an rtx for its value.
3215: Store the value in TARGET (specified as an rtx) if convenient.
1.1.1.2 root 3216: If the value is stored in TARGET then TARGET is returned.
3217: If IGNORE is nonzero, then we ignore the value of the function call. */
1.1 root 3218:
3219: static rtx
1.1.1.2 root 3220: expand_call (exp, target, ignore)
1.1 root 3221: tree exp;
3222: rtx target;
1.1.1.2 root 3223: int ignore;
1.1 root 3224: {
3225: tree actparms = TREE_OPERAND (exp, 1);
1.1.1.2 root 3226: tree funtype;
3227: rtx funexp;
3228: register tree p = TREE_OPERAND (exp, 0);
3229: struct args_size args_size;
1.1 root 3230: register int i;
3231: register tree *argvec;
1.1.1.2 root 3232: rtx *regvec;
3233: rtx *valvec;
3234: int *partial;
3235: struct args_size *arg_offset;
3236: struct args_size *arg_size;
1.1 root 3237: int num_actuals;
3238: rtx structure_value_addr = 0;
1.1.1.2 root 3239: tree fndecl = 0;
3240: int may_be_alloca;
3241: int inc;
3242: int is_setjmp;
3243: int is_integrable = 0;
3244: rtx argblock = 0;
3245: CUMULATIVE_ARGS args_so_far;
3246: int reg_parm_seen = 0;
3247: rtx valreg;
3248: rtx old_stack_level;
3249: int old_pending_adj;
3250: int old_current_args_size = current_args_size;
3251:
3252: /* Number of named args. Args after this are anonymous ones
3253: and they must all go on the stack. */
3254: int n_named_args;
3255:
3256: args_size.constant = 0;
3257: args_size.var = 0;
3258:
3259: /* See if we can find a DECL-node for the actual function.
3260: As a result, decide whether this is a call to an integrable function. */
3261:
3262: if (TREE_CODE (p) == ADDR_EXPR)
3263: {
3264: fndecl = TREE_OPERAND (p, 0);
3265: if (TREE_CODE (fndecl) != FUNCTION_DECL)
3266: fndecl = 0;
3267: else
3268: {
3269: extern tree current_function_decl;
1.1 root 3270:
1.1.1.2 root 3271: if (fndecl != current_function_decl
3272: && DECL_SAVED_INSNS (fndecl))
3273: is_integrable = 1;
3274: else
1.1.1.4 ! root 3275: {
! 3276: /* In case this function later becomes inlineable,
! 3277: record that there was already a non-inline call to it. */
! 3278: TREE_ADDRESSABLE (fndecl) = 1;
! 3279: TREE_ADDRESSABLE (DECL_NAME (fndecl)) = 1;
! 3280: }
1.1.1.2 root 3281: }
3282: }
1.1 root 3283:
1.1.1.2 root 3284: /* Set up a place to return a structure. */
1.1 root 3285:
3286: if (TYPE_MODE (TREE_TYPE (exp)) == BLKmode)
3287: {
3288: /* This call returns a big structure. */
3289: if (target)
3290: structure_value_addr = XEXP (target, 0);
3291: else
3292: /* Make room on the stack to hold the value. */
3293: structure_value_addr = get_structure_value_addr (expr_size (exp));
3294: }
3295:
1.1.1.2 root 3296: if (is_integrable)
3297: {
3298: extern int integration_time;
3299: extern rtx expand_inline_function ();
3300: rtx temp;
3301:
3302: temp = expand_inline_function (fndecl, actparms, target,
3303: ignore, TREE_TYPE (exp),
3304: structure_value_addr);
3305:
1.1.1.4 ! root 3306: if (temp != (rtx)-1)
1.1.1.2 root 3307: return temp;
3308: }
3309:
3310: #if 0
3311: /* Unless it's a call to a specific function that isn't alloca,
3312: if it has one argument, we must assume it might be alloca. */
3313:
3314: may_be_alloca =
3315: (!(fndecl != 0
3316: && strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)),
3317: "alloca"))
3318: && actparms != 0
3319: && TREE_CHAIN (actparms) == 0);
3320: #else
3321: /* We assume that alloca will always be called by name. It
3322: makes no sense to pass it as a pointer-to-function to
3323: anything that does not understand its behavior. */
3324: may_be_alloca =
3325: (fndecl && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "alloca"));
3326: #endif
3327:
3328: /* See if this is a call to a function that can return more than once. */
3329:
3330: is_setjmp
3331: = (fndecl != 0
3332: && (!strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "setjmp")
3333: || !strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "_setjmp")));
3334:
3335: if (may_be_alloca)
3336: {
3337: frame_pointer_needed = 1;
3338: may_call_alloca = 1;
3339: }
3340:
3341: /* Don't let pending stack adjusts add up to too much.
3342: Also, do all pending adjustments now
3343: if there is any chance this might be a call to alloca. */
3344:
3345: if (pending_stack_adjust >= 32
3346: || (pending_stack_adjust > 0 && may_be_alloca))
3347: do_pending_stack_adjust ();
3348:
3349: /* Operand 0 is a pointer-to-function; get the type of the function. */
3350: funtype = TREE_TYPE (TREE_OPERAND (exp, 0));
3351: if (TREE_CODE (funtype) != POINTER_TYPE)
3352: abort ();
3353: funtype = TREE_TYPE (funtype);
3354:
3355: /* Count the arguments and set NUM_ACTUALS. */
1.1 root 3356: for (p = actparms, i = 0; p; p = TREE_CHAIN (p)) i++;
3357: num_actuals = i;
1.1.1.2 root 3358:
3359: /* Compute number of named args.
3360: This may actually be 1 too large, but that happens
3361: only in the case when all args are named, so no trouble results. */
3362: if (TYPE_ARG_TYPES (funtype) != 0)
3363: n_named_args = list_length (TYPE_ARG_TYPES (funtype));
3364: else
3365: /* If we know nothing, treat all args as named. */
3366: n_named_args = num_actuals;
3367:
3368: /* Make a vector of the args, in the order we want to compute them,
3369: and a parallel vector of where we want to put them.
3370: regvec[I] is 0 to if should push argvec[I] or else a reg to put it in.
3371: valvec[i] is the arg value as an rtx. */
1.1 root 3372: argvec = (tree *) alloca (i * sizeof (tree));
1.1.1.2 root 3373: regvec = (rtx *) alloca (i * sizeof (rtx));
3374: valvec = (rtx *) alloca (i * sizeof (rtx));
3375: partial = (int *) alloca (i * sizeof (int));
3376: arg_size = (struct args_size *) alloca (i * sizeof (struct args_size));
3377: arg_offset = (struct args_size *) alloca (i * sizeof (struct args_size));
3378:
3379: /* In this loop, we consider args in the order they are written.
3380: We fill up argvec from the front of from the back
3381: so that the first arg to be pushed ends up at the front. */
1.1 root 3382:
1.1.1.2 root 3383: #ifdef PUSH_ARGS_REVERSED
3384: i = num_actuals - 1, inc = -1;
1.1 root 3385: /* In this case, must reverse order of args
1.1.1.2 root 3386: so that we compute and push the last arg first. */
1.1 root 3387: #else
1.1.1.2 root 3388: i = 0, inc = 1;
3389: #endif
3390:
3391: INIT_CUMULATIVE_ARGS (args_so_far, funtype);
3392:
3393: for (p = actparms; p; p = TREE_CHAIN (p), i += inc)
3394: {
3395: tree type = TREE_TYPE (TREE_VALUE (p));
3396: argvec[i] = p;
3397: regvec[i] = 0;
3398: valvec[i] = 0;
3399: partial[i] = 0;
3400: arg_size[i].constant = 0;
3401: arg_size[i].var = 0;
3402: arg_offset[i] = args_size;
3403:
1.1.1.4 ! root 3404: #ifdef STACK_POINTER_OFFSET
! 3405: /* ARG_OFFSET is used to index ARGS_ADDR, which is the stack ptr reg,
! 3406: so if there is a gap between that reg and the actual t.o.s. addr,
! 3407: we must include it in this offset. */
! 3408: arg_offset.constant += STACK_POINTER_OFFSET;
! 3409: #endif
! 3410:
1.1.1.2 root 3411: if (type == error_mark_node)
3412: continue;
3413:
3414: /* Decide where to pass this arg. */
3415: /* regvec[i] is nonzero if all or part is passed in registers.
3416: partial[i] is nonzero if part but not all is passed in registers,
3417: and the exact value says how many words are passed in registers. */
3418:
3419: if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
3420: || args_size.var != 0)
3421: {
3422: regvec[i] = FUNCTION_ARG (args_so_far, TYPE_MODE (type), type,
3423: i < n_named_args);
3424: #ifdef FUNCTION_ARG_PARTIAL_NREGS
3425: partial[i] = FUNCTION_ARG_PARTIAL_NREGS (args_so_far,
3426: TYPE_MODE (type), type,
3427: i < n_named_args);
3428: #endif
3429: }
3430:
3431: /* Once we see at least one parm that is being passed in a register,
3432: precompute that parm and all remaining parms (if they do arithmetic)
3433: before loading any of them into their specified registers.
3434: That way we don't lose if one of them involves
3435: a function call OR a library routine that needs the same regs. */
3436: if (regvec[i] != 0)
3437: reg_parm_seen = 1;
3438:
3439: if (reg_parm_seen)
3440: {
3441: valvec[i] = expand_expr (TREE_VALUE (p), 0, VOIDmode, 0);
3442: if (GET_CODE (valvec[i]) != MEM
3443: && ! CONSTANT_P (valvec[i])
3444: && GET_CODE (valvec[i]) != CONST_DOUBLE)
3445: valvec[i] = force_reg (TYPE_MODE (type), valvec[i]);
1.1.1.4 ! root 3446: /* ANSI doesn't require a sequence point here,
! 3447: but PCC has one, so this will avoid some problems. */
! 3448: emit_queue ();
1.1.1.2 root 3449: }
3450:
3451: /* Increment ARGS_SO_FAR, which has info about which arg-registers
3452: have been used, etc. */
3453:
3454: FUNCTION_ARG_ADVANCE (args_so_far, TYPE_MODE (type), type,
3455: i < n_named_args);
3456:
3457: /* Increment ARGS_SIZE, which is the size of all args so far. */
3458:
3459: if (regvec[i] != 0 && partial[i] == 0)
3460: /* A register-arg doesn't count. */
3461: ;
3462: else if (TYPE_MODE (type) != BLKmode)
3463: {
3464: register int size;
3465:
3466: size = GET_MODE_SIZE (TYPE_MODE (type));
3467: /* Compute how much space the push instruction will push.
3468: On many machines, pushing a byte will advance the stack
3469: pointer by a halfword. */
3470: #ifdef PUSH_ROUNDING
3471: size = PUSH_ROUNDING (size);
1.1 root 3472: #endif
1.1.1.2 root 3473: /* Compute how much space the argument should get:
3474: round up to a multiple of the alignment for arguments. */
3475: arg_size[i].constant
3476: = (((size + PARM_BOUNDARY / BITS_PER_UNIT - 1)
3477: / (PARM_BOUNDARY / BITS_PER_UNIT))
3478: * (PARM_BOUNDARY / BITS_PER_UNIT));
3479: }
3480: else
3481: {
3482: register tree size = size_in_bytes (type);
3483:
3484: /* A nonscalar. Round its size up to a multiple
3485: of the allocation unit for arguments. */
3486:
3487: /* Now round up to multiple of PARM_BOUNDARY bits,
3488: then express as number of bytes. */
3489: ADD_PARM_SIZE (arg_size[i],
3490: convert_units (convert_units (size, BITS_PER_UNIT, PARM_BOUNDARY),
3491: PARM_BOUNDARY, BITS_PER_UNIT));
3492:
3493: }
3494: /* If a part of the arg was put into registers,
3495: don't include that part in the amount pushed. */
3496: arg_size[i].constant
3497: -= ((partial[i] * UNITS_PER_WORD)
3498: / (PARM_BOUNDARY / BITS_PER_UNIT)
3499: * (PARM_BOUNDARY / BITS_PER_UNIT));
3500:
3501: args_size.constant += arg_size[i].constant;
3502:
3503: if (arg_size[i].var)
3504: {
3505: ADD_PARM_SIZE (args_size, arg_size[i].var);
3506: }
3507: }
3508:
3509: /* If we have no actual push instructions, or we need a variable
3510: amount of space, make space for all the args right now.
3511: In any case, round the needed size up to multiple of STACK_BOUNDARY. */
3512:
3513: if (args_size.var != 0)
3514: {
3515: old_stack_level = copy_to_mode_reg (Pmode, stack_pointer_rtx);
3516: old_pending_adj = pending_stack_adjust;
3517: argblock = push_block (round_push (ARGS_SIZE_RTX (args_size)));
3518: }
3519: else if (args_size.constant != 0)
3520: {
3521: int needed = args_size.constant;
3522:
3523: #ifdef STACK_BOUNDARY
3524: needed = (needed + STACK_BYTES - 1) / STACK_BYTES * STACK_BYTES;
3525: args_size.constant = needed;
3526: #endif
3527:
3528: #ifndef PUSH_ROUNDING
3529: /* Try to reuse some or all of the pending_stack_adjust
3530: to get this space. Maybe we can avoid any pushing. */
3531: if (needed > pending_stack_adjust)
3532: {
3533: needed -= pending_stack_adjust;
3534: pending_stack_adjust = 0;
3535: }
3536: else
3537: {
3538: pending_stack_adjust -= needed;
3539: needed = 0;
3540: }
1.1.1.3 root 3541: argblock = push_block (gen_rtx (CONST_INT, VOIDmode, needed));
1.1.1.2 root 3542: #endif /* no PUSH_ROUNDING */
3543: }
3544:
3545: /* Get the function to call, in the form of RTL. */
3546: if (fndecl)
3547: /* Get a SYMBOL_REF rtx for the function address. */
3548: funexp = XEXP (DECL_RTL (fndecl), 0);
3549: else
3550: /* Generate an rtx (probably a pseudo-register) for the address. */
1.1.1.4 ! root 3551: {
! 3552: funexp = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
! 3553: emit_queue ();
! 3554: }
1.1.1.2 root 3555:
3556: /* Now actually compute the args, and push those that need pushing. */
3557:
1.1 root 3558: for (i = 0; i < num_actuals; i++)
3559: {
3560: register tree p = argvec[i];
3561: register tree pval = TREE_VALUE (p);
1.1.1.2 root 3562: int used = 0;
1.1 root 3563:
3564: /* Push the next argument. Note that it has already been converted
3565: if necessary to the type that the called function expects. */
3566:
3567: if (TREE_CODE (pval) == ERROR_MARK)
3568: ;
1.1.1.2 root 3569: else if (regvec[i] != 0 && partial[i] == 0)
3570: {
3571: /* Being passed entirely in a register. */
3572: if (valvec[i] != 0)
3573: {
3574: if (GET_MODE (valvec[i]) == BLKmode)
3575: move_block_to_reg (REGNO (regvec[i]), valvec[i],
3576: (int_size_in_bytes (TREE_TYPE (pval))
3577: / UNITS_PER_WORD));
3578: else
3579: emit_move_insn (regvec[i], valvec[i]);
3580: }
3581: else
3582: store_expr (pval, regvec[i], 0);
3583:
3584: /* Don't allow anything left on stack from computation
3585: of argument to alloca. */
3586: if (may_be_alloca)
3587: do_pending_stack_adjust ();
3588: }
1.1 root 3589: else if (TYPE_MODE (TREE_TYPE (pval)) != BLKmode)
3590: {
1.1.1.2 root 3591: register int size;
3592: rtx tem;
3593:
3594: /* Argument is a scalar, not entirely passed in registers.
3595: (If part is passed in registers, partial[I] says how much
3596: and emit_push_insn will take care of putting it there.)
1.1 root 3597:
3598: Push it, and if its size is less than the
3599: amount of space allocated to it,
3600: also bump stack pointer by the additional space.
3601: Note that in C the default argument promotions
3602: will prevent such mismatches. */
3603:
3604: used = size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (pval)));
3605: /* Compute how much space the push instruction will push.
3606: On many machines, pushing a byte will advance the stack
3607: pointer by a halfword. */
1.1.1.2 root 3608: #ifdef PUSH_ROUNDING
1.1 root 3609: size = PUSH_ROUNDING (size);
1.1.1.2 root 3610: #endif
1.1 root 3611: /* Compute how much space the argument should get:
3612: round up to a multiple of the alignment for arguments. */
3613: used = (((size + PARM_BOUNDARY / BITS_PER_UNIT - 1)
3614: / (PARM_BOUNDARY / BITS_PER_UNIT))
3615: * (PARM_BOUNDARY / BITS_PER_UNIT));
3616:
1.1.1.2 root 3617: tem = valvec[i];
3618: if (tem == 0)
1.1.1.4 ! root 3619: {
! 3620: tem = expand_expr (pval, 0, VOIDmode, 0);
! 3621: /* ANSI doesn't require a sequence point here,
! 3622: but PCC has one, so this will avoid some problems. */
! 3623: emit_queue ();
! 3624: }
1.1.1.2 root 3625:
3626: /* Don't allow anything left on stack from computation
3627: of argument to alloca. */
3628: if (may_be_alloca)
3629: do_pending_stack_adjust ();
3630:
3631: emit_push_insn (tem, TYPE_MODE (TREE_TYPE (pval)), 0, 0,
3632: partial[i], regvec[i], used - size,
3633: argblock, ARGS_SIZE_RTX (arg_offset[i]));
1.1 root 3634: }
3635: else
3636: {
1.1.1.2 root 3637: register rtx tem
3638: = valvec[i] ? valvec[i] : expand_expr (pval, 0, VOIDmode, 0);
1.1 root 3639: register int excess;
1.1.1.2 root 3640: rtx size_rtx;
1.1 root 3641:
1.1.1.2 root 3642: /* Pushing a nonscalar.
3643: If part is passed in registers, partial[I] says how much
3644: and emit_push_insn will take care of putting it there. */
1.1 root 3645:
1.1.1.2 root 3646: /* Round its size up to a multiple
3647: of the allocation unit for arguments. */
1.1 root 3648:
1.1.1.2 root 3649: if (arg_size[i].var != 0)
3650: {
3651: excess = 0;
3652: size_rtx = ARGS_SIZE_RTX (arg_size[i]);
3653: }
3654: else
3655: {
3656: register tree size = size_in_bytes (TREE_TYPE (pval));
3657: /* PUSH_ROUNDING has no effect on us, because
3658: emit_push_insn for BLKmode is careful to avoid it. */
3659: excess = arg_size[i].constant - TREE_INT_CST_LOW (size);
3660: size_rtx = expand_expr (size, 0, VOIDmode, 0);
3661: }
1.1 root 3662:
1.1.1.2 root 3663: emit_push_insn (tem, TYPE_MODE (TREE_TYPE (pval)), size_rtx,
3664: TYPE_ALIGN (TREE_TYPE (pval)) / BITS_PER_UNIT,
3665: partial[i], regvec[i], excess, argblock,
3666: ARGS_SIZE_RTX (arg_offset[i]));
3667: }
1.1 root 3668:
1.1.1.2 root 3669: /* Account for the stack space thus used. */
1.1 root 3670:
3671:
1.1.1.2 root 3672: current_args_size += arg_size[i].constant;
3673: if (arg_size[i].var)
3674: current_args_size += 1;
1.1 root 3675: }
3676:
3677: /* Perform postincrements before actually calling the function. */
3678: emit_queue ();
3679:
3680: /* Pass the function the address in which to return a structure value. */
3681: if (structure_value_addr)
1.1.1.2 root 3682: emit_move_insn (struct_value_rtx, structure_value_addr);
3683:
3684: /* All arguments and registers used for the call must be set up by now! */
1.1 root 3685:
1.1.1.2 root 3686: /* ??? Other languages need a nontrivial second argument (static chain). */
3687: funexp = prepare_call_address (funexp, 0);
3688:
3689: /* Mark all register-parms as living through the call.
3690: ??? This is not quite correct, since it doesn't indicate
3691: that they are in use immediately before the call insn.
3692: Currently that doesn't matter since explicitly-used regs
3693: won't be used for reloading. But if the reloader becomes smarter,
3694: this will have to change somehow. */
3695: for (i = 0; i < num_actuals; i++)
3696: if (regvec[i] != 0)
3697: {
3698: if (partial[i] > 0)
3699: use_regs (REGNO (regvec[i]), partial[i]);
3700: else if (GET_MODE (regvec[i]) == BLKmode)
3701: use_regs (REGNO (regvec[i]),
3702: (int_size_in_bytes (TREE_TYPE (TREE_VALUE (argvec[i])))
3703: / UNITS_PER_WORD));
3704: else
3705: emit_insn (gen_rtx (USE, VOIDmode, regvec[i]));
3706: }
3707:
3708: if (structure_value_addr)
3709: emit_insn (gen_rtx (USE, VOIDmode, struct_value_rtx));
3710:
3711: /* Figure out the register where the value, if any, will come back. */
3712: valreg = 0;
3713: if (TYPE_MODE (TREE_TYPE (exp)) != VOIDmode
3714: && TYPE_MODE (TREE_TYPE (exp)) != BLKmode)
3715: valreg = hard_function_value (TREE_TYPE (exp), fndecl);
3716:
3717: /* Generate the actual call instruction. */
3718: emit_call_1 (funexp, funtype, args_size.constant,
3719: FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1),
3720: valreg, old_current_args_size);
1.1 root 3721:
3722: /* ??? Nothing has been done here to record control flow
3723: when contained functions can do nonlocal gotos. */
3724:
1.1.1.2 root 3725: /* For calls to `setjmp', etc., inform flow.c it should complain
3726: if nonvolatile values are live. */
3727:
3728: if (is_setjmp)
3729: emit_note (IDENTIFIER_POINTER (DECL_NAME (fndecl)), NOTE_INSN_SETJMP);
3730:
3731: /* If size of args is variable, restore saved stack-pointer value. */
3732:
3733: if (args_size.var != 0)
3734: {
3735: emit_move_insn (stack_pointer_rtx, old_stack_level);
3736: pending_stack_adjust = old_pending_adj;
3737: }
3738:
1.1 root 3739: /* If value type not void, return an rtx for the value. */
3740:
1.1.1.2 root 3741: if (TYPE_MODE (TREE_TYPE (exp)) == VOIDmode
3742: || ignore)
1.1 root 3743: return 0;
3744:
3745: if (structure_value_addr)
3746: {
3747: if (target)
3748: return target;
1.1.1.2 root 3749: return gen_rtx (MEM, BLKmode,
3750: memory_address (BLKmode, structure_value_addr));
1.1 root 3751: }
1.1.1.2 root 3752:
3753: if (target && GET_MODE (target) == TYPE_MODE (TREE_TYPE (exp)))
1.1 root 3754: {
1.1.1.2 root 3755: if (!rtx_equal_p (target, valreg))
3756: emit_move_insn (target, valreg);
3757: else
3758: /* This tells expand_inline_function to copy valreg to its target. */
3759: emit_insn (gen_rtx (USE, VOIDmode, valreg));
1.1 root 3760: return target;
3761: }
1.1.1.2 root 3762: return copy_to_reg (valreg);
1.1 root 3763: }
3764:
3765: /* Expand conditional expressions. */
3766:
3767: /* Generate code to evaluate EXP and jump to LABEL if the value is zero.
3768: LABEL is an rtx of code CODE_LABEL, in this function and all the
3769: functions here. */
3770:
1.1.1.2 root 3771: void
1.1 root 3772: jumpifnot (exp, label)
3773: tree exp;
3774: rtx label;
3775: {
3776: do_jump (exp, label, 0);
3777: }
3778:
3779: /* Generate code to evaluate EXP and jump to LABEL if the value is nonzero. */
3780:
1.1.1.2 root 3781: void
1.1 root 3782: jumpif (exp, label)
3783: tree exp;
3784: rtx label;
3785: {
3786: do_jump (exp, 0, label);
3787: }
3788:
3789: /* Generate code to evaluate EXP and jump to IF_FALSE_LABEL if
3790: the result is zero, or IF_TRUE_LABEL if the result is one.
3791: Either of IF_FALSE_LABEL and IF_TRUE_LABEL may be zero,
3792: meaning fall through in that case.
3793:
3794: This function is responsible for optimizing cases such as
3795: &&, || and comparison operators in EXP. */
3796:
1.1.1.2 root 3797: void
1.1 root 3798: do_jump (exp, if_false_label, if_true_label)
3799: tree exp;
3800: rtx if_false_label, if_true_label;
3801: {
3802: register enum tree_code code = TREE_CODE (exp);
3803: /* Some cases need to create a label to jump to
3804: in order to properly fall through.
3805: These cases set DROP_THROUGH_LABEL nonzero. */
3806: rtx drop_through_label = 0;
3807: rtx temp;
3808: rtx comparison = 0;
3809:
3810: emit_queue ();
3811:
3812: switch (code)
3813: {
3814: case ERROR_MARK:
3815: break;
3816:
3817: case INTEGER_CST:
3818: temp = integer_zerop (exp) ? if_false_label : if_true_label;
3819: if (temp)
3820: emit_jump (temp);
3821: break;
3822:
3823: case ADDR_EXPR:
3824: /* The address of something can never be zero. */
3825: if (if_true_label)
3826: emit_jump (if_true_label);
3827: break;
1.1.1.2 root 3828:
1.1 root 3829: case NOP_EXPR:
3830: do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
3831: break;
3832:
3833: case TRUTH_NOT_EXPR:
3834: do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
3835: break;
3836:
3837: case TRUTH_ANDIF_EXPR:
3838: if (if_false_label == 0)
3839: if_false_label = drop_through_label = gen_label_rtx ();
3840: do_jump (TREE_OPERAND (exp, 0), if_false_label, 0);
3841: do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
3842: break;
3843:
3844: case TRUTH_ORIF_EXPR:
3845: if (if_true_label == 0)
3846: if_true_label = drop_through_label = gen_label_rtx ();
3847: do_jump (TREE_OPERAND (exp, 0), 0, if_true_label);
3848: do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
3849: break;
3850:
3851: case COMPOUND_EXPR:
1.1.1.2 root 3852: expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
1.1 root 3853: emit_queue ();
3854: do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
3855: break;
3856:
3857: case COND_EXPR:
3858: {
3859: register rtx label1 = gen_label_rtx ();
3860: drop_through_label = gen_label_rtx ();
3861: do_jump (TREE_OPERAND (exp, 0), label1, 0);
3862: /* Now the THEN-expression. */
3863: do_jump (TREE_OPERAND (exp, 1),
3864: if_false_label ? if_false_label : drop_through_label,
3865: if_true_label ? if_true_label : drop_through_label);
3866: emit_label (label1);
3867: /* Now the ELSE-expression. */
3868: do_jump (TREE_OPERAND (exp, 2),
3869: if_false_label ? if_false_label : drop_through_label,
3870: if_true_label ? if_true_label : drop_through_label);
3871: }
3872: break;
3873:
3874: case EQ_EXPR:
3875: comparison = compare (exp, EQ, EQ, EQ, EQ);
3876: break;
3877:
3878: case NE_EXPR:
3879: comparison = compare (exp, NE, NE, NE, NE);
3880: break;
3881:
3882: case LT_EXPR:
3883: comparison = compare (exp, LT, LTU, GT, GTU);
3884: break;
3885:
3886: case LE_EXPR:
3887: comparison = compare (exp, LE, LEU, GE, GEU);
3888: break;
3889:
3890: case GT_EXPR:
3891: comparison = compare (exp, GT, GTU, LT, LTU);
3892: break;
3893:
3894: case GE_EXPR:
3895: comparison = compare (exp, GE, GEU, LE, LEU);
3896: break;
3897:
3898: default:
3899: temp = expand_expr (exp, 0, VOIDmode, 0);
1.1.1.2 root 3900: /* Copy to register to avoid generating bad insns by cse
3901: from (set (mem ...) (arithop)) (set (cc0) (mem ...)). */
3902: if (!cse_not_expected && GET_CODE (temp) == MEM)
3903: temp = copy_to_reg (temp);
1.1 root 3904: do_pending_stack_adjust ();
1.1.1.2 root 3905: {
3906: rtx zero;
3907: if (GET_MODE (temp) == SFmode)
3908: zero = fconst0_rtx;
3909: else if (GET_MODE (temp) == DFmode)
3910: zero = dconst0_rtx;
3911: else
3912: zero = const0_rtx;
1.1 root 3913:
1.1.1.2 root 3914: if (GET_CODE (temp) == CONST_INT)
3915: comparison = compare_constants (NE, 0,
3916: INTVAL (temp), 0, BITS_PER_WORD);
3917: else if (GET_MODE (temp) != VOIDmode)
3918: comparison = compare1 (temp, zero, NE, NE, 0, GET_MODE (temp));
3919: else
3920: abort ();
3921: }
1.1 root 3922: }
3923:
1.1.1.2 root 3924: /* Do any postincrements in the expression that was tested. */
3925: emit_queue ();
3926:
1.1 root 3927: /* If COMPARISON is nonzero here, it is an rtx that can be substituted
3928: straight into a conditional jump instruction as the jump condition.
3929: Otherwise, all the work has been done already. */
3930:
1.1.1.2 root 3931: if (comparison == const1_rtx)
3932: {
3933: if (if_true_label)
3934: emit_jump (if_true_label);
3935: }
3936: else if (comparison == const0_rtx)
3937: {
3938: if (if_false_label)
3939: emit_jump (if_false_label);
3940: }
3941: else if (comparison)
3942: {
3943: if (if_true_label)
3944: {
3945: emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx,
3946: gen_rtx (IF_THEN_ELSE, VOIDmode, comparison,
3947: gen_rtx (LABEL_REF, VOIDmode,
3948: if_true_label),
3949: pc_rtx)));
3950: if (if_false_label)
3951: emit_jump (if_false_label);
3952: }
3953: else if (if_false_label)
3954: {
3955: emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx,
3956: gen_rtx (IF_THEN_ELSE, VOIDmode, comparison,
3957: pc_rtx,
3958: gen_rtx (LABEL_REF, VOIDmode,
3959: if_false_label))));
3960: }
3961: }
1.1 root 3962:
3963: if (drop_through_label)
3964: emit_label (drop_through_label);
3965: }
3966:
1.1.1.2 root 3967: /* Compare two integer constant rtx's, OP0 and OP1.
3968: The comparison operation is OPERATION.
3969: Return an rtx representing the value 1 or 0.
3970: WIDTH is the width in bits that is significant. */
3971:
3972: static rtx
3973: compare_constants (operation, unsignedp, op0, op1, width)
3974: enum rtx_code operation;
3975: int unsignedp;
3976: int op0, op1;
3977: int width;
3978: {
3979: int val;
3980:
3981: /* Sign-extend or zero-extend the operands to a full word
3982: from an initial width of WIDTH bits. */
3983: if (width < HOST_BITS_PER_INT)
3984: {
3985: op0 &= (1 << width) - 1;
3986: op1 &= (1 << width) - 1;
3987:
3988: if (! unsignedp)
3989: {
3990: if (op0 & (1 << (width - 1)))
3991: op0 |= ((-1) << width);
3992: if (op1 & (1 << (width - 1)))
3993: op1 |= ((-1) << width);
3994: }
3995: }
3996:
3997: switch (operation)
3998: {
3999: case EQ:
4000: val = op0 == op1;
4001: break;
4002:
4003: case NE:
4004: val = op0 != op1;
4005: break;
4006:
4007: case GT:
4008: case GTU:
4009: val = op0 > op1;
4010: break;
4011:
4012: case LT:
4013: case LTU:
4014: val = op0 < op1;
4015: break;
4016:
4017: case GE:
4018: case GEU:
4019: val = op0 >= op1;
4020: break;
4021:
4022: case LE:
4023: case LEU:
4024: val = op0 <= op1;
4025: }
4026:
4027: return val ? const1_rtx : const0_rtx;
4028: }
4029:
1.1 root 4030: /* Generate code for a comparison expression EXP
4031: (including code to compute the values to be compared)
4032: and set (CC0) according to the result.
4033: SIGNED_FORWARD should be the rtx operation for this comparison for
4034: signed data; UNSIGNED_FORWARD, likewise for use if data is unsigned.
4035: SIGNED_REVERSE and UNSIGNED_REVERSE are used if it is desirable
4036: to interchange the operands for the compare instruction.
4037:
4038: We force a stack adjustment unless there are currently
4039: things pushed on the stack that aren't yet used. */
4040:
4041: static rtx
4042: compare (exp, signed_forward, unsigned_forward,
4043: signed_reverse, unsigned_reverse)
4044: register tree exp;
4045: enum rtx_code signed_forward, unsigned_forward;
4046: enum rtx_code signed_reverse, unsigned_reverse;
4047: {
1.1.1.2 root 4048:
1.1 root 4049: register rtx op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
4050: register rtx op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
4051: register enum machine_mode mode = GET_MODE (op0);
4052: int unsignedp;
4053:
4054: /* If one operand is 0, make it the second one. */
4055:
4056: if (op0 == const0_rtx || op0 == fconst0_rtx || op0 == dconst0_rtx)
4057: {
4058: rtx tem = op0;
4059: op0 = op1;
4060: op1 = tem;
4061: signed_forward = signed_reverse;
4062: unsigned_forward = unsigned_reverse;
4063: }
4064:
1.1.1.2 root 4065: if (flag_force_mem)
1.1 root 4066: {
4067: op0 = force_not_mem (op0);
4068: op1 = force_not_mem (op1);
4069: }
4070:
4071: do_pending_stack_adjust ();
4072:
1.1.1.2 root 4073: unsignedp = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)))
4074: || TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1))));
4075:
4076: if (GET_CODE (op0) == CONST_INT && GET_CODE (op1) == CONST_INT)
4077: return compare_constants (signed_forward, unsignedp,
4078: INTVAL (op0), INTVAL (op1),
4079: GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))));
1.1 root 4080:
4081: emit_cmp_insn (op0, op1,
4082: (mode == BLKmode) ? expr_size (TREE_OPERAND (exp, 0)) : 0,
4083: unsignedp);
4084:
4085: return gen_rtx ((unsignedp ? unsigned_forward : signed_forward),
4086: VOIDmode, cc0_rtx, const0_rtx);
4087: }
4088:
4089: /* Like compare but expects the values to compare as two rtx's.
4090: The decision as to signed or unsigned comparison must be made by the caller.
4091: BLKmode is not allowed. */
4092:
4093: static rtx
1.1.1.2 root 4094: compare1 (op0, op1, forward_op, reverse_op, unsignedp, mode)
1.1 root 4095: register rtx op0, op1;
4096: enum rtx_code forward_op, reverse_op;
4097: int unsignedp;
1.1.1.2 root 4098: enum machine_mode mode;
1.1 root 4099: {
4100: /* If one operand is 0, make it the second one. */
4101:
4102: if (op0 == const0_rtx || op0 == fconst0_rtx || op0 == dconst0_rtx)
4103: {
4104: rtx tem = op0;
4105: op0 = op1;
4106: op1 = tem;
4107: forward_op = reverse_op;
4108: }
4109:
1.1.1.2 root 4110: if (flag_force_mem)
1.1 root 4111: {
4112: op0 = force_not_mem (op0);
4113: op1 = force_not_mem (op1);
4114: }
4115:
4116: do_pending_stack_adjust ();
4117:
1.1.1.2 root 4118: if (GET_CODE (op0) == CONST_INT && GET_CODE (op1) == CONST_INT)
4119: return compare_constants (forward_op, unsignedp,
4120: INTVAL (op0), INTVAL (op1),
4121: GET_MODE_BITSIZE (mode));
4122:
1.1 root 4123: emit_cmp_insn (op0, op1, 0, unsignedp);
4124:
4125: return gen_rtx (forward_op, VOIDmode, cc0_rtx, const0_rtx);
4126: }
4127:
4128: /* Generate code to calculate EXP using a store-flag instruction
4129: and return an rtx for the result.
4130: If TARGET is nonzero, store the result there if convenient.
4131:
4132: Return zero if there is no suitable set-flag instruction
4133: available on this machine. */
4134:
4135: static rtx
1.1.1.2 root 4136: do_store_flag (exp, target, mode)
1.1 root 4137: tree exp;
4138: rtx target;
1.1.1.2 root 4139: enum machine_mode mode;
1.1 root 4140: {
4141: register enum tree_code code = TREE_CODE (exp);
4142: register rtx comparison = 0;
1.1.1.2 root 4143: enum machine_mode compare_mode;
1.1 root 4144:
4145: switch (code)
4146: {
1.1.1.2 root 4147: #ifdef HAVE_seq
1.1 root 4148: case EQ_EXPR:
1.1.1.2 root 4149: if (HAVE_seq)
4150: {
4151: comparison = compare (exp, EQ, EQ, EQ, EQ);
4152: compare_mode = insn_operand_mode[(int) CODE_FOR_seq][0];
4153: }
1.1 root 4154: break;
4155: #endif
4156:
1.1.1.2 root 4157: #ifdef HAVE_sne
1.1 root 4158: case NE_EXPR:
1.1.1.2 root 4159: if (HAVE_sne)
4160: {
4161: comparison = compare (exp, NE, NE, NE, NE);
4162: compare_mode = insn_operand_mode[(int) CODE_FOR_sne][0];
4163: }
1.1 root 4164: break;
4165: #endif
4166:
1.1.1.2 root 4167: #if defined (HAVE_slt) && defined (HAVE_sltu) && defined (HAVE_sgt) && defined (HAVE_sgtu)
1.1 root 4168: case LT_EXPR:
1.1.1.2 root 4169: if (HAVE_slt && HAVE_sltu && HAVE_sgt && HAVE_sgtu)
4170: {
4171: comparison = compare (exp, LT, LTU, GT, GTU);
4172: compare_mode = insn_operand_mode[(int) CODE_FOR_slt][0];
4173: }
1.1 root 4174: break;
4175:
4176: case GT_EXPR:
1.1.1.2 root 4177: if (HAVE_slt && HAVE_sltu && HAVE_sgt && HAVE_sgtu)
4178: {
4179: comparison = compare (exp, GT, GTU, LT, LTU);
4180: compare_mode = insn_operand_mode[(int) CODE_FOR_slt][0];
4181: }
1.1 root 4182: break;
4183: #endif
4184:
1.1.1.2 root 4185: #if defined (HAVE_sle) && defined (HAVE_sleu) && defined (HAVE_sge) && defined (HAVE_sgeu)
1.1 root 4186: case LE_EXPR:
1.1.1.2 root 4187: if (HAVE_sle && HAVE_sleu && HAVE_sge && HAVE_sgeu)
4188: {
4189: comparison = compare (exp, LE, LEU, GE, GEU);
4190: compare_mode = insn_operand_mode[(int) CODE_FOR_sle][0];
4191: }
1.1 root 4192: break;
4193:
4194: case GE_EXPR:
1.1.1.2 root 4195: if (HAVE_sle && HAVE_sleu && HAVE_sge && HAVE_sgeu)
4196: {
4197: comparison = compare (exp, GE, GEU, LE, LEU);
4198: compare_mode = insn_operand_mode[(int) CODE_FOR_sle][0];
4199: }
1.1 root 4200: break;
4201: #endif
4202: }
4203: if (comparison == 0)
4204: return 0;
4205:
1.1.1.2 root 4206: if (target == 0 || GET_MODE (target) != mode
4207: || (mode != compare_mode && GET_CODE (target) != REG))
4208: target = gen_reg_rtx (mode);
4209:
4210: /* Store the comparison in its proper mode. */
4211: if (GET_MODE (target) != compare_mode)
4212: emit_insn (gen_rtx (SET, VOIDmode,
4213: gen_rtx (SUBREG, compare_mode, target, 0),
4214: comparison));
4215: else
4216: emit_insn (gen_rtx (SET, VOIDmode, target, comparison));
4217:
4218: #if STORE_FLAG_VALUE != 1
4219: expand_bit_and (mode, target, const1_rtx, target);
4220: #endif
1.1 root 4221: return target;
4222: }
4223:
4224: /* Generate a tablejump instruction (used for switch statements). */
4225:
4226: #ifdef HAVE_tablejump
4227:
4228: /* INDEX is the value being switched on, with the lowest value
4229: in the table already subtracted.
4230: RANGE is the length of the jump table.
4231: TABLE_LABEL is a CODE_LABEL rtx for the table itself.
1.1.1.2 root 4232:
1.1 root 4233: DEFAULT_LABEL is a CODE_LABEL rtx to jump to if the
4234: index value is out of range. */
4235:
4236: void
4237: do_tablejump (index, range, table_label, default_label)
4238: rtx index, range, table_label, default_label;
4239: {
4240: register rtx temp;
4241:
4242: emit_cmp_insn (range, index, 0);
1.1.1.2 root 4243: emit_jump_insn (gen_bltu (default_label));
1.1.1.4 ! root 4244: /* If flag_force_addr were to affect this address
! 4245: it could interfere with the tricky assumptions made
! 4246: about addresses that contain label-refs,
! 4247: which may be valid only very near the tablejump itself. */
! 4248: index = memory_address_noforce
! 4249: (CASE_VECTOR_MODE,
! 4250: gen_rtx (PLUS, Pmode,
! 4251: gen_rtx (MULT, Pmode, index,
! 4252: gen_rtx (CONST_INT, VOIDmode,
! 4253: GET_MODE_SIZE (CASE_VECTOR_MODE))),
! 4254: gen_rtx (LABEL_REF, VOIDmode, table_label)));
1.1 root 4255: temp = gen_reg_rtx (CASE_VECTOR_MODE);
4256: convert_move (temp, gen_rtx (MEM, CASE_VECTOR_MODE, index), 0);
4257:
1.1.1.2 root 4258: emit_jump_insn (gen_tablejump (temp, table_label));
1.1 root 4259: }
4260:
1.1.1.2 root 4261: #endif /* HAVE_tablejump */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.