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