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