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"
42 int ns32k_num_files = 0;
45 /* This duplicates reg_class_contents in reg_class.c, but maybe that isn't
46 initialized in time. Also this is more convenient as an array of ints.
47 We know that HARD_REG_SET fits in an unsigned int */
49 unsigned int ns32k_reg_class_contents[N_REG_CLASSES][1] = REG_CLASS_CONTENTS;
51 enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] =
53 GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
54 GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
55 FLOAT_REG0, LONG_FLOAT_REG0, FLOAT_REGS, FLOAT_REGS,
56 FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, FLOAT_REGS,
57 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
58 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
59 FRAME_POINTER_REG, STACK_POINTER_REG
62 const char *const ns32k_out_reg_names[] = OUTPUT_REGISTER_NAMES;
64 static rtx gen_indexed_expr PARAMS ((rtx, rtx, rtx));
65 static const char *singlemove_string PARAMS ((rtx *));
66 static void move_tail PARAMS ((rtx[], int, int));
67 static int ns32k_valid_type_attribute_p PARAMS ((tree, tree, tree, tree));
68 static void ns32k_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
69 static void ns32k_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
71 /* Initialize the GCC target structure. */
72 #undef TARGET_VALID_TYPE_ATTRIBUTE
73 #define TARGET_VALID_TYPE_ATTRIBUTE ns32k_valid_type_attribute_p
75 #undef TARGET_ASM_FUNCTION_PROLOGUE
76 #define TARGET_ASM_FUNCTION_PROLOGUE ns32k_output_function_prologue
77 #undef TARGET_ASM_FUNCTION_EPILOGUE
78 #define TARGET_ASM_FUNCTION_EPILOGUE ns32k_output_function_epilogue
80 struct gcc_target targetm = TARGET_INITIALIZER;
82 /* Generate the assembly code for function entry. FILE is a stdio
83 stream to output the code to. SIZE is an int: how many units of
84 temporary storage to allocate.
86 Refer to the array `regs_ever_live' to determine which registers to
87 save; `regs_ever_live[I]' is nonzero if register number I is ever
88 used in the function. This function is responsible for knowing
89 which registers should not be saved even if used. */
92 * The function prologue for the ns32k is fairly simple.
93 * If a frame pointer is needed (decided in reload.c ?) then
94 * we need assembler of the form
96 * # Save the oldframe pointer, set the new frame pointer, make space
97 * # on the stack and save any general purpose registers necessary
99 * enter [<general purpose regs to save>], <local stack space>
101 * movf fn, tos # Save any floating point registers necessary
105 * If a frame pointer is not needed we need assembler of the form
107 * # Make space on the stack
109 * adjspd <local stack space + 4>
111 * # Save any general purpose registers necessary
113 * save [<general purpose regs to save>]
115 * movf fn, tos # Save any floating point registers necessary
120 #if !defined (MERLIN_TARGET) && !defined (UTEK_ASM)
122 #if defined(IMMEDIATE_PREFIX) && IMMEDIATE_PREFIX
123 #define ADJSP(FILE, N) \
124 fprintf (FILE, "\tadjspd %c%d\n", IMMEDIATE_PREFIX, (N))
126 #define ADJSP(FILE, N) \
127 fprintf (FILE, "\tadjspd %d\n", (N))
131 ns32k_output_function_prologue (file, size)
135 register int regno, g_regs_used = 0;
136 int used_regs_buf[8], *bufp = used_regs_buf;
137 int used_fregs_buf[17], *fbufp = used_fregs_buf;
138 extern char call_used_regs[];
140 for (regno = R0_REGNUM; regno < F0_REGNUM; regno++)
141 if (regs_ever_live[regno]
142 && ! call_used_regs[regno])
144 *bufp++ = regno; g_regs_used++;
148 for (; regno < FRAME_POINTER_REGNUM; regno++)
149 if (regs_ever_live[regno] && !call_used_regs[regno])
155 bufp = used_regs_buf;
156 if (frame_pointer_needed)
157 fprintf (file, "\tenter [");
161 ADJSP (file, size + 4);
162 if (g_regs_used && g_regs_used > 4)
163 fprintf (file, "\tsave [");
167 fprintf (file, "\tmovd r%d,tos\n", *bufp++);
174 fprintf (file, "r%d", *bufp++);
179 if (frame_pointer_needed)
180 fprintf (file, "],%d\n", size);
181 else if (g_regs_used)
182 fprintf (file, "]\n");
184 fbufp = used_fregs_buf;
187 if ((*fbufp & 1) || (fbufp[0] != fbufp[1] - 1))
188 fprintf (file, "\tmovf %s,tos\n", ns32k_out_reg_names[*fbufp++]);
191 fprintf (file, "\tmovl %s,tos\n",
192 ns32k_out_reg_names[fbufp[0]]);
197 if (flag_pic && current_function_uses_pic_offset_table)
199 fprintf (file, "\tsprd sb,tos\n");
202 fprintf (file, "\taddr __GLOBAL_OFFSET_TABLE_(pc),tos\n");
203 fprintf (file, "\tlprd sb,tos\n");
207 fprintf (file, "\taddr __GLOBAL_OFFSET_TABLE_(pc),r0\n");
208 fprintf (file, "\tlprd sb,r0\n");
213 #else /* MERLIN_TARGET || UTEK_ASM */
215 /* This differs from the standard one above in printing a bitmask
216 rather than a register list in the enter or save instruction. */
219 ns32k_output_function_prologue (file, size)
223 register int regno, g_regs_used = 0;
224 int used_regs_buf[8], *bufp = used_regs_buf;
225 int used_fregs_buf[8], *fbufp = used_fregs_buf;
226 extern char call_used_regs[];
228 for (regno = 0; regno < 8; regno++)
229 if (regs_ever_live[regno]
230 && ! call_used_regs[regno])
232 *bufp++ = regno; g_regs_used++;
236 for (; regno < 16; regno++)
237 if (regs_ever_live[regno] && !call_used_regs[regno]) {
242 bufp = used_regs_buf;
243 if (frame_pointer_needed)
244 fprintf (file, "\tenter ");
245 else if (g_regs_used)
246 fprintf (file, "\tsave ");
248 if (frame_pointer_needed || g_regs_used)
252 mask |= 1 << *bufp++;
253 fprintf (file, "$0x%x", (int) mask & 0xff);
256 if (frame_pointer_needed)
258 fprintf (file, ",$%d\n", size);
260 fprintf (file, ",%d\n", size);
262 else if (g_regs_used)
263 fprintf (file, "\n");
265 fbufp = used_fregs_buf;
268 if ((*fbufp & 1) || (fbufp[0] != fbufp[1] - 1))
269 fprintf (file, "\tmovf f%d,tos\n", *fbufp++ - 8);
272 fprintf (file, "\tmovl f%d,tos\n", fbufp[0] - 8);
278 #endif /* MERLIN_TARGET || UTEK_ASM */
280 /* This function generates the assembly code for function exit,
281 on machines that need it.
283 The function epilogue should not depend on the current stack pointer,
284 if EXIT_IGNORE_STACK is nonzero. That doesn't apply here.
286 If a frame pointer is needed (decided in reload.c ?) then
287 we need assembler of the form
289 movf tos, fn # Restore any saved floating point registers
293 # Restore any saved general purpose registers, restore the stack
294 # pointer from the frame pointer, restore the old frame pointer.
295 exit [<general purpose regs to save>]
297 If a frame pointer is not needed we need assembler of the form
298 # Restore any general purpose registers saved
300 movf tos, fn # Restore any saved floating point registers
304 restore [<general purpose regs to save>]
306 # reclaim space allocated on stack
308 adjspd <-(local stack space + 4)> */
310 #if !defined (MERLIN_TARGET) && !defined (UTEK_ASM)
313 ns32k_output_function_epilogue (file, size)
317 register int regno, g_regs_used = 0, f_regs_used = 0;
318 int used_regs_buf[8], *bufp = used_regs_buf;
319 int used_fregs_buf[17], *fbufp = used_fregs_buf;
320 extern char call_used_regs[];
322 if (flag_pic && current_function_uses_pic_offset_table)
323 fprintf (file, "\tlprd sb,tos\n");
326 for (regno = F0_REGNUM; regno < FRAME_POINTER_REGNUM; regno++)
327 if (regs_ever_live[regno] && !call_used_regs[regno])
329 *fbufp++ = regno; f_regs_used++;
333 for (regno = 0; regno < F0_REGNUM; regno++)
334 if (regs_ever_live[regno]
335 && ! call_used_regs[regno])
337 *bufp++ = regno; g_regs_used++;
340 while (fbufp > used_fregs_buf)
342 if ((*fbufp & 1) && fbufp[0] == fbufp[-1] + 1)
344 fprintf (file, "\tmovl tos,%s\n",
345 ns32k_out_reg_names[fbufp[-1]]);
348 else fprintf (file, "\tmovf tos,%s\n", ns32k_out_reg_names[*fbufp--]);
351 if (frame_pointer_needed)
352 fprintf (file, "\texit [");
355 if (g_regs_used && g_regs_used > 4)
356 fprintf (file, "\trestore [");
359 while (bufp > used_regs_buf)
360 fprintf (file, "\tmovd tos,r%d\n", *--bufp);
365 while (bufp > used_regs_buf)
367 fprintf (file, "r%d", *--bufp);
368 if (bufp > used_regs_buf)
372 if (g_regs_used || frame_pointer_needed)
373 fprintf (file, "]\n");
375 if (size && !frame_pointer_needed)
376 ADJSP (file, -(size + 4));
378 if (current_function_pops_args)
379 fprintf (file, "\tret %d\n", current_function_pops_args);
381 fprintf (file, "\tret 0\n");
384 #else /* MERLIN_TARGET || UTEK_ASM */
386 /* This differs from the standard one above in printing a bitmask
387 rather than a register list in the exit or restore instruction. */
390 ns32k_output_function_epilogue (file, size)
392 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
394 register int regno, g_regs_used = 0, f_regs_used = 0;
395 int used_regs_buf[8], *bufp = used_regs_buf;
396 int used_fregs_buf[8], *fbufp = used_fregs_buf;
397 extern char call_used_regs[];
400 for (regno = 8; regno < 16; regno++)
401 if (regs_ever_live[regno] && !call_used_regs[regno]) {
402 *fbufp++ = regno; f_regs_used++;
406 for (regno = 0; regno < 8; regno++)
407 if (regs_ever_live[regno]
408 && ! call_used_regs[regno])
410 *bufp++ = regno; g_regs_used++;
413 while (fbufp > used_fregs_buf)
415 if ((*fbufp & 1) && fbufp[0] == fbufp[-1] + 1)
417 fprintf (file, "\tmovl tos,f%d\n", fbufp[-1] - 8);
420 else fprintf (file, "\tmovf tos,f%d\n", *fbufp-- - 8);
423 if (frame_pointer_needed)
424 fprintf (file, "\texit ");
425 else if (g_regs_used)
426 fprintf (file, "\trestore ");
428 if (g_regs_used || frame_pointer_needed)
432 while (bufp > used_regs_buf)
434 /* Utek assembler takes care of reversing this */
435 mask |= 1 << *--bufp;
437 fprintf (file, "$0x%x\n", (int) mask & 0xff);
441 if (current_function_pops_args)
442 fprintf (file, "\tret $%d\n", current_function_pops_args);
444 fprintf (file, "\tret $0\n");
446 if (current_function_pops_args)
447 fprintf (file, "\tret %d\n", current_function_pops_args);
449 fprintf (file, "\tret 0\n");
453 #endif /* MERLIN_TARGET || UTEK_ASM */
455 /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */
457 hard_regno_mode_ok (regno, mode)
459 enum machine_mode mode;
461 int size = GET_MODE_UNIT_SIZE (mode);
463 if (FLOAT_MODE_P (mode))
465 if (size == UNITS_PER_WORD && regno < L1_REGNUM)
467 if (size == UNITS_PER_WORD * 2
468 && (((regno & 1) == 0 && regno < FRAME_POINTER_REGNUM)))
472 if (size == UNITS_PER_WORD * 2
473 && (regno & 1) == 0 && regno < F0_REGNUM)
475 if (size <= UNITS_PER_WORD
476 && (regno < F0_REGNUM || regno == FRAME_POINTER_REGNUM
477 || regno == STACK_POINTER_REGNUM))
482 int register_move_cost (CLASS1, CLASS2)
483 enum reg_class CLASS1;
484 enum reg_class CLASS2;
486 if (CLASS1 == NO_REGS || CLASS2 == NO_REGS)
488 if ((SUBSET_P (CLASS1, FP_REGS) && !SUBSET_P (CLASS2, FP_REGS))
489 || (!SUBSET_P (CLASS1, FP_REGS) && SUBSET_P (CLASS2, FP_REGS)))
491 if (((CLASS1) == STACK_POINTER_REG && !SUBSET_P (CLASS2,GENERAL_REGS))
492 || ((CLASS2) == STACK_POINTER_REG && !SUBSET_P (CLASS1,GENERAL_REGS)))
494 if (((CLASS1) == FRAME_POINTER_REG && !SUBSET_P (CLASS2,GENERAL_REGS))
495 || ((CLASS2) == FRAME_POINTER_REG && !SUBSET_P (CLASS1,GENERAL_REGS)))
501 /* We made the insn definitions copy from floating point to general
502 registers via the stack. */
503 int secondary_memory_needed (CLASS1, CLASS2, M)
504 enum reg_class CLASS1;
505 enum reg_class CLASS2;
508 int ret = ((SUBSET_P (CLASS1, FP_REGS) && !SUBSET_P (CLASS2, FP_REGS))
509 || (!SUBSET_P (CLASS1, FP_REGS) && SUBSET_P (CLASS2, FP_REGS)));
515 /* ADDRESS_COST calls this. This function is not optimal
516 for the 32032 & 32332, but it probably is better than
520 calc_address_cost (operand)
525 if (GET_CODE (operand) == MEM)
527 if (GET_CODE (operand) == MULT)
529 switch (GET_CODE (operand))
538 if (INTVAL (operand) <= 7 && INTVAL (operand) >= -8)
540 if (INTVAL (operand) < 0x2000 && INTVAL (operand) >= -0x2000)
554 cost += calc_address_cost (XEXP (operand, 0));
558 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (operand)); i++)
560 cost += calc_address_cost (XEXP (operand, i));
568 /* Return the register class of a scratch register needed to copy IN into
569 or out of a register in CLASS in MODE. If it can be done directly,
570 NO_REGS is returned. */
573 secondary_reload_class (class, mode, in)
574 enum reg_class class;
575 enum machine_mode mode ATTRIBUTE_UNUSED;
578 int regno = true_regnum (in);
580 if (regno >= FIRST_PSEUDO_REGISTER)
583 if ((class == FRAME_POINTER_REG && regno == STACK_POINTER_REGNUM)
584 || ( class == STACK_POINTER_REG && regno == FRAME_POINTER_REGNUM))
590 /* Generate the rtx that comes from an address expression in the md file */
591 /* The expression to be build is BASE[INDEX:SCALE]. To recognize this,
592 scale must be converted from an exponent (from ASHIFT) to a
593 multiplier (for MULT). */
596 gen_indexed_expr (base, index, scale)
597 rtx base, index, scale;
601 /* This generates an invalid addressing mode, if BASE is
602 fp or sp. This is handled by PRINT_OPERAND_ADDRESS. */
603 if (GET_CODE (base) != REG && GET_CODE (base) != CONST_INT)
604 base = gen_rtx_MEM (SImode, base);
605 addr = gen_rtx_MULT (SImode, index,
606 GEN_INT (1 << INTVAL (scale)));
607 addr = gen_rtx_PLUS (SImode, base, addr);
612 /* Split one or more DImode RTL references into pairs of SImode
613 references. The RTL can be REG, offsettable MEM, integer constant, or
614 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
615 split and "num" is its length. lo_half and hi_half are output arrays
616 that parallel "operands". */
619 split_di (operands, num, lo_half, hi_half)
622 rtx lo_half[], hi_half[];
626 if (GET_CODE (operands[num]) == REG)
628 lo_half[num] = gen_rtx_REG (SImode, REGNO (operands[num]));
629 hi_half[num] = gen_rtx_REG (SImode, REGNO (operands[num]) + 1);
631 else if (CONSTANT_P (operands[num]))
633 split_double (operands[num], &lo_half[num], &hi_half[num]);
635 else if (offsettable_memref_p (operands[num]))
637 lo_half[num] = operands[num];
638 hi_half[num] = adjust_address (operands[num], SImode, 4);
645 /* Return the best assembler insn template
646 for moving operands[1] into operands[0] as a fullword. */
649 singlemove_string (operands)
652 if (GET_CODE (operands[1]) == CONST_INT
653 && INTVAL (operands[1]) <= 7
654 && INTVAL (operands[1]) >= -8)
655 return "movqd %1,%0";
660 output_move_double (operands)
663 enum anon1 { REGOP, OFFSOP, PUSHOP, CNSTOP, RNDOP } optype0, optype1;
666 /* First classify both operands. */
668 if (REG_P (operands[0]))
670 else if (offsettable_memref_p (operands[0]))
672 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
677 if (REG_P (operands[1]))
679 else if (CONSTANT_P (operands[1])
680 || GET_CODE (operands[1]) == CONST_DOUBLE)
682 else if (offsettable_memref_p (operands[1]))
684 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
689 /* Check for the cases that the operand constraints are not
690 supposed to allow to happen. Abort if we get one,
691 because generating code for these cases is painful. */
693 if (optype0 == RNDOP || optype1 == RNDOP)
696 /* Ok, we can do one word at a time.
697 Normally we do the low-numbered word first,
698 but if either operand is autodecrementing then we
699 do the high-numbered word first.
701 In either case, set up in LATEHALF the operands to use
702 for the high-numbered word and in some cases alter the
703 operands in OPERANDS to be suitable for the low-numbered word. */
705 if (optype0 == REGOP)
706 latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
707 else if (optype0 == OFFSOP)
708 latehalf[0] = adjust_address (operands[0], SImode, 4);
710 latehalf[0] = operands[0];
712 if (optype1 == REGOP)
713 latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
714 else if (optype1 == OFFSOP)
715 latehalf[1] = adjust_address (operands[1], SImode, 4);
716 else if (optype1 == CNSTOP)
717 split_double (operands[1], &operands[1], &latehalf[1]);
719 latehalf[1] = operands[1];
721 /* If insn is effectively movd N(sp),tos then we will do the
722 high word first. We should use the adjusted operand 1 (which is N+4(sp))
723 for the low word as well, to compensate for the first decrement of sp.
724 Given this, it doesn't matter which half we do "first". */
725 if (optype0 == PUSHOP
726 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
727 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
728 operands[1] = latehalf[1];
730 /* If one or both operands autodecrementing,
731 do the two words, high-numbered first. */
732 else if (optype0 == PUSHOP || optype1 == PUSHOP)
734 output_asm_insn (singlemove_string (latehalf), latehalf);
735 return singlemove_string (operands);
738 /* If the first move would clobber the source of the second one,
739 do them in the other order. */
741 /* Overlapping registers. */
742 if (optype0 == REGOP && optype1 == REGOP
743 && REGNO (operands[0]) == REGNO (latehalf[1]))
746 output_asm_insn (singlemove_string (latehalf), latehalf);
747 /* Do low-numbered word. */
748 return singlemove_string (operands);
750 /* Loading into a register which overlaps a register used in the address. */
751 else if (optype0 == REGOP && optype1 != REGOP
752 && reg_overlap_mentioned_p (operands[0], operands[1]))
754 if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))
755 && reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
757 /* If both halves of dest are used in the src memory address,
758 load the destination address into the low reg (operands[0]).
759 Then it works to load latehalf first. */
761 xops[0] = XEXP (operands[1], 0);
762 xops[1] = operands[0];
763 output_asm_insn ("addr %a0,%1", xops);
764 operands[1] = gen_rtx_MEM (DImode, operands[0]);
765 latehalf[1] = adjust_address (operands[1], SImode, 4);
766 /* The first half has the overlap, Do the late half first. */
767 output_asm_insn (singlemove_string (latehalf), latehalf);
769 return singlemove_string (operands);
771 if (reg_mentioned_p (operands[0], XEXP (operands[1], 0)))
773 /* The first half has the overlap, Do the late half first. */
774 output_asm_insn (singlemove_string (latehalf), latehalf);
776 return singlemove_string (operands);
780 /* Normal case. Do the two words, low-numbered first. */
782 output_asm_insn (singlemove_string (operands), operands);
784 operands[0] = latehalf[0];
785 operands[1] = latehalf[1];
786 return singlemove_string (operands);
790 #define MAX_UNALIGNED_COPY (32)
791 /* Expand string/block move operations.
793 operands[0] is the pointer to the destination.
794 operands[1] is the pointer to the source.
795 operands[2] is the number of bytes to move.
796 operands[3] is the alignment. */
799 move_tail (operands, bytes, offset)
806 emit_move_insn (adjust_address (operands[0], HImode, offset),
807 adjust_address (operands[1], HImode, offset));
811 emit_move_insn (adjust_address (operands[0], QImode, offset),
812 adjust_address (operands[1], QImode, offset));
816 expand_block_move (operands)
819 rtx bytes_rtx = operands[2];
820 rtx align_rtx = operands[3];
821 int constp = (GET_CODE (bytes_rtx) == CONST_INT);
822 int bytes = (constp ? INTVAL (bytes_rtx) : 0);
823 int align = INTVAL (align_rtx);
824 rtx src_reg = gen_rtx_REG (Pmode, 1);
825 rtx dest_reg = gen_rtx_REG (Pmode, 2);
826 rtx count_reg = gen_rtx_REG (SImode, 0);
828 if (constp && bytes <= 0)
831 if (constp && bytes < 20)
833 int words = bytes >> 2;
837 if (words < 3 || flag_unroll_loops)
841 for (; words; words--, offset += 4)
842 emit_move_insn (adjust_address (operands[0], SImode, offset),
843 adjust_address (operands[1], SImode, offset));
847 /* Use movmd. It is slower than multiple movd's but more
848 compact. It is also slower than movsd for large copies
849 but causes less registers reloading so is better than movsd
852 dest = copy_addr_to_reg (XEXP (operands[0], 0));
853 src = copy_addr_to_reg (XEXP (operands[1], 0));
855 emit_insn (gen_movstrsi2(dest, src, GEN_INT (words)));
858 move_tail (operands, bytes & 3, bytes & ~3);
862 if (align > UNITS_PER_WORD)
863 align = UNITS_PER_WORD;
865 /* Move the address into scratch registers. */
866 emit_insn (gen_rtx_CLOBBER (VOIDmode, dest_reg));
867 emit_move_insn (dest_reg, XEXP (operands[0], 0));
868 operands[0] = gen_rtx_MEM (SImode, dest_reg);
869 emit_insn (gen_rtx_CLOBBER (VOIDmode, src_reg));
870 emit_move_insn (src_reg, XEXP (operands[1], 0));
871 operands[1] = gen_rtx_MEM (SImode, src_reg);
872 emit_insn (gen_rtx_CLOBBER (VOIDmode, count_reg));
874 if (constp && (align == UNITS_PER_WORD || bytes < MAX_UNALIGNED_COPY))
876 /* constant no of bytes and aligned or small enough copy to not bother
877 * aligning. Emit insns to copy by words.
881 emit_move_insn (count_reg, GEN_INT (bytes >> 2));
882 emit_insn (gen_movstrsi1 (GEN_INT (4)));
884 /* insns to copy rest */
885 move_tail (operands, bytes & 3, 0);
887 else if (align == UNITS_PER_WORD)
889 /* insns to copy by words */
890 emit_insn (gen_lshrsi3 (count_reg, bytes_rtx, GEN_INT (2)));
891 emit_insn (gen_movstrsi1 (GEN_INT (4)));
894 move_tail (operands, bytes & 3, 0);
898 /* insns to copy rest */
899 emit_insn (gen_andsi3 (count_reg, bytes_rtx, GEN_INT (3)));
900 emit_insn (gen_movstrsi1 (const1_rtx));
905 /* Not aligned and we may have a lot to copy so it is worth
908 rtx aligned_label = gen_label_rtx ();
911 bytes_reg = copy_to_mode_reg (SImode, bytes_rtx);
914 /* Emit insns to test and skip over the alignment if it is
915 * not worth it. This doubles as a test to ensure that the alignment
916 * operation can't copy too many bytes
918 emit_insn (gen_cmpsi (bytes_reg, GEN_INT (MAX_UNALIGNED_COPY)));
919 emit_jump_insn (gen_blt (aligned_label));
922 /* Emit insns to do alignment at run time */
923 emit_insn (gen_negsi2 (count_reg, src_reg));
924 emit_insn (gen_andsi3 (count_reg, count_reg, GEN_INT (3)));
925 emit_insn (gen_subsi3 (bytes_reg, bytes_reg, count_reg));
926 emit_insn (gen_movstrsi1 (const1_rtx));
928 emit_label (aligned_label);
930 /* insns to copy by words */
931 emit_insn (gen_lshrsi3 (count_reg, bytes_reg, GEN_INT (2)));
932 emit_insn (gen_movstrsi1 (GEN_INT (4)));
934 /* insns to copy rest */
935 emit_insn (gen_andsi3 (count_reg, bytes_reg, GEN_INT (3)));
936 emit_insn (gen_movstrsi1 (const1_rtx));
941 /* Returns 1 if OP contains a global symbol reference */
944 global_symbolic_reference_mentioned_p (op, f)
948 register const char *fmt;
951 if (GET_CODE (op) == SYMBOL_REF)
953 if (! SYMBOL_REF_FLAG (op))
958 else if (f && GET_CODE (op) != CONST)
961 fmt = GET_RTX_FORMAT (GET_CODE (op));
962 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
968 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
969 if (global_symbolic_reference_mentioned_p (XVECEXP (op, i, j), 0))
972 else if (fmt[i] == 'e'
973 && global_symbolic_reference_mentioned_p (XEXP (op, i), 0))
981 /* Returns 1 if OP contains a symbol reference */
984 symbolic_reference_mentioned_p (op)
987 register const char *fmt;
990 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
993 fmt = GET_RTX_FORMAT (GET_CODE (op));
994 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
1000 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
1001 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
1004 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
1011 /* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine specific
1012 attribute for TYPE. The attributes in ATTRIBUTES have previously been
1013 assigned to TYPE. */
1016 ns32k_valid_type_attribute_p (type, attributes, identifier, args)
1018 tree attributes ATTRIBUTE_UNUSED;
1022 if (TREE_CODE (type) != FUNCTION_TYPE
1023 && TREE_CODE (type) != FIELD_DECL
1024 && TREE_CODE (type) != TYPE_DECL)
1027 /* Stdcall attribute says callee is responsible for popping arguments
1028 if they are not variable. */
1029 if (is_attribute_p ("stdcall", identifier))
1030 return (args == NULL_TREE);
1032 /* Cdecl attribute says the callee is a normal C declaration */
1033 if (is_attribute_p ("cdecl", identifier))
1034 return (args == NULL_TREE);
1040 /* Value is the number of bytes of arguments automatically
1041 popped when returning from a subroutine call.
1042 FUNDECL is the declaration node of the function (as a tree),
1043 FUNTYPE is the data type of the function (as a tree),
1044 or for a library call it is an identifier node for the subroutine name.
1045 SIZE is the number of bytes of arguments passed on the stack.
1047 On the ns32k, the RET insn may be used to pop them if the number
1048 of args is fixed, but if the number is variable then the caller
1049 must pop them all. RET can't be used for library calls now
1050 because the library is compiled with the Unix compiler.
1051 Use of RET is a selectable option, since it is incompatible with
1052 standard Unix calling sequences. If the option is not selected,
1053 the caller must always pop the args.
1055 The attribute stdcall is equivalent to RET on a per module basis. */
1058 ns32k_return_pops_args (fundecl, funtype, size)
1059 tree fundecl ATTRIBUTE_UNUSED;
1063 int rtd = TARGET_RTD;
1065 if (TREE_CODE (funtype) == IDENTIFIER_NODE)
1066 return rtd ? size : 0;
1068 /* Cdecl functions override -mrtd, and never pop the stack */
1069 if (lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype)))
1072 /* Stdcall functions will pop the stack if not variable args */
1073 if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype)))
1078 if (TYPE_ARG_TYPES (funtype) == NULL_TREE
1079 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype))) == void_type_node))
1086 /* PRINT_OPERAND is defined to call this function,
1087 which is easier to debug than putting all the code in
1088 a macro definition in ns32k.h. */
1090 /* XXX time 12% of cpu time is in fprintf for non optimizing */
1092 print_operand (file, x, code)
1098 PUT_IMMEDIATE_PREFIX (file);
1099 else if (code == '?')
1100 PUT_EXTERNAL_PREFIX (file);
1101 else if (GET_CODE (x) == REG)
1102 fprintf (file, "%s", ns32k_out_reg_names[REGNO (x)]);
1103 else if (GET_CODE (x) == MEM)
1105 output_address (XEXP (x, 0));
1107 else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != VOIDmode)
1109 if (GET_MODE (x) == DFmode)
1111 union { double d; int i[2]; } u;
1112 u.i[0] = CONST_DOUBLE_LOW (x); u.i[1] = CONST_DOUBLE_HIGH (x);
1113 PUT_IMMEDIATE_PREFIX (file);
1115 /* Sequent likes its floating point constants as integers */
1116 fprintf (file, "0Dx%08x%08x", u.i[1], u.i[0]);
1119 fprintf (file, "0f%.20e", u.d);
1121 fprintf (file, "0d%.20e", u.d);
1127 union { double d; int i[2]; } u;
1128 u.i[0] = CONST_DOUBLE_LOW (x); u.i[1] = CONST_DOUBLE_HIGH (x);
1129 PUT_IMMEDIATE_PREFIX (file);
1131 /* We have no way of winning if we can't get the bits
1132 for a sequent floating point number. */
1133 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1137 union { float f; long l; } uu;
1139 fprintf (file, "0Fx%08x", uu.l);
1142 fprintf (file, "0f%.20e", u.d);
1149 && GET_CODE (x) == CONST
1150 && symbolic_reference_mentioned_p (x))
1152 fprintf (stderr, "illegal constant for pic-mode: \n");
1153 print_rtl (stderr, x);
1154 fprintf (stderr, "\nGET_CODE (x) == %d, CONST == %d, symbolic_reference_mentioned_p (x) == %d\n",
1155 GET_CODE (x), CONST, symbolic_reference_mentioned_p (x));
1159 && (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF))
1161 output_addr_const (file, x);
1162 fprintf (file, "(sb)");
1166 #ifdef NO_IMMEDIATE_PREFIX_IF_SYMBOLIC
1167 if (GET_CODE (x) == CONST_INT)
1169 PUT_IMMEDIATE_PREFIX (file);
1170 output_addr_const (file, x);
1175 /* PRINT_OPERAND_ADDRESS is defined to call this function,
1176 which is easier to debug than putting all the code in
1177 a macro definition in ns32k.h . */
1179 /* Completely rewritten to get this to work with Gas for PC532 Mach.
1180 This function didn't work and I just wasn't able (nor very willing) to
1181 figure out how it worked.
1182 90-11-25 Tatu Yl|nen <ylo@cs.hut.fi> */
1185 print_operand_address (file, addr)
1186 register FILE *file;
1189 static char scales[] = { 'b', 'w', 'd', 0, 'q', };
1190 rtx offset, base, indexexp, tmp;
1192 extern int flag_pic;
1194 if (GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == POST_DEC)
1196 fprintf (file, "tos");
1203 while (addr != NULL)
1205 if (GET_CODE (addr) == PLUS)
1207 if (GET_CODE (XEXP (addr, 0)) == PLUS)
1209 tmp = XEXP (addr, 1);
1210 addr = XEXP (addr, 0);
1214 tmp = XEXP (addr,0);
1215 addr = XEXP (addr,1);
1223 switch (GET_CODE (tmp))
1237 if (REGNO (tmp) < F0_REGNUM)
1257 if (flag_pic && ! CONSTANT_POOL_ADDRESS_P (tmp)
1258 && ! SYMBOL_REF_FLAG (tmp))
1270 if (flag_pic && GET_CODE (tmp) == CONST)
1273 tmp1 = XEXP (tmp,0);
1274 if (GET_CODE (tmp1) != PLUS)
1277 sym = XEXP (tmp1,0);
1278 if (GET_CODE (sym) != SYMBOL_REF)
1281 sym = XEXP (tmp1,1);
1284 off = XEXP (tmp1,1);
1285 if (GET_CODE (sym) == SYMBOL_REF)
1287 if (GET_CODE (off) != CONST_INT)
1290 if (CONSTANT_POOL_ADDRESS_P (sym)
1291 || SYMBOL_REF_FLAG (sym))
1293 SYMBOL_REF_FLAG (tmp) = 1;
1317 offset = gen_rtx_PLUS (SImode, tmp, offset);
1326 offset = const0_rtx;
1329 #ifndef INDEX_RATHER_THAN_BASE
1330 && (flag_pic || TARGET_HIMEM)
1331 && GET_CODE (base) != SYMBOL_REF
1332 && GET_CODE (offset) != CONST_INT
1334 /* This is a re-implementation of the SEQUENT_ADDRESS_BUG fix. */
1336 && !indexexp && GET_CODE (base) == REG
1337 && REG_OK_FOR_INDEX_P (base))
1343 /* now, offset, base and indexexp are set */
1344 #ifndef BASE_REG_NEEDED
1347 #if defined (PC_RELATIVE) || defined (NO_ABSOLUTE_PREFIX_IF_SYMBOLIC)
1348 if (GET_CODE (offset) == CONST_INT)
1350 PUT_ABSOLUTE_PREFIX (file);
1354 output_addr_const (file, offset);
1355 if (base) /* base can be (REG ...) or (MEM ...) */
1356 switch (GET_CODE (base))
1358 /* now we must output base. Possible alternatives are:
1362 (pc) (REG ...) used for SYMBOL_REF and LABEL_REF, output
1363 (disp(fp)) (MEM ...) just before possible [rX:y]
1364 (disp(sp)) (MEM ...)
1365 (disp(sb)) (MEM ...)
1368 fprintf (file, "(%s)", ns32k_out_reg_names[REGNO (base)]);
1374 fprintf (file, "(");
1375 output_addr_const (file, base);
1376 fprintf (file, "(sb))");
1379 addr = XEXP (base,0);
1382 while (addr != NULL)
1384 if (GET_CODE (addr) == PLUS)
1386 if (GET_CODE (XEXP (addr, 0)) == PLUS)
1388 tmp = XEXP (addr, 1);
1389 addr = XEXP (addr, 0);
1393 tmp = XEXP (addr, 0);
1394 addr = XEXP (addr, 1);
1402 switch (GET_CODE (tmp))
1412 offset = gen_rtx_PLUS (SImode, tmp, offset);
1421 offset = const0_rtx;
1422 fprintf (file, "(");
1423 output_addr_const (file, offset);
1425 fprintf (file, "(%s)", ns32k_out_reg_names[REGNO (base)]);
1427 fprintf (file, "(sb)");
1430 fprintf (file, ")");
1436 else if (GET_CODE (offset) != CONST_INT)
1437 fprintf (file, "(pc)");
1438 #ifdef BASE_REG_NEEDED
1440 fprintf (file, "(sb)");
1444 #endif /* PC_RELATIVE */
1446 /* now print index if we have one */
1449 if (GET_CODE (indexexp) == MULT)
1451 scale = INTVAL (XEXP (indexexp, 1)) >> 1;
1452 indexexp = XEXP (indexexp, 0);
1456 if (GET_CODE (indexexp) != REG || REGNO (indexexp) >= F0_REGNUM)
1460 fprintf (file, "[%c`%s]",
1462 ns32k_out_reg_names[REGNO (indexexp)]);
1464 fprintf (file, "[%s:%c]",
1465 ns32k_out_reg_names[REGNO (indexexp)],
1471 /* National 32032 shifting is so bad that we can get
1472 better performance in many common cases by using other
1475 output_shift_insn (operands)
1478 if (GET_CODE (operands[2]) == CONST_INT
1479 && INTVAL (operands[2]) > 0
1480 && INTVAL (operands[2]) <= 3)
1482 if (GET_CODE (operands[0]) == REG)
1484 if (GET_CODE (operands[1]) == REG)
1486 if (REGNO (operands[0]) == REGNO (operands[1]))
1488 if (operands[2] == const1_rtx)
1489 return "addd %0,%0";
1490 else if (INTVAL (operands[2]) == 2)
1491 return "addd %0,%0\n\taddd %0,%0";
1493 if (operands[2] == const1_rtx)
1494 return "movd %1,%0\n\taddd %0,%0";
1496 operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
1497 return "addr %a1,%0";
1499 if (operands[2] == const1_rtx)
1500 return "movd %1,%0\n\taddd %0,%0";
1502 else if (GET_CODE (operands[1]) == REG)
1504 operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
1505 return "addr %a1,%0";
1507 else if (INTVAL (operands[2]) == 1
1508 && GET_CODE (operands[1]) == MEM
1509 && rtx_equal_p (operands [0], operands[1]))
1511 rtx temp = XEXP (operands[1], 0);
1513 if (GET_CODE (temp) == REG
1514 || (GET_CODE (temp) == PLUS
1515 && GET_CODE (XEXP (temp, 0)) == REG
1516 && GET_CODE (XEXP (temp, 1)) == CONST_INT))
1517 return "addd %0,%0";
1519 else return "ashd %2,%0";
1521 return "ashd %2,%0";
1525 output_move_dconst (n, s)
1531 if (n > -9 && n < 8)
1532 strcpy (r, "movqd ");
1533 else if (n > 0 && n < 256)
1534 strcpy (r, "movzbd ");
1535 else if (n > 0 && n < 65536)
1536 strcpy (r, "movzwd ");
1537 else if (n < 0 && n > -129)
1538 strcpy (r, "movxbd ");
1539 else if (n < 0 && n > -32769)
1540 strcpy (r, "movxwd ");
1542 strcpy (r, "movd ");