Import final gcc2 snapshot (990109)
[official-gcc.git] / gcc / config / ns32k / ns32k.c
blob0d2d2ef343a7eef11c3c0cc9fac6df652f9d1e42
1 /* Subroutines for assembler code output on the NS32000.
2 Copyright (C) 1988, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
4 This file is part of GNU CC.
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 #include "config.h"
22 #include "system.h"
23 #include "rtl.h"
24 #include "regs.h"
25 #include "hard-reg-set.h"
26 #include "real.h"
27 #include "insn-config.h"
28 #include "conditions.h"
29 #include "insn-flags.h"
30 #include "output.h"
31 #include "insn-attr.h"
33 #ifdef OSF_OS
34 int ns32k_num_files = 0;
35 #endif
37 void
38 trace (s, s1, s2)
39 char *s, *s1, *s2;
41 fprintf (stderr, s, s1, s2);
44 /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */
46 int
47 hard_regno_mode_ok (regno, mode)
48 int regno;
49 enum machine_mode mode;
51 switch (mode)
53 case QImode:
54 case HImode:
55 case PSImode:
56 case SImode:
57 case PDImode:
58 case VOIDmode:
59 case BLKmode:
60 if (regno < 8 || regno == 16 || regno == 17)
61 return 1;
62 else
63 return 0;
65 case DImode:
66 if (regno < 8 && (regno & 1) == 0)
67 return 1;
68 else
69 return 0;
71 case SFmode:
72 case SCmode:
73 if (TARGET_32081)
75 if (regno < 16)
76 return 1;
77 else
78 return 0;
80 else
82 if (regno < 8)
83 return 1;
84 else
85 return 0;
88 case DFmode:
89 case DCmode:
90 if ((regno & 1) == 0)
92 if (TARGET_32081)
94 if (regno < 16)
95 return 1;
96 else
97 return 0;
99 else
101 if (regno < 8)
102 return 1;
103 else
104 return 0;
107 else
108 return 0;
111 /* Used to abort here, but simply saying "no" handles TImode
112 much better. */
113 return 0;
116 /* ADDRESS_COST calls this. This function is not optimal
117 for the 32032 & 32332, but it probably is better than
118 the default. */
121 calc_address_cost (operand)
122 rtx operand;
124 int i;
125 int cost = 0;
127 if (GET_CODE (operand) == MEM)
128 cost += 3;
129 if (GET_CODE (operand) == MULT)
130 cost += 2;
131 #if 0
132 if (GET_CODE (operand) == REG)
133 cost += 1; /* not really, but the documentation
134 says different amount of registers
135 shouldn't return the same costs */
136 #endif
137 switch (GET_CODE (operand))
139 case REG:
140 case CONST:
141 case CONST_INT:
142 case CONST_DOUBLE:
143 case SYMBOL_REF:
144 case LABEL_REF:
145 case POST_DEC:
146 case PRE_DEC:
147 break;
148 case MULT:
149 case MEM:
150 case PLUS:
151 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (operand)); i++)
153 cost += calc_address_cost (XEXP (operand, i));
155 default:
156 break;
158 return cost;
161 /* Return the register class of a scratch register needed to copy IN into
162 or out of a register in CLASS in MODE. If it can be done directly,
163 NO_REGS is returned. */
165 enum reg_class
166 secondary_reload_class (class, mode, in)
167 enum reg_class class;
168 enum machine_mode mode;
169 rtx in;
171 int regno = true_regnum (in);
173 if (regno >= FIRST_PSEUDO_REGISTER)
174 regno = -1;
176 /* We can place anything into GENERAL_REGS and can put GENERAL_REGS
177 into anything. */
178 if (class == GENERAL_REGS || (regno >= 0 && regno < 8))
179 return NO_REGS;
181 /* Constants, memory, and FP registers can go into FP registers. */
182 if ((regno == -1 || (regno >= 8 && regno < 16)) && (class == FLOAT_REGS))
183 return NO_REGS;
185 #if 0 /* This isn't strictly true (can't move fp to sp or vice versa),
186 so it's cleaner to use PREFERRED_RELOAD_CLASS
187 to make the right things happen. */
188 if (regno >= 16 && class == GEN_AND_MEM_REGS)
189 return NO_REGS;
190 #endif
192 /* Otherwise, we need GENERAL_REGS. */
193 return GENERAL_REGS;
195 /* Generate the rtx that comes from an address expression in the md file */
196 /* The expression to be build is BASE[INDEX:SCALE]. To recognize this,
197 scale must be converted from an exponent (from ASHIFT) to a
198 multiplier (for MULT). */
200 gen_indexed_expr (base, index, scale)
201 rtx base, index, scale;
203 rtx addr;
205 /* This generates an invalid addressing mode, if BASE is
206 fp or sp. This is handled by PRINT_OPERAND_ADDRESS. */
207 if (GET_CODE (base) != REG && GET_CODE (base) != CONST_INT)
208 base = gen_rtx_MEM (SImode, base);
209 addr = gen_rtx_MULT (SImode, index,
210 GEN_INT (1 << INTVAL (scale)));
211 addr = gen_rtx_PLUS (SImode, base, addr);
212 return addr;
215 /* Return 1 if OP is a valid operand of mode MODE. This
216 predicate rejects operands which do not have a mode
217 (such as CONST_INT which are VOIDmode). */
219 reg_or_mem_operand (op, mode)
220 register rtx op;
221 enum machine_mode mode;
223 return (GET_MODE (op) == mode
224 && (GET_CODE (op) == REG
225 || GET_CODE (op) == SUBREG
226 || GET_CODE (op) == MEM));
229 /* Split one or more DImode RTL references into pairs of SImode
230 references. The RTL can be REG, offsettable MEM, integer constant, or
231 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
232 split and "num" is its length. lo_half and hi_half are output arrays
233 that parallel "operands". */
235 void
236 split_di (operands, num, lo_half, hi_half)
237 rtx operands[];
238 int num;
239 rtx lo_half[], hi_half[];
241 while (num--)
243 if (GET_CODE (operands[num]) == REG)
245 lo_half[num] = gen_rtx_REG (SImode, REGNO (operands[num]));
246 hi_half[num] = gen_rtx_REG (SImode, REGNO (operands[num]) + 1);
248 else if (CONSTANT_P (operands[num]))
250 split_double (operands[num], &lo_half[num], &hi_half[num]);
252 else if (offsettable_memref_p (operands[num]))
254 lo_half[num] = operands[num];
255 hi_half[num] = adj_offsettable_operand (operands[num], 4);
257 else
258 abort();
262 /* Return the best assembler insn template
263 for moving operands[1] into operands[0] as a fullword. */
265 static char *
266 singlemove_string (operands)
267 rtx *operands;
269 if (GET_CODE (operands[1]) == CONST_INT
270 && INTVAL (operands[1]) <= 7
271 && INTVAL (operands[1]) >= -8)
272 return "movqd %1,%0";
273 return "movd %1,%0";
276 char *
277 output_move_double (operands)
278 rtx *operands;
280 enum anon1 { REGOP, OFFSOP, PUSHOP, CNSTOP, RNDOP } optype0, optype1;
281 rtx latehalf[2];
283 /* First classify both operands. */
285 if (REG_P (operands[0]))
286 optype0 = REGOP;
287 else if (offsettable_memref_p (operands[0]))
288 optype0 = OFFSOP;
289 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
290 optype0 = PUSHOP;
291 else
292 optype0 = RNDOP;
294 if (REG_P (operands[1]))
295 optype1 = REGOP;
296 else if (CONSTANT_P (operands[1])
297 || GET_CODE (operands[1]) == CONST_DOUBLE)
298 optype1 = CNSTOP;
299 else if (offsettable_memref_p (operands[1]))
300 optype1 = OFFSOP;
301 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
302 optype1 = PUSHOP;
303 else
304 optype1 = RNDOP;
306 /* Check for the cases that the operand constraints are not
307 supposed to allow to happen. Abort if we get one,
308 because generating code for these cases is painful. */
310 if (optype0 == RNDOP || optype1 == RNDOP)
311 abort ();
313 /* Ok, we can do one word at a time.
314 Normally we do the low-numbered word first,
315 but if either operand is autodecrementing then we
316 do the high-numbered word first.
318 In either case, set up in LATEHALF the operands to use
319 for the high-numbered word and in some cases alter the
320 operands in OPERANDS to be suitable for the low-numbered word. */
322 if (optype0 == REGOP)
323 latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
324 else if (optype0 == OFFSOP)
325 latehalf[0] = adj_offsettable_operand (operands[0], 4);
326 else
327 latehalf[0] = operands[0];
329 if (optype1 == REGOP)
330 latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
331 else if (optype1 == OFFSOP)
332 latehalf[1] = adj_offsettable_operand (operands[1], 4);
333 else if (optype1 == CNSTOP)
334 split_double (operands[1], &operands[1], &latehalf[1]);
335 else
336 latehalf[1] = operands[1];
338 /* If insn is effectively movd N(sp),tos then we will do the
339 high word first. We should use the adjusted operand 1 (which is N+4(sp))
340 for the low word as well, to compensate for the first decrement of sp.
341 Given this, it doesn't matter which half we do "first". */
342 if (optype0 == PUSHOP
343 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
344 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
345 operands[1] = latehalf[1];
347 /* If one or both operands autodecrementing,
348 do the two words, high-numbered first. */
349 else if (optype0 == PUSHOP || optype1 == PUSHOP)
351 output_asm_insn (singlemove_string (latehalf), latehalf);
352 return singlemove_string (operands);
355 /* If the first move would clobber the source of the second one,
356 do them in the other order. */
358 /* Overlapping registers. */
359 if (optype0 == REGOP && optype1 == REGOP
360 && REGNO (operands[0]) == REGNO (latehalf[1]))
362 /* Do that word. */
363 output_asm_insn (singlemove_string (latehalf), latehalf);
364 /* Do low-numbered word. */
365 return singlemove_string (operands);
367 /* Loading into a register which overlaps a register used in the address. */
368 else if (optype0 == REGOP && optype1 != REGOP
369 && reg_overlap_mentioned_p (operands[0], operands[1]))
371 if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))
372 && reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
374 /* If both halves of dest are used in the src memory address,
375 load the destination address into the low reg (operands[0]).
376 Then it works to load latehalf first. */
377 rtx xops[2];
378 xops[0] = XEXP (operands[1], 0);
379 xops[1] = operands[0];
380 output_asm_insn ("addr %a0,%1", xops);
381 operands[1] = gen_rtx_MEM (DImode, operands[0]);
382 latehalf[1] = adj_offsettable_operand (operands[1], 4);
383 /* The first half has the overlap, Do the late half first. */
384 output_asm_insn (singlemove_string (latehalf), latehalf);
385 /* Then clobber. */
386 return singlemove_string (operands);
388 if (reg_mentioned_p (operands[0], XEXP (operands[1], 0)))
390 /* The first half has the overlap, Do the late half first. */
391 output_asm_insn (singlemove_string (latehalf), latehalf);
392 /* Then clobber. */
393 return singlemove_string (operands);
397 /* Normal case. Do the two words, low-numbered first. */
399 output_asm_insn (singlemove_string (operands), operands);
401 operands[0] = latehalf[0];
402 operands[1] = latehalf[1];
403 return singlemove_string (operands);
407 check_reg (oper, reg)
408 rtx oper;
409 int reg;
411 register int i;
413 if (oper == 0)
414 return 0;
415 switch (GET_CODE(oper))
417 case REG:
418 return (REGNO(oper) == reg) ? 1 : 0;
419 case MEM:
420 return check_reg(XEXP(oper, 0), reg);
421 case PLUS:
422 case MULT:
423 return check_reg(XEXP(oper, 0), reg) || check_reg(XEXP(oper, 1), reg);
425 return 0;
428 /* Returns 1 if OP contains a global symbol reference */
431 global_symbolic_reference_mentioned_p (op, f)
432 rtx op;
433 int f;
435 register char *fmt;
436 register int i;
438 if (GET_CODE (op) == SYMBOL_REF)
440 if (! SYMBOL_REF_FLAG (op))
441 return 1;
442 else
443 return 0;
445 else if (f && GET_CODE (op) != CONST)
446 return 0;
448 fmt = GET_RTX_FORMAT (GET_CODE (op));
449 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
451 if (fmt[i] == 'E')
453 register int j;
455 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
456 if (global_symbolic_reference_mentioned_p (XVECEXP (op, i, j), 0))
457 return 1;
459 else if (fmt[i] == 'e'
460 && global_symbolic_reference_mentioned_p (XEXP (op, i), 0))
461 return 1;
464 return 0;
468 /* PRINT_OPERAND is defined to call this function,
469 which is easier to debug than putting all the code in
470 a macro definition in ns32k.h. */
472 void
473 print_operand (file, x, code)
474 FILE *file;
475 rtx x;
476 char code;
478 if (code == '$')
479 PUT_IMMEDIATE_PREFIX (file);
480 else if (code == '?')
481 PUT_EXTERNAL_PREFIX (file);
482 else if (GET_CODE (x) == REG)
483 fprintf (file, "%s", reg_names[REGNO (x)]);
484 else if (GET_CODE (x) == MEM)
486 rtx tmp = XEXP (x, 0);
487 output_address (XEXP (x, 0));
489 else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != VOIDmode)
491 if (GET_MODE (x) == DFmode)
493 union { double d; int i[2]; } u;
494 u.i[0] = CONST_DOUBLE_LOW (x); u.i[1] = CONST_DOUBLE_HIGH (x);
495 PUT_IMMEDIATE_PREFIX(file);
496 #ifdef SEQUENT_ASM
497 /* Sequent likes its floating point constants as integers */
498 fprintf (file, "0Dx%08x%08x", u.i[1], u.i[0]);
499 #else
500 #ifdef ENCORE_ASM
501 fprintf (file, "0f%.20e", u.d);
502 #else
503 fprintf (file, "0d%.20e", u.d);
504 #endif
505 #endif
507 else
509 union { double d; int i[2]; } u;
510 u.i[0] = CONST_DOUBLE_LOW (x); u.i[1] = CONST_DOUBLE_HIGH (x);
511 PUT_IMMEDIATE_PREFIX (file);
512 #ifdef SEQUENT_ASM
513 /* We have no way of winning if we can't get the bits
514 for a sequent floating point number. */
515 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
516 abort ();
517 #endif
519 union { float f; long l; } uu;
520 uu.f = u.d;
521 fprintf (file, "0Fx%08x", uu.l);
523 #else
524 fprintf (file, "0f%.20e", u.d);
525 #endif
528 else
530 #ifdef NO_IMMEDIATE_PREFIX_IF_SYMBOLIC
531 if (GET_CODE (x) == CONST_INT)
532 #endif
533 PUT_IMMEDIATE_PREFIX (file);
534 output_addr_const (file, x);
538 /* PRINT_OPERAND_ADDRESS is defined to call this function,
539 which is easier to debug than putting all the code in
540 a macro definition in ns32k.h . */
542 /* Completely rewritten to get this to work with Gas for PC532 Mach.
543 This function didn't work and I just wasn't able (nor very willing) to
544 figure out how it worked.
545 90-11-25 Tatu Yl|nen <ylo@cs.hut.fi> */
547 print_operand_address (file, addr)
548 register FILE *file;
549 register rtx addr;
551 static char scales[] = { 'b', 'w', 'd', 0, 'q', };
552 rtx offset, base, indexexp, tmp;
553 int scale;
554 extern int flag_pic;
556 if (GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == POST_DEC)
558 fprintf (file, "tos");
559 return;
562 offset = NULL;
563 base = NULL;
564 indexexp = NULL;
565 while (addr != NULL)
567 if (GET_CODE (addr) == PLUS)
569 if (GET_CODE (XEXP (addr, 0)) == PLUS)
571 tmp = XEXP (addr, 1);
572 addr = XEXP (addr, 0);
574 else
576 tmp = XEXP (addr,0);
577 addr = XEXP (addr,1);
580 else
582 tmp = addr;
583 addr = NULL;
585 switch (GET_CODE (tmp))
587 case PLUS:
588 abort ();
589 case MEM:
590 if (base)
592 indexexp = base;
593 base = tmp;
595 else
596 base = tmp;
597 break;
598 case REG:
599 if (REGNO (tmp) < 8)
600 if (base)
602 indexexp = tmp;
604 else
605 base = tmp;
606 else
607 if (base)
609 indexexp = base;
610 base = tmp;
612 else
613 base = tmp;
614 break;
615 case MULT:
616 indexexp = tmp;
617 break;
618 case SYMBOL_REF:
619 if (flag_pic && ! CONSTANT_POOL_ADDRESS_P (tmp)
620 && ! SYMBOL_REF_FLAG (tmp))
622 if (base)
624 if (indexexp)
625 abort ();
626 indexexp = base;
628 base = tmp;
629 break;
631 case CONST:
632 if (flag_pic && GET_CODE (tmp) == CONST)
634 rtx sym, off, tmp1;
635 tmp1 = XEXP (tmp,0);
636 if (GET_CODE (tmp1) != PLUS)
637 abort ();
639 sym = XEXP (tmp1,0);
640 if (GET_CODE (sym) != SYMBOL_REF)
642 off = sym;
643 sym = XEXP (tmp1,1);
645 else
646 off = XEXP (tmp1,1);
647 if (GET_CODE (sym) == SYMBOL_REF)
649 if (GET_CODE (off) != CONST_INT)
650 abort ();
652 if (CONSTANT_POOL_ADDRESS_P (sym)
653 || SYMBOL_REF_FLAG (sym))
655 SYMBOL_REF_FLAG (tmp) = 1;
657 else
659 if (base)
661 if (indexexp)
662 abort ();
664 indexexp = base;
667 if (offset != 0)
668 abort ();
670 base = sym;
671 offset = off;
672 break;
676 case CONST_INT:
677 case LABEL_REF:
678 if (offset)
679 offset = gen_rtx_PLUS (SImode, tmp, offset);
680 else
681 offset = tmp;
682 break;
683 default:
684 abort ();
687 if (! offset)
688 offset = const0_rtx;
690 if (base
691 #ifndef INDEX_RATHER_THAN_BASE
692 && (flag_pic || TARGET_HIMEM)
693 && GET_CODE (base) != SYMBOL_REF
694 && GET_CODE (offset) != CONST_INT
695 #else
696 /* This is a re-implementation of the SEQUENT_ADDRESS_BUG fix. */
697 #endif
698 && !indexexp && GET_CODE (base) == REG
699 && REG_OK_FOR_INDEX_P (base))
701 indexexp = base;
702 base = NULL;
705 /* now, offset, base and indexexp are set */
706 #ifndef BASE_REG_NEEDED
707 if (! base)
709 #if defined (PC_RELATIVE) || defined (NO_ABSOLUTE_PREFIX_IF_SYMBOLIC)
710 if (GET_CODE (offset) == CONST_INT)
711 #endif
712 PUT_ABSOLUTE_PREFIX (file);
714 #endif
716 output_addr_const (file, offset);
717 if (base) /* base can be (REG ...) or (MEM ...) */
718 switch (GET_CODE (base))
720 /* now we must output base. Possible alternatives are:
721 (rN) (REG ...)
722 (sp) (REG ...)
723 (fp) (REG ...)
724 (pc) (REG ...) used for SYMBOL_REF and LABEL_REF, output
725 (disp(fp)) (MEM ...) just before possible [rX:y]
726 (disp(sp)) (MEM ...)
727 (disp(sb)) (MEM ...)
729 case REG:
730 fprintf (file, "(%s)", reg_names[REGNO (base)]);
731 break;
732 case SYMBOL_REF:
733 if (! flag_pic)
734 abort ();
736 fprintf (file, "(");
737 output_addr_const (file, base);
738 fprintf (file, "(sb))");
739 break;
740 case MEM:
741 addr = XEXP(base,0);
742 base = NULL;
743 offset = NULL;
744 while (addr != NULL)
746 if (GET_CODE (addr) == PLUS)
748 if (GET_CODE (XEXP (addr, 0)) == PLUS)
750 tmp = XEXP (addr, 1);
751 addr = XEXP (addr, 0);
753 else
755 tmp = XEXP (addr, 0);
756 addr = XEXP (addr, 1);
759 else
761 tmp = addr;
762 addr = NULL;
764 switch (GET_CODE (tmp))
766 case REG:
767 base = tmp;
768 break;
769 case CONST:
770 case CONST_INT:
771 case SYMBOL_REF:
772 case LABEL_REF:
773 if (offset)
774 offset = gen_rtx_PLUS (SImode, tmp, offset);
775 else
776 offset = tmp;
777 break;
778 default:
779 abort ();
782 if (! offset)
783 offset = const0_rtx;
784 fprintf (file, "(");
785 output_addr_const (file, offset);
786 if (base)
787 fprintf (file, "(%s)", reg_names[REGNO (base)]);
788 else if (TARGET_SB)
789 fprintf (file, "(sb)");
790 else
791 abort ();
792 fprintf (file, ")");
793 break;
794 default:
795 abort ();
797 #ifdef PC_RELATIVE
798 else if (GET_CODE (offset) != CONST_INT)
799 fprintf (file, "(pc)");
800 #ifdef BASE_REG_NEEDED
801 else if (TARGET_SB)
802 fprintf (file, "(sb)");
803 else
804 abort ();
805 #endif
806 #endif /* PC_RELATIVE */
808 /* now print index if we have one */
809 if (indexexp)
811 if (GET_CODE (indexexp) == MULT)
813 scale = INTVAL (XEXP (indexexp, 1)) >> 1;
814 indexexp = XEXP (indexexp, 0);
816 else
817 scale = 0;
818 if (GET_CODE (indexexp) != REG || REGNO (indexexp) >= 8)
819 abort ();
821 #ifdef UTEK_ASM
822 fprintf (file, "[%c`%s]",
823 scales[scale],
824 reg_names[REGNO (indexexp)]);
825 #else
826 fprintf (file, "[%s:%c]",
827 reg_names[REGNO (indexexp)],
828 scales[scale]);
829 #endif
833 /* National 32032 shifting is so bad that we can get
834 better performance in many common cases by using other
835 techniques. */
836 char *
837 output_shift_insn (operands)
838 rtx *operands;
840 if (GET_CODE (operands[2]) == CONST_INT
841 && INTVAL (operands[2]) > 0
842 && INTVAL (operands[2]) <= 3)
843 if (GET_CODE (operands[0]) == REG)
845 if (GET_CODE (operands[1]) == REG)
847 if (REGNO (operands[0]) == REGNO (operands[1]))
849 if (operands[2] == const1_rtx)
850 return "addd %0,%0";
851 else if (INTVAL (operands[2]) == 2)
852 return "addd %0,%0\n\taddd %0,%0";
854 if (operands[2] == const1_rtx)
855 return "movd %1,%0\n\taddd %0,%0";
857 operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
858 return "addr %a1,%0";
860 if (operands[2] == const1_rtx)
861 return "movd %1,%0\n\taddd %0,%0";
863 else if (GET_CODE (operands[1]) == REG)
865 operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
866 return "addr %a1,%0";
868 else if (INTVAL (operands[2]) == 1
869 && GET_CODE (operands[1]) == MEM
870 && rtx_equal_p (operands [0], operands[1]))
872 rtx temp = XEXP (operands[1], 0);
874 if (GET_CODE (temp) == REG
875 || (GET_CODE (temp) == PLUS
876 && GET_CODE (XEXP (temp, 0)) == REG
877 && GET_CODE (XEXP (temp, 1)) == CONST_INT))
878 return "addd %0,%0";
880 else return "ashd %2,%0";
881 return "ashd %2,%0";
884 char *
885 output_move_dconst (n, s)
886 int n;
887 char *s;
889 static char r[32];
891 if (n > -9 && n < 8)
892 strcpy (r, "movqd ");
893 else if (n > 0 && n < 256)
894 strcpy (r, "movzbd ");
895 else if (n > 0 && n < 65536)
896 strcpy (r, "movzwd ");
897 else if (n < 0 && n > -129)
898 strcpy (r, "movxbd ");
899 else if (n < 0 && n > -32769)
900 strcpy (r, "movxwd ");
901 else
902 strcpy (r, "movd ");
903 strcat (r, s);
904 return r;