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