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