1 /* Subroutines for assembler code output on the NS32000.
2 Copyright (C) 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2004
3 Free Software Foundation, Inc.
5 This file is part of GCC.
7 GCC 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 GCC 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 GCC; 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 bool ns32k_handle_option (size_t, const char *, int);
68 static rtx gen_indexed_expr (rtx, rtx, rtx);
69 static const char *singlemove_string (rtx *);
70 static void move_tail (rtx[], int, int);
71 static tree ns32k_handle_fntype_attribute (tree *, tree, tree, int, bool *);
72 const struct attribute_spec ns32k_attribute_table[];
73 static void ns32k_output_function_prologue (FILE *, HOST_WIDE_INT);
74 static void ns32k_output_function_epilogue (FILE *, HOST_WIDE_INT);
75 static bool ns32k_rtx_costs (rtx, int, int, int *);
76 static int ns32k_address_cost (rtx);
77 static rtx ns32k_struct_value_rtx (tree, int);
78 static int ns32k_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
81 /* Initialize the GCC target structure. */
82 #undef TARGET_ATTRIBUTE_TABLE
83 #define TARGET_ATTRIBUTE_TABLE ns32k_attribute_table
85 #undef TARGET_ASM_ALIGNED_HI_OP
86 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
89 #undef TARGET_ASM_ALIGNED_SI_OP
90 #define TARGET_ASM_ALIGNED_SI_OP "\t.double\t"
93 #undef TARGET_ASM_FUNCTION_PROLOGUE
94 #define TARGET_ASM_FUNCTION_PROLOGUE ns32k_output_function_prologue
95 #undef TARGET_ASM_FUNCTION_EPILOGUE
96 #define TARGET_ASM_FUNCTION_EPILOGUE ns32k_output_function_epilogue
98 #undef TARGET_DEFAULT_TARGET_FLAGS
99 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
100 #undef TARGET_HANDLE_OPTION
101 #define TARGET_HANDLE_OPTION ns32k_handle_option
103 #undef TARGET_RTX_COSTS
104 #define TARGET_RTX_COSTS ns32k_rtx_costs
105 #undef TARGET_ADDRESS_COST
106 #define TARGET_ADDRESS_COST ns32k_address_cost
108 #undef TARGET_STRUCT_VALUE_RTX
109 #define TARGET_STRUCT_VALUE_RTX ns32k_struct_value_rtx
111 #undef TARGET_ARG_PARTIAL_BYTES
112 #define TARGET_ARG_PARTIAL_BYTES ns32k_arg_partial_bytes
114 #undef TARGET_ASM_FILE_START_APP_OFF
115 #define TARGET_ASM_FILE_START_APP_OFF true
117 struct gcc_target targetm = TARGET_INITIALIZER;
119 /* Implement TARGET_HANDLE_OPTION. */
122 ns32k_handle_option (size_t code, const char *arg ATTRIBUTE_UNUSED,
123 int value ATTRIBUTE_UNUSED)
128 target_flags &= ~MASK_32381;
131 case OPT_msoft_float:
132 target_flags &= ~(MASK_32081 | MASK_32381);
136 target_flags &= ~MASK_32532;
140 target_flags &= ~(MASK_32332 | MASK_32532);
148 /* Generate the assembly code for function entry. FILE is a stdio
149 stream to output the code to. SIZE is an int: how many units of
150 temporary storage to allocate.
152 Refer to the array `regs_ever_live' to determine which registers to
153 save; `regs_ever_live[I]' is nonzero if register number I is ever
154 used in the function. This function is responsible for knowing
155 which registers should not be saved even if used. */
158 * The function prologue for the ns32k is fairly simple.
159 * If a frame pointer is needed (decided in reload.c ?) then
160 * we need assembler of the form
162 * # Save the oldframe pointer, set the new frame pointer, make space
163 * # on the stack and save any general purpose registers necessary
165 * enter [<general purpose regs to save>], <local stack space>
167 * movf fn, tos # Save any floating point registers necessary
171 * If a frame pointer is not needed we need assembler of the form
173 * # Make space on the stack
175 * adjspd <local stack space + 4>
177 * # Save any general purpose registers necessary
179 * save [<general purpose regs to save>]
181 * movf fn, tos # Save any floating point registers necessary
186 #if !defined (MERLIN_TARGET) && !defined (UTEK_ASM)
188 #if defined(IMMEDIATE_PREFIX) && IMMEDIATE_PREFIX
189 #define ADJSP(FILE, N) \
190 fprintf (FILE, "\tadjspd %c" HOST_WIDE_INT_PRINT_DEC "\n", IMMEDIATE_PREFIX, (N))
192 #define ADJSP(FILE, N) \
193 fprintf (FILE, "\tadjspd " HOST_WIDE_INT_PRINT_DEC "\n", (N))
197 ns32k_output_function_prologue (FILE *file, HOST_WIDE_INT size)
199 register int regno, g_regs_used = 0;
200 int used_regs_buf[8], *bufp = used_regs_buf;
201 int used_fregs_buf[17], *fbufp = used_fregs_buf;
203 for (regno = R0_REGNUM; regno < F0_REGNUM; regno++)
204 if (regs_ever_live[regno]
205 && ! call_used_regs[regno])
207 *bufp++ = regno; g_regs_used++;
211 for (; regno < FRAME_POINTER_REGNUM; regno++)
212 if (regs_ever_live[regno] && !call_used_regs[regno])
218 bufp = used_regs_buf;
219 if (frame_pointer_needed)
220 fprintf (file, "\tenter [");
224 ADJSP (file, size + 4);
225 if (g_regs_used && g_regs_used > 4)
226 fprintf (file, "\tsave [");
230 fprintf (file, "\tmovd r%d,tos\n", *bufp++);
237 fprintf (file, "r%d", *bufp++);
242 if (frame_pointer_needed)
243 fprintf (file, "]," HOST_WIDE_INT_PRINT_DEC "\n", size);
244 else if (g_regs_used)
245 fprintf (file, "]\n");
247 fbufp = used_fregs_buf;
250 if ((*fbufp & 1) || (fbufp[0] != fbufp[1] - 1))
251 fprintf (file, "\tmovf %s,tos\n", ns32k_out_reg_names[*fbufp++]);
254 fprintf (file, "\tmovl %s,tos\n",
255 ns32k_out_reg_names[fbufp[0]]);
260 if (flag_pic && current_function_uses_pic_offset_table)
262 fprintf (file, "\tsprd sb,tos\n");
265 fprintf (file, "\taddr __GLOBAL_OFFSET_TABLE_(pc),tos\n");
266 fprintf (file, "\tlprd sb,tos\n");
270 fprintf (file, "\taddr __GLOBAL_OFFSET_TABLE_(pc),r0\n");
271 fprintf (file, "\tlprd sb,r0\n");
276 #else /* MERLIN_TARGET || UTEK_ASM */
278 /* This differs from the standard one above in printing a bitmask
279 rather than a register list in the enter or save instruction. */
282 ns32k_output_function_prologue (file, size)
286 register int regno, g_regs_used = 0;
287 int used_regs_buf[8], *bufp = used_regs_buf;
288 int used_fregs_buf[8], *fbufp = used_fregs_buf;
290 for (regno = 0; regno < 8; regno++)
291 if (regs_ever_live[regno]
292 && ! call_used_regs[regno])
294 *bufp++ = regno; g_regs_used++;
298 for (; regno < 16; regno++)
299 if (regs_ever_live[regno] && !call_used_regs[regno]) {
304 bufp = used_regs_buf;
305 if (frame_pointer_needed)
306 fprintf (file, "\tenter ");
307 else if (g_regs_used)
308 fprintf (file, "\tsave ");
310 if (frame_pointer_needed || g_regs_used)
314 mask |= 1 << *bufp++;
315 fprintf (file, "$0x%x", (int) mask & 0xff);
318 if (frame_pointer_needed)
320 fprintf (file, ",$%d\n", size);
322 fprintf (file, ",%d\n", size);
324 else if (g_regs_used)
325 fprintf (file, "\n");
327 fbufp = used_fregs_buf;
330 if ((*fbufp & 1) || (fbufp[0] != fbufp[1] - 1))
331 fprintf (file, "\tmovf f%d,tos\n", *fbufp++ - 8);
334 fprintf (file, "\tmovl f%d,tos\n", fbufp[0] - 8);
340 #endif /* MERLIN_TARGET || UTEK_ASM */
342 /* This function generates the assembly code for function exit,
343 on machines that need it.
345 The function epilogue should not depend on the current stack pointer,
346 if EXIT_IGNORE_STACK is nonzero. That doesn't apply here.
348 If a frame pointer is needed (decided in reload.c ?) then
349 we need assembler of the form
351 movf tos, fn # Restore any saved floating point registers
355 # Restore any saved general purpose registers, restore the stack
356 # pointer from the frame pointer, restore the old frame pointer.
357 exit [<general purpose regs to save>]
359 If a frame pointer is not needed we need assembler of the form
360 # Restore any general purpose registers saved
362 movf tos, fn # Restore any saved floating point registers
366 restore [<general purpose regs to save>]
368 # reclaim space allocated on stack
370 adjspd <-(local stack space + 4)> */
372 #if !defined (MERLIN_TARGET) && !defined (UTEK_ASM)
375 ns32k_output_function_epilogue (FILE *file, HOST_WIDE_INT size)
377 register int regno, g_regs_used = 0, f_regs_used = 0;
378 int used_regs_buf[8], *bufp = used_regs_buf;
379 int used_fregs_buf[17], *fbufp = used_fregs_buf;
381 if (flag_pic && current_function_uses_pic_offset_table)
382 fprintf (file, "\tlprd sb,tos\n");
385 for (regno = F0_REGNUM; regno < FRAME_POINTER_REGNUM; regno++)
386 if (regs_ever_live[regno] && !call_used_regs[regno])
388 *fbufp++ = regno; f_regs_used++;
392 for (regno = 0; regno < F0_REGNUM; regno++)
393 if (regs_ever_live[regno]
394 && ! call_used_regs[regno])
396 *bufp++ = regno; g_regs_used++;
399 while (fbufp > used_fregs_buf)
401 if ((*fbufp & 1) && fbufp[0] == fbufp[-1] + 1)
403 fprintf (file, "\tmovl tos,%s\n",
404 ns32k_out_reg_names[fbufp[-1]]);
407 else fprintf (file, "\tmovf tos,%s\n", ns32k_out_reg_names[*fbufp--]);
410 if (frame_pointer_needed)
411 fprintf (file, "\texit [");
414 if (g_regs_used && g_regs_used > 4)
415 fprintf (file, "\trestore [");
418 while (bufp > used_regs_buf)
419 fprintf (file, "\tmovd tos,r%d\n", *--bufp);
424 while (bufp > used_regs_buf)
426 fprintf (file, "r%d", *--bufp);
427 if (bufp > used_regs_buf)
431 if (g_regs_used || frame_pointer_needed)
432 fprintf (file, "]\n");
434 if (size && !frame_pointer_needed)
435 ADJSP (file, -(size + 4));
437 if (current_function_pops_args)
438 fprintf (file, "\tret %d\n", current_function_pops_args);
440 fprintf (file, "\tret 0\n");
443 #else /* MERLIN_TARGET || UTEK_ASM */
445 /* This differs from the standard one above in printing a bitmask
446 rather than a register list in the exit or restore instruction. */
449 ns32k_output_function_epilogue (file, size)
451 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
453 register int regno, g_regs_used = 0, f_regs_used = 0;
454 int used_regs_buf[8], *bufp = used_regs_buf;
455 int used_fregs_buf[8], *fbufp = used_fregs_buf;
458 for (regno = 8; regno < 16; regno++)
459 if (regs_ever_live[regno] && !call_used_regs[regno]) {
460 *fbufp++ = regno; f_regs_used++;
464 for (regno = 0; regno < 8; regno++)
465 if (regs_ever_live[regno]
466 && ! call_used_regs[regno])
468 *bufp++ = regno; g_regs_used++;
471 while (fbufp > used_fregs_buf)
473 if ((*fbufp & 1) && fbufp[0] == fbufp[-1] + 1)
475 fprintf (file, "\tmovl tos,f%d\n", fbufp[-1] - 8);
478 else fprintf (file, "\tmovf tos,f%d\n", *fbufp-- - 8);
481 if (frame_pointer_needed)
482 fprintf (file, "\texit ");
483 else if (g_regs_used)
484 fprintf (file, "\trestore ");
486 if (g_regs_used || frame_pointer_needed)
490 while (bufp > used_regs_buf)
492 /* Utek assembler takes care of reversing this */
493 mask |= 1 << *--bufp;
495 fprintf (file, "$0x%x\n", (int) mask & 0xff);
499 if (current_function_pops_args)
500 fprintf (file, "\tret $%d\n", current_function_pops_args);
502 fprintf (file, "\tret $0\n");
504 if (current_function_pops_args)
505 fprintf (file, "\tret %d\n", current_function_pops_args);
507 fprintf (file, "\tret 0\n");
511 #endif /* MERLIN_TARGET || UTEK_ASM */
513 /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */
515 hard_regno_mode_ok (int regno, enum machine_mode mode)
517 int size = GET_MODE_UNIT_SIZE (mode);
519 if (FLOAT_MODE_P (mode))
521 if (size == UNITS_PER_WORD && regno < L1_REGNUM)
523 if (size == UNITS_PER_WORD * 2
524 && (((regno & 1) == 0 && regno < FRAME_POINTER_REGNUM)))
528 if (size == UNITS_PER_WORD * 2
529 && (regno & 1) == 0 && regno < F0_REGNUM)
531 if (size <= UNITS_PER_WORD
532 && (regno < F0_REGNUM || regno == FRAME_POINTER_REGNUM
533 || regno == STACK_POINTER_REGNUM))
539 ns32k_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total)
544 if (INTVAL (x) <= 7 && INTVAL (x) >= -8)
546 else if (INTVAL (x) < 0x2000 && INTVAL (x) >= -0x2000)
568 register_move_cost (enum reg_class CLASS1, enum reg_class CLASS2)
570 if (CLASS1 == NO_REGS || CLASS2 == NO_REGS)
572 if ((SUBSET_P (CLASS1, FP_REGS) && !SUBSET_P (CLASS2, FP_REGS))
573 || (!SUBSET_P (CLASS1, FP_REGS) && SUBSET_P (CLASS2, FP_REGS)))
575 if (((CLASS1) == STACK_POINTER_REG && !SUBSET_P (CLASS2,GENERAL_REGS))
576 || ((CLASS2) == STACK_POINTER_REG && !SUBSET_P (CLASS1,GENERAL_REGS)))
578 if (((CLASS1) == FRAME_POINTER_REG && !SUBSET_P (CLASS2,GENERAL_REGS))
579 || ((CLASS2) == FRAME_POINTER_REG && !SUBSET_P (CLASS1,GENERAL_REGS)))
585 /* We made the insn definitions copy from floating point to general
586 registers via the stack. */
588 secondary_memory_needed (enum reg_class CLASS1,
589 enum reg_class CLASS2,
592 int ret = ((SUBSET_P (CLASS1, FP_REGS) && !SUBSET_P (CLASS2, FP_REGS))
593 || (!SUBSET_P (CLASS1, FP_REGS) && SUBSET_P (CLASS2, FP_REGS)));
599 /* TARGET_ADDRESS_COST calls this. This function is not optimal
600 for the 32032 & 32332, but it probably is better than
604 ns32k_address_cost (rtx operand)
608 switch (GET_CODE (operand))
619 if (INTVAL (operand) <= 7 && INTVAL (operand) >= -8)
621 if (INTVAL (operand) < 0x2000 && INTVAL (operand) >= -0x2000)
636 cost += ns32k_address_cost (XEXP (operand, 0)) + 3;
643 cost += ns32k_address_cost (XEXP (operand, 0));
644 cost += ns32k_address_cost (XEXP (operand, 1));
654 /* Return the register class of a scratch register needed to copy IN into
655 or out of a register in CLASS in MODE. If it can be done directly,
656 NO_REGS is returned. */
659 secondary_reload_class (enum reg_class class,
660 enum machine_mode mode ATTRIBUTE_UNUSED,
663 int regno = true_regnum (in);
665 if (regno >= FIRST_PSEUDO_REGISTER)
668 if ((class == FRAME_POINTER_REG && regno == STACK_POINTER_REGNUM)
669 || ( class == STACK_POINTER_REG && regno == FRAME_POINTER_REGNUM))
675 /* Generate the rtx that comes from an address expression in the md file */
676 /* The expression to be build is BASE[INDEX:SCALE]. To recognize this,
677 scale must be converted from an exponent (from ASHIFT) to a
678 multiplier (for MULT). */
681 gen_indexed_expr (rtx base, rtx index, rtx scale)
685 /* This generates an invalid addressing mode, if BASE is
686 fp or sp. This is handled by PRINT_OPERAND_ADDRESS. */
687 if (GET_CODE (base) != REG && GET_CODE (base) != CONST_INT)
688 base = gen_rtx_MEM (SImode, base);
689 addr = gen_rtx_MULT (SImode, index,
690 GEN_INT (1 << INTVAL (scale)));
691 addr = gen_rtx_PLUS (SImode, base, addr);
696 /* Split one or more DImode RTL references into pairs of SImode
697 references. The RTL can be REG, offsettable MEM, integer constant, or
698 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
699 split and "num" is its length. lo_half and hi_half are output arrays
700 that parallel "operands". */
703 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
707 if (GET_CODE (operands[num]) == REG)
709 lo_half[num] = gen_rtx_REG (SImode, REGNO (operands[num]));
710 hi_half[num] = gen_rtx_REG (SImode, REGNO (operands[num]) + 1);
712 else if (CONSTANT_P (operands[num]))
714 split_double (operands[num], &lo_half[num], &hi_half[num]);
716 else if (offsettable_memref_p (operands[num]))
718 lo_half[num] = operands[num];
719 hi_half[num] = adjust_address (operands[num], SImode, 4);
726 /* Return the best assembler insn template
727 for moving operands[1] into operands[0] as a fullword. */
730 singlemove_string (rtx *operands)
732 if (GET_CODE (operands[1]) == CONST_INT
733 && INTVAL (operands[1]) <= 7
734 && INTVAL (operands[1]) >= -8)
735 return "movqd %1,%0";
740 output_move_double (rtx *operands)
742 enum anon1 { REGOP, OFFSOP, PUSHOP, CNSTOP, RNDOP } optype0, optype1;
745 /* First classify both operands. */
747 if (REG_P (operands[0]))
749 else if (offsettable_memref_p (operands[0]))
751 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
756 if (REG_P (operands[1]))
758 else if (CONSTANT_P (operands[1])
759 || GET_CODE (operands[1]) == CONST_DOUBLE)
761 else if (offsettable_memref_p (operands[1]))
763 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
768 /* Check for the cases that the operand constraints are not
769 supposed to allow to happen. Abort if we get one,
770 because generating code for these cases is painful. */
772 if (optype0 == RNDOP || optype1 == RNDOP)
775 /* Ok, we can do one word at a time.
776 Normally we do the low-numbered word first,
777 but if either operand is autodecrementing then we
778 do the high-numbered word first.
780 In either case, set up in LATEHALF the operands to use
781 for the high-numbered word and in some cases alter the
782 operands in OPERANDS to be suitable for the low-numbered word. */
784 if (optype0 == REGOP)
785 latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
786 else if (optype0 == OFFSOP)
787 latehalf[0] = adjust_address (operands[0], SImode, 4);
789 latehalf[0] = operands[0];
791 if (optype1 == REGOP)
792 latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
793 else if (optype1 == OFFSOP)
794 latehalf[1] = adjust_address (operands[1], SImode, 4);
795 else if (optype1 == CNSTOP)
796 split_double (operands[1], &operands[1], &latehalf[1]);
798 latehalf[1] = operands[1];
800 /* If insn is effectively movd N(sp),tos then we will do the
801 high word first. We should use the adjusted operand 1 (which is N+4(sp))
802 for the low word as well, to compensate for the first decrement of sp.
803 Given this, it doesn't matter which half we do "first". */
804 if (optype0 == PUSHOP
805 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
806 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
807 operands[1] = latehalf[1];
809 /* If one or both operands autodecrementing,
810 do the two words, high-numbered first. */
811 else if (optype0 == PUSHOP || optype1 == PUSHOP)
813 output_asm_insn (singlemove_string (latehalf), latehalf);
814 return singlemove_string (operands);
817 /* If the first move would clobber the source of the second one,
818 do them in the other order. */
820 /* Overlapping registers. */
821 if (optype0 == REGOP && optype1 == REGOP
822 && REGNO (operands[0]) == REGNO (latehalf[1]))
825 output_asm_insn (singlemove_string (latehalf), latehalf);
826 /* Do low-numbered word. */
827 return singlemove_string (operands);
829 /* Loading into a register which overlaps a register used in the address. */
830 else if (optype0 == REGOP && optype1 != REGOP
831 && reg_overlap_mentioned_p (operands[0], operands[1]))
833 if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))
834 && reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
836 /* If both halves of dest are used in the src memory address,
837 load the destination address into the low reg (operands[0]).
838 Then it works to load latehalf first. */
840 xops[0] = XEXP (operands[1], 0);
841 xops[1] = operands[0];
842 output_asm_insn ("addr %a0,%1", xops);
843 operands[1] = gen_rtx_MEM (DImode, operands[0]);
844 latehalf[1] = adjust_address (operands[1], SImode, 4);
845 /* The first half has the overlap, Do the late half first. */
846 output_asm_insn (singlemove_string (latehalf), latehalf);
848 return singlemove_string (operands);
850 if (reg_mentioned_p (operands[0], XEXP (operands[1], 0)))
852 /* The first half has the overlap, Do the late half first. */
853 output_asm_insn (singlemove_string (latehalf), latehalf);
855 return singlemove_string (operands);
859 /* Normal case. Do the two words, low-numbered first. */
861 output_asm_insn (singlemove_string (operands), operands);
863 operands[0] = latehalf[0];
864 operands[1] = latehalf[1];
865 return singlemove_string (operands);
869 #define MAX_UNALIGNED_COPY (32)
870 /* Expand string/block move operations.
872 operands[0] is the pointer to the destination.
873 operands[1] is the pointer to the source.
874 operands[2] is the number of bytes to move.
875 operands[3] is the alignment. */
878 move_tail (rtx operands[], int bytes, int offset)
882 emit_move_insn (adjust_address (operands[0], HImode, offset),
883 adjust_address (operands[1], HImode, offset));
887 emit_move_insn (adjust_address (operands[0], QImode, offset),
888 adjust_address (operands[1], QImode, offset));
892 expand_block_move (rtx operands[])
894 rtx bytes_rtx = operands[2];
895 rtx align_rtx = operands[3];
896 int constp = (GET_CODE (bytes_rtx) == CONST_INT);
897 int bytes = (constp ? INTVAL (bytes_rtx) : 0);
898 int align = INTVAL (align_rtx);
899 rtx src_reg = gen_rtx_REG (Pmode, 1);
900 rtx dest_reg = gen_rtx_REG (Pmode, 2);
901 rtx count_reg = gen_rtx_REG (SImode, 0);
903 if (constp && bytes <= 0)
906 if (constp && bytes < 20)
908 int words = bytes >> 2;
916 for (; words; words--, offset += 4)
917 emit_move_insn (adjust_address (operands[0], SImode, offset),
918 adjust_address (operands[1], SImode, offset));
922 /* Use movmd. It is slower than multiple movd's but more
923 compact. It is also slower than movsd for large copies
924 but causes less registers reloading so is better than movsd
927 dest = copy_addr_to_reg (XEXP (operands[0], 0));
928 src = copy_addr_to_reg (XEXP (operands[1], 0));
930 emit_insn (gen_movmemsi2(dest, src, GEN_INT (words)));
933 move_tail (operands, bytes & 3, bytes & ~3);
937 if (align > UNITS_PER_WORD)
938 align = UNITS_PER_WORD;
940 /* Move the address into scratch registers. */
941 emit_insn (gen_rtx_CLOBBER (VOIDmode, dest_reg));
942 emit_move_insn (dest_reg, XEXP (operands[0], 0));
943 operands[0] = gen_rtx_MEM (SImode, dest_reg);
944 emit_insn (gen_rtx_CLOBBER (VOIDmode, src_reg));
945 emit_move_insn (src_reg, XEXP (operands[1], 0));
946 operands[1] = gen_rtx_MEM (SImode, src_reg);
947 emit_insn (gen_rtx_CLOBBER (VOIDmode, count_reg));
949 if (constp && (align == UNITS_PER_WORD || bytes < MAX_UNALIGNED_COPY))
951 /* constant no of bytes and aligned or small enough copy to not bother
952 * aligning. Emit insns to copy by words.
956 emit_move_insn (count_reg, GEN_INT (bytes >> 2));
957 emit_insn (gen_movmemsi1 (GEN_INT (4)));
959 /* insns to copy rest */
960 move_tail (operands, bytes & 3, 0);
962 else if (align == UNITS_PER_WORD)
964 /* insns to copy by words */
965 emit_insn (gen_lshrsi3 (count_reg, bytes_rtx, const2_rtx));
966 emit_insn (gen_movmemsi1 (GEN_INT (4)));
969 move_tail (operands, bytes & 3, 0);
973 /* insns to copy rest */
974 emit_insn (gen_andsi3 (count_reg, bytes_rtx, GEN_INT (3)));
975 emit_insn (gen_movmemsi1 (const1_rtx));
980 /* Not aligned and we may have a lot to copy so it is worth
983 rtx aligned_label = gen_label_rtx ();
986 bytes_reg = copy_to_mode_reg (SImode, bytes_rtx);
989 /* Emit insns to test and skip over the alignment if it is
990 * not worth it. This doubles as a test to ensure that the alignment
991 * operation can't copy too many bytes
993 emit_insn (gen_cmpsi (bytes_reg, GEN_INT (MAX_UNALIGNED_COPY)));
994 emit_jump_insn (gen_blt (aligned_label));
997 /* Emit insns to do alignment at run time */
998 emit_insn (gen_negsi2 (count_reg, src_reg));
999 emit_insn (gen_andsi3 (count_reg, count_reg, GEN_INT (3)));
1000 emit_insn (gen_subsi3 (bytes_reg, bytes_reg, count_reg));
1001 emit_insn (gen_movmemsi1 (const1_rtx));
1003 emit_label (aligned_label);
1005 /* insns to copy by words */
1006 emit_insn (gen_lshrsi3 (count_reg, bytes_reg, const2_rtx));
1007 emit_insn (gen_movmemsi1 (GEN_INT (4)));
1009 /* insns to copy rest */
1010 emit_insn (gen_andsi3 (count_reg, bytes_reg, GEN_INT (3)));
1011 emit_insn (gen_movmemsi1 (const1_rtx));
1016 /* Returns 1 if OP contains a global symbol reference */
1019 global_symbolic_reference_mentioned_p (rtx op, int f)
1021 register const char *fmt;
1024 if (GET_CODE (op) == SYMBOL_REF)
1026 if (! SYMBOL_REF_LOCAL_P (op))
1031 else if (f && GET_CODE (op) != CONST)
1034 fmt = GET_RTX_FORMAT (GET_CODE (op));
1035 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
1041 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
1042 if (global_symbolic_reference_mentioned_p (XVECEXP (op, i, j), 0))
1045 else if (fmt[i] == 'e'
1046 && global_symbolic_reference_mentioned_p (XEXP (op, i), 0))
1054 /* Returns 1 if OP contains a symbol reference */
1057 symbolic_reference_mentioned_p (rtx op)
1059 register const char *fmt;
1062 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
1065 fmt = GET_RTX_FORMAT (GET_CODE (op));
1066 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
1072 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
1073 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
1076 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
1083 /* Table of machine-specific attributes. */
1085 const struct attribute_spec ns32k_attribute_table[] =
1087 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
1088 /* Stdcall attribute says callee is responsible for popping arguments
1089 if they are not variable. */
1090 { "stdcall", 0, 0, false, true, true, ns32k_handle_fntype_attribute },
1091 /* Cdecl attribute says the callee is a normal C declaration */
1092 { "cdecl", 0, 0, false, true, true, ns32k_handle_fntype_attribute },
1093 { NULL, 0, 0, false, false, false, NULL }
1096 /* Handle an attribute requiring a FUNCTION_TYPE, FIELD_DECL or TYPE_DECL;
1097 arguments as in struct attribute_spec.handler. */
1099 ns32k_handle_fntype_attribute (tree *node, tree name,
1100 tree args ATTRIBUTE_UNUSED,
1101 int flags ATTRIBUTE_UNUSED,
1104 if (TREE_CODE (*node) != FUNCTION_TYPE
1105 && TREE_CODE (*node) != FIELD_DECL
1106 && TREE_CODE (*node) != TYPE_DECL)
1108 warning ("%qs attribute only applies to functions",
1109 IDENTIFIER_POINTER (name));
1110 *no_add_attrs = true;
1117 /* Value is the number of bytes of arguments automatically
1118 popped when returning from a subroutine call.
1119 FUNDECL is the declaration node of the function (as a tree),
1120 FUNTYPE is the data type of the function (as a tree),
1121 or for a library call it is an identifier node for the subroutine name.
1122 SIZE is the number of bytes of arguments passed on the stack.
1124 On the ns32k, the RET insn may be used to pop them if the number
1125 of args is fixed, but if the number is variable then the caller
1126 must pop them all. RET can't be used for library calls now
1127 because the library is compiled with the Unix compiler.
1128 Use of RET is a selectable option, since it is incompatible with
1129 standard Unix calling sequences. If the option is not selected,
1130 the caller must always pop the args.
1132 The attribute stdcall is equivalent to RET on a per module basis. */
1135 ns32k_return_pops_args (tree fundecl ATTRIBUTE_UNUSED, tree funtype, int size)
1137 int rtd = TARGET_RTD;
1139 if (TREE_CODE (funtype) == IDENTIFIER_NODE)
1140 return rtd ? size : 0;
1142 /* Cdecl functions override -mrtd, and never pop the stack */
1143 if (lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype)))
1146 /* Stdcall functions will pop the stack if not variable args */
1147 if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype)))
1152 if (TYPE_ARG_TYPES (funtype) == NULL_TREE
1153 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype))) == void_type_node))
1160 /* PRINT_OPERAND is defined to call this function,
1161 which is easier to debug than putting all the code in
1162 a macro definition in ns32k.h. */
1164 /* XXX time 12% of cpu time is in fprintf for non optimizing */
1166 print_operand (FILE *file, rtx x, int code)
1169 PUT_IMMEDIATE_PREFIX (file);
1170 else if (code == '?')
1171 PUT_EXTERNAL_PREFIX (file);
1172 else if (GET_CODE (x) == REG)
1173 fprintf (file, "%s", ns32k_out_reg_names[REGNO (x)]);
1174 else if (GET_CODE (x) == MEM)
1176 output_address (XEXP (x, 0));
1178 else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != VOIDmode)
1182 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
1183 PUT_IMMEDIATE_PREFIX (file);
1184 if (GET_MODE (x) == DFmode)
1187 /* Sequent likes its floating point constants as integers */
1189 REAL_VALUE_TO_TARGET_DOUBLE (r, l);
1190 fprintf (file, "0Dx%08x%08x",
1191 l[!WORDS_BIG_ENDIAN], l[WORDS_BIG_ENDIAN]);
1194 real_to_decimal (s, &r, sizeof (s), 0, 1);
1196 fprintf (file, "0f%s", s);
1198 fprintf (file, "0d%s", s);
1206 REAL_VALUE_TO_TARGET_SINGLE (r, l);
1207 fprintf (file, "0Fx%08lx", l);
1210 real_to_decimal (s, &r, sizeof (s), 0, 1);
1211 fprintf (file, "0f%s", s);
1218 && GET_CODE (x) == CONST
1219 && symbolic_reference_mentioned_p (x))
1221 fprintf (stderr, "illegal constant for pic-mode: \n");
1222 print_rtl (stderr, x);
1223 fprintf (stderr, "\nGET_CODE (x) == %d, CONST == %d, symbolic_reference_mentioned_p (x) == %d\n",
1224 GET_CODE (x), CONST, symbolic_reference_mentioned_p (x));
1228 && (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF))
1230 output_addr_const (file, x);
1231 fprintf (file, "(sb)");
1235 #ifdef NO_IMMEDIATE_PREFIX_IF_SYMBOLIC
1236 if (GET_CODE (x) == CONST_INT)
1238 PUT_IMMEDIATE_PREFIX (file);
1239 output_addr_const (file, x);
1244 /* PRINT_OPERAND_ADDRESS is defined to call this function,
1245 which is easier to debug than putting all the code in
1246 a macro definition in ns32k.h . */
1248 /* Completely rewritten to get this to work with Gas for PC532 Mach.
1249 This function didn't work and I just wasn't able (nor very willing) to
1250 figure out how it worked.
1251 90-11-25 Tatu Yl|nen <ylo@cs.hut.fi> */
1254 print_operand_address (register FILE *file, register rtx addr)
1256 static const char scales[] = { 'b', 'w', 'd', 0, 'q', };
1257 rtx offset, base, indexexp, tmp;
1259 extern int flag_pic;
1261 if (GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == POST_DEC)
1263 fprintf (file, "tos");
1270 while (addr != NULL)
1272 if (GET_CODE (addr) == PLUS)
1274 if (GET_CODE (XEXP (addr, 0)) == PLUS)
1276 tmp = XEXP (addr, 1);
1277 addr = XEXP (addr, 0);
1281 tmp = XEXP (addr,0);
1282 addr = XEXP (addr,1);
1290 switch (GET_CODE (tmp))
1304 if (REGNO (tmp) < F0_REGNUM)
1324 if (flag_pic && ! SYMBOL_REF_LOCAL_P (tmp))
1336 if (flag_pic && GET_CODE (tmp) == CONST)
1339 tmp1 = XEXP (tmp,0);
1340 if (GET_CODE (tmp1) != PLUS)
1343 sym = XEXP (tmp1,0);
1344 if (GET_CODE (sym) != SYMBOL_REF)
1347 sym = XEXP (tmp1,1);
1350 off = XEXP (tmp1,1);
1351 if (GET_CODE (sym) == SYMBOL_REF)
1353 if (GET_CODE (off) != CONST_INT)
1356 if (! SYMBOL_REF_LOCAL_P (sym))
1378 offset = gen_rtx_PLUS (SImode, tmp, offset);
1387 offset = const0_rtx;
1390 #ifndef INDEX_RATHER_THAN_BASE
1391 && (flag_pic || TARGET_HIMEM)
1392 && GET_CODE (base) != SYMBOL_REF
1393 && GET_CODE (offset) != CONST_INT
1395 /* This is a re-implementation of the SEQUENT_ADDRESS_BUG fix. */
1397 && !indexexp && GET_CODE (base) == REG
1398 && REG_OK_FOR_INDEX_P (base))
1404 /* now, offset, base and indexexp are set */
1405 #ifndef BASE_REG_NEEDED
1408 #if defined (PC_RELATIVE) || defined (NO_ABSOLUTE_PREFIX_IF_SYMBOLIC)
1409 if (GET_CODE (offset) == CONST_INT)
1411 PUT_ABSOLUTE_PREFIX (file);
1415 output_addr_const (file, offset);
1416 if (base) /* base can be (REG ...) or (MEM ...) */
1417 switch (GET_CODE (base))
1419 /* now we must output base. Possible alternatives are:
1423 (pc) (REG ...) used for SYMBOL_REF and LABEL_REF, output
1424 (disp(fp)) (MEM ...) just before possible [rX:y]
1425 (disp(sp)) (MEM ...)
1426 (disp(sb)) (MEM ...)
1429 fprintf (file, "(%s)", ns32k_out_reg_names[REGNO (base)]);
1435 fprintf (file, "(");
1436 output_addr_const (file, base);
1437 fprintf (file, "(sb))");
1440 addr = XEXP (base,0);
1443 while (addr != NULL)
1445 if (GET_CODE (addr) == PLUS)
1447 if (GET_CODE (XEXP (addr, 0)) == PLUS)
1449 tmp = XEXP (addr, 1);
1450 addr = XEXP (addr, 0);
1454 tmp = XEXP (addr, 0);
1455 addr = XEXP (addr, 1);
1463 switch (GET_CODE (tmp))
1473 offset = gen_rtx_PLUS (SImode, tmp, offset);
1482 offset = const0_rtx;
1483 fprintf (file, "(");
1484 output_addr_const (file, offset);
1486 fprintf (file, "(%s)", ns32k_out_reg_names[REGNO (base)]);
1488 fprintf (file, "(sb)");
1491 fprintf (file, ")");
1497 else if (GET_CODE (offset) != CONST_INT)
1498 fprintf (file, "(pc)");
1499 #ifdef BASE_REG_NEEDED
1501 fprintf (file, "(sb)");
1505 #endif /* PC_RELATIVE */
1507 /* now print index if we have one */
1510 if (GET_CODE (indexexp) == MULT)
1512 scale = INTVAL (XEXP (indexexp, 1)) >> 1;
1513 indexexp = XEXP (indexexp, 0);
1517 if (GET_CODE (indexexp) != REG || REGNO (indexexp) >= F0_REGNUM)
1521 fprintf (file, "[%c`%s]",
1523 ns32k_out_reg_names[REGNO (indexexp)]);
1525 fprintf (file, "[%s:%c]",
1526 ns32k_out_reg_names[REGNO (indexexp)],
1532 /* National 32032 shifting is so bad that we can get
1533 better performance in many common cases by using other
1536 output_shift_insn (rtx *operands)
1538 if (GET_CODE (operands[2]) == CONST_INT
1539 && INTVAL (operands[2]) > 0
1540 && INTVAL (operands[2]) <= 3)
1542 if (GET_CODE (operands[0]) == REG)
1544 if (GET_CODE (operands[1]) == REG)
1546 if (REGNO (operands[0]) == REGNO (operands[1]))
1548 if (operands[2] == const1_rtx)
1549 return "addd %0,%0";
1550 else if (INTVAL (operands[2]) == 2)
1551 return "addd %0,%0\n\taddd %0,%0";
1553 if (operands[2] == const1_rtx)
1554 return "movd %1,%0\n\taddd %0,%0";
1556 operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
1557 return "addr %a1,%0";
1559 if (operands[2] == const1_rtx)
1560 return "movd %1,%0\n\taddd %0,%0";
1562 else if (GET_CODE (operands[1]) == REG)
1564 operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
1565 return "addr %a1,%0";
1567 else if (INTVAL (operands[2]) == 1
1568 && GET_CODE (operands[1]) == MEM
1569 && rtx_equal_p (operands [0], operands[1]))
1571 rtx temp = XEXP (operands[1], 0);
1573 if (GET_CODE (temp) == REG
1574 || (GET_CODE (temp) == PLUS
1575 && GET_CODE (XEXP (temp, 0)) == REG
1576 && GET_CODE (XEXP (temp, 1)) == CONST_INT))
1577 return "addd %0,%0";
1579 else return "ashd %2,%0";
1581 return "ashd %2,%0";
1585 output_move_dconst (int n, const char *s)
1589 if (n > -9 && n < 8)
1590 strcpy (r, "movqd ");
1591 else if (n > 0 && n < 256)
1592 strcpy (r, "movzbd ");
1593 else if (n > 0 && n < 65536)
1594 strcpy (r, "movzwd ");
1595 else if (n < 0 && n > -129)
1596 strcpy (r, "movxbd ");
1597 else if (n < 0 && n > -32769)
1598 strcpy (r, "movxwd ");
1600 strcpy (r, "movd ");
1606 ns32k_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
1607 int incoming ATTRIBUTE_UNUSED)
1609 return gen_rtx_REG (Pmode, NS32K_STRUCT_VALUE_REGNUM);
1612 /* Worker function for NOTICE_UPDATE_CC. */
1615 ns32k_notice_update_cc (rtx exp, rtx insn ATTRIBUTE_UNUSED)
1617 if (GET_CODE (exp) == SET)
1619 if (GET_CODE (SET_DEST (exp)) == CC0)
1621 cc_status.flags = 0;
1622 cc_status.value1 = SET_DEST (exp);
1623 cc_status.value2 = SET_SRC (exp);
1625 else if (GET_CODE (SET_SRC (exp)) == CALL)
1629 else if (GET_CODE (SET_DEST (exp)) == REG)
1631 if (cc_status.value1
1632 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1))
1633 cc_status.value1 = 0;
1634 if (cc_status.value2
1635 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2))
1636 cc_status.value2 = 0;
1638 else if (GET_CODE (SET_DEST (exp)) == MEM)
1643 else if (GET_CODE (exp) == PARALLEL
1644 && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
1646 if (GET_CODE (SET_DEST (XVECEXP (exp, 0, 0))) == CC0)
1648 cc_status.flags = 0;
1649 cc_status.value1 = SET_DEST (XVECEXP (exp, 0, 0));
1650 cc_status.value2 = SET_SRC (XVECEXP (exp, 0, 0));
1652 else if (GET_CODE (SET_DEST (XVECEXP (exp, 0, 0))) == REG)
1654 if (cc_status.value1
1655 && reg_overlap_mentioned_p (SET_DEST (XVECEXP (exp, 0, 0)),
1657 cc_status.value1 = 0;
1658 if (cc_status.value2
1659 && reg_overlap_mentioned_p (SET_DEST (XVECEXP (exp, 0, 0)),
1661 cc_status.value2 = 0;
1663 else if (GET_CODE (SET_DEST (XVECEXP (exp, 0, 0))) == MEM)
1668 else if (GET_CODE (exp) == CALL)
1670 /* all bets are off */
1675 /* nothing happens? CC_STATUS_INIT; */
1677 if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
1679 && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
1683 /* Implement TARGET_ARG_PARTIAL_BYTES. */
1686 ns32k_arg_partial_bytes (CUMULATIVE_ARGS *pcum, enum machine_mode mode,
1687 tree type, bool named ATTRIBUTE_UNUSED)
1691 if (TARGET_REGPARM && cum < 8)
1695 if (mode == BLKmode)
1696 size = int_size_in_bytes (type);
1698 size = GET_MODE_SIZE (mode);