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. */
26 #include "hard-reg-set.h"
28 #include "insn-config.h"
29 #include "conditions.h"
31 #include "insn-attr.h"
39 #include "target-def.h"
43 int ns32k_num_files = 0;
46 /* This duplicates reg_class_contents in reg_class.c, but maybe that isn't
47 initialized in time. Also this is more convenient as an array of ints.
48 We know that HARD_REG_SET fits in an unsigned int */
50 const unsigned int ns32k_reg_class_contents[N_REG_CLASSES][1] = REG_CLASS_CONTENTS;
52 const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] =
54 GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
55 GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
56 FLOAT_REG0, LONG_FLOAT_REG0, FLOAT_REGS, FLOAT_REGS,
57 FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, FLOAT_REGS,
58 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
59 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
60 FRAME_POINTER_REG, STACK_POINTER_REG
63 static const char *const ns32k_out_reg_names[] = OUTPUT_REGISTER_NAMES;
65 static rtx gen_indexed_expr PARAMS ((rtx, rtx, rtx));
66 static const char *singlemove_string PARAMS ((rtx *));
67 static void move_tail PARAMS ((rtx[], int, int));
68 static tree ns32k_handle_fntype_attribute PARAMS ((tree *, tree, tree, int, bool *));
69 const struct attribute_spec ns32k_attribute_table[];
70 static void ns32k_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
71 static void ns32k_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
72 static void ns32k_encode_section_info PARAMS ((tree, int));
74 /* Initialize the GCC target structure. */
75 #undef TARGET_ATTRIBUTE_TABLE
76 #define TARGET_ATTRIBUTE_TABLE ns32k_attribute_table
78 #undef TARGET_ASM_ALIGNED_HI_OP
79 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
82 #undef TARGET_ASM_ALIGNED_SI_OP
83 #define TARGET_ASM_ALIGNED_SI_OP "\t.double\t"
86 #undef TARGET_ASM_FUNCTION_PROLOGUE
87 #define TARGET_ASM_FUNCTION_PROLOGUE ns32k_output_function_prologue
88 #undef TARGET_ASM_FUNCTION_EPILOGUE
89 #define TARGET_ASM_FUNCTION_EPILOGUE ns32k_output_function_epilogue
90 #undef TARGET_ENCODE_SECTION_INFO
91 #define TARGET_ENCODE_SECTION_INFO ns32k_encode_section_info
93 struct gcc_target targetm = TARGET_INITIALIZER;
95 /* Generate the assembly code for function entry. FILE is a stdio
96 stream to output the code to. SIZE is an int: how many units of
97 temporary storage to allocate.
99 Refer to the array `regs_ever_live' to determine which registers to
100 save; `regs_ever_live[I]' is nonzero if register number I is ever
101 used in the function. This function is responsible for knowing
102 which registers should not be saved even if used. */
105 * The function prologue for the ns32k is fairly simple.
106 * If a frame pointer is needed (decided in reload.c ?) then
107 * we need assembler of the form
109 * # Save the oldframe pointer, set the new frame pointer, make space
110 * # on the stack and save any general purpose registers necessary
112 * enter [<general purpose regs to save>], <local stack space>
114 * movf fn, tos # Save any floating point registers necessary
118 * If a frame pointer is not needed we need assembler of the form
120 * # Make space on the stack
122 * adjspd <local stack space + 4>
124 * # Save any general purpose registers necessary
126 * save [<general purpose regs to save>]
128 * movf fn, tos # Save any floating point registers necessary
133 #if !defined (MERLIN_TARGET) && !defined (UTEK_ASM)
135 #if defined(IMMEDIATE_PREFIX) && IMMEDIATE_PREFIX
136 #define ADJSP(FILE, N) \
137 fprintf (FILE, "\tadjspd %c%d\n", IMMEDIATE_PREFIX, (N))
139 #define ADJSP(FILE, N) \
140 fprintf (FILE, "\tadjspd %d\n", (N))
144 ns32k_output_function_prologue (file, size)
148 register int regno, g_regs_used = 0;
149 int used_regs_buf[8], *bufp = used_regs_buf;
150 int used_fregs_buf[17], *fbufp = used_fregs_buf;
152 for (regno = R0_REGNUM; regno < F0_REGNUM; regno++)
153 if (regs_ever_live[regno]
154 && ! call_used_regs[regno])
156 *bufp++ = regno; g_regs_used++;
160 for (; regno < FRAME_POINTER_REGNUM; regno++)
161 if (regs_ever_live[regno] && !call_used_regs[regno])
167 bufp = used_regs_buf;
168 if (frame_pointer_needed)
169 fprintf (file, "\tenter [");
173 ADJSP (file, size + 4);
174 if (g_regs_used && g_regs_used > 4)
175 fprintf (file, "\tsave [");
179 fprintf (file, "\tmovd r%d,tos\n", *bufp++);
186 fprintf (file, "r%d", *bufp++);
191 if (frame_pointer_needed)
192 fprintf (file, "],%d\n", size);
193 else if (g_regs_used)
194 fprintf (file, "]\n");
196 fbufp = used_fregs_buf;
199 if ((*fbufp & 1) || (fbufp[0] != fbufp[1] - 1))
200 fprintf (file, "\tmovf %s,tos\n", ns32k_out_reg_names[*fbufp++]);
203 fprintf (file, "\tmovl %s,tos\n",
204 ns32k_out_reg_names[fbufp[0]]);
209 if (flag_pic && current_function_uses_pic_offset_table)
211 fprintf (file, "\tsprd sb,tos\n");
214 fprintf (file, "\taddr __GLOBAL_OFFSET_TABLE_(pc),tos\n");
215 fprintf (file, "\tlprd sb,tos\n");
219 fprintf (file, "\taddr __GLOBAL_OFFSET_TABLE_(pc),r0\n");
220 fprintf (file, "\tlprd sb,r0\n");
225 #else /* MERLIN_TARGET || UTEK_ASM */
227 /* This differs from the standard one above in printing a bitmask
228 rather than a register list in the enter or save instruction. */
231 ns32k_output_function_prologue (file, size)
235 register int regno, g_regs_used = 0;
236 int used_regs_buf[8], *bufp = used_regs_buf;
237 int used_fregs_buf[8], *fbufp = used_fregs_buf;
239 for (regno = 0; regno < 8; regno++)
240 if (regs_ever_live[regno]
241 && ! call_used_regs[regno])
243 *bufp++ = regno; g_regs_used++;
247 for (; regno < 16; regno++)
248 if (regs_ever_live[regno] && !call_used_regs[regno]) {
253 bufp = used_regs_buf;
254 if (frame_pointer_needed)
255 fprintf (file, "\tenter ");
256 else if (g_regs_used)
257 fprintf (file, "\tsave ");
259 if (frame_pointer_needed || g_regs_used)
263 mask |= 1 << *bufp++;
264 fprintf (file, "$0x%x", (int) mask & 0xff);
267 if (frame_pointer_needed)
269 fprintf (file, ",$%d\n", size);
271 fprintf (file, ",%d\n", size);
273 else if (g_regs_used)
274 fprintf (file, "\n");
276 fbufp = used_fregs_buf;
279 if ((*fbufp & 1) || (fbufp[0] != fbufp[1] - 1))
280 fprintf (file, "\tmovf f%d,tos\n", *fbufp++ - 8);
283 fprintf (file, "\tmovl f%d,tos\n", fbufp[0] - 8);
289 #endif /* MERLIN_TARGET || UTEK_ASM */
291 /* This function generates the assembly code for function exit,
292 on machines that need it.
294 The function epilogue should not depend on the current stack pointer,
295 if EXIT_IGNORE_STACK is nonzero. That doesn't apply here.
297 If a frame pointer is needed (decided in reload.c ?) then
298 we need assembler of the form
300 movf tos, fn # Restore any saved floating point registers
304 # Restore any saved general purpose registers, restore the stack
305 # pointer from the frame pointer, restore the old frame pointer.
306 exit [<general purpose regs to save>]
308 If a frame pointer is not needed we need assembler of the form
309 # Restore any general purpose registers saved
311 movf tos, fn # Restore any saved floating point registers
315 restore [<general purpose regs to save>]
317 # reclaim space allocated on stack
319 adjspd <-(local stack space + 4)> */
321 #if !defined (MERLIN_TARGET) && !defined (UTEK_ASM)
324 ns32k_output_function_epilogue (file, size)
328 register int regno, g_regs_used = 0, f_regs_used = 0;
329 int used_regs_buf[8], *bufp = used_regs_buf;
330 int used_fregs_buf[17], *fbufp = used_fregs_buf;
332 if (flag_pic && current_function_uses_pic_offset_table)
333 fprintf (file, "\tlprd sb,tos\n");
336 for (regno = F0_REGNUM; regno < FRAME_POINTER_REGNUM; regno++)
337 if (regs_ever_live[regno] && !call_used_regs[regno])
339 *fbufp++ = regno; f_regs_used++;
343 for (regno = 0; regno < F0_REGNUM; regno++)
344 if (regs_ever_live[regno]
345 && ! call_used_regs[regno])
347 *bufp++ = regno; g_regs_used++;
350 while (fbufp > used_fregs_buf)
352 if ((*fbufp & 1) && fbufp[0] == fbufp[-1] + 1)
354 fprintf (file, "\tmovl tos,%s\n",
355 ns32k_out_reg_names[fbufp[-1]]);
358 else fprintf (file, "\tmovf tos,%s\n", ns32k_out_reg_names[*fbufp--]);
361 if (frame_pointer_needed)
362 fprintf (file, "\texit [");
365 if (g_regs_used && g_regs_used > 4)
366 fprintf (file, "\trestore [");
369 while (bufp > used_regs_buf)
370 fprintf (file, "\tmovd tos,r%d\n", *--bufp);
375 while (bufp > used_regs_buf)
377 fprintf (file, "r%d", *--bufp);
378 if (bufp > used_regs_buf)
382 if (g_regs_used || frame_pointer_needed)
383 fprintf (file, "]\n");
385 if (size && !frame_pointer_needed)
386 ADJSP (file, -(size + 4));
388 if (current_function_pops_args)
389 fprintf (file, "\tret %d\n", current_function_pops_args);
391 fprintf (file, "\tret 0\n");
394 #else /* MERLIN_TARGET || UTEK_ASM */
396 /* This differs from the standard one above in printing a bitmask
397 rather than a register list in the exit or restore instruction. */
400 ns32k_output_function_epilogue (file, size)
402 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
404 register int regno, g_regs_used = 0, f_regs_used = 0;
405 int used_regs_buf[8], *bufp = used_regs_buf;
406 int used_fregs_buf[8], *fbufp = used_fregs_buf;
409 for (regno = 8; regno < 16; regno++)
410 if (regs_ever_live[regno] && !call_used_regs[regno]) {
411 *fbufp++ = regno; f_regs_used++;
415 for (regno = 0; regno < 8; regno++)
416 if (regs_ever_live[regno]
417 && ! call_used_regs[regno])
419 *bufp++ = regno; g_regs_used++;
422 while (fbufp > used_fregs_buf)
424 if ((*fbufp & 1) && fbufp[0] == fbufp[-1] + 1)
426 fprintf (file, "\tmovl tos,f%d\n", fbufp[-1] - 8);
429 else fprintf (file, "\tmovf tos,f%d\n", *fbufp-- - 8);
432 if (frame_pointer_needed)
433 fprintf (file, "\texit ");
434 else if (g_regs_used)
435 fprintf (file, "\trestore ");
437 if (g_regs_used || frame_pointer_needed)
441 while (bufp > used_regs_buf)
443 /* Utek assembler takes care of reversing this */
444 mask |= 1 << *--bufp;
446 fprintf (file, "$0x%x\n", (int) mask & 0xff);
450 if (current_function_pops_args)
451 fprintf (file, "\tret $%d\n", current_function_pops_args);
453 fprintf (file, "\tret $0\n");
455 if (current_function_pops_args)
456 fprintf (file, "\tret %d\n", current_function_pops_args);
458 fprintf (file, "\tret 0\n");
462 #endif /* MERLIN_TARGET || UTEK_ASM */
464 /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */
466 hard_regno_mode_ok (regno, mode)
468 enum machine_mode mode;
470 int size = GET_MODE_UNIT_SIZE (mode);
472 if (FLOAT_MODE_P (mode))
474 if (size == UNITS_PER_WORD && regno < L1_REGNUM)
476 if (size == UNITS_PER_WORD * 2
477 && (((regno & 1) == 0 && regno < FRAME_POINTER_REGNUM)))
481 if (size == UNITS_PER_WORD * 2
482 && (regno & 1) == 0 && regno < F0_REGNUM)
484 if (size <= UNITS_PER_WORD
485 && (regno < F0_REGNUM || regno == FRAME_POINTER_REGNUM
486 || regno == STACK_POINTER_REGNUM))
491 int register_move_cost (CLASS1, CLASS2)
492 enum reg_class CLASS1;
493 enum reg_class CLASS2;
495 if (CLASS1 == NO_REGS || CLASS2 == NO_REGS)
497 if ((SUBSET_P (CLASS1, FP_REGS) && !SUBSET_P (CLASS2, FP_REGS))
498 || (!SUBSET_P (CLASS1, FP_REGS) && SUBSET_P (CLASS2, FP_REGS)))
500 if (((CLASS1) == STACK_POINTER_REG && !SUBSET_P (CLASS2,GENERAL_REGS))
501 || ((CLASS2) == STACK_POINTER_REG && !SUBSET_P (CLASS1,GENERAL_REGS)))
503 if (((CLASS1) == FRAME_POINTER_REG && !SUBSET_P (CLASS2,GENERAL_REGS))
504 || ((CLASS2) == FRAME_POINTER_REG && !SUBSET_P (CLASS1,GENERAL_REGS)))
510 /* We made the insn definitions copy from floating point to general
511 registers via the stack. */
512 int secondary_memory_needed (CLASS1, CLASS2, M)
513 enum reg_class CLASS1;
514 enum reg_class CLASS2;
517 int ret = ((SUBSET_P (CLASS1, FP_REGS) && !SUBSET_P (CLASS2, FP_REGS))
518 || (!SUBSET_P (CLASS1, FP_REGS) && SUBSET_P (CLASS2, FP_REGS)));
524 /* ADDRESS_COST calls this. This function is not optimal
525 for the 32032 & 32332, but it probably is better than
529 calc_address_cost (operand)
534 if (GET_CODE (operand) == MEM)
536 if (GET_CODE (operand) == MULT)
538 switch (GET_CODE (operand))
547 if (INTVAL (operand) <= 7 && INTVAL (operand) >= -8)
549 if (INTVAL (operand) < 0x2000 && INTVAL (operand) >= -0x2000)
563 cost += calc_address_cost (XEXP (operand, 0));
567 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (operand)); i++)
569 cost += calc_address_cost (XEXP (operand, i));
577 /* Return the register class of a scratch register needed to copy IN into
578 or out of a register in CLASS in MODE. If it can be done directly,
579 NO_REGS is returned. */
582 secondary_reload_class (class, mode, in)
583 enum reg_class class;
584 enum machine_mode mode ATTRIBUTE_UNUSED;
587 int regno = true_regnum (in);
589 if (regno >= FIRST_PSEUDO_REGISTER)
592 if ((class == FRAME_POINTER_REG && regno == STACK_POINTER_REGNUM)
593 || ( class == STACK_POINTER_REG && regno == FRAME_POINTER_REGNUM))
599 /* Generate the rtx that comes from an address expression in the md file */
600 /* The expression to be build is BASE[INDEX:SCALE]. To recognize this,
601 scale must be converted from an exponent (from ASHIFT) to a
602 multiplier (for MULT). */
605 gen_indexed_expr (base, index, scale)
606 rtx base, index, scale;
610 /* This generates an invalid addressing mode, if BASE is
611 fp or sp. This is handled by PRINT_OPERAND_ADDRESS. */
612 if (GET_CODE (base) != REG && GET_CODE (base) != CONST_INT)
613 base = gen_rtx_MEM (SImode, base);
614 addr = gen_rtx_MULT (SImode, index,
615 GEN_INT (1 << INTVAL (scale)));
616 addr = gen_rtx_PLUS (SImode, base, addr);
621 /* Split one or more DImode RTL references into pairs of SImode
622 references. The RTL can be REG, offsettable MEM, integer constant, or
623 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
624 split and "num" is its length. lo_half and hi_half are output arrays
625 that parallel "operands". */
628 split_di (operands, num, lo_half, hi_half)
631 rtx lo_half[], hi_half[];
635 if (GET_CODE (operands[num]) == REG)
637 lo_half[num] = gen_rtx_REG (SImode, REGNO (operands[num]));
638 hi_half[num] = gen_rtx_REG (SImode, REGNO (operands[num]) + 1);
640 else if (CONSTANT_P (operands[num]))
642 split_double (operands[num], &lo_half[num], &hi_half[num]);
644 else if (offsettable_memref_p (operands[num]))
646 lo_half[num] = operands[num];
647 hi_half[num] = adjust_address (operands[num], SImode, 4);
654 /* Return the best assembler insn template
655 for moving operands[1] into operands[0] as a fullword. */
658 singlemove_string (operands)
661 if (GET_CODE (operands[1]) == CONST_INT
662 && INTVAL (operands[1]) <= 7
663 && INTVAL (operands[1]) >= -8)
664 return "movqd %1,%0";
669 output_move_double (operands)
672 enum anon1 { REGOP, OFFSOP, PUSHOP, CNSTOP, RNDOP } optype0, optype1;
675 /* First classify both operands. */
677 if (REG_P (operands[0]))
679 else if (offsettable_memref_p (operands[0]))
681 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
686 if (REG_P (operands[1]))
688 else if (CONSTANT_P (operands[1])
689 || GET_CODE (operands[1]) == CONST_DOUBLE)
691 else if (offsettable_memref_p (operands[1]))
693 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
698 /* Check for the cases that the operand constraints are not
699 supposed to allow to happen. Abort if we get one,
700 because generating code for these cases is painful. */
702 if (optype0 == RNDOP || optype1 == RNDOP)
705 /* Ok, we can do one word at a time.
706 Normally we do the low-numbered word first,
707 but if either operand is autodecrementing then we
708 do the high-numbered word first.
710 In either case, set up in LATEHALF the operands to use
711 for the high-numbered word and in some cases alter the
712 operands in OPERANDS to be suitable for the low-numbered word. */
714 if (optype0 == REGOP)
715 latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
716 else if (optype0 == OFFSOP)
717 latehalf[0] = adjust_address (operands[0], SImode, 4);
719 latehalf[0] = operands[0];
721 if (optype1 == REGOP)
722 latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
723 else if (optype1 == OFFSOP)
724 latehalf[1] = adjust_address (operands[1], SImode, 4);
725 else if (optype1 == CNSTOP)
726 split_double (operands[1], &operands[1], &latehalf[1]);
728 latehalf[1] = operands[1];
730 /* If insn is effectively movd N(sp),tos then we will do the
731 high word first. We should use the adjusted operand 1 (which is N+4(sp))
732 for the low word as well, to compensate for the first decrement of sp.
733 Given this, it doesn't matter which half we do "first". */
734 if (optype0 == PUSHOP
735 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
736 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
737 operands[1] = latehalf[1];
739 /* If one or both operands autodecrementing,
740 do the two words, high-numbered first. */
741 else if (optype0 == PUSHOP || optype1 == PUSHOP)
743 output_asm_insn (singlemove_string (latehalf), latehalf);
744 return singlemove_string (operands);
747 /* If the first move would clobber the source of the second one,
748 do them in the other order. */
750 /* Overlapping registers. */
751 if (optype0 == REGOP && optype1 == REGOP
752 && REGNO (operands[0]) == REGNO (latehalf[1]))
755 output_asm_insn (singlemove_string (latehalf), latehalf);
756 /* Do low-numbered word. */
757 return singlemove_string (operands);
759 /* Loading into a register which overlaps a register used in the address. */
760 else if (optype0 == REGOP && optype1 != REGOP
761 && reg_overlap_mentioned_p (operands[0], operands[1]))
763 if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))
764 && reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
766 /* If both halves of dest are used in the src memory address,
767 load the destination address into the low reg (operands[0]).
768 Then it works to load latehalf first. */
770 xops[0] = XEXP (operands[1], 0);
771 xops[1] = operands[0];
772 output_asm_insn ("addr %a0,%1", xops);
773 operands[1] = gen_rtx_MEM (DImode, operands[0]);
774 latehalf[1] = adjust_address (operands[1], SImode, 4);
775 /* The first half has the overlap, Do the late half first. */
776 output_asm_insn (singlemove_string (latehalf), latehalf);
778 return singlemove_string (operands);
780 if (reg_mentioned_p (operands[0], XEXP (operands[1], 0)))
782 /* The first half has the overlap, Do the late half first. */
783 output_asm_insn (singlemove_string (latehalf), latehalf);
785 return singlemove_string (operands);
789 /* Normal case. Do the two words, low-numbered first. */
791 output_asm_insn (singlemove_string (operands), operands);
793 operands[0] = latehalf[0];
794 operands[1] = latehalf[1];
795 return singlemove_string (operands);
799 #define MAX_UNALIGNED_COPY (32)
800 /* Expand string/block move operations.
802 operands[0] is the pointer to the destination.
803 operands[1] is the pointer to the source.
804 operands[2] is the number of bytes to move.
805 operands[3] is the alignment. */
808 move_tail (operands, bytes, offset)
815 emit_move_insn (adjust_address (operands[0], HImode, offset),
816 adjust_address (operands[1], HImode, offset));
820 emit_move_insn (adjust_address (operands[0], QImode, offset),
821 adjust_address (operands[1], QImode, offset));
825 expand_block_move (operands)
828 rtx bytes_rtx = operands[2];
829 rtx align_rtx = operands[3];
830 int constp = (GET_CODE (bytes_rtx) == CONST_INT);
831 int bytes = (constp ? INTVAL (bytes_rtx) : 0);
832 int align = INTVAL (align_rtx);
833 rtx src_reg = gen_rtx_REG (Pmode, 1);
834 rtx dest_reg = gen_rtx_REG (Pmode, 2);
835 rtx count_reg = gen_rtx_REG (SImode, 0);
837 if (constp && bytes <= 0)
840 if (constp && bytes < 20)
842 int words = bytes >> 2;
846 if (words < 3 || flag_unroll_loops)
850 for (; words; words--, offset += 4)
851 emit_move_insn (adjust_address (operands[0], SImode, offset),
852 adjust_address (operands[1], SImode, offset));
856 /* Use movmd. It is slower than multiple movd's but more
857 compact. It is also slower than movsd for large copies
858 but causes less registers reloading so is better than movsd
861 dest = copy_addr_to_reg (XEXP (operands[0], 0));
862 src = copy_addr_to_reg (XEXP (operands[1], 0));
864 emit_insn (gen_movstrsi2(dest, src, GEN_INT (words)));
867 move_tail (operands, bytes & 3, bytes & ~3);
871 if (align > UNITS_PER_WORD)
872 align = UNITS_PER_WORD;
874 /* Move the address into scratch registers. */
875 emit_insn (gen_rtx_CLOBBER (VOIDmode, dest_reg));
876 emit_move_insn (dest_reg, XEXP (operands[0], 0));
877 operands[0] = gen_rtx_MEM (SImode, dest_reg);
878 emit_insn (gen_rtx_CLOBBER (VOIDmode, src_reg));
879 emit_move_insn (src_reg, XEXP (operands[1], 0));
880 operands[1] = gen_rtx_MEM (SImode, src_reg);
881 emit_insn (gen_rtx_CLOBBER (VOIDmode, count_reg));
883 if (constp && (align == UNITS_PER_WORD || bytes < MAX_UNALIGNED_COPY))
885 /* constant no of bytes and aligned or small enough copy to not bother
886 * aligning. Emit insns to copy by words.
890 emit_move_insn (count_reg, GEN_INT (bytes >> 2));
891 emit_insn (gen_movstrsi1 (GEN_INT (4)));
893 /* insns to copy rest */
894 move_tail (operands, bytes & 3, 0);
896 else if (align == UNITS_PER_WORD)
898 /* insns to copy by words */
899 emit_insn (gen_lshrsi3 (count_reg, bytes_rtx, GEN_INT (2)));
900 emit_insn (gen_movstrsi1 (GEN_INT (4)));
903 move_tail (operands, bytes & 3, 0);
907 /* insns to copy rest */
908 emit_insn (gen_andsi3 (count_reg, bytes_rtx, GEN_INT (3)));
909 emit_insn (gen_movstrsi1 (const1_rtx));
914 /* Not aligned and we may have a lot to copy so it is worth
917 rtx aligned_label = gen_label_rtx ();
920 bytes_reg = copy_to_mode_reg (SImode, bytes_rtx);
923 /* Emit insns to test and skip over the alignment if it is
924 * not worth it. This doubles as a test to ensure that the alignment
925 * operation can't copy too many bytes
927 emit_insn (gen_cmpsi (bytes_reg, GEN_INT (MAX_UNALIGNED_COPY)));
928 emit_jump_insn (gen_blt (aligned_label));
931 /* Emit insns to do alignment at run time */
932 emit_insn (gen_negsi2 (count_reg, src_reg));
933 emit_insn (gen_andsi3 (count_reg, count_reg, GEN_INT (3)));
934 emit_insn (gen_subsi3 (bytes_reg, bytes_reg, count_reg));
935 emit_insn (gen_movstrsi1 (const1_rtx));
937 emit_label (aligned_label);
939 /* insns to copy by words */
940 emit_insn (gen_lshrsi3 (count_reg, bytes_reg, GEN_INT (2)));
941 emit_insn (gen_movstrsi1 (GEN_INT (4)));
943 /* insns to copy rest */
944 emit_insn (gen_andsi3 (count_reg, bytes_reg, GEN_INT (3)));
945 emit_insn (gen_movstrsi1 (const1_rtx));
950 /* Returns 1 if OP contains a global symbol reference */
953 global_symbolic_reference_mentioned_p (op, f)
957 register const char *fmt;
960 if (GET_CODE (op) == SYMBOL_REF)
962 if (! SYMBOL_REF_FLAG (op))
967 else if (f && GET_CODE (op) != CONST)
970 fmt = GET_RTX_FORMAT (GET_CODE (op));
971 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
977 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
978 if (global_symbolic_reference_mentioned_p (XVECEXP (op, i, j), 0))
981 else if (fmt[i] == 'e'
982 && global_symbolic_reference_mentioned_p (XEXP (op, i), 0))
990 /* Returns 1 if OP contains a symbol reference */
993 symbolic_reference_mentioned_p (op)
996 register const char *fmt;
999 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
1002 fmt = GET_RTX_FORMAT (GET_CODE (op));
1003 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
1009 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
1010 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
1013 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
1020 /* Table of machine-specific attributes. */
1022 const struct attribute_spec ns32k_attribute_table[] =
1024 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
1025 /* Stdcall attribute says callee is responsible for popping arguments
1026 if they are not variable. */
1027 { "stdcall", 0, 0, false, true, true, ns32k_handle_fntype_attribute },
1028 /* Cdecl attribute says the callee is a normal C declaration */
1029 { "cdecl", 0, 0, false, true, true, ns32k_handle_fntype_attribute },
1030 { NULL, 0, 0, false, false, false, NULL }
1033 /* Handle an attribute requiring a FUNCTION_TYPE, FIELD_DECL or TYPE_DECL;
1034 arguments as in struct attribute_spec.handler. */
1036 ns32k_handle_fntype_attribute (node, name, args, flags, no_add_attrs)
1039 tree args ATTRIBUTE_UNUSED;
1040 int flags ATTRIBUTE_UNUSED;
1043 if (TREE_CODE (*node) != FUNCTION_TYPE
1044 && TREE_CODE (*node) != FIELD_DECL
1045 && TREE_CODE (*node) != TYPE_DECL)
1047 warning ("`%s' attribute only applies to functions",
1048 IDENTIFIER_POINTER (name));
1049 *no_add_attrs = true;
1056 /* Value is the number of bytes of arguments automatically
1057 popped when returning from a subroutine call.
1058 FUNDECL is the declaration node of the function (as a tree),
1059 FUNTYPE is the data type of the function (as a tree),
1060 or for a library call it is an identifier node for the subroutine name.
1061 SIZE is the number of bytes of arguments passed on the stack.
1063 On the ns32k, the RET insn may be used to pop them if the number
1064 of args is fixed, but if the number is variable then the caller
1065 must pop them all. RET can't be used for library calls now
1066 because the library is compiled with the Unix compiler.
1067 Use of RET is a selectable option, since it is incompatible with
1068 standard Unix calling sequences. If the option is not selected,
1069 the caller must always pop the args.
1071 The attribute stdcall is equivalent to RET on a per module basis. */
1074 ns32k_return_pops_args (fundecl, funtype, size)
1075 tree fundecl ATTRIBUTE_UNUSED;
1079 int rtd = TARGET_RTD;
1081 if (TREE_CODE (funtype) == IDENTIFIER_NODE)
1082 return rtd ? size : 0;
1084 /* Cdecl functions override -mrtd, and never pop the stack */
1085 if (lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype)))
1088 /* Stdcall functions will pop the stack if not variable args */
1089 if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype)))
1094 if (TYPE_ARG_TYPES (funtype) == NULL_TREE
1095 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype))) == void_type_node))
1102 /* PRINT_OPERAND is defined to call this function,
1103 which is easier to debug than putting all the code in
1104 a macro definition in ns32k.h. */
1106 /* XXX time 12% of cpu time is in fprintf for non optimizing */
1108 print_operand (file, x, code)
1114 PUT_IMMEDIATE_PREFIX (file);
1115 else if (code == '?')
1116 PUT_EXTERNAL_PREFIX (file);
1117 else if (GET_CODE (x) == REG)
1118 fprintf (file, "%s", ns32k_out_reg_names[REGNO (x)]);
1119 else if (GET_CODE (x) == MEM)
1121 output_address (XEXP (x, 0));
1123 else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != VOIDmode)
1127 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
1128 PUT_IMMEDIATE_PREFIX (file);
1129 if (GET_MODE (x) == DFmode)
1132 /* Sequent likes its floating point constants as integers */
1133 fprintf (file, "0Dx%08x%08x",
1134 CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
1137 REAL_VALUE_TO_DECIMAL (r, "%.20e", s);
1139 fprintf (file, "0f%s", s);
1141 fprintf (file, "0d%s", s);
1149 REAL_VALUE_TO_TARGET_SINGLE (r, l);
1150 fprintf (file, "0Fx%08lx", l);
1153 REAL_VALUE_TO_DECIMAL (r, "%.20e", s);
1154 fprintf (file, "0f%s", s);
1161 && GET_CODE (x) == CONST
1162 && symbolic_reference_mentioned_p (x))
1164 fprintf (stderr, "illegal constant for pic-mode: \n");
1165 print_rtl (stderr, x);
1166 fprintf (stderr, "\nGET_CODE (x) == %d, CONST == %d, symbolic_reference_mentioned_p (x) == %d\n",
1167 GET_CODE (x), CONST, symbolic_reference_mentioned_p (x));
1171 && (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF))
1173 output_addr_const (file, x);
1174 fprintf (file, "(sb)");
1178 #ifdef NO_IMMEDIATE_PREFIX_IF_SYMBOLIC
1179 if (GET_CODE (x) == CONST_INT)
1181 PUT_IMMEDIATE_PREFIX (file);
1182 output_addr_const (file, x);
1187 /* PRINT_OPERAND_ADDRESS is defined to call this function,
1188 which is easier to debug than putting all the code in
1189 a macro definition in ns32k.h . */
1191 /* Completely rewritten to get this to work with Gas for PC532 Mach.
1192 This function didn't work and I just wasn't able (nor very willing) to
1193 figure out how it worked.
1194 90-11-25 Tatu Yl|nen <ylo@cs.hut.fi> */
1197 print_operand_address (file, addr)
1198 register FILE *file;
1201 static const char scales[] = { 'b', 'w', 'd', 0, 'q', };
1202 rtx offset, base, indexexp, tmp;
1204 extern int flag_pic;
1206 if (GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == POST_DEC)
1208 fprintf (file, "tos");
1215 while (addr != NULL)
1217 if (GET_CODE (addr) == PLUS)
1219 if (GET_CODE (XEXP (addr, 0)) == PLUS)
1221 tmp = XEXP (addr, 1);
1222 addr = XEXP (addr, 0);
1226 tmp = XEXP (addr,0);
1227 addr = XEXP (addr,1);
1235 switch (GET_CODE (tmp))
1249 if (REGNO (tmp) < F0_REGNUM)
1269 if (flag_pic && ! CONSTANT_POOL_ADDRESS_P (tmp)
1270 && ! SYMBOL_REF_FLAG (tmp))
1282 if (flag_pic && GET_CODE (tmp) == CONST)
1285 tmp1 = XEXP (tmp,0);
1286 if (GET_CODE (tmp1) != PLUS)
1289 sym = XEXP (tmp1,0);
1290 if (GET_CODE (sym) != SYMBOL_REF)
1293 sym = XEXP (tmp1,1);
1296 off = XEXP (tmp1,1);
1297 if (GET_CODE (sym) == SYMBOL_REF)
1299 if (GET_CODE (off) != CONST_INT)
1302 if (CONSTANT_POOL_ADDRESS_P (sym)
1303 || SYMBOL_REF_FLAG (sym))
1305 SYMBOL_REF_FLAG (tmp) = 1;
1329 offset = gen_rtx_PLUS (SImode, tmp, offset);
1338 offset = const0_rtx;
1341 #ifndef INDEX_RATHER_THAN_BASE
1342 && (flag_pic || TARGET_HIMEM)
1343 && GET_CODE (base) != SYMBOL_REF
1344 && GET_CODE (offset) != CONST_INT
1346 /* This is a re-implementation of the SEQUENT_ADDRESS_BUG fix. */
1348 && !indexexp && GET_CODE (base) == REG
1349 && REG_OK_FOR_INDEX_P (base))
1355 /* now, offset, base and indexexp are set */
1356 #ifndef BASE_REG_NEEDED
1359 #if defined (PC_RELATIVE) || defined (NO_ABSOLUTE_PREFIX_IF_SYMBOLIC)
1360 if (GET_CODE (offset) == CONST_INT)
1362 PUT_ABSOLUTE_PREFIX (file);
1366 output_addr_const (file, offset);
1367 if (base) /* base can be (REG ...) or (MEM ...) */
1368 switch (GET_CODE (base))
1370 /* now we must output base. Possible alternatives are:
1374 (pc) (REG ...) used for SYMBOL_REF and LABEL_REF, output
1375 (disp(fp)) (MEM ...) just before possible [rX:y]
1376 (disp(sp)) (MEM ...)
1377 (disp(sb)) (MEM ...)
1380 fprintf (file, "(%s)", ns32k_out_reg_names[REGNO (base)]);
1386 fprintf (file, "(");
1387 output_addr_const (file, base);
1388 fprintf (file, "(sb))");
1391 addr = XEXP (base,0);
1394 while (addr != NULL)
1396 if (GET_CODE (addr) == PLUS)
1398 if (GET_CODE (XEXP (addr, 0)) == PLUS)
1400 tmp = XEXP (addr, 1);
1401 addr = XEXP (addr, 0);
1405 tmp = XEXP (addr, 0);
1406 addr = XEXP (addr, 1);
1414 switch (GET_CODE (tmp))
1424 offset = gen_rtx_PLUS (SImode, tmp, offset);
1433 offset = const0_rtx;
1434 fprintf (file, "(");
1435 output_addr_const (file, offset);
1437 fprintf (file, "(%s)", ns32k_out_reg_names[REGNO (base)]);
1439 fprintf (file, "(sb)");
1442 fprintf (file, ")");
1448 else if (GET_CODE (offset) != CONST_INT)
1449 fprintf (file, "(pc)");
1450 #ifdef BASE_REG_NEEDED
1452 fprintf (file, "(sb)");
1456 #endif /* PC_RELATIVE */
1458 /* now print index if we have one */
1461 if (GET_CODE (indexexp) == MULT)
1463 scale = INTVAL (XEXP (indexexp, 1)) >> 1;
1464 indexexp = XEXP (indexexp, 0);
1468 if (GET_CODE (indexexp) != REG || REGNO (indexexp) >= F0_REGNUM)
1472 fprintf (file, "[%c`%s]",
1474 ns32k_out_reg_names[REGNO (indexexp)]);
1476 fprintf (file, "[%s:%c]",
1477 ns32k_out_reg_names[REGNO (indexexp)],
1483 /* National 32032 shifting is so bad that we can get
1484 better performance in many common cases by using other
1487 output_shift_insn (operands)
1490 if (GET_CODE (operands[2]) == CONST_INT
1491 && INTVAL (operands[2]) > 0
1492 && INTVAL (operands[2]) <= 3)
1494 if (GET_CODE (operands[0]) == REG)
1496 if (GET_CODE (operands[1]) == REG)
1498 if (REGNO (operands[0]) == REGNO (operands[1]))
1500 if (operands[2] == const1_rtx)
1501 return "addd %0,%0";
1502 else if (INTVAL (operands[2]) == 2)
1503 return "addd %0,%0\n\taddd %0,%0";
1505 if (operands[2] == const1_rtx)
1506 return "movd %1,%0\n\taddd %0,%0";
1508 operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
1509 return "addr %a1,%0";
1511 if (operands[2] == const1_rtx)
1512 return "movd %1,%0\n\taddd %0,%0";
1514 else if (GET_CODE (operands[1]) == REG)
1516 operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
1517 return "addr %a1,%0";
1519 else if (INTVAL (operands[2]) == 1
1520 && GET_CODE (operands[1]) == MEM
1521 && rtx_equal_p (operands [0], operands[1]))
1523 rtx temp = XEXP (operands[1], 0);
1525 if (GET_CODE (temp) == REG
1526 || (GET_CODE (temp) == PLUS
1527 && GET_CODE (XEXP (temp, 0)) == REG
1528 && GET_CODE (XEXP (temp, 1)) == CONST_INT))
1529 return "addd %0,%0";
1531 else return "ashd %2,%0";
1533 return "ashd %2,%0";
1537 output_move_dconst (n, s)
1543 if (n > -9 && n < 8)
1544 strcpy (r, "movqd ");
1545 else if (n > 0 && n < 256)
1546 strcpy (r, "movzbd ");
1547 else if (n > 0 && n < 65536)
1548 strcpy (r, "movzwd ");
1549 else if (n < 0 && n > -129)
1550 strcpy (r, "movxbd ");
1551 else if (n < 0 && n > -32769)
1552 strcpy (r, "movxwd ");
1554 strcpy (r, "movd ");
1559 /* If using PIC, mark a SYMBOL_REF for a non-global symbol or a code
1560 symbol. These symbols are referenced via pc and not via sb. */
1563 ns32k_encode_section_info (decl, first)
1565 int first ATTRIBUTE_UNUSED;
1569 rtx rtl = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd'
1570 ? TREE_CST_RTL (decl) : DECL_RTL (decl));
1571 SYMBOL_REF_FLAG (XEXP (rtl, 0))
1572 = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd'
1573 || ! TREE_PUBLIC (decl));