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