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 rtx
gen_indexed_expr (rtx
, rtx
, rtx
);
68 static const char *singlemove_string (rtx
*);
69 static void move_tail (rtx
[], int, int);
70 static tree
ns32k_handle_fntype_attribute (tree
*, tree
, tree
, int, bool *);
71 const struct attribute_spec ns32k_attribute_table
[];
72 static void ns32k_output_function_prologue (FILE *, HOST_WIDE_INT
);
73 static void ns32k_output_function_epilogue (FILE *, HOST_WIDE_INT
);
74 static bool ns32k_rtx_costs (rtx
, int, int, int *);
75 static int ns32k_address_cost (rtx
);
76 static rtx
ns32k_struct_value_rtx (tree
, int);
78 /* Initialize the GCC target structure. */
79 #undef TARGET_ATTRIBUTE_TABLE
80 #define TARGET_ATTRIBUTE_TABLE ns32k_attribute_table
82 #undef TARGET_ASM_ALIGNED_HI_OP
83 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
86 #undef TARGET_ASM_ALIGNED_SI_OP
87 #define TARGET_ASM_ALIGNED_SI_OP "\t.double\t"
90 #undef TARGET_ASM_FUNCTION_PROLOGUE
91 #define TARGET_ASM_FUNCTION_PROLOGUE ns32k_output_function_prologue
92 #undef TARGET_ASM_FUNCTION_EPILOGUE
93 #define TARGET_ASM_FUNCTION_EPILOGUE ns32k_output_function_epilogue
95 #undef TARGET_RTX_COSTS
96 #define TARGET_RTX_COSTS ns32k_rtx_costs
97 #undef TARGET_ADDRESS_COST
98 #define TARGET_ADDRESS_COST ns32k_address_cost
100 #undef TARGET_STRUCT_VALUE_RTX
101 #define TARGET_STRUCT_VALUE_RTX ns32k_struct_value_rtx
103 #undef TARGET_ASM_FILE_START_APP_OFF
104 #define TARGET_ASM_FILE_START_APP_OFF true
106 struct gcc_target targetm
= TARGET_INITIALIZER
;
108 /* Generate the assembly code for function entry. FILE is a stdio
109 stream to output the code to. SIZE is an int: how many units of
110 temporary storage to allocate.
112 Refer to the array `regs_ever_live' to determine which registers to
113 save; `regs_ever_live[I]' is nonzero if register number I is ever
114 used in the function. This function is responsible for knowing
115 which registers should not be saved even if used. */
118 * The function prologue for the ns32k is fairly simple.
119 * If a frame pointer is needed (decided in reload.c ?) then
120 * we need assembler of the form
122 * # Save the oldframe pointer, set the new frame pointer, make space
123 * # on the stack and save any general purpose registers necessary
125 * enter [<general purpose regs to save>], <local stack space>
127 * movf fn, tos # Save any floating point registers necessary
131 * If a frame pointer is not needed we need assembler of the form
133 * # Make space on the stack
135 * adjspd <local stack space + 4>
137 * # Save any general purpose registers necessary
139 * save [<general purpose regs to save>]
141 * movf fn, tos # Save any floating point registers necessary
146 #if !defined (MERLIN_TARGET) && !defined (UTEK_ASM)
148 #if defined(IMMEDIATE_PREFIX) && IMMEDIATE_PREFIX
149 #define ADJSP(FILE, N) \
150 fprintf (FILE, "\tadjspd %c" HOST_WIDE_INT_PRINT_DEC "\n", IMMEDIATE_PREFIX, (N))
152 #define ADJSP(FILE, N) \
153 fprintf (FILE, "\tadjspd " HOST_WIDE_INT_PRINT_DEC "\n", (N))
157 ns32k_output_function_prologue (FILE *file
, HOST_WIDE_INT size
)
159 register int regno
, g_regs_used
= 0;
160 int used_regs_buf
[8], *bufp
= used_regs_buf
;
161 int used_fregs_buf
[17], *fbufp
= used_fregs_buf
;
163 for (regno
= R0_REGNUM
; regno
< F0_REGNUM
; regno
++)
164 if (regs_ever_live
[regno
]
165 && ! call_used_regs
[regno
])
167 *bufp
++ = regno
; g_regs_used
++;
171 for (; regno
< FRAME_POINTER_REGNUM
; regno
++)
172 if (regs_ever_live
[regno
] && !call_used_regs
[regno
])
178 bufp
= used_regs_buf
;
179 if (frame_pointer_needed
)
180 fprintf (file
, "\tenter [");
184 ADJSP (file
, size
+ 4);
185 if (g_regs_used
&& g_regs_used
> 4)
186 fprintf (file
, "\tsave [");
190 fprintf (file
, "\tmovd r%d,tos\n", *bufp
++);
197 fprintf (file
, "r%d", *bufp
++);
202 if (frame_pointer_needed
)
203 fprintf (file
, "]," HOST_WIDE_INT_PRINT_DEC
"\n", size
);
204 else if (g_regs_used
)
205 fprintf (file
, "]\n");
207 fbufp
= used_fregs_buf
;
210 if ((*fbufp
& 1) || (fbufp
[0] != fbufp
[1] - 1))
211 fprintf (file
, "\tmovf %s,tos\n", ns32k_out_reg_names
[*fbufp
++]);
214 fprintf (file
, "\tmovl %s,tos\n",
215 ns32k_out_reg_names
[fbufp
[0]]);
220 if (flag_pic
&& current_function_uses_pic_offset_table
)
222 fprintf (file
, "\tsprd sb,tos\n");
225 fprintf (file
, "\taddr __GLOBAL_OFFSET_TABLE_(pc),tos\n");
226 fprintf (file
, "\tlprd sb,tos\n");
230 fprintf (file
, "\taddr __GLOBAL_OFFSET_TABLE_(pc),r0\n");
231 fprintf (file
, "\tlprd sb,r0\n");
236 #else /* MERLIN_TARGET || UTEK_ASM */
238 /* This differs from the standard one above in printing a bitmask
239 rather than a register list in the enter or save instruction. */
242 ns32k_output_function_prologue (file
, size
)
246 register int regno
, g_regs_used
= 0;
247 int used_regs_buf
[8], *bufp
= used_regs_buf
;
248 int used_fregs_buf
[8], *fbufp
= used_fregs_buf
;
250 for (regno
= 0; regno
< 8; regno
++)
251 if (regs_ever_live
[regno
]
252 && ! call_used_regs
[regno
])
254 *bufp
++ = regno
; g_regs_used
++;
258 for (; regno
< 16; regno
++)
259 if (regs_ever_live
[regno
] && !call_used_regs
[regno
]) {
264 bufp
= used_regs_buf
;
265 if (frame_pointer_needed
)
266 fprintf (file
, "\tenter ");
267 else if (g_regs_used
)
268 fprintf (file
, "\tsave ");
270 if (frame_pointer_needed
|| g_regs_used
)
274 mask
|= 1 << *bufp
++;
275 fprintf (file
, "$0x%x", (int) mask
& 0xff);
278 if (frame_pointer_needed
)
280 fprintf (file
, ",$%d\n", size
);
282 fprintf (file
, ",%d\n", size
);
284 else if (g_regs_used
)
285 fprintf (file
, "\n");
287 fbufp
= used_fregs_buf
;
290 if ((*fbufp
& 1) || (fbufp
[0] != fbufp
[1] - 1))
291 fprintf (file
, "\tmovf f%d,tos\n", *fbufp
++ - 8);
294 fprintf (file
, "\tmovl f%d,tos\n", fbufp
[0] - 8);
300 #endif /* MERLIN_TARGET || UTEK_ASM */
302 /* This function generates the assembly code for function exit,
303 on machines that need it.
305 The function epilogue should not depend on the current stack pointer,
306 if EXIT_IGNORE_STACK is nonzero. That doesn't apply here.
308 If a frame pointer is needed (decided in reload.c ?) then
309 we need assembler of the form
311 movf tos, fn # Restore any saved floating point registers
315 # Restore any saved general purpose registers, restore the stack
316 # pointer from the frame pointer, restore the old frame pointer.
317 exit [<general purpose regs to save>]
319 If a frame pointer is not needed we need assembler of the form
320 # Restore any general purpose registers saved
322 movf tos, fn # Restore any saved floating point registers
326 restore [<general purpose regs to save>]
328 # reclaim space allocated on stack
330 adjspd <-(local stack space + 4)> */
332 #if !defined (MERLIN_TARGET) && !defined (UTEK_ASM)
335 ns32k_output_function_epilogue (FILE *file
, HOST_WIDE_INT size
)
337 register int regno
, g_regs_used
= 0, f_regs_used
= 0;
338 int used_regs_buf
[8], *bufp
= used_regs_buf
;
339 int used_fregs_buf
[17], *fbufp
= used_fregs_buf
;
341 if (flag_pic
&& current_function_uses_pic_offset_table
)
342 fprintf (file
, "\tlprd sb,tos\n");
345 for (regno
= F0_REGNUM
; regno
< FRAME_POINTER_REGNUM
; regno
++)
346 if (regs_ever_live
[regno
] && !call_used_regs
[regno
])
348 *fbufp
++ = regno
; f_regs_used
++;
352 for (regno
= 0; regno
< F0_REGNUM
; regno
++)
353 if (regs_ever_live
[regno
]
354 && ! call_used_regs
[regno
])
356 *bufp
++ = regno
; g_regs_used
++;
359 while (fbufp
> used_fregs_buf
)
361 if ((*fbufp
& 1) && fbufp
[0] == fbufp
[-1] + 1)
363 fprintf (file
, "\tmovl tos,%s\n",
364 ns32k_out_reg_names
[fbufp
[-1]]);
367 else fprintf (file
, "\tmovf tos,%s\n", ns32k_out_reg_names
[*fbufp
--]);
370 if (frame_pointer_needed
)
371 fprintf (file
, "\texit [");
374 if (g_regs_used
&& g_regs_used
> 4)
375 fprintf (file
, "\trestore [");
378 while (bufp
> used_regs_buf
)
379 fprintf (file
, "\tmovd tos,r%d\n", *--bufp
);
384 while (bufp
> used_regs_buf
)
386 fprintf (file
, "r%d", *--bufp
);
387 if (bufp
> used_regs_buf
)
391 if (g_regs_used
|| frame_pointer_needed
)
392 fprintf (file
, "]\n");
394 if (size
&& !frame_pointer_needed
)
395 ADJSP (file
, -(size
+ 4));
397 if (current_function_pops_args
)
398 fprintf (file
, "\tret %d\n", current_function_pops_args
);
400 fprintf (file
, "\tret 0\n");
403 #else /* MERLIN_TARGET || UTEK_ASM */
405 /* This differs from the standard one above in printing a bitmask
406 rather than a register list in the exit or restore instruction. */
409 ns32k_output_function_epilogue (file
, size
)
411 HOST_WIDE_INT size ATTRIBUTE_UNUSED
;
413 register int regno
, g_regs_used
= 0, f_regs_used
= 0;
414 int used_regs_buf
[8], *bufp
= used_regs_buf
;
415 int used_fregs_buf
[8], *fbufp
= used_fregs_buf
;
418 for (regno
= 8; regno
< 16; regno
++)
419 if (regs_ever_live
[regno
] && !call_used_regs
[regno
]) {
420 *fbufp
++ = regno
; f_regs_used
++;
424 for (regno
= 0; regno
< 8; regno
++)
425 if (regs_ever_live
[regno
]
426 && ! call_used_regs
[regno
])
428 *bufp
++ = regno
; g_regs_used
++;
431 while (fbufp
> used_fregs_buf
)
433 if ((*fbufp
& 1) && fbufp
[0] == fbufp
[-1] + 1)
435 fprintf (file
, "\tmovl tos,f%d\n", fbufp
[-1] - 8);
438 else fprintf (file
, "\tmovf tos,f%d\n", *fbufp
-- - 8);
441 if (frame_pointer_needed
)
442 fprintf (file
, "\texit ");
443 else if (g_regs_used
)
444 fprintf (file
, "\trestore ");
446 if (g_regs_used
|| frame_pointer_needed
)
450 while (bufp
> used_regs_buf
)
452 /* Utek assembler takes care of reversing this */
453 mask
|= 1 << *--bufp
;
455 fprintf (file
, "$0x%x\n", (int) mask
& 0xff);
459 if (current_function_pops_args
)
460 fprintf (file
, "\tret $%d\n", current_function_pops_args
);
462 fprintf (file
, "\tret $0\n");
464 if (current_function_pops_args
)
465 fprintf (file
, "\tret %d\n", current_function_pops_args
);
467 fprintf (file
, "\tret 0\n");
471 #endif /* MERLIN_TARGET || UTEK_ASM */
473 /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */
475 hard_regno_mode_ok (int regno
, enum machine_mode mode
)
477 int size
= GET_MODE_UNIT_SIZE (mode
);
479 if (FLOAT_MODE_P (mode
))
481 if (size
== UNITS_PER_WORD
&& regno
< L1_REGNUM
)
483 if (size
== UNITS_PER_WORD
* 2
484 && (((regno
& 1) == 0 && regno
< FRAME_POINTER_REGNUM
)))
488 if (size
== UNITS_PER_WORD
* 2
489 && (regno
& 1) == 0 && regno
< F0_REGNUM
)
491 if (size
<= UNITS_PER_WORD
492 && (regno
< F0_REGNUM
|| regno
== FRAME_POINTER_REGNUM
493 || regno
== STACK_POINTER_REGNUM
))
499 ns32k_rtx_costs (rtx x
, int code
, int outer_code ATTRIBUTE_UNUSED
, int *total
)
504 if (INTVAL (x
) <= 7 && INTVAL (x
) >= -8)
506 else if (INTVAL (x
) < 0x2000 && INTVAL (x
) >= -0x2000)
528 register_move_cost (enum reg_class CLASS1
, enum reg_class CLASS2
)
530 if (CLASS1
== NO_REGS
|| CLASS2
== NO_REGS
)
532 if ((SUBSET_P (CLASS1
, FP_REGS
) && !SUBSET_P (CLASS2
, FP_REGS
))
533 || (!SUBSET_P (CLASS1
, FP_REGS
) && SUBSET_P (CLASS2
, FP_REGS
)))
535 if (((CLASS1
) == STACK_POINTER_REG
&& !SUBSET_P (CLASS2
,GENERAL_REGS
))
536 || ((CLASS2
) == STACK_POINTER_REG
&& !SUBSET_P (CLASS1
,GENERAL_REGS
)))
538 if (((CLASS1
) == FRAME_POINTER_REG
&& !SUBSET_P (CLASS2
,GENERAL_REGS
))
539 || ((CLASS2
) == FRAME_POINTER_REG
&& !SUBSET_P (CLASS1
,GENERAL_REGS
)))
545 /* We made the insn definitions copy from floating point to general
546 registers via the stack. */
548 secondary_memory_needed (enum reg_class CLASS1
,
549 enum reg_class CLASS2
,
552 int ret
= ((SUBSET_P (CLASS1
, FP_REGS
) && !SUBSET_P (CLASS2
, FP_REGS
))
553 || (!SUBSET_P (CLASS1
, FP_REGS
) && SUBSET_P (CLASS2
, FP_REGS
)));
559 /* TARGET_ADDRESS_COST calls this. This function is not optimal
560 for the 32032 & 32332, but it probably is better than
564 ns32k_address_cost (rtx operand
)
568 switch (GET_CODE (operand
))
579 if (INTVAL (operand
) <= 7 && INTVAL (operand
) >= -8)
581 if (INTVAL (operand
) < 0x2000 && INTVAL (operand
) >= -0x2000)
596 cost
+= ns32k_address_cost (XEXP (operand
, 0)) + 3;
603 cost
+= ns32k_address_cost (XEXP (operand
, 0));
604 cost
+= ns32k_address_cost (XEXP (operand
, 1));
614 /* Return the register class of a scratch register needed to copy IN into
615 or out of a register in CLASS in MODE. If it can be done directly,
616 NO_REGS is returned. */
619 secondary_reload_class (enum reg_class
class,
620 enum machine_mode mode ATTRIBUTE_UNUSED
,
623 int regno
= true_regnum (in
);
625 if (regno
>= FIRST_PSEUDO_REGISTER
)
628 if ((class == FRAME_POINTER_REG
&& regno
== STACK_POINTER_REGNUM
)
629 || ( class == STACK_POINTER_REG
&& regno
== FRAME_POINTER_REGNUM
))
635 /* Generate the rtx that comes from an address expression in the md file */
636 /* The expression to be build is BASE[INDEX:SCALE]. To recognize this,
637 scale must be converted from an exponent (from ASHIFT) to a
638 multiplier (for MULT). */
641 gen_indexed_expr (rtx base
, rtx index
, rtx scale
)
645 /* This generates an invalid addressing mode, if BASE is
646 fp or sp. This is handled by PRINT_OPERAND_ADDRESS. */
647 if (GET_CODE (base
) != REG
&& GET_CODE (base
) != CONST_INT
)
648 base
= gen_rtx_MEM (SImode
, base
);
649 addr
= gen_rtx_MULT (SImode
, index
,
650 GEN_INT (1 << INTVAL (scale
)));
651 addr
= gen_rtx_PLUS (SImode
, base
, addr
);
656 /* Split one or more DImode RTL references into pairs of SImode
657 references. The RTL can be REG, offsettable MEM, integer constant, or
658 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
659 split and "num" is its length. lo_half and hi_half are output arrays
660 that parallel "operands". */
663 split_di (rtx operands
[], int num
, rtx lo_half
[], rtx hi_half
[])
667 if (GET_CODE (operands
[num
]) == REG
)
669 lo_half
[num
] = gen_rtx_REG (SImode
, REGNO (operands
[num
]));
670 hi_half
[num
] = gen_rtx_REG (SImode
, REGNO (operands
[num
]) + 1);
672 else if (CONSTANT_P (operands
[num
]))
674 split_double (operands
[num
], &lo_half
[num
], &hi_half
[num
]);
676 else if (offsettable_memref_p (operands
[num
]))
678 lo_half
[num
] = operands
[num
];
679 hi_half
[num
] = adjust_address (operands
[num
], SImode
, 4);
686 /* Return the best assembler insn template
687 for moving operands[1] into operands[0] as a fullword. */
690 singlemove_string (rtx
*operands
)
692 if (GET_CODE (operands
[1]) == CONST_INT
693 && INTVAL (operands
[1]) <= 7
694 && INTVAL (operands
[1]) >= -8)
695 return "movqd %1,%0";
700 output_move_double (rtx
*operands
)
702 enum anon1
{ REGOP
, OFFSOP
, PUSHOP
, CNSTOP
, RNDOP
} optype0
, optype1
;
705 /* First classify both operands. */
707 if (REG_P (operands
[0]))
709 else if (offsettable_memref_p (operands
[0]))
711 else if (GET_CODE (XEXP (operands
[0], 0)) == PRE_DEC
)
716 if (REG_P (operands
[1]))
718 else if (CONSTANT_P (operands
[1])
719 || GET_CODE (operands
[1]) == CONST_DOUBLE
)
721 else if (offsettable_memref_p (operands
[1]))
723 else if (GET_CODE (XEXP (operands
[1], 0)) == PRE_DEC
)
728 /* Check for the cases that the operand constraints are not
729 supposed to allow to happen. Abort if we get one,
730 because generating code for these cases is painful. */
732 if (optype0
== RNDOP
|| optype1
== RNDOP
)
735 /* Ok, we can do one word at a time.
736 Normally we do the low-numbered word first,
737 but if either operand is autodecrementing then we
738 do the high-numbered word first.
740 In either case, set up in LATEHALF the operands to use
741 for the high-numbered word and in some cases alter the
742 operands in OPERANDS to be suitable for the low-numbered word. */
744 if (optype0
== REGOP
)
745 latehalf
[0] = gen_rtx_REG (SImode
, REGNO (operands
[0]) + 1);
746 else if (optype0
== OFFSOP
)
747 latehalf
[0] = adjust_address (operands
[0], SImode
, 4);
749 latehalf
[0] = operands
[0];
751 if (optype1
== REGOP
)
752 latehalf
[1] = gen_rtx_REG (SImode
, REGNO (operands
[1]) + 1);
753 else if (optype1
== OFFSOP
)
754 latehalf
[1] = adjust_address (operands
[1], SImode
, 4);
755 else if (optype1
== CNSTOP
)
756 split_double (operands
[1], &operands
[1], &latehalf
[1]);
758 latehalf
[1] = operands
[1];
760 /* If insn is effectively movd N(sp),tos then we will do the
761 high word first. We should use the adjusted operand 1 (which is N+4(sp))
762 for the low word as well, to compensate for the first decrement of sp.
763 Given this, it doesn't matter which half we do "first". */
764 if (optype0
== PUSHOP
765 && REGNO (XEXP (XEXP (operands
[0], 0), 0)) == STACK_POINTER_REGNUM
766 && reg_overlap_mentioned_p (stack_pointer_rtx
, operands
[1]))
767 operands
[1] = latehalf
[1];
769 /* If one or both operands autodecrementing,
770 do the two words, high-numbered first. */
771 else if (optype0
== PUSHOP
|| optype1
== PUSHOP
)
773 output_asm_insn (singlemove_string (latehalf
), latehalf
);
774 return singlemove_string (operands
);
777 /* If the first move would clobber the source of the second one,
778 do them in the other order. */
780 /* Overlapping registers. */
781 if (optype0
== REGOP
&& optype1
== REGOP
782 && REGNO (operands
[0]) == REGNO (latehalf
[1]))
785 output_asm_insn (singlemove_string (latehalf
), latehalf
);
786 /* Do low-numbered word. */
787 return singlemove_string (operands
);
789 /* Loading into a register which overlaps a register used in the address. */
790 else if (optype0
== REGOP
&& optype1
!= REGOP
791 && reg_overlap_mentioned_p (operands
[0], operands
[1]))
793 if (reg_mentioned_p (operands
[0], XEXP (operands
[1], 0))
794 && reg_mentioned_p (latehalf
[0], XEXP (operands
[1], 0)))
796 /* If both halves of dest are used in the src memory address,
797 load the destination address into the low reg (operands[0]).
798 Then it works to load latehalf first. */
800 xops
[0] = XEXP (operands
[1], 0);
801 xops
[1] = operands
[0];
802 output_asm_insn ("addr %a0,%1", xops
);
803 operands
[1] = gen_rtx_MEM (DImode
, operands
[0]);
804 latehalf
[1] = adjust_address (operands
[1], SImode
, 4);
805 /* The first half has the overlap, Do the late half first. */
806 output_asm_insn (singlemove_string (latehalf
), latehalf
);
808 return singlemove_string (operands
);
810 if (reg_mentioned_p (operands
[0], XEXP (operands
[1], 0)))
812 /* The first half has the overlap, Do the late half first. */
813 output_asm_insn (singlemove_string (latehalf
), latehalf
);
815 return singlemove_string (operands
);
819 /* Normal case. Do the two words, low-numbered first. */
821 output_asm_insn (singlemove_string (operands
), operands
);
823 operands
[0] = latehalf
[0];
824 operands
[1] = latehalf
[1];
825 return singlemove_string (operands
);
829 #define MAX_UNALIGNED_COPY (32)
830 /* Expand string/block move operations.
832 operands[0] is the pointer to the destination.
833 operands[1] is the pointer to the source.
834 operands[2] is the number of bytes to move.
835 operands[3] is the alignment. */
838 move_tail (rtx operands
[], int bytes
, int offset
)
842 emit_move_insn (adjust_address (operands
[0], HImode
, offset
),
843 adjust_address (operands
[1], HImode
, offset
));
847 emit_move_insn (adjust_address (operands
[0], QImode
, offset
),
848 adjust_address (operands
[1], QImode
, offset
));
852 expand_block_move (rtx operands
[])
854 rtx bytes_rtx
= operands
[2];
855 rtx align_rtx
= operands
[3];
856 int constp
= (GET_CODE (bytes_rtx
) == CONST_INT
);
857 int bytes
= (constp
? INTVAL (bytes_rtx
) : 0);
858 int align
= INTVAL (align_rtx
);
859 rtx src_reg
= gen_rtx_REG (Pmode
, 1);
860 rtx dest_reg
= gen_rtx_REG (Pmode
, 2);
861 rtx count_reg
= gen_rtx_REG (SImode
, 0);
863 if (constp
&& bytes
<= 0)
866 if (constp
&& bytes
< 20)
868 int words
= bytes
>> 2;
876 for (; words
; words
--, offset
+= 4)
877 emit_move_insn (adjust_address (operands
[0], SImode
, offset
),
878 adjust_address (operands
[1], SImode
, offset
));
882 /* Use movmd. It is slower than multiple movd's but more
883 compact. It is also slower than movsd for large copies
884 but causes less registers reloading so is better than movsd
887 dest
= copy_addr_to_reg (XEXP (operands
[0], 0));
888 src
= copy_addr_to_reg (XEXP (operands
[1], 0));
890 emit_insn (gen_movstrsi2(dest
, src
, GEN_INT (words
)));
893 move_tail (operands
, bytes
& 3, bytes
& ~3);
897 if (align
> UNITS_PER_WORD
)
898 align
= UNITS_PER_WORD
;
900 /* Move the address into scratch registers. */
901 emit_insn (gen_rtx_CLOBBER (VOIDmode
, dest_reg
));
902 emit_move_insn (dest_reg
, XEXP (operands
[0], 0));
903 operands
[0] = gen_rtx_MEM (SImode
, dest_reg
);
904 emit_insn (gen_rtx_CLOBBER (VOIDmode
, src_reg
));
905 emit_move_insn (src_reg
, XEXP (operands
[1], 0));
906 operands
[1] = gen_rtx_MEM (SImode
, src_reg
);
907 emit_insn (gen_rtx_CLOBBER (VOIDmode
, count_reg
));
909 if (constp
&& (align
== UNITS_PER_WORD
|| bytes
< MAX_UNALIGNED_COPY
))
911 /* constant no of bytes and aligned or small enough copy to not bother
912 * aligning. Emit insns to copy by words.
916 emit_move_insn (count_reg
, GEN_INT (bytes
>> 2));
917 emit_insn (gen_movstrsi1 (GEN_INT (4)));
919 /* insns to copy rest */
920 move_tail (operands
, bytes
& 3, 0);
922 else if (align
== UNITS_PER_WORD
)
924 /* insns to copy by words */
925 emit_insn (gen_lshrsi3 (count_reg
, bytes_rtx
, const2_rtx
));
926 emit_insn (gen_movstrsi1 (GEN_INT (4)));
929 move_tail (operands
, bytes
& 3, 0);
933 /* insns to copy rest */
934 emit_insn (gen_andsi3 (count_reg
, bytes_rtx
, GEN_INT (3)));
935 emit_insn (gen_movstrsi1 (const1_rtx
));
940 /* Not aligned and we may have a lot to copy so it is worth
943 rtx aligned_label
= gen_label_rtx ();
946 bytes_reg
= copy_to_mode_reg (SImode
, bytes_rtx
);
949 /* Emit insns to test and skip over the alignment if it is
950 * not worth it. This doubles as a test to ensure that the alignment
951 * operation can't copy too many bytes
953 emit_insn (gen_cmpsi (bytes_reg
, GEN_INT (MAX_UNALIGNED_COPY
)));
954 emit_jump_insn (gen_blt (aligned_label
));
957 /* Emit insns to do alignment at run time */
958 emit_insn (gen_negsi2 (count_reg
, src_reg
));
959 emit_insn (gen_andsi3 (count_reg
, count_reg
, GEN_INT (3)));
960 emit_insn (gen_subsi3 (bytes_reg
, bytes_reg
, count_reg
));
961 emit_insn (gen_movstrsi1 (const1_rtx
));
963 emit_label (aligned_label
);
965 /* insns to copy by words */
966 emit_insn (gen_lshrsi3 (count_reg
, bytes_reg
, const2_rtx
));
967 emit_insn (gen_movstrsi1 (GEN_INT (4)));
969 /* insns to copy rest */
970 emit_insn (gen_andsi3 (count_reg
, bytes_reg
, GEN_INT (3)));
971 emit_insn (gen_movstrsi1 (const1_rtx
));
976 /* Returns 1 if OP contains a global symbol reference */
979 global_symbolic_reference_mentioned_p (rtx op
, int f
)
981 register const char *fmt
;
984 if (GET_CODE (op
) == SYMBOL_REF
)
986 if (! SYMBOL_REF_LOCAL_P (op
))
991 else if (f
&& GET_CODE (op
) != CONST
)
994 fmt
= GET_RTX_FORMAT (GET_CODE (op
));
995 for (i
= GET_RTX_LENGTH (GET_CODE (op
)) - 1; i
>= 0; i
--)
1001 for (j
= XVECLEN (op
, i
) - 1; j
>= 0; j
--)
1002 if (global_symbolic_reference_mentioned_p (XVECEXP (op
, i
, j
), 0))
1005 else if (fmt
[i
] == 'e'
1006 && global_symbolic_reference_mentioned_p (XEXP (op
, i
), 0))
1014 /* Returns 1 if OP contains a symbol reference */
1017 symbolic_reference_mentioned_p (rtx op
)
1019 register const char *fmt
;
1022 if (GET_CODE (op
) == SYMBOL_REF
|| GET_CODE (op
) == LABEL_REF
)
1025 fmt
= GET_RTX_FORMAT (GET_CODE (op
));
1026 for (i
= GET_RTX_LENGTH (GET_CODE (op
)) - 1; i
>= 0; i
--)
1032 for (j
= XVECLEN (op
, i
) - 1; j
>= 0; j
--)
1033 if (symbolic_reference_mentioned_p (XVECEXP (op
, i
, j
)))
1036 else if (fmt
[i
] == 'e' && symbolic_reference_mentioned_p (XEXP (op
, i
)))
1043 /* Table of machine-specific attributes. */
1045 const struct attribute_spec ns32k_attribute_table
[] =
1047 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
1048 /* Stdcall attribute says callee is responsible for popping arguments
1049 if they are not variable. */
1050 { "stdcall", 0, 0, false, true, true, ns32k_handle_fntype_attribute
},
1051 /* Cdecl attribute says the callee is a normal C declaration */
1052 { "cdecl", 0, 0, false, true, true, ns32k_handle_fntype_attribute
},
1053 { NULL
, 0, 0, false, false, false, NULL
}
1056 /* Handle an attribute requiring a FUNCTION_TYPE, FIELD_DECL or TYPE_DECL;
1057 arguments as in struct attribute_spec.handler. */
1059 ns32k_handle_fntype_attribute (tree
*node
, tree name
,
1060 tree args ATTRIBUTE_UNUSED
,
1061 int flags ATTRIBUTE_UNUSED
,
1064 if (TREE_CODE (*node
) != FUNCTION_TYPE
1065 && TREE_CODE (*node
) != FIELD_DECL
1066 && TREE_CODE (*node
) != TYPE_DECL
)
1068 warning ("`%s' attribute only applies to functions",
1069 IDENTIFIER_POINTER (name
));
1070 *no_add_attrs
= true;
1077 /* Value is the number of bytes of arguments automatically
1078 popped when returning from a subroutine call.
1079 FUNDECL is the declaration node of the function (as a tree),
1080 FUNTYPE is the data type of the function (as a tree),
1081 or for a library call it is an identifier node for the subroutine name.
1082 SIZE is the number of bytes of arguments passed on the stack.
1084 On the ns32k, the RET insn may be used to pop them if the number
1085 of args is fixed, but if the number is variable then the caller
1086 must pop them all. RET can't be used for library calls now
1087 because the library is compiled with the Unix compiler.
1088 Use of RET is a selectable option, since it is incompatible with
1089 standard Unix calling sequences. If the option is not selected,
1090 the caller must always pop the args.
1092 The attribute stdcall is equivalent to RET on a per module basis. */
1095 ns32k_return_pops_args (tree fundecl ATTRIBUTE_UNUSED
, tree funtype
, int size
)
1097 int rtd
= TARGET_RTD
;
1099 if (TREE_CODE (funtype
) == IDENTIFIER_NODE
)
1100 return rtd
? size
: 0;
1102 /* Cdecl functions override -mrtd, and never pop the stack */
1103 if (lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype
)))
1106 /* Stdcall functions will pop the stack if not variable args */
1107 if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype
)))
1112 if (TYPE_ARG_TYPES (funtype
) == NULL_TREE
1113 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype
))) == void_type_node
))
1120 /* PRINT_OPERAND is defined to call this function,
1121 which is easier to debug than putting all the code in
1122 a macro definition in ns32k.h. */
1124 /* XXX time 12% of cpu time is in fprintf for non optimizing */
1126 print_operand (FILE *file
, rtx x
, int code
)
1129 PUT_IMMEDIATE_PREFIX (file
);
1130 else if (code
== '?')
1131 PUT_EXTERNAL_PREFIX (file
);
1132 else if (GET_CODE (x
) == REG
)
1133 fprintf (file
, "%s", ns32k_out_reg_names
[REGNO (x
)]);
1134 else if (GET_CODE (x
) == MEM
)
1136 output_address (XEXP (x
, 0));
1138 else if (GET_CODE (x
) == CONST_DOUBLE
&& GET_MODE (x
) != VOIDmode
)
1142 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
1143 PUT_IMMEDIATE_PREFIX (file
);
1144 if (GET_MODE (x
) == DFmode
)
1147 /* Sequent likes its floating point constants as integers */
1149 REAL_VALUE_TO_TARGET_DOUBLE (r
, l
);
1150 fprintf (file
, "0Dx%08x%08x",
1151 l
[!WORDS_BIG_ENDIAN
], l
[WORDS_BIG_ENDIAN
]);
1154 real_to_decimal (s
, &r
, sizeof (s
), 0, 1);
1156 fprintf (file
, "0f%s", s
);
1158 fprintf (file
, "0d%s", s
);
1166 REAL_VALUE_TO_TARGET_SINGLE (r
, l
);
1167 fprintf (file
, "0Fx%08lx", l
);
1170 real_to_decimal (s
, &r
, sizeof (s
), 0, 1);
1171 fprintf (file
, "0f%s", s
);
1178 && GET_CODE (x
) == CONST
1179 && symbolic_reference_mentioned_p (x
))
1181 fprintf (stderr
, "illegal constant for pic-mode: \n");
1182 print_rtl (stderr
, x
);
1183 fprintf (stderr
, "\nGET_CODE (x) == %d, CONST == %d, symbolic_reference_mentioned_p (x) == %d\n",
1184 GET_CODE (x
), CONST
, symbolic_reference_mentioned_p (x
));
1188 && (GET_CODE (x
) == SYMBOL_REF
|| GET_CODE (x
) == LABEL_REF
))
1190 output_addr_const (file
, x
);
1191 fprintf (file
, "(sb)");
1195 #ifdef NO_IMMEDIATE_PREFIX_IF_SYMBOLIC
1196 if (GET_CODE (x
) == CONST_INT
)
1198 PUT_IMMEDIATE_PREFIX (file
);
1199 output_addr_const (file
, x
);
1204 /* PRINT_OPERAND_ADDRESS is defined to call this function,
1205 which is easier to debug than putting all the code in
1206 a macro definition in ns32k.h . */
1208 /* Completely rewritten to get this to work with Gas for PC532 Mach.
1209 This function didn't work and I just wasn't able (nor very willing) to
1210 figure out how it worked.
1211 90-11-25 Tatu Yl|nen <ylo@cs.hut.fi> */
1214 print_operand_address (register FILE *file
, register rtx addr
)
1216 static const char scales
[] = { 'b', 'w', 'd', 0, 'q', };
1217 rtx offset
, base
, indexexp
, tmp
;
1219 extern int flag_pic
;
1221 if (GET_CODE (addr
) == PRE_DEC
|| GET_CODE (addr
) == POST_DEC
)
1223 fprintf (file
, "tos");
1230 while (addr
!= NULL
)
1232 if (GET_CODE (addr
) == PLUS
)
1234 if (GET_CODE (XEXP (addr
, 0)) == PLUS
)
1236 tmp
= XEXP (addr
, 1);
1237 addr
= XEXP (addr
, 0);
1241 tmp
= XEXP (addr
,0);
1242 addr
= XEXP (addr
,1);
1250 switch (GET_CODE (tmp
))
1264 if (REGNO (tmp
) < F0_REGNUM
)
1284 if (flag_pic
&& ! SYMBOL_REF_LOCAL_P (tmp
))
1296 if (flag_pic
&& GET_CODE (tmp
) == CONST
)
1299 tmp1
= XEXP (tmp
,0);
1300 if (GET_CODE (tmp1
) != PLUS
)
1303 sym
= XEXP (tmp1
,0);
1304 if (GET_CODE (sym
) != SYMBOL_REF
)
1307 sym
= XEXP (tmp1
,1);
1310 off
= XEXP (tmp1
,1);
1311 if (GET_CODE (sym
) == SYMBOL_REF
)
1313 if (GET_CODE (off
) != CONST_INT
)
1316 if (! SYMBOL_REF_LOCAL_P (sym
))
1338 offset
= gen_rtx_PLUS (SImode
, tmp
, offset
);
1347 offset
= const0_rtx
;
1350 #ifndef INDEX_RATHER_THAN_BASE
1351 && (flag_pic
|| TARGET_HIMEM
)
1352 && GET_CODE (base
) != SYMBOL_REF
1353 && GET_CODE (offset
) != CONST_INT
1355 /* This is a re-implementation of the SEQUENT_ADDRESS_BUG fix. */
1357 && !indexexp
&& GET_CODE (base
) == REG
1358 && REG_OK_FOR_INDEX_P (base
))
1364 /* now, offset, base and indexexp are set */
1365 #ifndef BASE_REG_NEEDED
1368 #if defined (PC_RELATIVE) || defined (NO_ABSOLUTE_PREFIX_IF_SYMBOLIC)
1369 if (GET_CODE (offset
) == CONST_INT
)
1371 PUT_ABSOLUTE_PREFIX (file
);
1375 output_addr_const (file
, offset
);
1376 if (base
) /* base can be (REG ...) or (MEM ...) */
1377 switch (GET_CODE (base
))
1379 /* now we must output base. Possible alternatives are:
1383 (pc) (REG ...) used for SYMBOL_REF and LABEL_REF, output
1384 (disp(fp)) (MEM ...) just before possible [rX:y]
1385 (disp(sp)) (MEM ...)
1386 (disp(sb)) (MEM ...)
1389 fprintf (file
, "(%s)", ns32k_out_reg_names
[REGNO (base
)]);
1395 fprintf (file
, "(");
1396 output_addr_const (file
, base
);
1397 fprintf (file
, "(sb))");
1400 addr
= XEXP (base
,0);
1403 while (addr
!= NULL
)
1405 if (GET_CODE (addr
) == PLUS
)
1407 if (GET_CODE (XEXP (addr
, 0)) == PLUS
)
1409 tmp
= XEXP (addr
, 1);
1410 addr
= XEXP (addr
, 0);
1414 tmp
= XEXP (addr
, 0);
1415 addr
= XEXP (addr
, 1);
1423 switch (GET_CODE (tmp
))
1433 offset
= gen_rtx_PLUS (SImode
, tmp
, offset
);
1442 offset
= const0_rtx
;
1443 fprintf (file
, "(");
1444 output_addr_const (file
, offset
);
1446 fprintf (file
, "(%s)", ns32k_out_reg_names
[REGNO (base
)]);
1448 fprintf (file
, "(sb)");
1451 fprintf (file
, ")");
1457 else if (GET_CODE (offset
) != CONST_INT
)
1458 fprintf (file
, "(pc)");
1459 #ifdef BASE_REG_NEEDED
1461 fprintf (file
, "(sb)");
1465 #endif /* PC_RELATIVE */
1467 /* now print index if we have one */
1470 if (GET_CODE (indexexp
) == MULT
)
1472 scale
= INTVAL (XEXP (indexexp
, 1)) >> 1;
1473 indexexp
= XEXP (indexexp
, 0);
1477 if (GET_CODE (indexexp
) != REG
|| REGNO (indexexp
) >= F0_REGNUM
)
1481 fprintf (file
, "[%c`%s]",
1483 ns32k_out_reg_names
[REGNO (indexexp
)]);
1485 fprintf (file
, "[%s:%c]",
1486 ns32k_out_reg_names
[REGNO (indexexp
)],
1492 /* National 32032 shifting is so bad that we can get
1493 better performance in many common cases by using other
1496 output_shift_insn (rtx
*operands
)
1498 if (GET_CODE (operands
[2]) == CONST_INT
1499 && INTVAL (operands
[2]) > 0
1500 && INTVAL (operands
[2]) <= 3)
1502 if (GET_CODE (operands
[0]) == REG
)
1504 if (GET_CODE (operands
[1]) == REG
)
1506 if (REGNO (operands
[0]) == REGNO (operands
[1]))
1508 if (operands
[2] == const1_rtx
)
1509 return "addd %0,%0";
1510 else if (INTVAL (operands
[2]) == 2)
1511 return "addd %0,%0\n\taddd %0,%0";
1513 if (operands
[2] == const1_rtx
)
1514 return "movd %1,%0\n\taddd %0,%0";
1516 operands
[1] = gen_indexed_expr (const0_rtx
, operands
[1], operands
[2]);
1517 return "addr %a1,%0";
1519 if (operands
[2] == const1_rtx
)
1520 return "movd %1,%0\n\taddd %0,%0";
1522 else if (GET_CODE (operands
[1]) == REG
)
1524 operands
[1] = gen_indexed_expr (const0_rtx
, operands
[1], operands
[2]);
1525 return "addr %a1,%0";
1527 else if (INTVAL (operands
[2]) == 1
1528 && GET_CODE (operands
[1]) == MEM
1529 && rtx_equal_p (operands
[0], operands
[1]))
1531 rtx temp
= XEXP (operands
[1], 0);
1533 if (GET_CODE (temp
) == REG
1534 || (GET_CODE (temp
) == PLUS
1535 && GET_CODE (XEXP (temp
, 0)) == REG
1536 && GET_CODE (XEXP (temp
, 1)) == CONST_INT
))
1537 return "addd %0,%0";
1539 else return "ashd %2,%0";
1541 return "ashd %2,%0";
1545 output_move_dconst (int n
, const char *s
)
1549 if (n
> -9 && n
< 8)
1550 strcpy (r
, "movqd ");
1551 else if (n
> 0 && n
< 256)
1552 strcpy (r
, "movzbd ");
1553 else if (n
> 0 && n
< 65536)
1554 strcpy (r
, "movzwd ");
1555 else if (n
< 0 && n
> -129)
1556 strcpy (r
, "movxbd ");
1557 else if (n
< 0 && n
> -32769)
1558 strcpy (r
, "movxwd ");
1560 strcpy (r
, "movd ");
1566 ns32k_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED
,
1567 int incoming ATTRIBUTE_UNUSED
)
1569 return gen_rtx_REG (Pmode
, NS32K_STRUCT_VALUE_REGNUM
);
1572 /* Worker function for NOTICE_UPDATE_CC. */
1575 ns32k_notice_update_cc (rtx exp
, rtx insn ATTRIBUTE_UNUSED
)
1577 if (GET_CODE (exp
) == SET
)
1579 if (GET_CODE (SET_DEST (exp
)) == CC0
)
1581 cc_status
.flags
= 0;
1582 cc_status
.value1
= SET_DEST (exp
);
1583 cc_status
.value2
= SET_SRC (exp
);
1585 else if (GET_CODE (SET_SRC (exp
)) == CALL
)
1589 else if (GET_CODE (SET_DEST (exp
)) == REG
)
1591 if (cc_status
.value1
1592 && reg_overlap_mentioned_p (SET_DEST (exp
), cc_status
.value1
))
1593 cc_status
.value1
= 0;
1594 if (cc_status
.value2
1595 && reg_overlap_mentioned_p (SET_DEST (exp
), cc_status
.value2
))
1596 cc_status
.value2
= 0;
1598 else if (GET_CODE (SET_DEST (exp
)) == MEM
)
1603 else if (GET_CODE (exp
) == PARALLEL
1604 && GET_CODE (XVECEXP (exp
, 0, 0)) == SET
)
1606 if (GET_CODE (SET_DEST (XVECEXP (exp
, 0, 0))) == CC0
)
1608 cc_status
.flags
= 0;
1609 cc_status
.value1
= SET_DEST (XVECEXP (exp
, 0, 0));
1610 cc_status
.value2
= SET_SRC (XVECEXP (exp
, 0, 0));
1612 else if (GET_CODE (SET_DEST (XVECEXP (exp
, 0, 0))) == REG
)
1614 if (cc_status
.value1
1615 && reg_overlap_mentioned_p (SET_DEST (XVECEXP (exp
, 0, 0)),
1617 cc_status
.value1
= 0;
1618 if (cc_status
.value2
1619 && reg_overlap_mentioned_p (SET_DEST (XVECEXP (exp
, 0, 0)),
1621 cc_status
.value2
= 0;
1623 else if (GET_CODE (SET_DEST (XVECEXP (exp
, 0, 0))) == MEM
)
1628 else if (GET_CODE (exp
) == CALL
)
1630 /* all bets are off */
1635 /* nothing happens? CC_STATUS_INIT; */
1637 if (cc_status
.value1
&& GET_CODE (cc_status
.value1
) == REG
1639 && reg_overlap_mentioned_p (cc_status
.value1
, cc_status
.value2
))