1 /* Subroutines for assembler code output on the NS32000.
2 Copyright (C) 1988, 94, 95, 96, 97, 98, 1999 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)
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. */
25 #include "hard-reg-set.h"
27 #include "insn-config.h"
28 #include "conditions.h"
29 #include "insn-flags.h"
31 #include "insn-attr.h"
38 int ns32k_num_files = 0;
41 /* This duplicates reg_class_contens in reg_class.c, but maybe that isn't
42 initialized in time. Also this is more convenient as an array of ints.
43 We know that HARD_REG_SET fits in an unsigned int */
45 unsigned int ns32k_reg_class_contents[N_REG_CLASSES] = REG_CLASS_CONTENTS;
47 enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] =
49 GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
50 GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
51 FLOAT_REG0, LONG_FLOAT_REG0, FLOAT_REGS, FLOAT_REGS,
52 FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, FLOAT_REGS,
53 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
54 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
55 FRAME_POINTER_REG, STACK_POINTER_REG
58 char *ns32k_out_reg_names[] = OUTPUT_REGISTER_NAMES;
64 fprintf (stderr, s, s1, s2);
68 /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */
70 hard_regno_mode_ok (regno, mode)
72 enum machine_mode mode;
74 int size = GET_MODE_UNIT_SIZE(mode);
76 if (FLOAT_MODE_P(mode))
78 if (size == UNITS_PER_WORD && regno < L1_REGNUM)
80 if (size == UNITS_PER_WORD * 2
81 && (((regno & 1) == 0 && regno < FRAME_POINTER_REGNUM)))
85 if (size == UNITS_PER_WORD * 2
86 && (regno & 1) == 0 && regno < F0_REGNUM)
88 if (size <= UNITS_PER_WORD
89 && (regno < F0_REGNUM || regno == FRAME_POINTER_REGNUM
90 || regno == STACK_POINTER_REGNUM))
95 int register_move_cost(CLASS1, CLASS2)
96 enum reg_class CLASS1;
97 enum reg_class CLASS2;
99 if (CLASS1 == NO_REGS || CLASS2 == NO_REGS)
101 if((SUBSET_P(CLASS1, FP_REGS) && !SUBSET_P(CLASS2, FP_REGS))
102 || (!SUBSET_P(CLASS1, FP_REGS) && SUBSET_P(CLASS2, FP_REGS)))
104 if (((CLASS1) == STACK_POINTER_REG && !SUBSET_P(CLASS2,GENERAL_REGS))
105 || ((CLASS2) == STACK_POINTER_REG && !SUBSET_P(CLASS1,GENERAL_REGS)))
107 if (((CLASS1) == FRAME_POINTER_REG && !SUBSET_P(CLASS2,GENERAL_REGS))
108 || ((CLASS2) == FRAME_POINTER_REG && !SUBSET_P(CLASS1,GENERAL_REGS)))
114 /* We made the insn definitions copy from floating point to general
115 registers via the stack. */
116 int secondary_memory_needed(CLASS1, CLASS2, M)
117 enum reg_class CLASS1;
118 enum reg_class CLASS2;
121 int ret = ((SUBSET_P(CLASS1, FP_REGS) && !SUBSET_P(CLASS2, FP_REGS))
122 || (!SUBSET_P(CLASS1, FP_REGS) && SUBSET_P(CLASS2, FP_REGS)));
128 /* ADDRESS_COST calls this. This function is not optimal
129 for the 32032 & 32332, but it probably is better than
133 calc_address_cost (operand)
139 if (GET_CODE (operand) == MEM)
141 if (GET_CODE (operand) == MULT)
144 if (GET_CODE (operand) == REG)
145 cost += 1; /* not really, but the documentation
146 says different amount of registers
147 shouldn't return the same costs */
149 switch (GET_CODE (operand))
161 cost += calc_address_cost (XEXP (operand, 0));
165 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (operand)); i++)
167 cost += calc_address_cost (XEXP (operand, i));
175 /* Return the register class of a scratch register needed to copy IN into
176 or out of a register in CLASS in MODE. If it can be done directly,
177 NO_REGS is returned. */
180 secondary_reload_class (class, mode, in)
181 enum reg_class class;
182 enum machine_mode mode;
185 int regno = true_regnum (in);
187 if (regno >= FIRST_PSEUDO_REGISTER)
190 if ((class == FRAME_POINTER_REG && regno == STACK_POINTER_REGNUM)
191 || ( class == STACK_POINTER_REG && regno == FRAME_POINTER_REGNUM))
197 /* Generate the rtx that comes from an address expression in the md file */
198 /* The expression to be build is BASE[INDEX:SCALE]. To recognize this,
199 scale must be converted from an exponent (from ASHIFT) to a
200 multiplier (for MULT). */
202 gen_indexed_expr (base, index, scale)
203 rtx base, index, scale;
207 /* This generates an invalid addressing mode, if BASE is
208 fp or sp. This is handled by PRINT_OPERAND_ADDRESS. */
209 if (GET_CODE (base) != REG && GET_CODE (base) != CONST_INT)
210 base = gen_rtx_MEM (SImode, base);
211 addr = gen_rtx_MULT (SImode, index,
212 GEN_INT (1 << INTVAL (scale)));
213 addr = gen_rtx_PLUS (SImode, base, addr);
217 /* Return 1 if OP is a valid operand of mode MODE. This
218 predicate rejects operands which do not have a mode
219 (such as CONST_INT which are VOIDmode). */
221 reg_or_mem_operand (op, mode)
223 enum machine_mode mode;
225 return (GET_MODE (op) == mode
226 && (GET_CODE (op) == REG
227 || GET_CODE (op) == SUBREG
228 || GET_CODE (op) == MEM));
232 /* Split one or more DImode RTL references into pairs of SImode
233 references. The RTL can be REG, offsettable MEM, integer constant, or
234 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
235 split and "num" is its length. lo_half and hi_half are output arrays
236 that parallel "operands". */
239 split_di (operands, num, lo_half, hi_half)
242 rtx lo_half[], hi_half[];
246 if (GET_CODE (operands[num]) == REG)
248 lo_half[num] = gen_rtx_REG (SImode, REGNO (operands[num]));
249 hi_half[num] = gen_rtx_REG (SImode, REGNO (operands[num]) + 1);
251 else if (CONSTANT_P (operands[num]))
253 split_double (operands[num], &lo_half[num], &hi_half[num]);
255 else if (offsettable_memref_p (operands[num]))
257 lo_half[num] = operands[num];
258 hi_half[num] = adj_offsettable_operand (operands[num], 4);
265 /* Return the best assembler insn template
266 for moving operands[1] into operands[0] as a fullword. */
269 singlemove_string (operands)
272 if (GET_CODE (operands[1]) == CONST_INT
273 && INTVAL (operands[1]) <= 7
274 && INTVAL (operands[1]) >= -8)
275 return "movqd %1,%0";
280 output_move_double (operands)
283 enum anon1 { REGOP, OFFSOP, PUSHOP, CNSTOP, RNDOP } optype0, optype1;
286 /* First classify both operands. */
288 if (REG_P (operands[0]))
290 else if (offsettable_memref_p (operands[0]))
292 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
297 if (REG_P (operands[1]))
299 else if (CONSTANT_P (operands[1])
300 || GET_CODE (operands[1]) == CONST_DOUBLE)
302 else if (offsettable_memref_p (operands[1]))
304 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
309 /* Check for the cases that the operand constraints are not
310 supposed to allow to happen. Abort if we get one,
311 because generating code for these cases is painful. */
313 if (optype0 == RNDOP || optype1 == RNDOP)
316 /* Ok, we can do one word at a time.
317 Normally we do the low-numbered word first,
318 but if either operand is autodecrementing then we
319 do the high-numbered word first.
321 In either case, set up in LATEHALF the operands to use
322 for the high-numbered word and in some cases alter the
323 operands in OPERANDS to be suitable for the low-numbered word. */
325 if (optype0 == REGOP)
326 latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
327 else if (optype0 == OFFSOP)
328 latehalf[0] = adj_offsettable_operand (operands[0], 4);
330 latehalf[0] = operands[0];
332 if (optype1 == REGOP)
333 latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
334 else if (optype1 == OFFSOP)
335 latehalf[1] = adj_offsettable_operand (operands[1], 4);
336 else if (optype1 == CNSTOP)
337 split_double (operands[1], &operands[1], &latehalf[1]);
339 latehalf[1] = operands[1];
341 /* If insn is effectively movd N(sp),tos then we will do the
342 high word first. We should use the adjusted operand 1 (which is N+4(sp))
343 for the low word as well, to compensate for the first decrement of sp.
344 Given this, it doesn't matter which half we do "first". */
345 if (optype0 == PUSHOP
346 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
347 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
348 operands[1] = latehalf[1];
350 /* If one or both operands autodecrementing,
351 do the two words, high-numbered first. */
352 else if (optype0 == PUSHOP || optype1 == PUSHOP)
354 output_asm_insn (singlemove_string (latehalf), latehalf);
355 return singlemove_string (operands);
358 /* If the first move would clobber the source of the second one,
359 do them in the other order. */
361 /* Overlapping registers. */
362 if (optype0 == REGOP && optype1 == REGOP
363 && REGNO (operands[0]) == REGNO (latehalf[1]))
366 output_asm_insn (singlemove_string (latehalf), latehalf);
367 /* Do low-numbered word. */
368 return singlemove_string (operands);
370 /* Loading into a register which overlaps a register used in the address. */
371 else if (optype0 == REGOP && optype1 != REGOP
372 && reg_overlap_mentioned_p (operands[0], operands[1]))
374 if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))
375 && reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
377 /* If both halves of dest are used in the src memory address,
378 load the destination address into the low reg (operands[0]).
379 Then it works to load latehalf first. */
381 xops[0] = XEXP (operands[1], 0);
382 xops[1] = operands[0];
383 output_asm_insn ("addr %a0,%1", xops);
384 operands[1] = gen_rtx_MEM (DImode, operands[0]);
385 latehalf[1] = adj_offsettable_operand (operands[1], 4);
386 /* The first half has the overlap, Do the late half first. */
387 output_asm_insn (singlemove_string (latehalf), latehalf);
389 return singlemove_string (operands);
391 if (reg_mentioned_p (operands[0], XEXP (operands[1], 0)))
393 /* The first half has the overlap, Do the late half first. */
394 output_asm_insn (singlemove_string (latehalf), latehalf);
396 return singlemove_string (operands);
400 /* Normal case. Do the two words, low-numbered first. */
402 output_asm_insn (singlemove_string (operands), operands);
404 operands[0] = latehalf[0];
405 operands[1] = latehalf[1];
406 return singlemove_string (operands);
410 #define MAX_UNALIGNED_COPY (32)
411 /* Expand string/block move operations.
413 operands[0] is the pointer to the destination.
414 operands[1] is the pointer to the source.
415 operands[2] is the number of bytes to move.
416 operands[3] is the alignment. */
419 move_tail(operands, bytes, offset)
427 dest = change_address(operands[0], HImode,
428 plus_constant(XEXP(operands[0], 0), offset));
429 src = change_address(operands[1], HImode,
430 plus_constant(XEXP(operands[1], 0), offset));
431 emit_move_insn(dest, src);
437 dest = change_address(operands[0], QImode,
438 plus_constant(XEXP(operands[0], 0), offset));
439 src = change_address(operands[1], QImode,
440 plus_constant(XEXP(operands[1], 0), offset));
441 emit_move_insn(dest, src);
446 expand_block_move (operands)
449 rtx bytes_rtx = operands[2];
450 rtx align_rtx = operands[3];
451 int constp = (GET_CODE (bytes_rtx) == CONST_INT);
452 int bytes = (constp ? INTVAL (bytes_rtx) : 0);
453 int align = INTVAL (align_rtx);
454 rtx src_reg = gen_rtx(REG, Pmode, 1);
455 rtx dest_reg = gen_rtx(REG, Pmode, 2);
456 rtx count_reg = gen_rtx(REG, SImode, 0);
459 if (constp && bytes <= 0)
462 if (constp && bytes < 20)
464 int words = bytes >> 2;
466 if (words < 3 || flag_unroll_loops)
469 for (; words; words--, offset += 4)
472 dest = change_address(operands[0], SImode,
473 plus_constant(XEXP(operands[0], 0), offset));
474 src = change_address(operands[1], SImode,
475 plus_constant(XEXP(operands[1], 0), offset));
476 emit_move_insn(dest, src);
481 /* Use movmd. It is slower than multiple movd's but more
482 compact. It is also slower than movsd for large copies
483 but causes less registers reloading so is better than movsd
486 dest = copy_addr_to_reg (XEXP(operands[0], 0));
487 src = copy_addr_to_reg (XEXP(operands[1], 0));
489 emit_insn(gen_movstrsi2(dest, src, GEN_INT(words)));
491 move_tail(operands, bytes & 3, bytes & ~3);
495 if (align > UNITS_PER_WORD)
496 align = UNITS_PER_WORD;
498 /* Move the address into scratch registers. */
499 emit_insn(gen_rtx(CLOBBER, VOIDmode, dest_reg));
500 emit_move_insn(dest_reg, XEXP (operands[0], 0));
501 emit_insn(gen_rtx(CLOBBER, VOIDmode, src_reg));
502 emit_move_insn(src_reg, XEXP (operands[1], 0));
503 emit_insn(gen_rtx(CLOBBER, VOIDmode, count_reg));
505 if (constp && (align == UNITS_PER_WORD || bytes < MAX_UNALIGNED_COPY))
509 /* constant no of bytes and aligned or small enough copy to not bother
510 * aligning. Emit insns to copy by words.
514 emit_move_insn(count_reg, GEN_INT(bytes >> 2));
515 emit_insn(gen_movstrsi1 (GEN_INT(4)));
517 /* insns to copy rest */
518 move_tail(operands, bytes & 3, bytes & ~3);
520 else if (align == UNITS_PER_WORD)
522 /* insns to copy by words */
523 emit_insn(gen_lshrsi3 (count_reg, bytes_rtx, GEN_INT(2)));
524 emit_insn(gen_movstrsi1 (GEN_INT(4)));
525 /* insns to copy rest */
526 emit_insn(gen_andsi3 (count_reg, bytes_rtx, GEN_INT(3)));
527 emit_insn(gen_movstrsi1 (const1_rtx));
531 /* Not aligned and we may have a lot to copy so it is worth
534 rtx aligned_label = gen_label_rtx ();
537 bytes_reg = copy_to_mode_reg(SImode, bytes_rtx);
540 /* Emit insns to test and skip over the alignment if it is
541 * not worth it. This doubles as a test to ensure that the alignment
542 * operation can't copy too many bytes
544 emit_insn(gen_cmpsi (bytes_reg, GEN_INT(MAX_UNALIGNED_COPY)));
545 emit_jump_insn (gen_blt (aligned_label));
548 /* Emit insns to do alignment at run time */
549 emit_insn(gen_negsi2 (count_reg, src_reg));
550 emit_insn(gen_andsi3 (count_reg, count_reg, GEN_INT(3)));
551 emit_insn(gen_subsi3 (bytes_reg, bytes_reg, count_reg));
552 emit_insn(gen_movstrsi1 (const1_rtx));
554 emit_label (aligned_label);
556 /* insns to copy by words */
557 emit_insn (gen_lshrsi3 (count_reg, bytes_reg, GEN_INT(2)));
558 emit_insn(gen_movstrsi1 (GEN_INT(4)));
560 /* insns to copy rest */
561 emit_insn (gen_andsi3 (count_reg, bytes_reg, GEN_INT(3)));
562 emit_insn(gen_movstrsi1 (const1_rtx));
567 /* Returns 1 if OP contains a global symbol reference */
570 global_symbolic_reference_mentioned_p (op, f)
574 register const char *fmt;
577 if (GET_CODE (op) == SYMBOL_REF)
579 if (! SYMBOL_REF_FLAG (op))
584 else if (f && GET_CODE (op) != CONST)
587 fmt = GET_RTX_FORMAT (GET_CODE (op));
588 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
594 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
595 if (global_symbolic_reference_mentioned_p (XVECEXP (op, i, j), 0))
598 else if (fmt[i] == 'e'
599 && global_symbolic_reference_mentioned_p (XEXP (op, i), 0))
607 /* Returns 1 if OP contains a symbol reference */
610 symbolic_reference_mentioned_p (op)
613 register const char *fmt;
616 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
619 fmt = GET_RTX_FORMAT (GET_CODE (op));
620 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
626 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
627 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
630 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
637 /* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine specific
638 attribute for DECL. The attributes in ATTRIBUTES have previously been
642 ns32k_valid_decl_attribute_p (decl, attributes, identifier, args)
651 /* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine specific
652 attribute for TYPE. The attributes in ATTRIBUTES have previously been
656 ns32k_valid_type_attribute_p (type, attributes, identifier, args)
662 if (TREE_CODE (type) != FUNCTION_TYPE
663 && TREE_CODE (type) != FIELD_DECL
664 && TREE_CODE (type) != TYPE_DECL)
667 /* Stdcall attribute says callee is responsible for popping arguments
668 if they are not variable. */
669 if (is_attribute_p ("stdcall", identifier))
670 return (args == NULL_TREE);
672 /* Cdecl attribute says the callee is a normal C declaration */
673 if (is_attribute_p ("cdecl", identifier))
674 return (args == NULL_TREE);
679 /* Return 0 if the attributes for two types are incompatible, 1 if they
680 are compatible, and 2 if they are nearly compatible (which causes a
681 warning to be generated). */
684 ns32k_comp_type_attributes (type1, type2)
692 /* Value is the number of bytes of arguments automatically
693 popped when returning from a subroutine call.
694 FUNDECL is the declaration node of the function (as a tree),
695 FUNTYPE is the data type of the function (as a tree),
696 or for a library call it is an identifier node for the subroutine name.
697 SIZE is the number of bytes of arguments passed on the stack.
699 On the ns32k, the RET insn may be used to pop them if the number
700 of args is fixed, but if the number is variable then the caller
701 must pop them all. RET can't be used for library calls now
702 because the library is compiled with the Unix compiler.
703 Use of RET is a selectable option, since it is incompatible with
704 standard Unix calling sequences. If the option is not selected,
705 the caller must always pop the args.
707 The attribute stdcall is equivalent to RET on a per module basis. */
710 ns32k_return_pops_args (fundecl, funtype, size)
715 int rtd = TARGET_RTD;
717 if (TREE_CODE (funtype) == IDENTIFIER_NODE)
718 return rtd ? size : 0;
720 /* Cdecl functions override -mrtd, and never pop the stack */
721 if (lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype)))
724 /* Stdcall functions will pop the stack if not variable args */
725 if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype)))
730 if (TYPE_ARG_TYPES (funtype) == NULL_TREE
731 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype))) == void_type_node))
738 /* PRINT_OPERAND is defined to call this function,
739 which is easier to debug than putting all the code in
740 a macro definition in ns32k.h. */
742 /* XXX time 12% of cpu time is in fprintf for non optimizing */
744 print_operand (file, x, code)
750 PUT_IMMEDIATE_PREFIX (file);
751 else if (code == '?')
752 PUT_EXTERNAL_PREFIX (file);
753 else if (GET_CODE (x) == REG)
754 fprintf (file, "%s", ns32k_out_reg_names[REGNO (x)]);
755 else if (GET_CODE (x) == MEM)
757 rtx tmp = XEXP (x, 0);
758 output_address (XEXP (x, 0));
760 else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != VOIDmode)
762 if (GET_MODE (x) == DFmode)
764 union { double d; int i[2]; } u;
765 u.i[0] = CONST_DOUBLE_LOW (x); u.i[1] = CONST_DOUBLE_HIGH (x);
766 PUT_IMMEDIATE_PREFIX(file);
768 /* Sequent likes its floating point constants as integers */
769 fprintf (file, "0Dx%08x%08x", u.i[1], u.i[0]);
772 fprintf (file, "0f%.20e", u.d);
774 fprintf (file, "0d%.20e", u.d);
780 union { double d; int i[2]; } u;
781 u.i[0] = CONST_DOUBLE_LOW (x); u.i[1] = CONST_DOUBLE_HIGH (x);
782 PUT_IMMEDIATE_PREFIX (file);
784 /* We have no way of winning if we can't get the bits
785 for a sequent floating point number. */
786 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
790 union { float f; long l; } uu;
792 fprintf (file, "0Fx%08x", uu.l);
795 fprintf (file, "0f%.20e", u.d);
802 && GET_CODE (x) == CONST
803 && symbolic_reference_mentioned_p (x))
805 fprintf(stderr, "illegal constant for pic-mode: \n");
806 print_rtl(stderr, x);
807 fprintf(stderr, "\nGET_CODE (x) == %d, CONST == %d, symbolic_reference_mentioned_p (x) == %d\n",
808 GET_CODE (x), CONST, symbolic_reference_mentioned_p(x));
812 && (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF))
814 output_addr_const (file, x);
815 fprintf (file, "(sb)");
819 #ifdef NO_IMMEDIATE_PREFIX_IF_SYMBOLIC
820 if (GET_CODE (x) == CONST_INT)
822 PUT_IMMEDIATE_PREFIX (file);
823 output_addr_const (file, x);
828 /* PRINT_OPERAND_ADDRESS is defined to call this function,
829 which is easier to debug than putting all the code in
830 a macro definition in ns32k.h . */
832 /* Completely rewritten to get this to work with Gas for PC532 Mach.
833 This function didn't work and I just wasn't able (nor very willing) to
834 figure out how it worked.
835 90-11-25 Tatu Yl|nen <ylo@cs.hut.fi> */
838 print_operand_address (file, addr)
842 static char scales[] = { 'b', 'w', 'd', 0, 'q', };
843 rtx offset, base, indexexp, tmp;
847 if (GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == POST_DEC)
849 fprintf (file, "tos");
858 if (GET_CODE (addr) == PLUS)
860 if (GET_CODE (XEXP (addr, 0)) == PLUS)
862 tmp = XEXP (addr, 1);
863 addr = XEXP (addr, 0);
868 addr = XEXP (addr,1);
876 switch (GET_CODE (tmp))
890 if (REGNO (tmp) < F0_REGNUM)
910 if (flag_pic && ! CONSTANT_POOL_ADDRESS_P (tmp)
911 && ! SYMBOL_REF_FLAG (tmp))
923 if (flag_pic && GET_CODE (tmp) == CONST)
927 if (GET_CODE (tmp1) != PLUS)
931 if (GET_CODE (sym) != SYMBOL_REF)
938 if (GET_CODE (sym) == SYMBOL_REF)
940 if (GET_CODE (off) != CONST_INT)
943 if (CONSTANT_POOL_ADDRESS_P (sym)
944 || SYMBOL_REF_FLAG (sym))
946 SYMBOL_REF_FLAG (tmp) = 1;
970 offset = gen_rtx_PLUS (SImode, tmp, offset);
982 #ifndef INDEX_RATHER_THAN_BASE
983 && (flag_pic || TARGET_HIMEM)
984 && GET_CODE (base) != SYMBOL_REF
985 && GET_CODE (offset) != CONST_INT
987 /* This is a re-implementation of the SEQUENT_ADDRESS_BUG fix. */
989 && !indexexp && GET_CODE (base) == REG
990 && REG_OK_FOR_INDEX_P (base))
996 /* now, offset, base and indexexp are set */
997 #ifndef BASE_REG_NEEDED
1000 #if defined (PC_RELATIVE) || defined (NO_ABSOLUTE_PREFIX_IF_SYMBOLIC)
1001 if (GET_CODE (offset) == CONST_INT)
1003 PUT_ABSOLUTE_PREFIX (file);
1007 output_addr_const (file, offset);
1008 if (base) /* base can be (REG ...) or (MEM ...) */
1009 switch (GET_CODE (base))
1011 /* now we must output base. Possible alternatives are:
1015 (pc) (REG ...) used for SYMBOL_REF and LABEL_REF, output
1016 (disp(fp)) (MEM ...) just before possible [rX:y]
1017 (disp(sp)) (MEM ...)
1018 (disp(sb)) (MEM ...)
1021 fprintf (file, "(%s)", ns32k_out_reg_names[REGNO (base)]);
1027 fprintf (file, "(");
1028 output_addr_const (file, base);
1029 fprintf (file, "(sb))");
1032 addr = XEXP(base,0);
1035 while (addr != NULL)
1037 if (GET_CODE (addr) == PLUS)
1039 if (GET_CODE (XEXP (addr, 0)) == PLUS)
1041 tmp = XEXP (addr, 1);
1042 addr = XEXP (addr, 0);
1046 tmp = XEXP (addr, 0);
1047 addr = XEXP (addr, 1);
1055 switch (GET_CODE (tmp))
1065 offset = gen_rtx_PLUS (SImode, tmp, offset);
1074 offset = const0_rtx;
1075 fprintf (file, "(");
1076 output_addr_const (file, offset);
1078 fprintf (file, "(%s)", ns32k_out_reg_names[REGNO (base)]);
1080 fprintf (file, "(sb)");
1083 fprintf (file, ")");
1089 else if (GET_CODE (offset) != CONST_INT)
1090 fprintf (file, "(pc)");
1091 #ifdef BASE_REG_NEEDED
1093 fprintf (file, "(sb)");
1097 #endif /* PC_RELATIVE */
1099 /* now print index if we have one */
1102 if (GET_CODE (indexexp) == MULT)
1104 scale = INTVAL (XEXP (indexexp, 1)) >> 1;
1105 indexexp = XEXP (indexexp, 0);
1109 if (GET_CODE (indexexp) != REG || REGNO (indexexp) >= F0_REGNUM)
1113 fprintf (file, "[%c`%s]",
1115 ns32k_out_reg_names[REGNO (indexexp)]);
1117 fprintf (file, "[%s:%c]",
1118 ns32k_out_reg_names[REGNO (indexexp)],
1124 /* National 32032 shifting is so bad that we can get
1125 better performance in many common cases by using other
1128 output_shift_insn (operands)
1131 if (GET_CODE (operands[2]) == CONST_INT
1132 && INTVAL (operands[2]) > 0
1133 && INTVAL (operands[2]) <= 3)
1134 if (GET_CODE (operands[0]) == REG)
1136 if (GET_CODE (operands[1]) == REG)
1138 if (REGNO (operands[0]) == REGNO (operands[1]))
1140 if (operands[2] == const1_rtx)
1141 return "addd %0,%0";
1142 else if (INTVAL (operands[2]) == 2)
1143 return "addd %0,%0\n\taddd %0,%0";
1145 if (operands[2] == const1_rtx)
1146 return "movd %1,%0\n\taddd %0,%0";
1148 operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
1149 return "addr %a1,%0";
1151 if (operands[2] == const1_rtx)
1152 return "movd %1,%0\n\taddd %0,%0";
1154 else if (GET_CODE (operands[1]) == REG)
1156 operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
1157 return "addr %a1,%0";
1159 else if (INTVAL (operands[2]) == 1
1160 && GET_CODE (operands[1]) == MEM
1161 && rtx_equal_p (operands [0], operands[1]))
1163 rtx temp = XEXP (operands[1], 0);
1165 if (GET_CODE (temp) == REG
1166 || (GET_CODE (temp) == PLUS
1167 && GET_CODE (XEXP (temp, 0)) == REG
1168 && GET_CODE (XEXP (temp, 1)) == CONST_INT))
1169 return "addd %0,%0";
1171 else return "ashd %2,%0";
1172 return "ashd %2,%0";
1176 output_move_dconst (n, s)
1182 if (n > -9 && n < 8)
1183 strcpy (r, "movqd ");
1184 else if (n > 0 && n < 256)
1185 strcpy (r, "movzbd ");
1186 else if (n > 0 && n < 65536)
1187 strcpy (r, "movzwd ");
1188 else if (n < 0 && n > -129)
1189 strcpy (r, "movxbd ");
1190 else if (n < 0 && n > -32769)
1191 strcpy (r, "movxwd ");
1193 strcpy (r, "movd ");