|
|
1.1 root 1: /* Subroutines for insn-output.c for Intel 80386.
2: Copyright (C) 1988, 1992 Free Software Foundation, Inc.
3:
4: This file is part of GNU CC.
5:
6: GNU CC is free software; you can redistribute it and/or modify
7: it under the terms of the GNU General Public License as published by
8: the Free Software Foundation; either version 2, or (at your option)
9: any later version.
10:
11: GNU CC is distributed in the hope that it will be useful,
12: but WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14: GNU General Public License for more details.
15:
16: You should have received a copy of the GNU General Public License
17: along with GNU CC; see the file COPYING. If not, write to
18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19:
20: #include <stdio.h>
21: #include <setjmp.h>
22: #include "config.h"
23: #include "rtl.h"
24: #include "regs.h"
25: #include "hard-reg-set.h"
26: #include "real.h"
27: #include "insn-config.h"
28: #include "conditions.h"
29: #include "insn-flags.h"
30: #include "output.h"
31: #include "insn-attr.h"
32: #include "tree.h"
33: #include "flags.h"
34:
35: #ifdef EXTRA_CONSTRAINT
36: /* If EXTRA_CONSTRAINT is defined, then the 'S'
37: constraint in REG_CLASS_FROM_LETTER will no longer work, and various
38: asm statements that need 'S' for class SIREG will break. */
39: error EXTRA_CONSTRAINT conflicts with S constraint letter
40: /* The previous line used to be #error, but some compilers barf
41: even if the conditional was untrue. */
42: #endif
43:
44: #define AT_BP(mode) (gen_rtx (MEM, (mode), frame_pointer_rtx))
45:
46: extern FILE *asm_out_file;
47: extern char *strcat ();
48:
49: char *singlemove_string ();
50: char *output_move_const_single ();
51: char *output_fp_cc0_set ();
52:
53: char *hi_reg_name[] = HI_REGISTER_NAMES;
54: char *qi_reg_name[] = QI_REGISTER_NAMES;
55: char *qi_high_reg_name[] = QI_HIGH_REGISTER_NAMES;
56:
57: /* Array of the smallest class containing reg number REGNO, indexed by
58: REGNO. Used by REGNO_REG_CLASS in i386.h. */
59:
60: enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] =
61: {
62: /* ax, dx, cx, bx */
63: AREG, DREG, CREG, BREG,
64: /* si, di, bp, sp */
65: SIREG, DIREG, INDEX_REGS, GENERAL_REGS,
66: /* FP registers */
67: FP_TOP_REG, FP_SECOND_REG, FLOAT_REGS, FLOAT_REGS,
68: FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, FLOAT_REGS,
69: /* arg pointer */
70: INDEX_REGS
71: };
72:
73: /* Test and compare insns in i386.md store the information needed to
74: generate branch and scc insns here. */
75:
76: struct rtx_def *i386_compare_op0, *i386_compare_op1;
77: struct rtx_def *(*i386_compare_gen)(), *(*i386_compare_gen_eq)();
78:
79: /* Output an insn whose source is a 386 integer register. SRC is the
80: rtx for the register, and TEMPLATE is the op-code template. SRC may
81: be either SImode or DImode.
82:
83: The template will be output with operands[0] as SRC, and operands[1]
84: as a pointer to the top of the 386 stack. So a call from floatsidf2
85: would look like this:
86:
87: output_op_from_reg (operands[1], AS1 (fild%z0,%1));
88:
89: where %z0 corresponds to the caller's operands[1], and is used to
90: emit the proper size suffix.
91:
92: ??? Extend this to handle HImode - a 387 can load and store HImode
93: values directly. */
94:
95: void
96: output_op_from_reg (src, template)
97: rtx src;
98: char *template;
99: {
100: rtx xops[4];
101:
102: xops[0] = src;
103: xops[1] = AT_SP (Pmode);
104: xops[2] = GEN_INT (GET_MODE_SIZE (GET_MODE (src)));
105: xops[3] = stack_pointer_rtx;
106:
107: if (GET_MODE_SIZE (GET_MODE (src)) > UNITS_PER_WORD)
108: {
109: rtx high = gen_rtx (REG, SImode, REGNO (src) + 1);
110: output_asm_insn (AS1 (push%L0,%0), &high);
111: }
112: output_asm_insn (AS1 (push%L0,%0), &src);
113:
114: output_asm_insn (template, xops);
115:
116: output_asm_insn (AS2 (add%L3,%2,%3), xops);
117: }
118:
119: /* Output an insn to pop an value from the 387 top-of-stack to 386
120: register DEST. The 387 register stack is popped if DIES is true. If
121: the mode of DEST is an integer mode, a `fist' integer store is done,
122: otherwise a `fst' float store is done. */
123:
124: void
125: output_to_reg (dest, dies)
126: rtx dest;
127: int dies;
128: {
129: rtx xops[4];
130:
131: xops[0] = AT_SP (Pmode);
132: xops[1] = stack_pointer_rtx;
133: xops[2] = GEN_INT (GET_MODE_SIZE (GET_MODE (dest)));
134: xops[3] = dest;
135:
136: output_asm_insn (AS2 (sub%L1,%2,%1), xops);
137:
138: if (GET_MODE_CLASS (GET_MODE (dest)) == MODE_INT)
139: {
140: if (dies)
141: output_asm_insn (AS1 (fistp%z3,%y0), xops);
142: else
143: output_asm_insn (AS1 (fist%z3,%y0), xops);
144: }
145: else if (GET_MODE_CLASS (GET_MODE (dest)) == MODE_FLOAT)
146: {
147: if (dies)
148: output_asm_insn (AS1 (fstp%z3,%y0), xops);
149: else
150: output_asm_insn (AS1 (fst%z3,%y0), xops);
151: }
152: else
153: abort ();
154:
155: output_asm_insn (AS1 (pop%L0,%0), &dest);
156:
157: if (GET_MODE_SIZE (GET_MODE (dest)) > UNITS_PER_WORD)
158: {
159: dest = gen_rtx (REG, SImode, REGNO (dest) + 1);
160: output_asm_insn (AS1 (pop%L0,%0), &dest);
161: }
162: }
163:
164: char *
165: singlemove_string (operands)
166: rtx *operands;
167: {
168: rtx x;
169: if (GET_CODE (operands[0]) == MEM
170: && GET_CODE (x = XEXP (operands[0], 0)) == PRE_DEC)
171: {
172: if (XEXP (x, 0) != stack_pointer_rtx)
173: abort ();
174: return "push%L1 %1";
175: }
176: else if (GET_CODE (operands[1]) == CONST_DOUBLE)
177: {
178: return output_move_const_single (operands);
179: }
180: else if (GET_CODE (operands[0]) == REG || GET_CODE (operands[1]) == REG)
181: return AS2 (mov%L0,%1,%0);
182: else if (CONSTANT_P (operands[1]))
183: return AS2 (mov%L0,%1,%0);
184: else
185: {
186: output_asm_insn ("push%L1 %1", operands);
187: return "pop%L0 %0";
188: }
189: }
190:
191: /* Return a REG that occurs in ADDR with coefficient 1.
192: ADDR can be effectively incremented by incrementing REG. */
193:
194: static rtx
195: find_addr_reg (addr)
196: rtx addr;
197: {
198: while (GET_CODE (addr) == PLUS)
199: {
200: if (GET_CODE (XEXP (addr, 0)) == REG)
201: addr = XEXP (addr, 0);
202: else if (GET_CODE (XEXP (addr, 1)) == REG)
203: addr = XEXP (addr, 1);
204: else if (CONSTANT_P (XEXP (addr, 0)))
205: addr = XEXP (addr, 1);
206: else if (CONSTANT_P (XEXP (addr, 1)))
207: addr = XEXP (addr, 0);
208: else
209: abort ();
210: }
211: if (GET_CODE (addr) == REG)
212: return addr;
213: abort ();
214: }
215:
216: /* Output an insn to add the constant N to the register X. */
217:
218: static void
219: asm_add (n, x)
220: int n;
221: rtx x;
222: {
223: rtx xops[2];
224: xops[1] = x;
225: if (n < 0)
226: {
227: xops[0] = GEN_INT (-n);
228: output_asm_insn (AS2 (sub%L0,%0,%1), xops);
229: }
230: else if (n > 0)
231: {
232: xops[0] = GEN_INT (n);
233: output_asm_insn (AS2 (add%L0,%0,%1), xops);
234: }
235: }
236:
237: /* Output assembler code to perform a doubleword move insn
238: with operands OPERANDS. */
239:
240: char *
241: output_move_double (operands)
242: rtx *operands;
243: {
244: enum {REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
245: rtx latehalf[2];
246: rtx addreg0 = 0, addreg1 = 0;
247: int dest_overlapped_low = 0;
248:
249: /* First classify both operands. */
250:
251: if (REG_P (operands[0]))
252: optype0 = REGOP;
253: else if (offsettable_memref_p (operands[0]))
254: optype0 = OFFSOP;
255: else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
256: optype0 = POPOP;
257: else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
258: optype0 = PUSHOP;
259: else if (GET_CODE (operands[0]) == MEM)
260: optype0 = MEMOP;
261: else
262: optype0 = RNDOP;
263:
264: if (REG_P (operands[1]))
265: optype1 = REGOP;
266: else if (CONSTANT_P (operands[1]))
267: optype1 = CNSTOP;
268: else if (offsettable_memref_p (operands[1]))
269: optype1 = OFFSOP;
270: else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
271: optype1 = POPOP;
272: else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
273: optype1 = PUSHOP;
274: else if (GET_CODE (operands[1]) == MEM)
275: optype1 = MEMOP;
276: else
277: optype1 = RNDOP;
278:
279: /* Check for the cases that the operand constraints are not
280: supposed to allow to happen. Abort if we get one,
281: because generating code for these cases is painful. */
282:
283: if (optype0 == RNDOP || optype1 == RNDOP)
284: abort ();
285:
286: /* If one operand is decrementing and one is incrementing
287: decrement the former register explicitly
288: and change that operand into ordinary indexing. */
289:
290: if (optype0 == PUSHOP && optype1 == POPOP)
291: {
292: operands[0] = XEXP (XEXP (operands[0], 0), 0);
293: asm_add (-8, operands[0]);
294: operands[0] = gen_rtx (MEM, DImode, operands[0]);
295: optype0 = OFFSOP;
296: }
297: if (optype0 == POPOP && optype1 == PUSHOP)
298: {
299: operands[1] = XEXP (XEXP (operands[1], 0), 0);
300: asm_add (-8, operands[1]);
301: operands[1] = gen_rtx (MEM, DImode, operands[1]);
302: optype1 = OFFSOP;
303: }
304:
305: /* If an operand is an unoffsettable memory ref, find a register
306: we can increment temporarily to make it refer to the second word. */
307:
308: if (optype0 == MEMOP)
309: addreg0 = find_addr_reg (XEXP (operands[0], 0));
310:
311: if (optype1 == MEMOP)
312: addreg1 = find_addr_reg (XEXP (operands[1], 0));
313:
314: /* Ok, we can do one word at a time.
315: Normally we do the low-numbered word first,
316: but if either operand is autodecrementing then we
317: do the high-numbered word first.
318:
319: In either case, set up in LATEHALF the operands to use
320: for the high-numbered word and in some cases alter the
321: operands in OPERANDS to be suitable for the low-numbered word. */
322:
323: if (optype0 == REGOP)
324: latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
325: else if (optype0 == OFFSOP)
326: latehalf[0] = adj_offsettable_operand (operands[0], 4);
327: else
328: latehalf[0] = operands[0];
329:
330: if (optype1 == REGOP)
331: latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
332: else if (optype1 == OFFSOP)
333: latehalf[1] = adj_offsettable_operand (operands[1], 4);
334: else if (optype1 == CNSTOP)
335: {
336: if (GET_CODE (operands[1]) == CONST_DOUBLE)
337: split_double (operands[1], &operands[1], &latehalf[1]);
338: else if (CONSTANT_P (operands[1]))
339: {
340: if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 0)
341: latehalf[1] = constm1_rtx;
342: else
343: latehalf[1] = const0_rtx;
344: }
345: }
346: else
347: latehalf[1] = operands[1];
348:
349: /* If insn is effectively movd N (sp),-(sp) then we will do the
350: high word first. We should use the adjusted operand 1 (which is N+4 (sp))
351: for the low word as well, to compensate for the first decrement of sp. */
352: if (optype0 == PUSHOP
353: && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
354: && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
355: operands[1] = latehalf[1];
356:
357: /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)),
358: if the upper part of reg N does not appear in the MEM, arrange to
359: emit the move late-half first. Otherwise, compute the MEM address
360: into the upper part of N and use that as a pointer to the memory
361: operand. */
362: if (optype0 == REGOP
363: && (optype1 == OFFSOP || optype1 == MEMOP))
364: {
365: if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))
366: && reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
367: {
368: /* If both halves of dest are used in the src memory address,
369: compute the address into latehalf of dest. */
370: rtx xops[2];
371: xops[0] = latehalf[0];
372: xops[1] = XEXP (operands[1], 0);
373: output_asm_insn (AS2 (lea%L0,%a1,%0), xops);
374: operands[1] = gen_rtx (MEM, DImode, latehalf[0]);
375: latehalf[1] = adj_offsettable_operand (operands[1], 4);
376: }
377: else if (reg_mentioned_p (operands[0], XEXP (operands[1], 0)))
378: /* If the low half of dest is mentioned in the source memory
379: address, the arrange to emit the move late half first. */
380: dest_overlapped_low = 1;
381: }
382:
383: /* If one or both operands autodecrementing,
384: do the two words, high-numbered first. */
385:
386: /* Likewise, the first move would clobber the source of the second one,
387: do them in the other order. This happens only for registers;
388: such overlap can't happen in memory unless the user explicitly
389: sets it up, and that is an undefined circumstance. */
390:
391: if (optype0 == PUSHOP || optype1 == PUSHOP
392: || (optype0 == REGOP && optype1 == REGOP
393: && REGNO (operands[0]) == REGNO (latehalf[1]))
394: || dest_overlapped_low)
395: {
396: /* Make any unoffsettable addresses point at high-numbered word. */
397: if (addreg0)
398: asm_add (4, addreg0);
399: if (addreg1)
400: asm_add (4, addreg1);
401:
402: /* Do that word. */
403: output_asm_insn (singlemove_string (latehalf), latehalf);
404:
405: /* Undo the adds we just did. */
406: if (addreg0)
407: asm_add (-4, addreg0);
408: if (addreg1)
409: asm_add (-4, addreg1);
410:
411: /* Do low-numbered word. */
412: return singlemove_string (operands);
413: }
414:
415: /* Normal case: do the two words, low-numbered first. */
416:
417: output_asm_insn (singlemove_string (operands), operands);
418:
419: /* Make any unoffsettable addresses point at high-numbered word. */
420: if (addreg0)
421: asm_add (4, addreg0);
422: if (addreg1)
423: asm_add (4, addreg1);
424:
425: /* Do that word. */
426: output_asm_insn (singlemove_string (latehalf), latehalf);
427:
428: /* Undo the adds we just did. */
429: if (addreg0)
430: asm_add (-4, addreg0);
431: if (addreg1)
432: asm_add (-4, addreg1);
433:
434: return "";
435: }
436:
437: int
438: standard_80387_constant_p (x)
439: rtx x;
440: {
441: #if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
442: REAL_VALUE_TYPE d;
443: jmp_buf handler;
444: int is0, is1;
445:
446: if (setjmp (handler))
447: return 0;
448:
449: set_float_handler (handler);
450: REAL_VALUE_FROM_CONST_DOUBLE (d, x);
451: is0 = REAL_VALUES_EQUAL (d, dconst0);
452: is1 = REAL_VALUES_EQUAL (d, dconst1);
453: set_float_handler (NULL_PTR);
454:
455: if (is0)
456: return 1;
457:
458: if (is1)
459: return 2;
460:
461: /* Note that on the 80387, other constants, such as pi,
462: are much slower to load as standard constants
463: than to load from doubles in memory! */
464: #endif
465:
466: return 0;
467: }
468:
469: char *
470: output_move_const_single (operands)
471: rtx *operands;
472: {
473: if (FP_REG_P (operands[0]))
474: {
475: int conval = standard_80387_constant_p (operands[1]);
476:
477: if (conval == 1)
478: return "fldz";
479:
480: if (conval == 2)
481: return "fld1";
482: }
483: if (GET_CODE (operands[1]) == CONST_DOUBLE)
484: {
485: union { int i[2]; double d;} u1;
486: union { int i; float f;} u2;
487: u1.i[0] = CONST_DOUBLE_LOW (operands[1]);
488: u1.i[1] = CONST_DOUBLE_HIGH (operands[1]);
489: u2.f = u1.d;
490: operands[1] = GEN_INT (u2.i);
491: }
492: return singlemove_string (operands);
493: }
494:
495: /* Returns 1 if OP is either a symbol reference or a sum of a symbol
496: reference and a constant. */
497:
498: int
499: symbolic_operand (op, mode)
500: register rtx op;
501: enum machine_mode mode;
502: {
503: switch (GET_CODE (op))
504: {
505: case SYMBOL_REF:
506: case LABEL_REF:
507: return 1;
508: case CONST:
509: op = XEXP (op, 0);
510: return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
511: || GET_CODE (XEXP (op, 0)) == LABEL_REF)
512: && GET_CODE (XEXP (op, 1)) == CONST_INT);
513: default:
514: return 0;
515: }
516: }
517:
518: /* Test for a valid operand for a call instruction.
519: Don't allow the arg pointer register or virtual regs
520: since they may change into reg + const, which the patterns
521: can't handle yet. */
522:
523: int
524: call_insn_operand (op, mode)
525: rtx op;
526: enum machine_mode mode;
527: {
528: if (GET_CODE (op) == MEM
529: && ((CONSTANT_ADDRESS_P (XEXP (op, 0))
530: /* This makes a difference for PIC. */
531: && general_operand (XEXP (op, 0), Pmode))
532: || (GET_CODE (XEXP (op, 0)) == REG
533: && XEXP (op, 0) != arg_pointer_rtx
534: && !(REGNO (XEXP (op, 0)) >= FIRST_PSEUDO_REGISTER
535: && REGNO (XEXP (op, 0)) <= LAST_VIRTUAL_REGISTER))))
536: return 1;
537: return 0;
538: }
539:
540: /* Like call_insn_operand but allow (mem (symbol_ref ...))
541: even if pic. */
542:
543: int
544: expander_call_insn_operand (op, mode)
545: rtx op;
546: enum machine_mode mode;
547: {
548: if (GET_CODE (op) == MEM
549: && (CONSTANT_ADDRESS_P (XEXP (op, 0))
550: || (GET_CODE (XEXP (op, 0)) == REG
551: && XEXP (op, 0) != arg_pointer_rtx
552: && !(REGNO (XEXP (op, 0)) >= FIRST_PSEUDO_REGISTER
553: && REGNO (XEXP (op, 0)) <= LAST_VIRTUAL_REGISTER))))
554: return 1;
555: return 0;
556: }
557:
558: /* Returns 1 if OP contains a symbol reference */
559:
560: int
561: symbolic_reference_mentioned_p (op)
562: rtx op;
563: {
564: register char *fmt;
565: register int i;
566:
567: if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
568: return 1;
569:
570: fmt = GET_RTX_FORMAT (GET_CODE (op));
571: for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
572: {
573: if (fmt[i] == 'E')
574: {
575: register int j;
576:
577: for (j = XVECLEN (op, i) - 1; j >= 0; j--)
578: if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
579: return 1;
580: }
581: else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
582: return 1;
583: }
584:
585: return 0;
586: }
587:
588: /* Return a legitimate reference for ORIG (an address) using the
589: register REG. If REG is 0, a new pseudo is generated.
590:
591: There are three types of references that must be handled:
592:
593: 1. Global data references must load the address from the GOT, via
594: the PIC reg. An insn is emitted to do this load, and the reg is
595: returned.
596:
597: 2. Static data references must compute the address as an offset
598: from the GOT, whose base is in the PIC reg. An insn is emitted to
599: compute the address into a reg, and the reg is returned. Static
600: data objects have SYMBOL_REF_FLAG set to differentiate them from
601: global data objects.
602:
603: 3. Constant pool addresses must be handled special. They are
604: considered legitimate addresses, but only if not used with regs.
605: When printed, the output routines know to print the reference with the
606: PIC reg, even though the PIC reg doesn't appear in the RTL.
607:
608: GO_IF_LEGITIMATE_ADDRESS rejects symbolic references unless the PIC
609: reg also appears in the address (except for constant pool references,
610: noted above).
611:
612: "switch" statements also require special handling when generating
613: PIC code. See comments by the `casesi' insn in i386.md for details. */
614:
615: rtx
616: legitimize_pic_address (orig, reg)
617: rtx orig;
618: rtx reg;
619: {
620: rtx addr = orig;
621: rtx new = orig;
622:
623: if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
624: {
625: if (GET_CODE (addr) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (addr))
626: reg = new = orig;
627: else
628: {
629: if (reg == 0)
630: reg = gen_reg_rtx (Pmode);
631:
632: if (GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FLAG (addr))
633: new = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, orig);
634: else
635: new = gen_rtx (MEM, Pmode,
636: gen_rtx (PLUS, Pmode,
637: pic_offset_table_rtx, orig));
638:
639: emit_move_insn (reg, new);
640: }
641: current_function_uses_pic_offset_table = 1;
642: return reg;
643: }
644: else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
645: {
646: rtx base;
647:
648: if (GET_CODE (addr) == CONST)
649: {
650: addr = XEXP (addr, 0);
651: if (GET_CODE (addr) != PLUS)
652: abort ();
653: }
654:
655: if (XEXP (addr, 0) == pic_offset_table_rtx)
656: return orig;
657:
658: if (reg == 0)
659: reg = gen_reg_rtx (Pmode);
660:
661: base = legitimize_pic_address (XEXP (addr, 0), reg);
662: addr = legitimize_pic_address (XEXP (addr, 1),
663: base == reg ? NULL_RTX : reg);
664:
665: if (GET_CODE (addr) == CONST_INT)
666: return plus_constant (base, INTVAL (addr));
667:
668: if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
669: {
670: base = gen_rtx (PLUS, Pmode, base, XEXP (addr, 0));
671: addr = XEXP (addr, 1);
672: }
673: return gen_rtx (PLUS, Pmode, base, addr);
674: }
675: return new;
676: }
677:
678: /* Emit insns to move operands[1] into operands[0]. */
679:
680: void
681: emit_pic_move (operands, mode)
682: rtx *operands;
683: enum machine_mode mode;
684: {
685: rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
686:
687: if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
688: operands[1] = (rtx) force_reg (SImode, operands[1]);
689: else
690: operands[1] = legitimize_pic_address (operands[1], temp);
691: }
692:
693: /* This function generates the assembly code for function entry.
694: FILE is an stdio stream to output the code to.
695: SIZE is an int: how many units of temporary storage to allocate. */
696:
697: void
698: function_prologue (file, size)
699: FILE *file;
700: int size;
701: {
702: register int regno;
703: int limit;
704: rtx xops[4];
705: int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
706: || current_function_uses_const_pool);
707:
708: xops[0] = stack_pointer_rtx;
709: xops[1] = frame_pointer_rtx;
710: xops[2] = GEN_INT (size);
711: if (frame_pointer_needed)
712: {
713: output_asm_insn ("push%L1 %1", xops);
714: output_asm_insn (AS2 (mov%L0,%0,%1), xops);
715: }
716:
717: if (size)
718: output_asm_insn (AS2 (sub%L0,%2,%0), xops);
719:
720: /* Note If use enter it is NOT reversed args.
721: This one is not reversed from intel!!
722: I think enter is slower. Also sdb doesn't like it.
723: But if you want it the code is:
724: {
725: xops[3] = const0_rtx;
726: output_asm_insn ("enter %2,%3", xops);
727: }
728: */
729: limit = (frame_pointer_needed ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
730: for (regno = limit - 1; regno >= 0; regno--)
731: if ((regs_ever_live[regno] && ! call_used_regs[regno])
732: || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
733: {
734: xops[0] = gen_rtx (REG, SImode, regno);
735: output_asm_insn ("push%L0 %0", xops);
736: }
737:
738: if (pic_reg_used)
739: {
740: xops[0] = pic_offset_table_rtx;
741: xops[1] = (rtx) gen_label_rtx ();
742:
743: output_asm_insn (AS1 (call,%P1), xops);
744: ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (xops[1]));
745: output_asm_insn (AS1 (pop%L0,%0), xops);
746: output_asm_insn ("addl $_GLOBAL_OFFSET_TABLE_+[.-%P1],%0", xops);
747: }
748: }
749:
750: /* Return 1 if it is appropriate to emit `ret' instructions in the
751: body of a function. Do this only if the epilogue is simple, needing a
752: couple of insns. Prior to reloading, we can't tell how many registers
753: must be saved, so return 0 then.
754:
755: If NON_SAVING_SETJMP is defined and true, then it is not possible
756: for the epilogue to be simple, so return 0. This is a special case
757: since NON_SAVING_SETJMP will not cause regs_ever_live to change until
758: final, but jump_optimize may need to know sooner if a `return' is OK. */
759:
760: int
761: simple_386_epilogue ()
762: {
763: int regno;
764: int nregs = 0;
765: int reglimit = (frame_pointer_needed
766: ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
767: int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
768: || current_function_uses_const_pool);
769:
770: #ifdef NON_SAVING_SETJMP
771: if (NON_SAVING_SETJMP && current_function_calls_setjmp)
772: return 0;
773: #endif
774:
775: if (! reload_completed)
776: return 0;
777:
778: for (regno = reglimit - 1; regno >= 0; regno--)
779: if ((regs_ever_live[regno] && ! call_used_regs[regno])
780: || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
781: nregs++;
782:
783: return nregs == 0 || ! frame_pointer_needed;
784: }
785:
786: /* This function generates the assembly code for function exit.
787: FILE is an stdio stream to output the code to.
788: SIZE is an int: how many units of temporary storage to deallocate. */
789:
790: void
791: function_epilogue (file, size)
792: FILE *file;
793: int size;
794: {
795: register int regno;
796: register int nregs, limit;
797: int offset;
798: rtx xops[3];
799: int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
800: || current_function_uses_const_pool);
801:
802: /* Compute the number of registers to pop */
803:
804: limit = (frame_pointer_needed
805: ? FRAME_POINTER_REGNUM
806: : STACK_POINTER_REGNUM);
807:
808: nregs = 0;
809:
810: for (regno = limit - 1; regno >= 0; regno--)
811: if ((regs_ever_live[regno] && ! call_used_regs[regno])
812: || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
813: nregs++;
814:
815: /* sp is often unreliable so we must go off the frame pointer,
816: */
817:
818: /* In reality, we may not care if sp is unreliable, because we can
819: restore the register relative to the frame pointer. In theory,
820: since each move is the same speed as a pop, and we don't need the
821: leal, this is faster. For now restore multiple registers the old
822: way. */
823:
824: offset = -size - (nregs * UNITS_PER_WORD);
825:
826: xops[2] = stack_pointer_rtx;
827:
828: if (nregs > 1 || ! frame_pointer_needed)
829: {
830: if (frame_pointer_needed)
831: {
832: xops[0] = adj_offsettable_operand (AT_BP (Pmode), offset);
833: output_asm_insn (AS2 (lea%L2,%0,%2), xops);
834: }
835:
836: for (regno = 0; regno < limit; regno++)
837: if ((regs_ever_live[regno] && ! call_used_regs[regno])
838: || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
839: {
840: xops[0] = gen_rtx (REG, SImode, regno);
841: output_asm_insn ("pop%L0 %0", xops);
842: }
843: }
844: else
845: for (regno = 0; regno < limit; regno++)
846: if ((regs_ever_live[regno] && ! call_used_regs[regno])
847: || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
848: {
849: xops[0] = gen_rtx (REG, SImode, regno);
850: xops[1] = adj_offsettable_operand (AT_BP (Pmode), offset);
851: output_asm_insn (AS2 (mov%L0,%1,%0), xops);
852: offset += 4;
853: }
854:
855: if (frame_pointer_needed)
856: {
857: /* On i486, mov & pop is faster than "leave". */
858:
859: if (TARGET_486)
860: {
861: xops[0] = frame_pointer_rtx;
862: output_asm_insn (AS2 (mov%L2,%0,%2), xops);
863: output_asm_insn ("pop%L0 %0", xops);
864: }
865: else
866: output_asm_insn ("leave", xops);
867: }
868: else if (size)
869: {
870: /* If there is no frame pointer, we must still release the frame. */
871:
872: xops[0] = GEN_INT (size);
873: output_asm_insn (AS2 (add%L2,%0,%2), xops);
874: }
875:
876: if (current_function_pops_args && current_function_args_size)
877: {
878: xops[1] = GEN_INT (current_function_pops_args);
879:
880: /* i386 can only pop 32K bytes (maybe 64K? Is it signed?). If
881: asked to pop more, pop return address, do explicit add, and jump
882: indirectly to the caller. */
883:
884: if (current_function_pops_args >= 32768)
885: {
886: /* ??? Which register to use here? */
887: xops[0] = gen_rtx (REG, SImode, 2);
888: output_asm_insn ("pop%L0 %0", xops);
889: output_asm_insn (AS2 (add%L2,%1,%2), xops);
890: output_asm_insn ("jmp %*%0", xops);
891: }
892: else
893: output_asm_insn ("ret %1", xops);
894: }
895: else
896: output_asm_insn ("ret", xops);
897: }
898:
899: /* Print an integer constant expression in assembler syntax. Addition
900: and subtraction are the only arithmetic that may appear in these
901: expressions. FILE is the stdio stream to write to, X is the rtx, and
902: CODE is the operand print code from the output string. */
903:
904: static void
905: output_pic_addr_const (file, x, code)
906: FILE *file;
907: rtx x;
908: int code;
909: {
910: char buf[256];
911:
912: switch (GET_CODE (x))
913: {
914: case PC:
915: if (flag_pic)
916: putc ('.', file);
917: else
918: abort ();
919: break;
920:
921: case SYMBOL_REF:
922: case LABEL_REF:
923: if (GET_CODE (x) == SYMBOL_REF)
924: assemble_name (file, XSTR (x, 0));
925: else
926: {
927: ASM_GENERATE_INTERNAL_LABEL (buf, "L",
928: CODE_LABEL_NUMBER (XEXP (x, 0)));
929: assemble_name (asm_out_file, buf);
930: }
931:
932: if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
933: fprintf (file, "@GOTOFF(%%ebx)");
934: else if (code == 'P')
935: fprintf (file, "@PLT");
936: else if (GET_CODE (x) == LABEL_REF || ! SYMBOL_REF_FLAG (x))
937: fprintf (file, "@GOT");
938: else
939: fprintf (file, "@GOTOFF");
940:
941: break;
942:
943: case CODE_LABEL:
944: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
945: assemble_name (asm_out_file, buf);
946: break;
947:
948: case CONST_INT:
949: fprintf (file, "%d", INTVAL (x));
950: break;
951:
952: case CONST:
953: /* This used to output parentheses around the expression,
954: but that does not work on the 386 (either ATT or BSD assembler). */
955: output_pic_addr_const (file, XEXP (x, 0), code);
956: break;
957:
958: case CONST_DOUBLE:
959: if (GET_MODE (x) == VOIDmode)
960: {
961: /* We can use %d if the number is <32 bits and positive. */
962: if (CONST_DOUBLE_HIGH (x) || CONST_DOUBLE_LOW (x) < 0)
963: fprintf (file, "0x%x%08x",
964: CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
965: else
966: fprintf (file, "%d", CONST_DOUBLE_LOW (x));
967: }
968: else
969: /* We can't handle floating point constants;
970: PRINT_OPERAND must handle them. */
971: output_operand_lossage ("floating constant misused");
972: break;
973:
974: case PLUS:
975: /* Some assemblers need integer constants to appear last (eg masm). */
976: if (GET_CODE (XEXP (x, 0)) == CONST_INT)
977: {
978: output_pic_addr_const (file, XEXP (x, 1), code);
979: if (INTVAL (XEXP (x, 0)) >= 0)
980: fprintf (file, "+");
981: output_pic_addr_const (file, XEXP (x, 0), code);
982: }
983: else
984: {
985: output_pic_addr_const (file, XEXP (x, 0), code);
986: if (INTVAL (XEXP (x, 1)) >= 0)
987: fprintf (file, "+");
988: output_pic_addr_const (file, XEXP (x, 1), code);
989: }
990: break;
991:
992: case MINUS:
993: output_pic_addr_const (file, XEXP (x, 0), code);
994: fprintf (file, "-");
995: output_pic_addr_const (file, XEXP (x, 1), code);
996: break;
997:
998: default:
999: output_operand_lossage ("invalid expression as operand");
1000: }
1001: }
1002:
1003: /* Meaning of CODE:
1004: f -- float insn (print a CONST_DOUBLE as a float rather than in hex).
1005: D,L,W,B,Q,S -- print the opcode suffix for specified size of operand.
1006: R -- print the prefix for register names.
1007: z -- print the opcode suffix for the size of the current operand.
1008: * -- print a star (in certain assembler syntax)
1009: w -- print the operand as if it's a "word" (HImode) even if it isn't.
1010: c -- don't print special prefixes before constant operands.
1011: */
1012:
1013: void
1014: print_operand (file, x, code)
1015: FILE *file;
1016: rtx x;
1017: int code;
1018: {
1019: if (code)
1020: {
1021: switch (code)
1022: {
1023: case '*':
1024: if (USE_STAR)
1025: putc ('*', file);
1026: return;
1027:
1028: case 'L':
1029: PUT_OP_SIZE (code, 'l', file);
1030: return;
1031:
1032: case 'W':
1033: PUT_OP_SIZE (code, 'w', file);
1034: return;
1035:
1036: case 'B':
1037: PUT_OP_SIZE (code, 'b', file);
1038: return;
1039:
1040: case 'Q':
1041: PUT_OP_SIZE (code, 'l', file);
1042: return;
1043:
1044: case 'S':
1045: PUT_OP_SIZE (code, 's', file);
1046: return;
1047:
1048: case 'z':
1049: /* 387 opcodes don't get size suffixes if the operands are
1050: registers. */
1051:
1052: if (STACK_REG_P (x))
1053: return;
1054:
1055: /* this is the size of op from size of operand */
1056: switch (GET_MODE_SIZE (GET_MODE (x)))
1057: {
1058: case 1:
1059: PUT_OP_SIZE ('B', 'b', file);
1060: return;
1061:
1062: case 2:
1063: PUT_OP_SIZE ('W', 'w', file);
1064: return;
1065:
1066: case 4:
1067: if (GET_MODE (x) == SFmode)
1068: {
1069: PUT_OP_SIZE ('S', 's', file);
1070: return;
1071: }
1072: else
1073: PUT_OP_SIZE ('L', 'l', file);
1074: return;
1075:
1076: case 8:
1077: if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
1078: {
1079: #ifdef GAS_MNEMONICS
1080: PUT_OP_SIZE ('Q', 'q', file);
1081: return;
1082: #else
1083: PUT_OP_SIZE ('Q', 'l', file); /* Fall through */
1084: #endif
1085: }
1086:
1087: PUT_OP_SIZE ('Q', 'l', file);
1088: return;
1089: }
1090:
1091: case 'b':
1092: case 'w':
1093: case 'k':
1094: case 'h':
1095: case 'y':
1096: case 'P':
1097: break;
1098:
1099: default:
1100: {
1101: char str[50];
1102:
1103: sprintf (str, "invalid operand code `%c'", code);
1104: output_operand_lossage (str);
1105: }
1106: }
1107: }
1108: if (GET_CODE (x) == REG)
1109: {
1110: PRINT_REG (x, code, file);
1111: }
1112: else if (GET_CODE (x) == MEM)
1113: {
1114: PRINT_PTR (x, file);
1115: if (CONSTANT_ADDRESS_P (XEXP (x, 0)))
1116: {
1117: if (flag_pic)
1118: output_pic_addr_const (file, XEXP (x, 0), code);
1119: else
1120: output_addr_const (file, XEXP (x, 0));
1121: }
1122: else
1123: output_address (XEXP (x, 0));
1124: }
1125: else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode)
1126: {
1127: union { double d; int i[2]; } u;
1128: union { float f; int i; } u1;
1129: u.i[0] = CONST_DOUBLE_LOW (x);
1130: u.i[1] = CONST_DOUBLE_HIGH (x);
1131: u1.f = u.d;
1132: PRINT_IMMED_PREFIX (file);
1133: fprintf (file, "0x%x", u1.i);
1134: }
1135: else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)
1136: {
1137: union { double d; int i[2]; } u;
1138: u.i[0] = CONST_DOUBLE_LOW (x);
1139: u.i[1] = CONST_DOUBLE_HIGH (x);
1140: fprintf (file, "%.22e", u.d);
1141: }
1142: else
1143: {
1144: if (code != 'P')
1145: {
1146: if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
1147: PRINT_IMMED_PREFIX (file);
1148: else if (GET_CODE (x) == CONST || GET_CODE (x) == SYMBOL_REF
1149: || GET_CODE (x) == LABEL_REF)
1150: PRINT_OFFSET_PREFIX (file);
1151: }
1152: if (flag_pic)
1153: output_pic_addr_const (file, x, code);
1154: else
1155: output_addr_const (file, x);
1156: }
1157: }
1158:
1159: /* Print a memory operand whose address is ADDR. */
1160:
1161: void
1162: print_operand_address (file, addr)
1163: FILE *file;
1164: register rtx addr;
1165: {
1166: register rtx reg1, reg2, breg, ireg;
1167: rtx offset;
1168:
1169: switch (GET_CODE (addr))
1170: {
1171: case REG:
1172: ADDR_BEG (file);
1173: fprintf (file, "%se", RP);
1174: fputs (hi_reg_name[REGNO (addr)], file);
1175: ADDR_END (file);
1176: break;
1177:
1178: case PLUS:
1179: reg1 = 0;
1180: reg2 = 0;
1181: ireg = 0;
1182: breg = 0;
1183: offset = 0;
1184: if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
1185: {
1186: offset = XEXP (addr, 0);
1187: addr = XEXP (addr, 1);
1188: }
1189: else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
1190: {
1191: offset = XEXP (addr, 1);
1192: addr = XEXP (addr, 0);
1193: }
1194: if (GET_CODE (addr) != PLUS) ;
1195: else if (GET_CODE (XEXP (addr, 0)) == MULT)
1196: {
1197: reg1 = XEXP (addr, 0);
1198: addr = XEXP (addr, 1);
1199: }
1200: else if (GET_CODE (XEXP (addr, 1)) == MULT)
1201: {
1202: reg1 = XEXP (addr, 1);
1203: addr = XEXP (addr, 0);
1204: }
1205: else if (GET_CODE (XEXP (addr, 0)) == REG)
1206: {
1207: reg1 = XEXP (addr, 0);
1208: addr = XEXP (addr, 1);
1209: }
1210: else if (GET_CODE (XEXP (addr, 1)) == REG)
1211: {
1212: reg1 = XEXP (addr, 1);
1213: addr = XEXP (addr, 0);
1214: }
1215: if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
1216: {
1217: if (reg1 == 0) reg1 = addr;
1218: else reg2 = addr;
1219: addr = 0;
1220: }
1221: if (offset != 0)
1222: {
1223: if (addr != 0) abort ();
1224: addr = offset;
1225: }
1226: if ((reg1 && GET_CODE (reg1) == MULT)
1227: || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
1228: {
1229: breg = reg2;
1230: ireg = reg1;
1231: }
1232: else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
1233: {
1234: breg = reg1;
1235: ireg = reg2;
1236: }
1237:
1238: if (ireg != 0 || breg != 0)
1239: {
1240: int scale = 1;
1241:
1242: if (addr != 0)
1243: {
1244: if (GET_CODE (addr) == LABEL_REF)
1245: output_asm_label (addr);
1246: else
1247: {
1248: if (flag_pic)
1249: output_pic_addr_const (file, addr, 0);
1250: else
1251: output_addr_const (file, addr);
1252: }
1253: }
1254:
1255: if (ireg != 0 && GET_CODE (ireg) == MULT)
1256: {
1257: scale = INTVAL (XEXP (ireg, 1));
1258: ireg = XEXP (ireg, 0);
1259: }
1260:
1261: /* The stack pointer can only appear as a base register,
1262: never an index register, so exchange the regs if it is wrong. */
1263:
1264: if (scale == 1 && ireg && REGNO (ireg) == STACK_POINTER_REGNUM)
1265: {
1266: rtx tmp;
1267:
1268: tmp = breg;
1269: breg = ireg;
1270: ireg = tmp;
1271: }
1272:
1273: /* output breg+ireg*scale */
1274: PRINT_B_I_S (breg, ireg, scale, file);
1275: break;
1276: }
1277:
1278: case MULT:
1279: {
1280: int scale;
1281: if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
1282: {
1283: scale = INTVAL (XEXP (addr, 0));
1284: ireg = XEXP (addr, 1);
1285: }
1286: else
1287: {
1288: scale = INTVAL (XEXP (addr, 1));
1289: ireg = XEXP (addr, 0);
1290: }
1291: output_addr_const (file, const0_rtx);
1292: PRINT_B_I_S ((rtx) 0, ireg, scale, file);
1293: }
1294: break;
1295:
1296: default:
1297: if (GET_CODE (addr) == CONST_INT
1298: && INTVAL (addr) < 0x8000
1299: && INTVAL (addr) >= -0x8000)
1300: fprintf (file, "%d", INTVAL (addr));
1301: else
1302: {
1303: if (flag_pic)
1304: output_pic_addr_const (file, addr, 0);
1305: else
1306: output_addr_const (file, addr);
1307: }
1308: }
1309: }
1310:
1311: /* Set the cc_status for the results of an insn whose pattern is EXP.
1312: On the 80386, we assume that only test and compare insns, as well
1313: as SI, HI, & DI mode ADD, SUB, NEG, AND, IOR, XOR, ASHIFT, LSHIFT,
1314: ASHIFTRT, and LSHIFTRT instructions set the condition codes usefully.
1315: Also, we assume that jumps, moves and sCOND don't affect the condition
1316: codes. All else clobbers the condition codes, by assumption.
1317:
1318: We assume that ALL integer add, minus, etc. instructions effect the
1319: condition codes. This MUST be consistent with i386.md.
1320:
1321: We don't record any float test or compare - the redundant test &
1322: compare check in final.c does not handle stack-like regs correctly. */
1323:
1324: void
1325: notice_update_cc (exp)
1326: rtx exp;
1327: {
1328: if (GET_CODE (exp) == SET)
1329: {
1330: /* Jumps do not alter the cc's. */
1331: if (SET_DEST (exp) == pc_rtx)
1332: return;
1333: /* Moving register or memory into a register:
1334: it doesn't alter the cc's, but it might invalidate
1335: the RTX's which we remember the cc's came from.
1336: (Note that moving a constant 0 or 1 MAY set the cc's). */
1337: if (REG_P (SET_DEST (exp))
1338: && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM
1339: || GET_RTX_CLASS (GET_CODE (SET_SRC (exp))) == '<'))
1340: {
1341: if (cc_status.value1
1342: && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1))
1343: cc_status.value1 = 0;
1344: if (cc_status.value2
1345: && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2))
1346: cc_status.value2 = 0;
1347: return;
1348: }
1349: /* Moving register into memory doesn't alter the cc's.
1350: It may invalidate the RTX's which we remember the cc's came from. */
1351: if (GET_CODE (SET_DEST (exp)) == MEM
1352: && (REG_P (SET_SRC (exp))
1353: || GET_RTX_CLASS (GET_CODE (SET_SRC (exp))) == '<'))
1354: {
1355: if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM)
1356: cc_status.value1 = 0;
1357: if (cc_status.value2 && GET_CODE (cc_status.value2) == MEM)
1358: cc_status.value2 = 0;
1359: return;
1360: }
1361: /* Function calls clobber the cc's. */
1362: else if (GET_CODE (SET_SRC (exp)) == CALL)
1363: {
1364: CC_STATUS_INIT;
1365: return;
1366: }
1367: /* Tests and compares set the cc's in predictable ways. */
1368: else if (SET_DEST (exp) == cc0_rtx)
1369: {
1370: CC_STATUS_INIT;
1371: cc_status.value1 = SET_SRC (exp);
1372: return;
1373: }
1374: /* Certain instructions effect the condition codes. */
1375: else if (GET_MODE (SET_SRC (exp)) == SImode
1376: || GET_MODE (SET_SRC (exp)) == HImode
1377: || GET_MODE (SET_SRC (exp)) == QImode)
1378: switch (GET_CODE (SET_SRC (exp)))
1379: {
1380: case ASHIFTRT: case LSHIFTRT:
1381: case ASHIFT: case LSHIFT:
1382: /* Shifts on the 386 don't set the condition codes if the
1383: shift count is zero. */
1384: if (GET_CODE (XEXP (SET_SRC (exp), 1)) != CONST_INT)
1385: {
1386: CC_STATUS_INIT;
1387: break;
1388: }
1389: /* We assume that the CONST_INT is non-zero (this rtx would
1390: have been deleted if it were zero. */
1391:
1392: case PLUS: case MINUS: case NEG:
1393: case AND: case IOR: case XOR:
1394: cc_status.flags = CC_NO_OVERFLOW;
1395: cc_status.value1 = SET_SRC (exp);
1396: cc_status.value2 = SET_DEST (exp);
1397: break;
1398:
1399: default:
1400: CC_STATUS_INIT;
1401: }
1402: else
1403: {
1404: CC_STATUS_INIT;
1405: }
1406: }
1407: else if (GET_CODE (exp) == PARALLEL
1408: && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
1409: {
1410: if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx)
1411: return;
1412: if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx)
1413: {
1414: CC_STATUS_INIT;
1415: if (stack_regs_mentioned_p (SET_SRC (XVECEXP (exp, 0, 0))))
1416: cc_status.flags |= CC_IN_80387;
1417: else
1418: cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0));
1419: return;
1420: }
1421: CC_STATUS_INIT;
1422: }
1423: else
1424: {
1425: CC_STATUS_INIT;
1426: }
1427: }
1428:
1429: /* Split one or more DImode RTL references into pairs of SImode
1430: references. The RTL can be REG, offsettable MEM, integer constant, or
1431: CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
1432: split and "num" is its length. lo_half and hi_half are output arrays
1433: that parallel "operands". */
1434:
1435: void
1436: split_di (operands, num, lo_half, hi_half)
1437: rtx operands[];
1438: int num;
1439: rtx lo_half[], hi_half[];
1440: {
1441: while (num--)
1442: {
1443: if (GET_CODE (operands[num]) == REG)
1444: {
1445: lo_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]));
1446: hi_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]) + 1);
1447: }
1448: else if (CONSTANT_P (operands[num]))
1449: {
1450: split_double (operands[num], &lo_half[num], &hi_half[num]);
1451: }
1452: else if (offsettable_memref_p (operands[num]))
1453: {
1454: lo_half[num] = operands[num];
1455: hi_half[num] = adj_offsettable_operand (operands[num], 4);
1456: }
1457: else
1458: abort();
1459: }
1460: }
1461:
1462: /* Return 1 if this is a valid binary operation on a 387.
1463: OP is the expression matched, and MODE is its mode. */
1464:
1465: int
1466: binary_387_op (op, mode)
1467: register rtx op;
1468: enum machine_mode mode;
1469: {
1470: if (mode != VOIDmode && mode != GET_MODE (op))
1471: return 0;
1472:
1473: switch (GET_CODE (op))
1474: {
1475: case PLUS:
1476: case MINUS:
1477: case MULT:
1478: case DIV:
1479: return GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT;
1480:
1481: default:
1482: return 0;
1483: }
1484: }
1485:
1486: /* Return 1 if this is a valid conversion operation on a 387.
1487: OP is the expression matched, and MODE is its mode. */
1488:
1489: int
1490: convert_387_op (op, mode)
1491: register rtx op;
1492: enum machine_mode mode;
1493: {
1494: if (mode != VOIDmode && mode != GET_MODE (op))
1495: return 0;
1496:
1497: switch (GET_CODE (op))
1498: {
1499: case FLOAT:
1500: return GET_MODE (XEXP (op, 0)) == SImode;
1501:
1502: case FLOAT_EXTEND:
1503: return mode == DFmode && GET_MODE (XEXP (op, 0)) == SFmode;
1504:
1505: default:
1506: return 0;
1507: }
1508: }
1509:
1510: /* Return 1 if this is a valid shift or rotate operation on a 386.
1511: OP is the expression matched, and MODE is its mode. */
1512:
1513: int
1514: shift_op (op, mode)
1515: register rtx op;
1516: enum machine_mode mode;
1517: {
1518: rtx operand = XEXP (op, 0);
1519:
1520: if (mode != VOIDmode && mode != GET_MODE (op))
1521: return 0;
1522:
1523: if (GET_MODE (operand) != GET_MODE (op)
1524: || GET_MODE_CLASS (GET_MODE (op)) != MODE_INT)
1525: return 0;
1526:
1527: return (GET_CODE (op) == ASHIFT
1528: || GET_CODE (op) == ASHIFTRT
1529: || GET_CODE (op) == LSHIFTRT
1530: || GET_CODE (op) == ROTATE
1531: || GET_CODE (op) == ROTATERT);
1532: }
1533:
1534: /* Return 1 if OP is COMPARE rtx with mode VOIDmode.
1535: MODE is not used. */
1536:
1537: int
1538: VOIDmode_compare_op (op, mode)
1539: register rtx op;
1540: enum machine_mode mode;
1541: {
1542: return GET_CODE (op) == COMPARE && GET_MODE (op) == VOIDmode;
1543: }
1544:
1545: /* Output code to perform a 387 binary operation in INSN, one of PLUS,
1546: MINUS, MULT or DIV. OPERANDS are the insn operands, where operands[3]
1547: is the expression of the binary operation. The output may either be
1548: emitted here, or returned to the caller, like all output_* functions.
1549:
1550: There is no guarantee that the operands are the same mode, as they
1551: might be within FLOAT or FLOAT_EXTEND expressions. */
1552:
1553: char *
1554: output_387_binary_op (insn, operands)
1555: rtx insn;
1556: rtx *operands;
1557: {
1558: rtx temp;
1559: char *base_op;
1560: static char buf[100];
1561:
1562: switch (GET_CODE (operands[3]))
1563: {
1564: case PLUS:
1565: if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
1566: || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
1567: base_op = "fiadd";
1568: else
1569: base_op = "fadd";
1570: break;
1571:
1572: case MINUS:
1573: if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
1574: || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
1575: base_op = "fisub";
1576: else
1577: base_op = "fsub";
1578: break;
1579:
1580: case MULT:
1581: if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
1582: || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
1583: base_op = "fimul";
1584: else
1585: base_op = "fmul";
1586: break;
1587:
1588: case DIV:
1589: if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
1590: || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
1591: base_op = "fidiv";
1592: else
1593: base_op = "fdiv";
1594: break;
1595:
1596: default:
1597: abort ();
1598: }
1599:
1600: strcpy (buf, base_op);
1601:
1602: switch (GET_CODE (operands[3]))
1603: {
1604: case MULT:
1605: case PLUS:
1606: if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2]))
1607: {
1608: temp = operands[2];
1609: operands[2] = operands[1];
1610: operands[1] = temp;
1611: }
1612:
1613: if (GET_CODE (operands[2]) == MEM)
1614: return strcat (buf, AS1 (%z2,%2));
1615:
1616: if (NON_STACK_REG_P (operands[1]))
1617: {
1618: output_op_from_reg (operands[1], strcat (buf, AS1 (%z0,%1)));
1619: RET;
1620: }
1621: else if (NON_STACK_REG_P (operands[2]))
1622: {
1623: output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1)));
1624: RET;
1625: }
1626:
1627: if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))
1628: return strcat (buf, AS2 (p,%2,%0));
1629:
1630: if (STACK_TOP_P (operands[0]))
1631: return strcat (buf, AS2 (,%y2,%0));
1632: else
1633: return strcat (buf, AS2 (,%2,%0));
1634:
1635: case MINUS:
1636: case DIV:
1637: if (GET_CODE (operands[1]) == MEM)
1638: return strcat (buf, AS1 (r%z1,%1));
1639:
1640: if (GET_CODE (operands[2]) == MEM)
1641: return strcat (buf, AS1 (%z2,%2));
1642:
1643: if (NON_STACK_REG_P (operands[1]))
1644: {
1645: output_op_from_reg (operands[1], strcat (buf, AS1 (r%z0,%1)));
1646: RET;
1647: }
1648: else if (NON_STACK_REG_P (operands[2]))
1649: {
1650: output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1)));
1651: RET;
1652: }
1653:
1654: if (! STACK_REG_P (operands[1]) || ! STACK_REG_P (operands[2]))
1655: abort ();
1656:
1657: if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))
1658: return strcat (buf, AS2 (rp,%2,%0));
1659:
1660: if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
1661: return strcat (buf, AS2 (p,%1,%0));
1662:
1663: if (STACK_TOP_P (operands[0]))
1664: {
1665: if (STACK_TOP_P (operands[1]))
1666: return strcat (buf, AS2 (,%y2,%0));
1667: else
1668: return strcat (buf, AS2 (r,%y1,%0));
1669: }
1670: else if (STACK_TOP_P (operands[1]))
1671: return strcat (buf, AS2 (,%1,%0));
1672: else
1673: return strcat (buf, AS2 (r,%2,%0));
1674:
1675: default:
1676: abort ();
1677: }
1678: }
1679:
1680: /* Output code for INSN to convert a float to a signed int. OPERANDS
1681: are the insn operands. The output may be SFmode or DFmode and the
1682: input operand may be SImode or DImode. As a special case, make sure
1683: that the 387 stack top dies if the output mode is DImode, because the
1684: hardware requires this. */
1685:
1686: char *
1687: output_fix_trunc (insn, operands)
1688: rtx insn;
1689: rtx *operands;
1690: {
1691: int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
1692: rtx xops[2];
1693:
1694: if (! STACK_TOP_P (operands[1]) ||
1695: (GET_MODE (operands[0]) == DImode && ! stack_top_dies))
1696: abort ();
1697:
1698: xops[0] = GEN_INT (12);
1699: xops[1] = operands[4];
1700:
1701: output_asm_insn (AS1 (fnstc%W2,%2), operands);
1702: output_asm_insn (AS2 (mov%L2,%2,%4), operands);
1703: output_asm_insn (AS2 (mov%B1,%0,%h1), xops);
1704: output_asm_insn (AS2 (mov%L4,%4,%3), operands);
1705: output_asm_insn (AS1 (fldc%W3,%3), operands);
1706:
1707: if (NON_STACK_REG_P (operands[0]))
1708: output_to_reg (operands[0], stack_top_dies);
1709: else if (GET_CODE (operands[0]) == MEM)
1710: {
1711: if (stack_top_dies)
1712: output_asm_insn (AS1 (fistp%z0,%0), operands);
1713: else
1714: output_asm_insn (AS1 (fist%z0,%0), operands);
1715: }
1716: else
1717: abort ();
1718:
1719: return AS1 (fldc%W2,%2);
1720: }
1721:
1722: /* Output code for INSN to compare OPERANDS. The two operands might
1723: not have the same mode: one might be within a FLOAT or FLOAT_EXTEND
1724: expression. If the compare is in mode CCFPEQmode, use an opcode that
1725: will not fault if a qNaN is present. */
1726:
1727: char *
1728: output_float_compare (insn, operands)
1729: rtx insn;
1730: rtx *operands;
1731: {
1732: int stack_top_dies;
1733: rtx body = XVECEXP (PATTERN (insn), 0, 0);
1734: int unordered_compare = GET_MODE (SET_SRC (body)) == CCFPEQmode;
1735:
1736: if (! STACK_TOP_P (operands[0]))
1737: abort ();
1738:
1739: stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
1740:
1741: if (STACK_REG_P (operands[1])
1742: && stack_top_dies
1743: && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))
1744: && REGNO (operands[1]) != FIRST_STACK_REG)
1745: {
1746: /* If both the top of the 387 stack dies, and the other operand
1747: is also a stack register that dies, then this must be a
1748: `fcompp' float compare */
1749:
1750: if (unordered_compare)
1751: output_asm_insn ("fucompp", operands);
1752: else
1753: output_asm_insn ("fcompp", operands);
1754: }
1755: else
1756: {
1757: static char buf[100];
1758:
1759: /* Decide if this is the integer or float compare opcode, or the
1760: unordered float compare. */
1761:
1762: if (unordered_compare)
1763: strcpy (buf, "fucom");
1764: else if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_FLOAT)
1765: strcpy (buf, "fcom");
1766: else
1767: strcpy (buf, "ficom");
1768:
1769: /* Modify the opcode if the 387 stack is to be popped. */
1770:
1771: if (stack_top_dies)
1772: strcat (buf, "p");
1773:
1774: if (NON_STACK_REG_P (operands[1]))
1775: output_op_from_reg (operands[1], strcat (buf, AS1 (%z0,%1)));
1776: else
1777: output_asm_insn (strcat (buf, AS1 (%z1,%y1)), operands);
1778: }
1779:
1780: /* Now retrieve the condition code. */
1781:
1782: return output_fp_cc0_set (insn);
1783: }
1784:
1785: /* Output opcodes to transfer the results of FP compare or test INSN
1786: from the FPU to the CPU flags. If TARGET_IEEE_FP, ensure that if the
1787: result of the compare or test is unordered, no comparison operator
1788: succeeds except NE. Return an output template, if any. */
1789:
1790: char *
1791: output_fp_cc0_set (insn)
1792: rtx insn;
1793: {
1794: rtx xops[3];
1795: rtx unordered_label;
1796: rtx next;
1797: enum rtx_code code;
1798:
1799: xops[0] = gen_rtx (REG, HImode, 0);
1800: output_asm_insn (AS1 (fnsts%W0,%0), xops);
1801:
1802: if (! TARGET_IEEE_FP)
1803: return "sahf";
1804:
1805: next = next_cc0_user (insn);
1806: if (next == NULL_RTX)
1807: abort ();
1808:
1809: if (GET_CODE (next) == JUMP_INSN
1810: && GET_CODE (PATTERN (next)) == SET
1811: && SET_DEST (PATTERN (next)) == pc_rtx
1812: && GET_CODE (SET_SRC (PATTERN (next))) == IF_THEN_ELSE)
1813: {
1814: code = GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0));
1815: }
1816: else if (GET_CODE (PATTERN (next)) == SET)
1817: {
1818: code = GET_CODE (SET_SRC (PATTERN (next)));
1819: }
1820: else
1821: abort ();
1822:
1823: xops[0] = gen_rtx (REG, QImode, 0);
1824:
1825: switch (code)
1826: {
1827: case GT:
1828: xops[1] = GEN_INT (0x45);
1829: output_asm_insn (AS2 (and%B0,%1,%h0), xops);
1830: /* je label */
1831: break;
1832:
1833: case LT:
1834: xops[1] = GEN_INT (0x45);
1835: xops[2] = GEN_INT (0x01);
1836: output_asm_insn (AS2 (and%B0,%1,%h0), xops);
1837: output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
1838: /* je label */
1839: break;
1840:
1841: case GE:
1842: xops[1] = GEN_INT (0x05);
1843: output_asm_insn (AS2 (and%B0,%1,%h0), xops);
1844: /* je label */
1845: break;
1846:
1847: case LE:
1848: xops[1] = GEN_INT (0x45);
1849: xops[2] = GEN_INT (0x40);
1850: output_asm_insn (AS2 (and%B0,%1,%h0), xops);
1851: output_asm_insn (AS1 (dec%B0,%h0), xops);
1852: output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
1853: /* jb label */
1854: break;
1855:
1856: case EQ:
1857: xops[1] = GEN_INT (0x45);
1858: xops[2] = GEN_INT (0x40);
1859: output_asm_insn (AS2 (and%B0,%1,%h0), xops);
1860: output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
1861: /* je label */
1862: break;
1863:
1864: case NE:
1865: xops[1] = GEN_INT (0x44);
1866: xops[2] = GEN_INT (0x40);
1867: output_asm_insn (AS2 (and%B0,%1,%h0), xops);
1868: output_asm_insn (AS2 (xor%B0,%2,%h0), xops);
1869: /* jne label */
1870: break;
1871:
1872: case GTU:
1873: case LTU:
1874: case GEU:
1875: case LEU:
1876: default:
1877: abort ();
1878: }
1879: RET;
1880: }
1881:
1882: #define MAX_386_STACK_LOCALS 2
1883:
1884: static rtx i386_stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS];
1885:
1886: /* Clear stack slot assignments remembered from previous functions.
1887: This is called from INIT_EXPANDERS once before RTL is emitted for each
1888: function. */
1889:
1890: void
1891: clear_386_stack_locals ()
1892: {
1893: enum machine_mode mode;
1894: int n;
1895:
1896: for (mode = VOIDmode; (int) mode < (int) MAX_MACHINE_MODE;
1897: mode = (enum machine_mode) ((int) mode + 1))
1898: for (n = 0; n < MAX_386_STACK_LOCALS; n++)
1899: i386_stack_locals[(int) mode][n] = NULL_RTX;
1900: }
1901:
1902: /* Return a MEM corresponding to a stack slot with mode MODE.
1903: Allocate a new slot if necessary.
1904:
1905: The RTL for a function can have several slots available: N is
1906: which slot to use. */
1907:
1908: rtx
1909: assign_386_stack_local (mode, n)
1910: enum machine_mode mode;
1911: int n;
1912: {
1913: if (n < 0 || n >= MAX_386_STACK_LOCALS)
1914: abort ();
1915:
1916: if (i386_stack_locals[(int) mode][n] == NULL_RTX)
1917: i386_stack_locals[(int) mode][n]
1918: = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
1919:
1920: return i386_stack_locals[(int) mode][n];
1921: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.