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