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