1 /* Subroutines for assembler code output on the NS32000.
2 Copyright (C) 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
3 Free Software Foundation, Inc.
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
24 #include "coretypes.h"
28 #include "hard-reg-set.h"
30 #include "insn-config.h"
31 #include "conditions.h"
33 #include "insn-attr.h"
41 #include "target-def.h"
45 int ns32k_num_files = 0;
48 /* This duplicates reg_class_contents in reg_class.c, but maybe that isn't
49 initialized in time. Also this is more convenient as an array of ints.
50 We know that HARD_REG_SET fits in an unsigned int */
52 const unsigned int ns32k_reg_class_contents[N_REG_CLASSES][1] = REG_CLASS_CONTENTS;
54 const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] =
56 GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
57 GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
58 FLOAT_REG0, LONG_FLOAT_REG0, FLOAT_REGS, FLOAT_REGS,
59 FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, FLOAT_REGS,
60 LONG_REGS, LONG_REGS, LONG_REGS, LONG_REGS,
61 LONG_REGS, LONG_REGS, LONG_REGS, LONG_REGS,
62 FRAME_POINTER_REG, STACK_POINTER_REG
65 static const char *const ns32k_out_reg_names[] = OUTPUT_REGISTER_NAMES;
67 static rtx gen_indexed_expr PARAMS ((rtx, rtx, rtx));
68 static const char *singlemove_string PARAMS ((rtx *));
69 static void move_tail PARAMS ((rtx[], int, int));
70 static tree ns32k_handle_fntype_attribute PARAMS ((tree *, tree, tree, int, bool *));
71 const struct attribute_spec ns32k_attribute_table[];
72 static void ns32k_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
73 static void ns32k_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
74 static bool ns32k_rtx_costs PARAMS ((rtx, int, int, int *));
75 static int ns32k_address_cost PARAMS ((rtx));
77 /* Initialize the GCC target structure. */
78 #undef TARGET_ATTRIBUTE_TABLE
79 #define TARGET_ATTRIBUTE_TABLE ns32k_attribute_table
81 #undef TARGET_ASM_ALIGNED_HI_OP
82 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
85 #undef TARGET_ASM_ALIGNED_SI_OP
86 #define TARGET_ASM_ALIGNED_SI_OP "\t.double\t"
89 #undef TARGET_ASM_FUNCTION_PROLOGUE
90 #define TARGET_ASM_FUNCTION_PROLOGUE ns32k_output_function_prologue
91 #undef TARGET_ASM_FUNCTION_EPILOGUE
92 #define TARGET_ASM_FUNCTION_EPILOGUE ns32k_output_function_epilogue
94 #undef TARGET_RTX_COSTS
95 #define TARGET_RTX_COSTS ns32k_rtx_costs
96 #undef TARGET_ADDRESS_COST
97 #define TARGET_ADDRESS_COST ns32k_address_cost
99 struct gcc_target targetm = TARGET_INITIALIZER;
101 /* Generate the assembly code for function entry. FILE is a stdio
102 stream to output the code to. SIZE is an int: how many units of
103 temporary storage to allocate.
105 Refer to the array `regs_ever_live' to determine which registers to
106 save; `regs_ever_live[I]' is nonzero if register number I is ever
107 used in the function. This function is responsible for knowing
108 which registers should not be saved even if used. */
111 * The function prologue for the ns32k is fairly simple.
112 * If a frame pointer is needed (decided in reload.c ?) then
113 * we need assembler of the form
115 * # Save the oldframe pointer, set the new frame pointer, make space
116 * # on the stack and save any general purpose registers necessary
118 * enter [<general purpose regs to save>], <local stack space>
120 * movf fn, tos # Save any floating point registers necessary
124 * If a frame pointer is not needed we need assembler of the form
126 * # Make space on the stack
128 * adjspd <local stack space + 4>
130 * # Save any general purpose registers necessary
132 * save [<general purpose regs to save>]
134 * movf fn, tos # Save any floating point registers necessary
139 #if !defined (MERLIN_TARGET) && !defined (UTEK_ASM)
141 #if defined(IMMEDIATE_PREFIX) && IMMEDIATE_PREFIX
142 #define ADJSP(FILE, N) \
143 fprintf (FILE, "\tadjspd %c" HOST_WIDE_INT_PRINT_DEC "\n", IMMEDIATE_PREFIX, (N))
145 #define ADJSP(FILE, N) \
146 fprintf (FILE, "\tadjspd " HOST_WIDE_INT_PRINT_DEC "\n", (N))
150 ns32k_output_function_prologue (file, size)
154 register int regno, g_regs_used = 0;
155 int used_regs_buf[8], *bufp = used_regs_buf;
156 int used_fregs_buf[17], *fbufp = used_fregs_buf;
158 for (regno = R0_REGNUM; regno < F0_REGNUM; regno++)
159 if (regs_ever_live[regno]
160 && ! call_used_regs[regno])
162 *bufp++ = regno; g_regs_used++;
166 for (; regno < FRAME_POINTER_REGNUM; regno++)
167 if (regs_ever_live[regno] && !call_used_regs[regno])
173 bufp = used_regs_buf;
174 if (frame_pointer_needed)
175 fprintf (file, "\tenter [");
179 ADJSP (file, size + 4);
180 if (g_regs_used && g_regs_used > 4)
181 fprintf (file, "\tsave [");
185 fprintf (file, "\tmovd r%d,tos\n", *bufp++);
192 fprintf (file, "r%d", *bufp++);
197 if (frame_pointer_needed)
198 fprintf (file, "]," HOST_WIDE_INT_PRINT_DEC "\n", size);
199 else if (g_regs_used)
200 fprintf (file, "]\n");
202 fbufp = used_fregs_buf;
205 if ((*fbufp & 1) || (fbufp[0] != fbufp[1] - 1))
206 fprintf (file, "\tmovf %s,tos\n", ns32k_out_reg_names[*fbufp++]);
209 fprintf (file, "\tmovl %s,tos\n",
210 ns32k_out_reg_names[fbufp[0]]);
215 if (flag_pic && current_function_uses_pic_offset_table)
217 fprintf (file, "\tsprd sb,tos\n");
220 fprintf (file, "\taddr __GLOBAL_OFFSET_TABLE_(pc),tos\n");
221 fprintf (file, "\tlprd sb,tos\n");
225 fprintf (file, "\taddr __GLOBAL_OFFSET_TABLE_(pc),r0\n");
226 fprintf (file, "\tlprd sb,r0\n");
231 #else /* MERLIN_TARGET || UTEK_ASM */
233 /* This differs from the standard one above in printing a bitmask
234 rather than a register list in the enter or save instruction. */
237 ns32k_output_function_prologue (file, size)
241 register int regno, g_regs_used = 0;
242 int used_regs_buf[8], *bufp = used_regs_buf;
243 int used_fregs_buf[8], *fbufp = used_fregs_buf;
245 for (regno = 0; regno < 8; regno++)
246 if (regs_ever_live[regno]
247 && ! call_used_regs[regno])
249 *bufp++ = regno; g_regs_used++;
253 for (; regno < 16; regno++)
254 if (regs_ever_live[regno] && !call_used_regs[regno]) {
259 bufp = used_regs_buf;
260 if (frame_pointer_needed)
261 fprintf (file, "\tenter ");
262 else if (g_regs_used)
263 fprintf (file, "\tsave ");
265 if (frame_pointer_needed || g_regs_used)
269 mask |= 1 << *bufp++;
270 fprintf (file, "$0x%x", (int) mask & 0xff);
273 if (frame_pointer_needed)
275 fprintf (file, ",$%d\n", size);
277 fprintf (file, ",%d\n", size);
279 else if (g_regs_used)
280 fprintf (file, "\n");
282 fbufp = used_fregs_buf;
285 if ((*fbufp & 1) || (fbufp[0] != fbufp[1] - 1))
286 fprintf (file, "\tmovf f%d,tos\n", *fbufp++ - 8);
289 fprintf (file, "\tmovl f%d,tos\n", fbufp[0] - 8);
295 #endif /* MERLIN_TARGET || UTEK_ASM */
297 /* This function generates the assembly code for function exit,
298 on machines that need it.
300 The function epilogue should not depend on the current stack pointer,
301 if EXIT_IGNORE_STACK is nonzero. That doesn't apply here.
303 If a frame pointer is needed (decided in reload.c ?) then
304 we need assembler of the form
306 movf tos, fn # Restore any saved floating point registers
310 # Restore any saved general purpose registers, restore the stack
311 # pointer from the frame pointer, restore the old frame pointer.
312 exit [<general purpose regs to save>]
314 If a frame pointer is not needed we need assembler of the form
315 # Restore any general purpose registers saved
317 movf tos, fn # Restore any saved floating point registers
321 restore [<general purpose regs to save>]
323 # reclaim space allocated on stack
325 adjspd <-(local stack space + 4)> */
327 #if !defined (MERLIN_TARGET) && !defined (UTEK_ASM)
330 ns32k_output_function_epilogue (file, size)
334 register int regno, g_regs_used = 0, f_regs_used = 0;
335 int used_regs_buf[8], *bufp = used_regs_buf;
336 int used_fregs_buf[17], *fbufp = used_fregs_buf;
338 if (flag_pic && current_function_uses_pic_offset_table)
339 fprintf (file, "\tlprd sb,tos\n");
342 for (regno = F0_REGNUM; regno < FRAME_POINTER_REGNUM; regno++)
343 if (regs_ever_live[regno] && !call_used_regs[regno])
345 *fbufp++ = regno; f_regs_used++;
349 for (regno = 0; regno < F0_REGNUM; regno++)
350 if (regs_ever_live[regno]
351 && ! call_used_regs[regno])
353 *bufp++ = regno; g_regs_used++;
356 while (fbufp > used_fregs_buf)
358 if ((*fbufp & 1) && fbufp[0] == fbufp[-1] + 1)
360 fprintf (file, "\tmovl tos,%s\n",
361 ns32k_out_reg_names[fbufp[-1]]);
364 else fprintf (file, "\tmovf tos,%s\n", ns32k_out_reg_names[*fbufp--]);
367 if (frame_pointer_needed)
368 fprintf (file, "\texit [");
371 if (g_regs_used && g_regs_used > 4)
372 fprintf (file, "\trestore [");
375 while (bufp > used_regs_buf)
376 fprintf (file, "\tmovd tos,r%d\n", *--bufp);
381 while (bufp > used_regs_buf)
383 fprintf (file, "r%d", *--bufp);
384 if (bufp > used_regs_buf)
388 if (g_regs_used || frame_pointer_needed)
389 fprintf (file, "]\n");
391 if (size && !frame_pointer_needed)
392 ADJSP (file, -(size + 4));
394 if (current_function_pops_args)
395 fprintf (file, "\tret %d\n", current_function_pops_args);
397 fprintf (file, "\tret 0\n");
400 #else /* MERLIN_TARGET || UTEK_ASM */
402 /* This differs from the standard one above in printing a bitmask
403 rather than a register list in the exit or restore instruction. */
406 ns32k_output_function_epilogue (file, size)
408 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
410 register int regno, g_regs_used = 0, f_regs_used = 0;
411 int used_regs_buf[8], *bufp = used_regs_buf;
412 int used_fregs_buf[8], *fbufp = used_fregs_buf;
415 for (regno = 8; regno < 16; regno++)
416 if (regs_ever_live[regno] && !call_used_regs[regno]) {
417 *fbufp++ = regno; f_regs_used++;
421 for (regno = 0; regno < 8; regno++)
422 if (regs_ever_live[regno]
423 && ! call_used_regs[regno])
425 *bufp++ = regno; g_regs_used++;
428 while (fbufp > used_fregs_buf)
430 if ((*fbufp & 1) && fbufp[0] == fbufp[-1] + 1)
432 fprintf (file, "\tmovl tos,f%d\n", fbufp[-1] - 8);
435 else fprintf (file, "\tmovf tos,f%d\n", *fbufp-- - 8);
438 if (frame_pointer_needed)
439 fprintf (file, "\texit ");
440 else if (g_regs_used)
441 fprintf (file, "\trestore ");
443 if (g_regs_used || frame_pointer_needed)
447 while (bufp > used_regs_buf)
449 /* Utek assembler takes care of reversing this */
450 mask |= 1 << *--bufp;
452 fprintf (file, "$0x%x\n", (int) mask & 0xff);
456 if (current_function_pops_args)
457 fprintf (file, "\tret $%d\n", current_function_pops_args);
459 fprintf (file, "\tret $0\n");
461 if (current_function_pops_args)
462 fprintf (file, "\tret %d\n", current_function_pops_args);
464 fprintf (file, "\tret 0\n");
468 #endif /* MERLIN_TARGET || UTEK_ASM */
470 /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */
472 hard_regno_mode_ok (regno, mode)
474 enum machine_mode mode;
476 int size = GET_MODE_UNIT_SIZE (mode);
478 if (FLOAT_MODE_P (mode))
480 if (size == UNITS_PER_WORD && regno < L1_REGNUM)
482 if (size == UNITS_PER_WORD * 2
483 && (((regno & 1) == 0 && regno < FRAME_POINTER_REGNUM)))
487 if (size == UNITS_PER_WORD * 2
488 && (regno & 1) == 0 && regno < F0_REGNUM)
490 if (size <= UNITS_PER_WORD
491 && (regno < F0_REGNUM || regno == FRAME_POINTER_REGNUM
492 || regno == STACK_POINTER_REGNUM))
498 ns32k_rtx_costs (x, code, outer_code, total)
500 int code, outer_code ATTRIBUTE_UNUSED;
506 if (INTVAL (x) <= 7 && INTVAL (x) >= -8)
508 else if (INTVAL (x) < 0x2000 && INTVAL (x) >= -0x2000)
529 int register_move_cost (CLASS1, CLASS2)
530 enum reg_class CLASS1;
531 enum reg_class CLASS2;
533 if (CLASS1 == NO_REGS || CLASS2 == NO_REGS)
535 if ((SUBSET_P (CLASS1, FP_REGS) && !SUBSET_P (CLASS2, FP_REGS))
536 || (!SUBSET_P (CLASS1, FP_REGS) && SUBSET_P (CLASS2, FP_REGS)))
538 if (((CLASS1) == STACK_POINTER_REG && !SUBSET_P (CLASS2,GENERAL_REGS))
539 || ((CLASS2) == STACK_POINTER_REG && !SUBSET_P (CLASS1,GENERAL_REGS)))
541 if (((CLASS1) == FRAME_POINTER_REG && !SUBSET_P (CLASS2,GENERAL_REGS))
542 || ((CLASS2) == FRAME_POINTER_REG && !SUBSET_P (CLASS1,GENERAL_REGS)))
548 /* We made the insn definitions copy from floating point to general
549 registers via the stack. */
550 int secondary_memory_needed (CLASS1, CLASS2, M)
551 enum reg_class CLASS1;
552 enum reg_class CLASS2;
555 int ret = ((SUBSET_P (CLASS1, FP_REGS) && !SUBSET_P (CLASS2, FP_REGS))
556 || (!SUBSET_P (CLASS1, FP_REGS) && SUBSET_P (CLASS2, FP_REGS)));
562 /* TARGET_ADDRESS_COST calls this. This function is not optimal
563 for the 32032 & 32332, but it probably is better than
567 ns32k_address_cost (operand)
572 switch (GET_CODE (operand))
583 if (INTVAL (operand) <= 7 && INTVAL (operand) >= -8)
585 if (INTVAL (operand) < 0x2000 && INTVAL (operand) >= -0x2000)
600 cost += ns32k_address_cost (XEXP (operand, 0)) + 3;
607 cost += ns32k_address_cost (XEXP (operand, 0));
608 cost += ns32k_address_cost (XEXP (operand, 1));
618 /* Return the register class of a scratch register needed to copy IN into
619 or out of a register in CLASS in MODE. If it can be done directly,
620 NO_REGS is returned. */
623 secondary_reload_class (class, mode, in)
624 enum reg_class class;
625 enum machine_mode mode ATTRIBUTE_UNUSED;
628 int regno = true_regnum (in);
630 if (regno >= FIRST_PSEUDO_REGISTER)
633 if ((class == FRAME_POINTER_REG && regno == STACK_POINTER_REGNUM)
634 || ( class == STACK_POINTER_REG && regno == FRAME_POINTER_REGNUM))
640 /* Generate the rtx that comes from an address expression in the md file */
641 /* The expression to be build is BASE[INDEX:SCALE]. To recognize this,
642 scale must be converted from an exponent (from ASHIFT) to a
643 multiplier (for MULT). */
646 gen_indexed_expr (base, index, scale)
647 rtx base, index, scale;
651 /* This generates an invalid addressing mode, if BASE is
652 fp or sp. This is handled by PRINT_OPERAND_ADDRESS. */
653 if (GET_CODE (base) != REG && GET_CODE (base) != CONST_INT)
654 base = gen_rtx_MEM (SImode, base);
655 addr = gen_rtx_MULT (SImode, index,
656 GEN_INT (1 << INTVAL (scale)));
657 addr = gen_rtx_PLUS (SImode, base, addr);
662 /* Split one or more DImode RTL references into pairs of SImode
663 references. The RTL can be REG, offsettable MEM, integer constant, or
664 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
665 split and "num" is its length. lo_half and hi_half are output arrays
666 that parallel "operands". */
669 split_di (operands, num, lo_half, hi_half)
672 rtx lo_half[], hi_half[];
676 if (GET_CODE (operands[num]) == REG)
678 lo_half[num] = gen_rtx_REG (SImode, REGNO (operands[num]));
679 hi_half[num] = gen_rtx_REG (SImode, REGNO (operands[num]) + 1);
681 else if (CONSTANT_P (operands[num]))
683 split_double (operands[num], &lo_half[num], &hi_half[num]);
685 else if (offsettable_memref_p (operands[num]))
687 lo_half[num] = operands[num];
688 hi_half[num] = adjust_address (operands[num], SImode, 4);
695 /* Return the best assembler insn template
696 for moving operands[1] into operands[0] as a fullword. */
699 singlemove_string (operands)
702 if (GET_CODE (operands[1]) == CONST_INT
703 && INTVAL (operands[1]) <= 7
704 && INTVAL (operands[1]) >= -8)
705 return "movqd %1,%0";
710 output_move_double (operands)
713 enum anon1 { REGOP, OFFSOP, PUSHOP, CNSTOP, RNDOP } optype0, optype1;
716 /* First classify both operands. */
718 if (REG_P (operands[0]))
720 else if (offsettable_memref_p (operands[0]))
722 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
727 if (REG_P (operands[1]))
729 else if (CONSTANT_P (operands[1])
730 || GET_CODE (operands[1]) == CONST_DOUBLE)
732 else if (offsettable_memref_p (operands[1]))
734 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
739 /* Check for the cases that the operand constraints are not
740 supposed to allow to happen. Abort if we get one,
741 because generating code for these cases is painful. */
743 if (optype0 == RNDOP || optype1 == RNDOP)
746 /* Ok, we can do one word at a time.
747 Normally we do the low-numbered word first,
748 but if either operand is autodecrementing then we
749 do the high-numbered word first.
751 In either case, set up in LATEHALF the operands to use
752 for the high-numbered word and in some cases alter the
753 operands in OPERANDS to be suitable for the low-numbered word. */
755 if (optype0 == REGOP)
756 latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
757 else if (optype0 == OFFSOP)
758 latehalf[0] = adjust_address (operands[0], SImode, 4);
760 latehalf[0] = operands[0];
762 if (optype1 == REGOP)
763 latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
764 else if (optype1 == OFFSOP)
765 latehalf[1] = adjust_address (operands[1], SImode, 4);
766 else if (optype1 == CNSTOP)
767 split_double (operands[1], &operands[1], &latehalf[1]);
769 latehalf[1] = operands[1];
771 /* If insn is effectively movd N(sp),tos then we will do the
772 high word first. We should use the adjusted operand 1 (which is N+4(sp))
773 for the low word as well, to compensate for the first decrement of sp.
774 Given this, it doesn't matter which half we do "first". */
775 if (optype0 == PUSHOP
776 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
777 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
778 operands[1] = latehalf[1];
780 /* If one or both operands autodecrementing,
781 do the two words, high-numbered first. */
782 else if (optype0 == PUSHOP || optype1 == PUSHOP)
784 output_asm_insn (singlemove_string (latehalf), latehalf);
785 return singlemove_string (operands);
788 /* If the first move would clobber the source of the second one,
789 do them in the other order. */
791 /* Overlapping registers. */
792 if (optype0 == REGOP && optype1 == REGOP
793 && REGNO (operands[0]) == REGNO (latehalf[1]))
796 output_asm_insn (singlemove_string (latehalf), latehalf);
797 /* Do low-numbered word. */
798 return singlemove_string (operands);
800 /* Loading into a register which overlaps a register used in the address. */
801 else if (optype0 == REGOP && optype1 != REGOP
802 && reg_overlap_mentioned_p (operands[0], operands[1]))
804 if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))
805 && reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
807 /* If both halves of dest are used in the src memory address,
808 load the destination address into the low reg (operands[0]).
809 Then it works to load latehalf first. */
811 xops[0] = XEXP (operands[1], 0);
812 xops[1] = operands[0];
813 output_asm_insn ("addr %a0,%1", xops);
814 operands[1] = gen_rtx_MEM (DImode, operands[0]);
815 latehalf[1] = adjust_address (operands[1], SImode, 4);
816 /* The first half has the overlap, Do the late half first. */
817 output_asm_insn (singlemove_string (latehalf), latehalf);
819 return singlemove_string (operands);
821 if (reg_mentioned_p (operands[0], XEXP (operands[1], 0)))
823 /* The first half has the overlap, Do the late half first. */
824 output_asm_insn (singlemove_string (latehalf), latehalf);
826 return singlemove_string (operands);
830 /* Normal case. Do the two words, low-numbered first. */
832 output_asm_insn (singlemove_string (operands), operands);
834 operands[0] = latehalf[0];
835 operands[1] = latehalf[1];
836 return singlemove_string (operands);
840 #define MAX_UNALIGNED_COPY (32)
841 /* Expand string/block move operations.
843 operands[0] is the pointer to the destination.
844 operands[1] is the pointer to the source.
845 operands[2] is the number of bytes to move.
846 operands[3] is the alignment. */
849 move_tail (operands, bytes, offset)
856 emit_move_insn (adjust_address (operands[0], HImode, offset),
857 adjust_address (operands[1], HImode, offset));
861 emit_move_insn (adjust_address (operands[0], QImode, offset),
862 adjust_address (operands[1], QImode, offset));
866 expand_block_move (operands)
869 rtx bytes_rtx = operands[2];
870 rtx align_rtx = operands[3];
871 int constp = (GET_CODE (bytes_rtx) == CONST_INT);
872 int bytes = (constp ? INTVAL (bytes_rtx) : 0);
873 int align = INTVAL (align_rtx);
874 rtx src_reg = gen_rtx_REG (Pmode, 1);
875 rtx dest_reg = gen_rtx_REG (Pmode, 2);
876 rtx count_reg = gen_rtx_REG (SImode, 0);
878 if (constp && bytes <= 0)
881 if (constp && bytes < 20)
883 int words = bytes >> 2;
891 for (; words; words--, offset += 4)
892 emit_move_insn (adjust_address (operands[0], SImode, offset),
893 adjust_address (operands[1], SImode, offset));
897 /* Use movmd. It is slower than multiple movd's but more
898 compact. It is also slower than movsd for large copies
899 but causes less registers reloading so is better than movsd
902 dest = copy_addr_to_reg (XEXP (operands[0], 0));
903 src = copy_addr_to_reg (XEXP (operands[1], 0));
905 emit_insn (gen_movstrsi2(dest, src, GEN_INT (words)));
908 move_tail (operands, bytes & 3, bytes & ~3);
912 if (align > UNITS_PER_WORD)
913 align = UNITS_PER_WORD;
915 /* Move the address into scratch registers. */
916 emit_insn (gen_rtx_CLOBBER (VOIDmode, dest_reg));
917 emit_move_insn (dest_reg, XEXP (operands[0], 0));
918 operands[0] = gen_rtx_MEM (SImode, dest_reg);
919 emit_insn (gen_rtx_CLOBBER (VOIDmode, src_reg));
920 emit_move_insn (src_reg, XEXP (operands[1], 0));
921 operands[1] = gen_rtx_MEM (SImode, src_reg);
922 emit_insn (gen_rtx_CLOBBER (VOIDmode, count_reg));
924 if (constp && (align == UNITS_PER_WORD || bytes < MAX_UNALIGNED_COPY))
926 /* constant no of bytes and aligned or small enough copy to not bother
927 * aligning. Emit insns to copy by words.
931 emit_move_insn (count_reg, GEN_INT (bytes >> 2));
932 emit_insn (gen_movstrsi1 (GEN_INT (4)));
934 /* insns to copy rest */
935 move_tail (operands, bytes & 3, 0);
937 else if (align == UNITS_PER_WORD)
939 /* insns to copy by words */
940 emit_insn (gen_lshrsi3 (count_reg, bytes_rtx, GEN_INT (2)));
941 emit_insn (gen_movstrsi1 (GEN_INT (4)));
944 move_tail (operands, bytes & 3, 0);
948 /* insns to copy rest */
949 emit_insn (gen_andsi3 (count_reg, bytes_rtx, GEN_INT (3)));
950 emit_insn (gen_movstrsi1 (const1_rtx));
955 /* Not aligned and we may have a lot to copy so it is worth
958 rtx aligned_label = gen_label_rtx ();
961 bytes_reg = copy_to_mode_reg (SImode, bytes_rtx);
964 /* Emit insns to test and skip over the alignment if it is
965 * not worth it. This doubles as a test to ensure that the alignment
966 * operation can't copy too many bytes
968 emit_insn (gen_cmpsi (bytes_reg, GEN_INT (MAX_UNALIGNED_COPY)));
969 emit_jump_insn (gen_blt (aligned_label));
972 /* Emit insns to do alignment at run time */
973 emit_insn (gen_negsi2 (count_reg, src_reg));
974 emit_insn (gen_andsi3 (count_reg, count_reg, GEN_INT (3)));
975 emit_insn (gen_subsi3 (bytes_reg, bytes_reg, count_reg));
976 emit_insn (gen_movstrsi1 (const1_rtx));
978 emit_label (aligned_label);
980 /* insns to copy by words */
981 emit_insn (gen_lshrsi3 (count_reg, bytes_reg, GEN_INT (2)));
982 emit_insn (gen_movstrsi1 (GEN_INT (4)));
984 /* insns to copy rest */
985 emit_insn (gen_andsi3 (count_reg, bytes_reg, GEN_INT (3)));
986 emit_insn (gen_movstrsi1 (const1_rtx));
991 /* Returns 1 if OP contains a global symbol reference */
994 global_symbolic_reference_mentioned_p (op, f)
998 register const char *fmt;
1001 if (GET_CODE (op) == SYMBOL_REF)
1003 if (! SYMBOL_REF_LOCAL_P (op))
1008 else if (f && GET_CODE (op) != CONST)
1011 fmt = GET_RTX_FORMAT (GET_CODE (op));
1012 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
1018 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
1019 if (global_symbolic_reference_mentioned_p (XVECEXP (op, i, j), 0))
1022 else if (fmt[i] == 'e'
1023 && global_symbolic_reference_mentioned_p (XEXP (op, i), 0))
1031 /* Returns 1 if OP contains a symbol reference */
1034 symbolic_reference_mentioned_p (op)
1037 register const char *fmt;
1040 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
1043 fmt = GET_RTX_FORMAT (GET_CODE (op));
1044 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
1050 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
1051 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
1054 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
1061 /* Table of machine-specific attributes. */
1063 const struct attribute_spec ns32k_attribute_table[] =
1065 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
1066 /* Stdcall attribute says callee is responsible for popping arguments
1067 if they are not variable. */
1068 { "stdcall", 0, 0, false, true, true, ns32k_handle_fntype_attribute },
1069 /* Cdecl attribute says the callee is a normal C declaration */
1070 { "cdecl", 0, 0, false, true, true, ns32k_handle_fntype_attribute },
1071 { NULL, 0, 0, false, false, false, NULL }
1074 /* Handle an attribute requiring a FUNCTION_TYPE, FIELD_DECL or TYPE_DECL;
1075 arguments as in struct attribute_spec.handler. */
1077 ns32k_handle_fntype_attribute (node, name, args, flags, no_add_attrs)
1080 tree args ATTRIBUTE_UNUSED;
1081 int flags ATTRIBUTE_UNUSED;
1084 if (TREE_CODE (*node) != FUNCTION_TYPE
1085 && TREE_CODE (*node) != FIELD_DECL
1086 && TREE_CODE (*node) != TYPE_DECL)
1088 warning ("`%s' attribute only applies to functions",
1089 IDENTIFIER_POINTER (name));
1090 *no_add_attrs = true;
1097 /* Value is the number of bytes of arguments automatically
1098 popped when returning from a subroutine call.
1099 FUNDECL is the declaration node of the function (as a tree),
1100 FUNTYPE is the data type of the function (as a tree),
1101 or for a library call it is an identifier node for the subroutine name.
1102 SIZE is the number of bytes of arguments passed on the stack.
1104 On the ns32k, the RET insn may be used to pop them if the number
1105 of args is fixed, but if the number is variable then the caller
1106 must pop them all. RET can't be used for library calls now
1107 because the library is compiled with the Unix compiler.
1108 Use of RET is a selectable option, since it is incompatible with
1109 standard Unix calling sequences. If the option is not selected,
1110 the caller must always pop the args.
1112 The attribute stdcall is equivalent to RET on a per module basis. */
1115 ns32k_return_pops_args (fundecl, funtype, size)
1116 tree fundecl ATTRIBUTE_UNUSED;
1120 int rtd = TARGET_RTD;
1122 if (TREE_CODE (funtype) == IDENTIFIER_NODE)
1123 return rtd ? size : 0;
1125 /* Cdecl functions override -mrtd, and never pop the stack */
1126 if (lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype)))
1129 /* Stdcall functions will pop the stack if not variable args */
1130 if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype)))
1135 if (TYPE_ARG_TYPES (funtype) == NULL_TREE
1136 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype))) == void_type_node))
1143 /* PRINT_OPERAND is defined to call this function,
1144 which is easier to debug than putting all the code in
1145 a macro definition in ns32k.h. */
1147 /* XXX time 12% of cpu time is in fprintf for non optimizing */
1149 print_operand (file, x, code)
1155 PUT_IMMEDIATE_PREFIX (file);
1156 else if (code == '?')
1157 PUT_EXTERNAL_PREFIX (file);
1158 else if (GET_CODE (x) == REG)
1159 fprintf (file, "%s", ns32k_out_reg_names[REGNO (x)]);
1160 else if (GET_CODE (x) == MEM)
1162 output_address (XEXP (x, 0));
1164 else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != VOIDmode)
1168 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
1169 PUT_IMMEDIATE_PREFIX (file);
1170 if (GET_MODE (x) == DFmode)
1173 /* Sequent likes its floating point constants as integers */
1175 REAL_VALUE_TO_TARGET_DOUBLE (r, l);
1176 fprintf (file, "0Dx%08x%08x",
1177 l[!WORDS_BIG_ENDIAN], l[WORDS_BIG_ENDIAN]);
1180 real_to_decimal (s, &r, sizeof (s), 0, 1);
1182 fprintf (file, "0f%s", s);
1184 fprintf (file, "0d%s", s);
1192 REAL_VALUE_TO_TARGET_SINGLE (r, l);
1193 fprintf (file, "0Fx%08lx", l);
1196 real_to_decimal (s, &r, sizeof (s), 0, 1);
1197 fprintf (file, "0f%s", s);
1204 && GET_CODE (x) == CONST
1205 && symbolic_reference_mentioned_p (x))
1207 fprintf (stderr, "illegal constant for pic-mode: \n");
1208 print_rtl (stderr, x);
1209 fprintf (stderr, "\nGET_CODE (x) == %d, CONST == %d, symbolic_reference_mentioned_p (x) == %d\n",
1210 GET_CODE (x), CONST, symbolic_reference_mentioned_p (x));
1214 && (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF))
1216 output_addr_const (file, x);
1217 fprintf (file, "(sb)");
1221 #ifdef NO_IMMEDIATE_PREFIX_IF_SYMBOLIC
1222 if (GET_CODE (x) == CONST_INT)
1224 PUT_IMMEDIATE_PREFIX (file);
1225 output_addr_const (file, x);
1230 /* PRINT_OPERAND_ADDRESS is defined to call this function,
1231 which is easier to debug than putting all the code in
1232 a macro definition in ns32k.h . */
1234 /* Completely rewritten to get this to work with Gas for PC532 Mach.
1235 This function didn't work and I just wasn't able (nor very willing) to
1236 figure out how it worked.
1237 90-11-25 Tatu Yl|nen <ylo@cs.hut.fi> */
1240 print_operand_address (file, addr)
1241 register FILE *file;
1244 static const char scales[] = { 'b', 'w', 'd', 0, 'q', };
1245 rtx offset, base, indexexp, tmp;
1247 extern int flag_pic;
1249 if (GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == POST_DEC)
1251 fprintf (file, "tos");
1258 while (addr != NULL)
1260 if (GET_CODE (addr) == PLUS)
1262 if (GET_CODE (XEXP (addr, 0)) == PLUS)
1264 tmp = XEXP (addr, 1);
1265 addr = XEXP (addr, 0);
1269 tmp = XEXP (addr,0);
1270 addr = XEXP (addr,1);
1278 switch (GET_CODE (tmp))
1292 if (REGNO (tmp) < F0_REGNUM)
1312 if (flag_pic && ! SYMBOL_REF_LOCAL_P (tmp))
1324 if (flag_pic && GET_CODE (tmp) == CONST)
1327 tmp1 = XEXP (tmp,0);
1328 if (GET_CODE (tmp1) != PLUS)
1331 sym = XEXP (tmp1,0);
1332 if (GET_CODE (sym) != SYMBOL_REF)
1335 sym = XEXP (tmp1,1);
1338 off = XEXP (tmp1,1);
1339 if (GET_CODE (sym) == SYMBOL_REF)
1341 if (GET_CODE (off) != CONST_INT)
1344 if (! SYMBOL_REF_LOCAL_P (sym))
1366 offset = gen_rtx_PLUS (SImode, tmp, offset);
1375 offset = const0_rtx;
1378 #ifndef INDEX_RATHER_THAN_BASE
1379 && (flag_pic || TARGET_HIMEM)
1380 && GET_CODE (base) != SYMBOL_REF
1381 && GET_CODE (offset) != CONST_INT
1383 /* This is a re-implementation of the SEQUENT_ADDRESS_BUG fix. */
1385 && !indexexp && GET_CODE (base) == REG
1386 && REG_OK_FOR_INDEX_P (base))
1392 /* now, offset, base and indexexp are set */
1393 #ifndef BASE_REG_NEEDED
1396 #if defined (PC_RELATIVE) || defined (NO_ABSOLUTE_PREFIX_IF_SYMBOLIC)
1397 if (GET_CODE (offset) == CONST_INT)
1399 PUT_ABSOLUTE_PREFIX (file);
1403 output_addr_const (file, offset);
1404 if (base) /* base can be (REG ...) or (MEM ...) */
1405 switch (GET_CODE (base))
1407 /* now we must output base. Possible alternatives are:
1411 (pc) (REG ...) used for SYMBOL_REF and LABEL_REF, output
1412 (disp(fp)) (MEM ...) just before possible [rX:y]
1413 (disp(sp)) (MEM ...)
1414 (disp(sb)) (MEM ...)
1417 fprintf (file, "(%s)", ns32k_out_reg_names[REGNO (base)]);
1423 fprintf (file, "(");
1424 output_addr_const (file, base);
1425 fprintf (file, "(sb))");
1428 addr = XEXP (base,0);
1431 while (addr != NULL)
1433 if (GET_CODE (addr) == PLUS)
1435 if (GET_CODE (XEXP (addr, 0)) == PLUS)
1437 tmp = XEXP (addr, 1);
1438 addr = XEXP (addr, 0);
1442 tmp = XEXP (addr, 0);
1443 addr = XEXP (addr, 1);
1451 switch (GET_CODE (tmp))
1461 offset = gen_rtx_PLUS (SImode, tmp, offset);
1470 offset = const0_rtx;
1471 fprintf (file, "(");
1472 output_addr_const (file, offset);
1474 fprintf (file, "(%s)", ns32k_out_reg_names[REGNO (base)]);
1476 fprintf (file, "(sb)");
1479 fprintf (file, ")");
1485 else if (GET_CODE (offset) != CONST_INT)
1486 fprintf (file, "(pc)");
1487 #ifdef BASE_REG_NEEDED
1489 fprintf (file, "(sb)");
1493 #endif /* PC_RELATIVE */
1495 /* now print index if we have one */
1498 if (GET_CODE (indexexp) == MULT)
1500 scale = INTVAL (XEXP (indexexp, 1)) >> 1;
1501 indexexp = XEXP (indexexp, 0);
1505 if (GET_CODE (indexexp) != REG || REGNO (indexexp) >= F0_REGNUM)
1509 fprintf (file, "[%c`%s]",
1511 ns32k_out_reg_names[REGNO (indexexp)]);
1513 fprintf (file, "[%s:%c]",
1514 ns32k_out_reg_names[REGNO (indexexp)],
1520 /* National 32032 shifting is so bad that we can get
1521 better performance in many common cases by using other
1524 output_shift_insn (operands)
1527 if (GET_CODE (operands[2]) == CONST_INT
1528 && INTVAL (operands[2]) > 0
1529 && INTVAL (operands[2]) <= 3)
1531 if (GET_CODE (operands[0]) == REG)
1533 if (GET_CODE (operands[1]) == REG)
1535 if (REGNO (operands[0]) == REGNO (operands[1]))
1537 if (operands[2] == const1_rtx)
1538 return "addd %0,%0";
1539 else if (INTVAL (operands[2]) == 2)
1540 return "addd %0,%0\n\taddd %0,%0";
1542 if (operands[2] == const1_rtx)
1543 return "movd %1,%0\n\taddd %0,%0";
1545 operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
1546 return "addr %a1,%0";
1548 if (operands[2] == const1_rtx)
1549 return "movd %1,%0\n\taddd %0,%0";
1551 else if (GET_CODE (operands[1]) == REG)
1553 operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
1554 return "addr %a1,%0";
1556 else if (INTVAL (operands[2]) == 1
1557 && GET_CODE (operands[1]) == MEM
1558 && rtx_equal_p (operands [0], operands[1]))
1560 rtx temp = XEXP (operands[1], 0);
1562 if (GET_CODE (temp) == REG
1563 || (GET_CODE (temp) == PLUS
1564 && GET_CODE (XEXP (temp, 0)) == REG
1565 && GET_CODE (XEXP (temp, 1)) == CONST_INT))
1566 return "addd %0,%0";
1568 else return "ashd %2,%0";
1570 return "ashd %2,%0";
1574 output_move_dconst (n, s)
1580 if (n > -9 && n < 8)
1581 strcpy (r, "movqd ");
1582 else if (n > 0 && n < 256)
1583 strcpy (r, "movzbd ");
1584 else if (n > 0 && n < 65536)
1585 strcpy (r, "movzwd ");
1586 else if (n < 0 && n > -129)
1587 strcpy (r, "movxbd ");
1588 else if (n < 0 && n > -32769)
1589 strcpy (r, "movxwd ");
1591 strcpy (r, "movd ");