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