1132718Skan/* Subroutines for insn-output.c for SPARC.
272562Sobrien   Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3169689Skan   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
4169689Skan   Free Software Foundation, Inc.
550397Sobrien   Contributed by Michael Tiemann (tiemann@cygnus.com)
6132718Skan   64-bit SPARC-V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
750397Sobrien   at Cygnus Support.
850397Sobrien
9132718SkanThis file is part of GCC.
1050397Sobrien
11132718SkanGCC is free software; you can redistribute it and/or modify
1250397Sobrienit under the terms of the GNU General Public License as published by
1350397Sobrienthe Free Software Foundation; either version 2, or (at your option)
1450397Sobrienany later version.
1550397Sobrien
16132718SkanGCC is distributed in the hope that it will be useful,
1750397Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of
1850397SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1950397SobrienGNU General Public License for more details.
2050397Sobrien
2150397SobrienYou should have received a copy of the GNU General Public License
22132718Skanalong with GCC; see the file COPYING.  If not, write to
23169689Skanthe Free Software Foundation, 51 Franklin Street, Fifth Floor,
24169689SkanBoston, MA 02110-1301, USA.  */
2550397Sobrien
2650397Sobrien#include "config.h"
2750397Sobrien#include "system.h"
28132718Skan#include "coretypes.h"
29132718Skan#include "tm.h"
3050397Sobrien#include "tree.h"
3150397Sobrien#include "rtl.h"
3250397Sobrien#include "regs.h"
3350397Sobrien#include "hard-reg-set.h"
3450397Sobrien#include "real.h"
3550397Sobrien#include "insn-config.h"
36169689Skan#include "insn-codes.h"
3750397Sobrien#include "conditions.h"
3850397Sobrien#include "output.h"
3950397Sobrien#include "insn-attr.h"
4050397Sobrien#include "flags.h"
4190075Sobrien#include "function.h"
4250397Sobrien#include "expr.h"
4390075Sobrien#include "optabs.h"
4450397Sobrien#include "recog.h"
4550397Sobrien#include "toplev.h"
4690075Sobrien#include "ggc.h"
4790075Sobrien#include "tm_p.h"
4890075Sobrien#include "debug.h"
4990075Sobrien#include "target.h"
5090075Sobrien#include "target-def.h"
51132718Skan#include "cfglayout.h"
52169689Skan#include "tree-gimple.h"
53169689Skan#include "langhooks.h"
5450397Sobrien
55169689Skan/* Processor costs */
56169689Skanstatic const
57169689Skanstruct processor_costs cypress_costs = {
58169689Skan  COSTS_N_INSNS (2), /* int load */
59169689Skan  COSTS_N_INSNS (2), /* int signed load */
60169689Skan  COSTS_N_INSNS (2), /* int zeroed load */
61169689Skan  COSTS_N_INSNS (2), /* float load */
62169689Skan  COSTS_N_INSNS (5), /* fmov, fneg, fabs */
63169689Skan  COSTS_N_INSNS (5), /* fadd, fsub */
64169689Skan  COSTS_N_INSNS (1), /* fcmp */
65169689Skan  COSTS_N_INSNS (1), /* fmov, fmovr */
66169689Skan  COSTS_N_INSNS (7), /* fmul */
67169689Skan  COSTS_N_INSNS (37), /* fdivs */
68169689Skan  COSTS_N_INSNS (37), /* fdivd */
69169689Skan  COSTS_N_INSNS (63), /* fsqrts */
70169689Skan  COSTS_N_INSNS (63), /* fsqrtd */
71169689Skan  COSTS_N_INSNS (1), /* imul */
72169689Skan  COSTS_N_INSNS (1), /* imulX */
73169689Skan  0, /* imul bit factor */
74169689Skan  COSTS_N_INSNS (1), /* idiv */
75169689Skan  COSTS_N_INSNS (1), /* idivX */
76169689Skan  COSTS_N_INSNS (1), /* movcc/movr */
77169689Skan  0, /* shift penalty */
78169689Skan};
7950397Sobrien
80169689Skanstatic const
81169689Skanstruct processor_costs supersparc_costs = {
82169689Skan  COSTS_N_INSNS (1), /* int load */
83169689Skan  COSTS_N_INSNS (1), /* int signed load */
84169689Skan  COSTS_N_INSNS (1), /* int zeroed load */
85169689Skan  COSTS_N_INSNS (0), /* float load */
86169689Skan  COSTS_N_INSNS (3), /* fmov, fneg, fabs */
87169689Skan  COSTS_N_INSNS (3), /* fadd, fsub */
88169689Skan  COSTS_N_INSNS (3), /* fcmp */
89169689Skan  COSTS_N_INSNS (1), /* fmov, fmovr */
90169689Skan  COSTS_N_INSNS (3), /* fmul */
91169689Skan  COSTS_N_INSNS (6), /* fdivs */
92169689Skan  COSTS_N_INSNS (9), /* fdivd */
93169689Skan  COSTS_N_INSNS (12), /* fsqrts */
94169689Skan  COSTS_N_INSNS (12), /* fsqrtd */
95169689Skan  COSTS_N_INSNS (4), /* imul */
96169689Skan  COSTS_N_INSNS (4), /* imulX */
97169689Skan  0, /* imul bit factor */
98169689Skan  COSTS_N_INSNS (4), /* idiv */
99169689Skan  COSTS_N_INSNS (4), /* idivX */
100169689Skan  COSTS_N_INSNS (1), /* movcc/movr */
101169689Skan  1, /* shift penalty */
102169689Skan};
10350397Sobrien
104169689Skanstatic const
105169689Skanstruct processor_costs hypersparc_costs = {
106169689Skan  COSTS_N_INSNS (1), /* int load */
107169689Skan  COSTS_N_INSNS (1), /* int signed load */
108169689Skan  COSTS_N_INSNS (1), /* int zeroed load */
109169689Skan  COSTS_N_INSNS (1), /* float load */
110169689Skan  COSTS_N_INSNS (1), /* fmov, fneg, fabs */
111169689Skan  COSTS_N_INSNS (1), /* fadd, fsub */
112169689Skan  COSTS_N_INSNS (1), /* fcmp */
113169689Skan  COSTS_N_INSNS (1), /* fmov, fmovr */
114169689Skan  COSTS_N_INSNS (1), /* fmul */
115169689Skan  COSTS_N_INSNS (8), /* fdivs */
116169689Skan  COSTS_N_INSNS (12), /* fdivd */
117169689Skan  COSTS_N_INSNS (17), /* fsqrts */
118169689Skan  COSTS_N_INSNS (17), /* fsqrtd */
119169689Skan  COSTS_N_INSNS (17), /* imul */
120169689Skan  COSTS_N_INSNS (17), /* imulX */
121169689Skan  0, /* imul bit factor */
122169689Skan  COSTS_N_INSNS (17), /* idiv */
123169689Skan  COSTS_N_INSNS (17), /* idivX */
124169689Skan  COSTS_N_INSNS (1), /* movcc/movr */
125169689Skan  0, /* shift penalty */
126169689Skan};
127169689Skan
128169689Skanstatic const
129169689Skanstruct processor_costs sparclet_costs = {
130169689Skan  COSTS_N_INSNS (3), /* int load */
131169689Skan  COSTS_N_INSNS (3), /* int signed load */
132169689Skan  COSTS_N_INSNS (1), /* int zeroed load */
133169689Skan  COSTS_N_INSNS (1), /* float load */
134169689Skan  COSTS_N_INSNS (1), /* fmov, fneg, fabs */
135169689Skan  COSTS_N_INSNS (1), /* fadd, fsub */
136169689Skan  COSTS_N_INSNS (1), /* fcmp */
137169689Skan  COSTS_N_INSNS (1), /* fmov, fmovr */
138169689Skan  COSTS_N_INSNS (1), /* fmul */
139169689Skan  COSTS_N_INSNS (1), /* fdivs */
140169689Skan  COSTS_N_INSNS (1), /* fdivd */
141169689Skan  COSTS_N_INSNS (1), /* fsqrts */
142169689Skan  COSTS_N_INSNS (1), /* fsqrtd */
143169689Skan  COSTS_N_INSNS (5), /* imul */
144169689Skan  COSTS_N_INSNS (5), /* imulX */
145169689Skan  0, /* imul bit factor */
146169689Skan  COSTS_N_INSNS (5), /* idiv */
147169689Skan  COSTS_N_INSNS (5), /* idivX */
148169689Skan  COSTS_N_INSNS (1), /* movcc/movr */
149169689Skan  0, /* shift penalty */
150169689Skan};
151169689Skan
152169689Skanstatic const
153169689Skanstruct processor_costs ultrasparc_costs = {
154169689Skan  COSTS_N_INSNS (2), /* int load */
155169689Skan  COSTS_N_INSNS (3), /* int signed load */
156169689Skan  COSTS_N_INSNS (2), /* int zeroed load */
157169689Skan  COSTS_N_INSNS (2), /* float load */
158169689Skan  COSTS_N_INSNS (1), /* fmov, fneg, fabs */
159169689Skan  COSTS_N_INSNS (4), /* fadd, fsub */
160169689Skan  COSTS_N_INSNS (1), /* fcmp */
161169689Skan  COSTS_N_INSNS (2), /* fmov, fmovr */
162169689Skan  COSTS_N_INSNS (4), /* fmul */
163169689Skan  COSTS_N_INSNS (13), /* fdivs */
164169689Skan  COSTS_N_INSNS (23), /* fdivd */
165169689Skan  COSTS_N_INSNS (13), /* fsqrts */
166169689Skan  COSTS_N_INSNS (23), /* fsqrtd */
167169689Skan  COSTS_N_INSNS (4), /* imul */
168169689Skan  COSTS_N_INSNS (4), /* imulX */
169169689Skan  2, /* imul bit factor */
170169689Skan  COSTS_N_INSNS (37), /* idiv */
171169689Skan  COSTS_N_INSNS (68), /* idivX */
172169689Skan  COSTS_N_INSNS (2), /* movcc/movr */
173169689Skan  2, /* shift penalty */
174169689Skan};
175169689Skan
176169689Skanstatic const
177169689Skanstruct processor_costs ultrasparc3_costs = {
178169689Skan  COSTS_N_INSNS (2), /* int load */
179169689Skan  COSTS_N_INSNS (3), /* int signed load */
180169689Skan  COSTS_N_INSNS (3), /* int zeroed load */
181169689Skan  COSTS_N_INSNS (2), /* float load */
182169689Skan  COSTS_N_INSNS (3), /* fmov, fneg, fabs */
183169689Skan  COSTS_N_INSNS (4), /* fadd, fsub */
184169689Skan  COSTS_N_INSNS (5), /* fcmp */
185169689Skan  COSTS_N_INSNS (3), /* fmov, fmovr */
186169689Skan  COSTS_N_INSNS (4), /* fmul */
187169689Skan  COSTS_N_INSNS (17), /* fdivs */
188169689Skan  COSTS_N_INSNS (20), /* fdivd */
189169689Skan  COSTS_N_INSNS (20), /* fsqrts */
190169689Skan  COSTS_N_INSNS (29), /* fsqrtd */
191169689Skan  COSTS_N_INSNS (6), /* imul */
192169689Skan  COSTS_N_INSNS (6), /* imulX */
193169689Skan  0, /* imul bit factor */
194169689Skan  COSTS_N_INSNS (40), /* idiv */
195169689Skan  COSTS_N_INSNS (71), /* idivX */
196169689Skan  COSTS_N_INSNS (2), /* movcc/movr */
197169689Skan  0, /* shift penalty */
198169689Skan};
199169689Skan
200169689Skanstatic const
201169689Skanstruct processor_costs niagara_costs = {
202169689Skan  COSTS_N_INSNS (3), /* int load */
203169689Skan  COSTS_N_INSNS (3), /* int signed load */
204169689Skan  COSTS_N_INSNS (3), /* int zeroed load */
205169689Skan  COSTS_N_INSNS (9), /* float load */
206169689Skan  COSTS_N_INSNS (8), /* fmov, fneg, fabs */
207169689Skan  COSTS_N_INSNS (8), /* fadd, fsub */
208169689Skan  COSTS_N_INSNS (26), /* fcmp */
209169689Skan  COSTS_N_INSNS (8), /* fmov, fmovr */
210169689Skan  COSTS_N_INSNS (29), /* fmul */
211169689Skan  COSTS_N_INSNS (54), /* fdivs */
212169689Skan  COSTS_N_INSNS (83), /* fdivd */
213169689Skan  COSTS_N_INSNS (100), /* fsqrts - not implemented in hardware */
214169689Skan  COSTS_N_INSNS (100), /* fsqrtd - not implemented in hardware */
215169689Skan  COSTS_N_INSNS (11), /* imul */
216169689Skan  COSTS_N_INSNS (11), /* imulX */
217169689Skan  0, /* imul bit factor */
218169689Skan  COSTS_N_INSNS (72), /* idiv */
219169689Skan  COSTS_N_INSNS (72), /* idivX */
220169689Skan  COSTS_N_INSNS (1), /* movcc/movr */
221169689Skan  0, /* shift penalty */
222169689Skan};
223169689Skan
224169689Skanconst struct processor_costs *sparc_costs = &cypress_costs;
225169689Skan
226169689Skan#ifdef HAVE_AS_RELAX_OPTION
227169689Skan/* If 'as' and 'ld' are relaxing tail call insns into branch always, use
228169689Skan   "or %o7,%g0,X; call Y; or X,%g0,%o7" always, so that it can be optimized.
229169689Skan   With sethi/jmp, neither 'as' nor 'ld' has an easy way how to find out if
230169689Skan   somebody does not branch between the sethi and jmp.  */
231169689Skan#define LEAF_SIBCALL_SLOT_RESERVED_P 1
232169689Skan#else
233169689Skan#define LEAF_SIBCALL_SLOT_RESERVED_P \
234169689Skan  ((TARGET_ARCH64 && !TARGET_CM_MEDLOW) || flag_pic)
235169689Skan#endif
236169689Skan
23750397Sobrien/* Global variables for machine-dependent things.  */
23850397Sobrien
23950397Sobrien/* Size of frame.  Need to know this to emit return insns from leaf procedures.
240169689Skan   ACTUAL_FSIZE is set by sparc_compute_frame_size() which is called during the
241169689Skan   reload pass.  This is important as the value is later used for scheduling
242169689Skan   (to see what can go in a delay slot).
24350397Sobrien   APPARENT_FSIZE is the size of the stack less the register save area and less
24450397Sobrien   the outgoing argument area.  It is used when saving call preserved regs.  */
245132718Skanstatic HOST_WIDE_INT apparent_fsize;
246132718Skanstatic HOST_WIDE_INT actual_fsize;
24750397Sobrien
24896263Sobrien/* Number of live general or floating point registers needed to be
24996263Sobrien   saved (as 4-byte quantities).  */
25090075Sobrienstatic int num_gfregs;
25190075Sobrien
252169689Skan/* The alias set for prologue/epilogue register save/restore.  */
253169689Skanstatic GTY(()) int sparc_sr_alias_set;
254169689Skan
255169689Skan/* The alias set for the structure return value.  */
256169689Skanstatic GTY(()) int struct_value_alias_set;
257169689Skan
25850397Sobrien/* Save the operands last given to a compare for use when we
25950397Sobrien   generate a scc or bcc insn.  */
260169689Skanrtx sparc_compare_op0, sparc_compare_op1, sparc_compare_emitted;
26150397Sobrien
26296263Sobrien/* Vector to say how input registers are mapped to output registers.
26396263Sobrien   HARD_FRAME_POINTER_REGNUM cannot be remapped by this function to
26496263Sobrien   eliminate it.  You must use -fomit-frame-pointer to get that.  */
26596263Sobrienchar leaf_reg_remap[] =
26650397Sobrien{ 0, 1, 2, 3, 4, 5, 6, 7,
26750397Sobrien  -1, -1, -1, -1, -1, -1, 14, -1,
26850397Sobrien  -1, -1, -1, -1, -1, -1, -1, -1,
26950397Sobrien  8, 9, 10, 11, 12, 13, -1, 15,
27050397Sobrien
27150397Sobrien  32, 33, 34, 35, 36, 37, 38, 39,
27250397Sobrien  40, 41, 42, 43, 44, 45, 46, 47,
27350397Sobrien  48, 49, 50, 51, 52, 53, 54, 55,
27450397Sobrien  56, 57, 58, 59, 60, 61, 62, 63,
27550397Sobrien  64, 65, 66, 67, 68, 69, 70, 71,
27650397Sobrien  72, 73, 74, 75, 76, 77, 78, 79,
27750397Sobrien  80, 81, 82, 83, 84, 85, 86, 87,
27850397Sobrien  88, 89, 90, 91, 92, 93, 94, 95,
27950397Sobrien  96, 97, 98, 99, 100};
28050397Sobrien
28190075Sobrien/* Vector, indexed by hard register number, which contains 1
28290075Sobrien   for a register that is allowable in a candidate for leaf
28390075Sobrien   function treatment.  */
28490075Sobrienchar sparc_leaf_regs[] =
28590075Sobrien{ 1, 1, 1, 1, 1, 1, 1, 1,
28690075Sobrien  0, 0, 0, 0, 0, 0, 1, 0,
28790075Sobrien  0, 0, 0, 0, 0, 0, 0, 0,
28890075Sobrien  1, 1, 1, 1, 1, 1, 0, 1,
28990075Sobrien  1, 1, 1, 1, 1, 1, 1, 1,
29090075Sobrien  1, 1, 1, 1, 1, 1, 1, 1,
29190075Sobrien  1, 1, 1, 1, 1, 1, 1, 1,
29290075Sobrien  1, 1, 1, 1, 1, 1, 1, 1,
29390075Sobrien  1, 1, 1, 1, 1, 1, 1, 1,
29490075Sobrien  1, 1, 1, 1, 1, 1, 1, 1,
29590075Sobrien  1, 1, 1, 1, 1, 1, 1, 1,
29690075Sobrien  1, 1, 1, 1, 1, 1, 1, 1,
29790075Sobrien  1, 1, 1, 1, 1};
29890075Sobrien
299132718Skanstruct machine_function GTY(())
300132718Skan{
301132718Skan  /* Some local-dynamic TLS symbol name.  */
302132718Skan  const char *some_ld_name;
303169689Skan
304169689Skan  /* True if the current function is leaf and uses only leaf regs,
305169689Skan     so that the SPARC leaf function optimization can be applied.
306169689Skan     Private version of current_function_uses_only_leaf_regs, see
307169689Skan     sparc_expand_prologue for the rationale.  */
308169689Skan  int leaf_function_p;
309169689Skan
310169689Skan  /* True if the data calculated by sparc_expand_prologue are valid.  */
311169689Skan  bool prologue_data_valid_p;
312132718Skan};
313132718Skan
314169689Skan#define sparc_leaf_function_p  cfun->machine->leaf_function_p
315169689Skan#define sparc_prologue_data_valid_p  cfun->machine->prologue_data_valid_p
31650397Sobrien
317169689Skan/* Register we pretend to think the frame pointer is allocated to.
318169689Skan   Normally, this is %fp, but if we are in a leaf procedure, this
319169689Skan   is %sp+"something".  We record "something" separately as it may
320169689Skan   be too big for reg+constant addressing.  */
321169689Skanstatic rtx frame_base_reg;
322132718Skanstatic HOST_WIDE_INT frame_base_offset;
32350397Sobrien
324169689Skan/* 1 if the next opcode is to be specially indented.  */
325169689Skanint sparc_indent_opcode = 0;
326169689Skan
327169689Skanstatic bool sparc_handle_option (size_t, const char *, int);
328132718Skanstatic void sparc_init_modes (void);
329132718Skanstatic void scan_record_type (tree, int *, int *, int *);
330132718Skanstatic int function_arg_slotno (const CUMULATIVE_ARGS *, enum machine_mode,
331132718Skan				tree, int, int, int *, int *);
33250397Sobrien
333132718Skanstatic int supersparc_adjust_cost (rtx, rtx, rtx, int);
334132718Skanstatic int hypersparc_adjust_cost (rtx, rtx, rtx, int);
33552284Sobrien
336132718Skanstatic void sparc_output_addr_vec (rtx);
337132718Skanstatic void sparc_output_addr_diff_vec (rtx);
338132718Skanstatic void sparc_output_deferred_case_vectors (void);
339169689Skanstatic rtx sparc_builtin_saveregs (void);
340132718Skanstatic int epilogue_renumber (rtx *, int);
341132718Skanstatic bool sparc_assemble_integer (rtx, unsigned int, int);
342132718Skanstatic int set_extends (rtx);
343169689Skanstatic void emit_pic_helper (void);
344169689Skanstatic void load_pic_register (bool);
345169689Skanstatic int save_or_restore_regs (int, int, rtx, int, int);
346169689Skanstatic void emit_save_or_restore_regs (int);
347169689Skanstatic void sparc_asm_function_prologue (FILE *, HOST_WIDE_INT);
348169689Skanstatic void sparc_asm_function_epilogue (FILE *, HOST_WIDE_INT);
34990075Sobrien#ifdef OBJECT_FORMAT_ELF
350169689Skanstatic void sparc_elf_asm_named_section (const char *, unsigned int, tree);
35190075Sobrien#endif
35252284Sobrien
353132718Skanstatic int sparc_adjust_cost (rtx, rtx, rtx, int);
354132718Skanstatic int sparc_issue_rate (void);
355132718Skanstatic void sparc_sched_init (FILE *, int, int);
356132718Skanstatic int sparc_use_sched_lookahead (void);
35796263Sobrien
358132718Skanstatic void emit_soft_tfmode_libcall (const char *, int, rtx *);
359132718Skanstatic void emit_soft_tfmode_binop (enum rtx_code, rtx *);
360132718Skanstatic void emit_soft_tfmode_unop (enum rtx_code, rtx *);
361132718Skanstatic void emit_soft_tfmode_cvt (enum rtx_code, rtx *);
362132718Skanstatic void emit_hard_tfmode_operation (enum rtx_code, rtx *);
363117395Skan
364132718Skanstatic bool sparc_function_ok_for_sibcall (tree, tree);
365132718Skanstatic void sparc_init_libfuncs (void);
366169689Skanstatic void sparc_init_builtins (void);
367169689Skanstatic void sparc_vis_init_builtins (void);
368169689Skanstatic rtx sparc_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
369169689Skanstatic tree sparc_fold_builtin (tree, tree, bool);
370169689Skanstatic int sparc_vis_mul8x16 (int, int);
371169689Skanstatic tree sparc_handle_vis_mul8x16 (int, tree, tree, tree);
372132718Skanstatic void sparc_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
373132718Skan				   HOST_WIDE_INT, tree);
374146895Skanstatic bool sparc_can_output_mi_thunk (tree, HOST_WIDE_INT,
375146895Skan				       HOST_WIDE_INT, tree);
376132718Skanstatic struct machine_function * sparc_init_machine_status (void);
377132718Skanstatic bool sparc_cannot_force_const_mem (rtx);
378132718Skanstatic rtx sparc_tls_get_addr (void);
379132718Skanstatic rtx sparc_tls_got (void);
380132718Skanstatic const char *get_some_local_dynamic_name (void);
381132718Skanstatic int get_some_local_dynamic_name_1 (rtx *, void *);
382132718Skanstatic bool sparc_rtx_costs (rtx, int, int, int *);
383169689Skanstatic bool sparc_promote_prototypes (tree);
384169689Skanstatic rtx sparc_struct_value_rtx (tree, int);
385169689Skanstatic bool sparc_return_in_memory (tree, tree);
386169689Skanstatic bool sparc_strict_argument_naming (CUMULATIVE_ARGS *);
387169689Skanstatic tree sparc_gimplify_va_arg (tree, tree, tree *, tree *);
388169689Skanstatic bool sparc_vector_mode_supported_p (enum machine_mode);
389169689Skanstatic bool sparc_pass_by_reference (CUMULATIVE_ARGS *,
390169689Skan				     enum machine_mode, tree, bool);
391169689Skanstatic int sparc_arg_partial_bytes (CUMULATIVE_ARGS *,
392169689Skan				    enum machine_mode, tree, bool);
393169689Skanstatic void sparc_dwarf_handle_frame_unspec (const char *, rtx, int);
394169689Skanstatic void sparc_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
395169689Skanstatic void sparc_file_end (void);
396169689Skan#ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
397169689Skanstatic const char *sparc_mangle_fundamental_type (tree);
398169689Skan#endif
399169689Skan#ifdef SUBTARGET_ATTRIBUTE_TABLE
400169689Skanconst struct attribute_spec sparc_attribute_table[];
401169689Skan#endif
40250397Sobrien
40350397Sobrien/* Option handling.  */
40450397Sobrien
40550397Sobrien/* Parsed value.  */
40650397Sobrienenum cmodel sparc_cmodel;
40750397Sobrien
40890075Sobrienchar sparc_hard_reg_printed[8];
40950397Sobrien
41050397Sobrienstruct sparc_cpu_select sparc_select[] =
41150397Sobrien{
41250397Sobrien  /* switch	name,		tune	arch */
41350397Sobrien  { (char *)0,	"default",	1,	1 },
41450397Sobrien  { (char *)0,	"-mcpu=",	1,	1 },
41550397Sobrien  { (char *)0,	"-mtune=",	1,	0 },
41650397Sobrien  { 0, 0, 0, 0 }
41750397Sobrien};
41850397Sobrien
41950397Sobrien/* CPU type.  This is set from TARGET_CPU_DEFAULT and -m{cpu,tune}=xxx.  */
42050397Sobrienenum processor_type sparc_cpu;
421169689Skan
422169689Skan/* Whetheran FPU option was specified.  */
423169689Skanstatic bool fpu_option_set = false;
424169689Skan
42590075Sobrien/* Initialize the GCC target structure.  */
42650397Sobrien
42790075Sobrien/* The sparc default is to use .half rather than .short for aligned
42890075Sobrien   HI objects.  Use .word instead of .long on non-ELF systems.  */
42990075Sobrien#undef TARGET_ASM_ALIGNED_HI_OP
43090075Sobrien#define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
43190075Sobrien#ifndef OBJECT_FORMAT_ELF
43290075Sobrien#undef TARGET_ASM_ALIGNED_SI_OP
43390075Sobrien#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
43490075Sobrien#endif
43590075Sobrien
43690075Sobrien#undef TARGET_ASM_UNALIGNED_HI_OP
43790075Sobrien#define TARGET_ASM_UNALIGNED_HI_OP "\t.uahalf\t"
43890075Sobrien#undef TARGET_ASM_UNALIGNED_SI_OP
43990075Sobrien#define TARGET_ASM_UNALIGNED_SI_OP "\t.uaword\t"
44090075Sobrien#undef TARGET_ASM_UNALIGNED_DI_OP
44190075Sobrien#define TARGET_ASM_UNALIGNED_DI_OP "\t.uaxword\t"
44290075Sobrien
44390075Sobrien/* The target hook has to handle DI-mode values.  */
44490075Sobrien#undef TARGET_ASM_INTEGER
44590075Sobrien#define TARGET_ASM_INTEGER sparc_assemble_integer
44690075Sobrien
44790075Sobrien#undef TARGET_ASM_FUNCTION_PROLOGUE
448169689Skan#define TARGET_ASM_FUNCTION_PROLOGUE sparc_asm_function_prologue
44990075Sobrien#undef TARGET_ASM_FUNCTION_EPILOGUE
450169689Skan#define TARGET_ASM_FUNCTION_EPILOGUE sparc_asm_function_epilogue
45190075Sobrien
45290075Sobrien#undef TARGET_SCHED_ADJUST_COST
45390075Sobrien#define TARGET_SCHED_ADJUST_COST sparc_adjust_cost
45490075Sobrien#undef TARGET_SCHED_ISSUE_RATE
45590075Sobrien#define TARGET_SCHED_ISSUE_RATE sparc_issue_rate
45690075Sobrien#undef TARGET_SCHED_INIT
45790075Sobrien#define TARGET_SCHED_INIT sparc_sched_init
458117395Skan#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
459117395Skan#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD sparc_use_sched_lookahead
46090075Sobrien
461132718Skan#undef TARGET_FUNCTION_OK_FOR_SIBCALL
462132718Skan#define TARGET_FUNCTION_OK_FOR_SIBCALL sparc_function_ok_for_sibcall
463117395Skan
464132718Skan#undef TARGET_INIT_LIBFUNCS
465132718Skan#define TARGET_INIT_LIBFUNCS sparc_init_libfuncs
466169689Skan#undef TARGET_INIT_BUILTINS
467169689Skan#define TARGET_INIT_BUILTINS sparc_init_builtins
468132718Skan
469169689Skan#undef TARGET_EXPAND_BUILTIN
470169689Skan#define TARGET_EXPAND_BUILTIN sparc_expand_builtin
471169689Skan#undef TARGET_FOLD_BUILTIN
472169689Skan#define TARGET_FOLD_BUILTIN sparc_fold_builtin
473169689Skan
474169689Skan#if TARGET_TLS
475132718Skan#undef TARGET_HAVE_TLS
476132718Skan#define TARGET_HAVE_TLS true
477132718Skan#endif
478169689Skan
479132718Skan#undef TARGET_CANNOT_FORCE_CONST_MEM
480132718Skan#define TARGET_CANNOT_FORCE_CONST_MEM sparc_cannot_force_const_mem
481132718Skan
482117395Skan#undef TARGET_ASM_OUTPUT_MI_THUNK
483117395Skan#define TARGET_ASM_OUTPUT_MI_THUNK sparc_output_mi_thunk
484117395Skan#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
485146895Skan#define TARGET_ASM_CAN_OUTPUT_MI_THUNK sparc_can_output_mi_thunk
486117395Skan
487132718Skan#undef TARGET_RTX_COSTS
488132718Skan#define TARGET_RTX_COSTS sparc_rtx_costs
489132718Skan#undef TARGET_ADDRESS_COST
490132718Skan#define TARGET_ADDRESS_COST hook_int_rtx_0
491132718Skan
492169689Skan/* This is only needed for TARGET_ARCH64, but since PROMOTE_FUNCTION_MODE is a
493169689Skan   no-op for TARGET_ARCH32 this is ok.  Otherwise we'd need to add a runtime
494169689Skan   test for this value.  */
495169689Skan#undef TARGET_PROMOTE_FUNCTION_ARGS
496169689Skan#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
497169689Skan
498169689Skan/* This is only needed for TARGET_ARCH64, but since PROMOTE_FUNCTION_MODE is a
499169689Skan   no-op for TARGET_ARCH32 this is ok.  Otherwise we'd need to add a runtime
500169689Skan   test for this value.  */
501169689Skan#undef TARGET_PROMOTE_FUNCTION_RETURN
502169689Skan#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
503169689Skan
504169689Skan#undef TARGET_PROMOTE_PROTOTYPES
505169689Skan#define TARGET_PROMOTE_PROTOTYPES sparc_promote_prototypes
506169689Skan
507169689Skan#undef TARGET_STRUCT_VALUE_RTX
508169689Skan#define TARGET_STRUCT_VALUE_RTX sparc_struct_value_rtx
509169689Skan#undef TARGET_RETURN_IN_MEMORY
510169689Skan#define TARGET_RETURN_IN_MEMORY sparc_return_in_memory
511169689Skan#undef TARGET_MUST_PASS_IN_STACK
512169689Skan#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
513169689Skan#undef TARGET_PASS_BY_REFERENCE
514169689Skan#define TARGET_PASS_BY_REFERENCE sparc_pass_by_reference
515169689Skan#undef TARGET_ARG_PARTIAL_BYTES
516169689Skan#define TARGET_ARG_PARTIAL_BYTES sparc_arg_partial_bytes
517169689Skan
518169689Skan#undef TARGET_EXPAND_BUILTIN_SAVEREGS
519169689Skan#define TARGET_EXPAND_BUILTIN_SAVEREGS sparc_builtin_saveregs
520169689Skan#undef TARGET_STRICT_ARGUMENT_NAMING
521169689Skan#define TARGET_STRICT_ARGUMENT_NAMING sparc_strict_argument_naming
522169689Skan
523169689Skan#undef TARGET_GIMPLIFY_VA_ARG_EXPR
524169689Skan#define TARGET_GIMPLIFY_VA_ARG_EXPR sparc_gimplify_va_arg
525169689Skan
526169689Skan#undef TARGET_VECTOR_MODE_SUPPORTED_P
527169689Skan#define TARGET_VECTOR_MODE_SUPPORTED_P sparc_vector_mode_supported_p
528169689Skan
529169689Skan#undef TARGET_DWARF_HANDLE_FRAME_UNSPEC
530169689Skan#define TARGET_DWARF_HANDLE_FRAME_UNSPEC sparc_dwarf_handle_frame_unspec
531169689Skan
532169689Skan#ifdef SUBTARGET_INSERT_ATTRIBUTES
533169689Skan#undef TARGET_INSERT_ATTRIBUTES
534169689Skan#define TARGET_INSERT_ATTRIBUTES SUBTARGET_INSERT_ATTRIBUTES
535169689Skan#endif
536169689Skan
537169689Skan#ifdef SUBTARGET_ATTRIBUTE_TABLE
538169689Skan#undef TARGET_ATTRIBUTE_TABLE
539169689Skan#define TARGET_ATTRIBUTE_TABLE sparc_attribute_table
540169689Skan#endif
541169689Skan
542169689Skan#undef TARGET_RELAXED_ORDERING
543169689Skan#define TARGET_RELAXED_ORDERING SPARC_RELAXED_ORDERING
544169689Skan
545169689Skan#undef TARGET_DEFAULT_TARGET_FLAGS
546169689Skan#define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
547169689Skan#undef TARGET_HANDLE_OPTION
548169689Skan#define TARGET_HANDLE_OPTION sparc_handle_option
549169689Skan
550169689Skan#if TARGET_GNU_TLS
551169689Skan#undef TARGET_ASM_OUTPUT_DWARF_DTPREL
552169689Skan#define TARGET_ASM_OUTPUT_DWARF_DTPREL sparc_output_dwarf_dtprel
553169689Skan#endif
554169689Skan
555169689Skan#undef TARGET_ASM_FILE_END
556169689Skan#define TARGET_ASM_FILE_END sparc_file_end
557169689Skan
558169689Skan#ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
559169689Skan#undef TARGET_MANGLE_FUNDAMENTAL_TYPE
560169689Skan#define TARGET_MANGLE_FUNDAMENTAL_TYPE sparc_mangle_fundamental_type
561169689Skan#endif
562169689Skan
56390075Sobrienstruct gcc_target targetm = TARGET_INITIALIZER;
564169689Skan
565169689Skan/* Implement TARGET_HANDLE_OPTION.  */
566169689Skan
567169689Skanstatic bool
568169689Skansparc_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
569169689Skan{
570169689Skan  switch (code)
571169689Skan    {
572169689Skan    case OPT_mfpu:
573169689Skan    case OPT_mhard_float:
574169689Skan    case OPT_msoft_float:
575169689Skan      fpu_option_set = true;
576169689Skan      break;
577169689Skan
578169689Skan    case OPT_mcpu_:
579169689Skan      sparc_select[1].string = arg;
580169689Skan      break;
581169689Skan
582169689Skan    case OPT_mtune_:
583169689Skan      sparc_select[2].string = arg;
584169689Skan      break;
585169689Skan    }
586169689Skan
587169689Skan  return true;
588169689Skan}
589169689Skan
59050397Sobrien/* Validate and override various options, and do some machine dependent
59150397Sobrien   initialization.  */
59250397Sobrien
59350397Sobrienvoid
594132718Skansparc_override_options (void)
59550397Sobrien{
59650397Sobrien  static struct code_model {
59790075Sobrien    const char *const name;
59890075Sobrien    const int value;
59990075Sobrien  } const cmodels[] = {
60050397Sobrien    { "32", CM_32 },
60150397Sobrien    { "medlow", CM_MEDLOW },
60250397Sobrien    { "medmid", CM_MEDMID },
60350397Sobrien    { "medany", CM_MEDANY },
60450397Sobrien    { "embmedany", CM_EMBMEDANY },
60550397Sobrien    { 0, 0 }
60650397Sobrien  };
60790075Sobrien  const struct code_model *cmodel;
60850397Sobrien  /* Map TARGET_CPU_DEFAULT to value for -m{arch,tune}=.  */
60950397Sobrien  static struct cpu_default {
61090075Sobrien    const int cpu;
61190075Sobrien    const char *const name;
61290075Sobrien  } const cpu_default[] = {
61350397Sobrien    /* There must be one entry here for each TARGET_CPU value.  */
61450397Sobrien    { TARGET_CPU_sparc, "cypress" },
61550397Sobrien    { TARGET_CPU_sparclet, "tsc701" },
61650397Sobrien    { TARGET_CPU_sparclite, "f930" },
61750397Sobrien    { TARGET_CPU_v8, "v8" },
61852284Sobrien    { TARGET_CPU_hypersparc, "hypersparc" },
61952284Sobrien    { TARGET_CPU_sparclite86x, "sparclite86x" },
62050397Sobrien    { TARGET_CPU_supersparc, "supersparc" },
62150397Sobrien    { TARGET_CPU_v9, "v9" },
62250397Sobrien    { TARGET_CPU_ultrasparc, "ultrasparc" },
623117395Skan    { TARGET_CPU_ultrasparc3, "ultrasparc3" },
624169689Skan    { TARGET_CPU_niagara, "niagara" },
62550397Sobrien    { 0, 0 }
62650397Sobrien  };
62790075Sobrien  const struct cpu_default *def;
62850397Sobrien  /* Table of values for -m{cpu,tune}=.  */
62950397Sobrien  static struct cpu_table {
63090075Sobrien    const char *const name;
63190075Sobrien    const enum processor_type processor;
63290075Sobrien    const int disable;
63390075Sobrien    const int enable;
63490075Sobrien  } const cpu_table[] = {
63550397Sobrien    { "v7",         PROCESSOR_V7, MASK_ISA, 0 },
63650397Sobrien    { "cypress",    PROCESSOR_CYPRESS, MASK_ISA, 0 },
63750397Sobrien    { "v8",         PROCESSOR_V8, MASK_ISA, MASK_V8 },
63850397Sobrien    /* TI TMS390Z55 supersparc */
63950397Sobrien    { "supersparc", PROCESSOR_SUPERSPARC, MASK_ISA, MASK_V8 },
64050397Sobrien    { "sparclite",  PROCESSOR_SPARCLITE, MASK_ISA, MASK_SPARCLITE },
64150397Sobrien    /* The Fujitsu MB86930 is the original sparclite chip, with no fpu.
64250397Sobrien       The Fujitsu MB86934 is the recent sparclite chip, with an fpu.  */
64350397Sobrien    { "f930",       PROCESSOR_F930, MASK_ISA|MASK_FPU, MASK_SPARCLITE },
64450397Sobrien    { "f934",       PROCESSOR_F934, MASK_ISA, MASK_SPARCLITE|MASK_FPU },
64552284Sobrien    { "hypersparc", PROCESSOR_HYPERSPARC, MASK_ISA, MASK_V8|MASK_FPU },
64690075Sobrien    { "sparclite86x",  PROCESSOR_SPARCLITE86X, MASK_ISA|MASK_FPU,
64790075Sobrien      MASK_SPARCLITE },
64850397Sobrien    { "sparclet",   PROCESSOR_SPARCLET, MASK_ISA, MASK_SPARCLET },
64950397Sobrien    /* TEMIC sparclet */
65050397Sobrien    { "tsc701",     PROCESSOR_TSC701, MASK_ISA, MASK_SPARCLET },
65150397Sobrien    { "v9",         PROCESSOR_V9, MASK_ISA, MASK_V9 },
65290075Sobrien    /* TI ultrasparc I, II, IIi */
65390075Sobrien    { "ultrasparc", PROCESSOR_ULTRASPARC, MASK_ISA, MASK_V9
65490075Sobrien    /* Although insns using %y are deprecated, it is a clear win on current
65590075Sobrien       ultrasparcs.  */
65690075Sobrien    						    |MASK_DEPRECATED_V8_INSNS},
657117395Skan    /* TI ultrasparc III */
658117395Skan    /* ??? Check if %y issue still holds true in ultra3.  */
659117395Skan    { "ultrasparc3", PROCESSOR_ULTRASPARC3, MASK_ISA, MASK_V9|MASK_DEPRECATED_V8_INSNS},
660169689Skan    /* UltraSPARC T1 */
661169689Skan    { "niagara", PROCESSOR_NIAGARA, MASK_ISA, MASK_V9|MASK_DEPRECATED_V8_INSNS},
66250397Sobrien    { 0, 0, 0, 0 }
66350397Sobrien  };
66490075Sobrien  const struct cpu_table *cpu;
66590075Sobrien  const struct sparc_cpu_select *sel;
66650397Sobrien  int fpu;
66752284Sobrien
66850397Sobrien#ifndef SPARC_BI_ARCH
66950397Sobrien  /* Check for unsupported architecture size.  */
67050397Sobrien  if (! TARGET_64BIT != DEFAULT_ARCH32_P)
67190075Sobrien    error ("%s is not supported by this configuration",
67290075Sobrien	   DEFAULT_ARCH32_P ? "-m64" : "-m32");
67350397Sobrien#endif
67450397Sobrien
67590075Sobrien  /* We force all 64bit archs to use 128 bit long double */
67690075Sobrien  if (TARGET_64BIT && ! TARGET_LONG_DOUBLE_128)
67752284Sobrien    {
67890075Sobrien      error ("-mlong-double-64 not allowed with -m64");
67990075Sobrien      target_flags |= MASK_LONG_DOUBLE_128;
68052284Sobrien    }
68152284Sobrien
68250397Sobrien  /* Code model selection.  */
68350397Sobrien  sparc_cmodel = SPARC_DEFAULT_CMODEL;
68452284Sobrien
68552284Sobrien#ifdef SPARC_BI_ARCH
68652284Sobrien  if (TARGET_ARCH32)
68752284Sobrien    sparc_cmodel = CM_32;
68852284Sobrien#endif
68952284Sobrien
69050397Sobrien  if (sparc_cmodel_string != NULL)
69150397Sobrien    {
69250397Sobrien      if (TARGET_ARCH64)
69350397Sobrien	{
69450397Sobrien	  for (cmodel = &cmodels[0]; cmodel->name; cmodel++)
69550397Sobrien	    if (strcmp (sparc_cmodel_string, cmodel->name) == 0)
69650397Sobrien	      break;
69750397Sobrien	  if (cmodel->name == NULL)
69850397Sobrien	    error ("bad value (%s) for -mcmodel= switch", sparc_cmodel_string);
69950397Sobrien	  else
70050397Sobrien	    sparc_cmodel = cmodel->value;
70150397Sobrien	}
70250397Sobrien      else
70350397Sobrien	error ("-mcmodel= is not supported on 32 bit systems");
70450397Sobrien    }
70550397Sobrien
706171825Skan  fpu = target_flags & MASK_FPU; /* save current -mfpu status */
70750397Sobrien
70850397Sobrien  /* Set the default CPU.  */
70950397Sobrien  for (def = &cpu_default[0]; def->name; ++def)
71050397Sobrien    if (def->cpu == TARGET_CPU_DEFAULT)
71150397Sobrien      break;
712169689Skan  gcc_assert (def->name);
71350397Sobrien  sparc_select[0].string = def->name;
71450397Sobrien
71550397Sobrien  for (sel = &sparc_select[0]; sel->name; ++sel)
71650397Sobrien    {
71750397Sobrien      if (sel->string)
71850397Sobrien	{
71950397Sobrien	  for (cpu = &cpu_table[0]; cpu->name; ++cpu)
72050397Sobrien	    if (! strcmp (sel->string, cpu->name))
72150397Sobrien	      {
72250397Sobrien		if (sel->set_tune_p)
72350397Sobrien		  sparc_cpu = cpu->processor;
72450397Sobrien
72550397Sobrien		if (sel->set_arch_p)
72650397Sobrien		  {
72750397Sobrien		    target_flags &= ~cpu->disable;
72850397Sobrien		    target_flags |= cpu->enable;
72950397Sobrien		  }
73050397Sobrien		break;
73150397Sobrien	      }
73250397Sobrien
73350397Sobrien	  if (! cpu->name)
73450397Sobrien	    error ("bad value (%s) for %s switch", sel->string, sel->name);
73550397Sobrien	}
73650397Sobrien    }
73750397Sobrien
73850397Sobrien  /* If -mfpu or -mno-fpu was explicitly used, don't override with
739169689Skan     the processor default.  */
740169689Skan  if (fpu_option_set)
741169689Skan    target_flags = (target_flags & ~MASK_FPU) | fpu;
74250397Sobrien
74390075Sobrien  /* Don't allow -mvis if FPU is disabled.  */
74490075Sobrien  if (! TARGET_FPU)
74590075Sobrien    target_flags &= ~MASK_VIS;
74690075Sobrien
74790075Sobrien  /* -mvis assumes UltraSPARC+, so we are sure v9 instructions
74890075Sobrien     are available.
74990075Sobrien     -m64 also implies v9.  */
75090075Sobrien  if (TARGET_VIS || TARGET_ARCH64)
75190075Sobrien    {
75290075Sobrien      target_flags |= MASK_V9;
75390075Sobrien      target_flags &= ~(MASK_V8 | MASK_SPARCLET | MASK_SPARCLITE);
75490075Sobrien    }
75590075Sobrien
75650397Sobrien  /* Use the deprecated v8 insns for sparc64 in 32 bit mode.  */
75750397Sobrien  if (TARGET_V9 && TARGET_ARCH32)
75850397Sobrien    target_flags |= MASK_DEPRECATED_V8_INSNS;
75950397Sobrien
76052284Sobrien  /* V8PLUS requires V9, makes no sense in 64 bit mode.  */
76152284Sobrien  if (! TARGET_V9 || TARGET_ARCH64)
76250397Sobrien    target_flags &= ~MASK_V8PLUS;
76350397Sobrien
76450397Sobrien  /* Don't use stack biasing in 32 bit mode.  */
76550397Sobrien  if (TARGET_ARCH32)
76650397Sobrien    target_flags &= ~MASK_STACK_BIAS;
76752284Sobrien
76890075Sobrien  /* Supply a default value for align_functions.  */
769117395Skan  if (align_functions == 0
770117395Skan      && (sparc_cpu == PROCESSOR_ULTRASPARC
771169689Skan	  || sparc_cpu == PROCESSOR_ULTRASPARC3
772169689Skan	  || sparc_cpu == PROCESSOR_NIAGARA))
77390075Sobrien    align_functions = 32;
77450397Sobrien
77550397Sobrien  /* Validate PCC_STRUCT_RETURN.  */
77650397Sobrien  if (flag_pcc_struct_return == DEFAULT_PCC_STRUCT_RETURN)
77750397Sobrien    flag_pcc_struct_return = (TARGET_ARCH64 ? 0 : 1);
77850397Sobrien
77990075Sobrien  /* Only use .uaxword when compiling for a 64-bit target.  */
78090075Sobrien  if (!TARGET_ARCH64)
78190075Sobrien    targetm.asm_out.unaligned_op.di = NULL;
78290075Sobrien
78350397Sobrien  /* Do various machine dependent initializations.  */
78450397Sobrien  sparc_init_modes ();
785132718Skan
786169689Skan  /* Acquire unique alias sets for our private stuff.  */
787169689Skan  sparc_sr_alias_set = new_alias_set ();
788169689Skan  struct_value_alias_set = new_alias_set ();
789169689Skan
790132718Skan  /* Set up function hooks.  */
791132718Skan  init_machine_status = sparc_init_machine_status;
792169689Skan
793169689Skan  switch (sparc_cpu)
794169689Skan    {
795169689Skan    case PROCESSOR_V7:
796169689Skan    case PROCESSOR_CYPRESS:
797169689Skan      sparc_costs = &cypress_costs;
798169689Skan      break;
799169689Skan    case PROCESSOR_V8:
800169689Skan    case PROCESSOR_SPARCLITE:
801169689Skan    case PROCESSOR_SUPERSPARC:
802169689Skan      sparc_costs = &supersparc_costs;
803169689Skan      break;
804169689Skan    case PROCESSOR_F930:
805169689Skan    case PROCESSOR_F934:
806169689Skan    case PROCESSOR_HYPERSPARC:
807169689Skan    case PROCESSOR_SPARCLITE86X:
808169689Skan      sparc_costs = &hypersparc_costs;
809169689Skan      break;
810169689Skan    case PROCESSOR_SPARCLET:
811169689Skan    case PROCESSOR_TSC701:
812169689Skan      sparc_costs = &sparclet_costs;
813169689Skan      break;
814169689Skan    case PROCESSOR_V9:
815169689Skan    case PROCESSOR_ULTRASPARC:
816169689Skan      sparc_costs = &ultrasparc_costs;
817169689Skan      break;
818169689Skan    case PROCESSOR_ULTRASPARC3:
819169689Skan      sparc_costs = &ultrasparc3_costs;
820169689Skan      break;
821169689Skan    case PROCESSOR_NIAGARA:
822169689Skan      sparc_costs = &niagara_costs;
823169689Skan      break;
824169689Skan    };
825169689Skan
826169689Skan#ifdef TARGET_DEFAULT_LONG_DOUBLE_128
827169689Skan  if (!(target_flags_explicit & MASK_LONG_DOUBLE_128))
828169689Skan    target_flags |= MASK_LONG_DOUBLE_128;
829169689Skan#endif
83050397Sobrien}
83150397Sobrien
832169689Skan#ifdef SUBTARGET_ATTRIBUTE_TABLE
833169689Skan/* Table of valid machine attributes.  */
834169689Skanconst struct attribute_spec sparc_attribute_table[] =
835169689Skan{
836169689Skan  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
837169689Skan  SUBTARGET_ATTRIBUTE_TABLE,
838169689Skan  { NULL,        0, 0, false, false, false, NULL }
839169689Skan};
840169689Skan#endif
841169689Skan
84250397Sobrien/* Miscellaneous utilities.  */
84350397Sobrien
84450397Sobrien/* Nonzero if CODE, a comparison, is suitable for use in v9 conditional move
84550397Sobrien   or branch on register contents instructions.  */
84650397Sobrien
84750397Sobrienint
848132718Skanv9_regcmp_p (enum rtx_code code)
84950397Sobrien{
85050397Sobrien  return (code == EQ || code == NE || code == GE || code == LT
85150397Sobrien	  || code == LE || code == GT);
85250397Sobrien}
85350397Sobrien
85490075Sobrien/* Nonzero if OP is a floating point constant which can
85590075Sobrien   be loaded into an integer register using a single
85690075Sobrien   sethi instruction.  */
85790075Sobrien
85890075Sobrienint
859132718Skanfp_sethi_p (rtx op)
86090075Sobrien{
86190075Sobrien  if (GET_CODE (op) == CONST_DOUBLE)
86290075Sobrien    {
86390075Sobrien      REAL_VALUE_TYPE r;
86490075Sobrien      long i;
86590075Sobrien
86690075Sobrien      REAL_VALUE_FROM_CONST_DOUBLE (r, op);
86790075Sobrien      REAL_VALUE_TO_TARGET_SINGLE (r, i);
868169689Skan      return !SPARC_SIMM13_P (i) && SPARC_SETHI_P (i);
86990075Sobrien    }
87090075Sobrien
87190075Sobrien  return 0;
87250397Sobrien}
87350397Sobrien
87490075Sobrien/* Nonzero if OP is a floating point constant which can
87590075Sobrien   be loaded into an integer register using a single
87690075Sobrien   mov instruction.  */
87790075Sobrien
87890075Sobrienint
879132718Skanfp_mov_p (rtx op)
88090075Sobrien{
88190075Sobrien  if (GET_CODE (op) == CONST_DOUBLE)
88290075Sobrien    {
88390075Sobrien      REAL_VALUE_TYPE r;
88490075Sobrien      long i;
88590075Sobrien
88690075Sobrien      REAL_VALUE_FROM_CONST_DOUBLE (r, op);
88790075Sobrien      REAL_VALUE_TO_TARGET_SINGLE (r, i);
888169689Skan      return SPARC_SIMM13_P (i);
88990075Sobrien    }
89090075Sobrien
89190075Sobrien  return 0;
89290075Sobrien}
89390075Sobrien
89490075Sobrien/* Nonzero if OP is a floating point constant which can
89590075Sobrien   be loaded into an integer register using a high/losum
89690075Sobrien   instruction sequence.  */
89790075Sobrien
89890075Sobrienint
899132718Skanfp_high_losum_p (rtx op)
90090075Sobrien{
90190075Sobrien  /* The constraints calling this should only be in
90290075Sobrien     SFmode move insns, so any constant which cannot
90390075Sobrien     be moved using a single insn will do.  */
90490075Sobrien  if (GET_CODE (op) == CONST_DOUBLE)
90590075Sobrien    {
90690075Sobrien      REAL_VALUE_TYPE r;
90790075Sobrien      long i;
90890075Sobrien
90990075Sobrien      REAL_VALUE_FROM_CONST_DOUBLE (r, op);
91090075Sobrien      REAL_VALUE_TO_TARGET_SINGLE (r, i);
911169689Skan      return !SPARC_SIMM13_P (i) && !SPARC_SETHI_P (i);
91290075Sobrien    }
91390075Sobrien
91490075Sobrien  return 0;
91590075Sobrien}
91690075Sobrien
917169689Skan/* Expand a move instruction.  Return true if all work is done.  */
91850397Sobrien
919169689Skanbool
920169689Skansparc_expand_move (enum machine_mode mode, rtx *operands)
92150397Sobrien{
922169689Skan  /* Handle sets of MEM first.  */
923169689Skan  if (GET_CODE (operands[0]) == MEM)
924169689Skan    {
925169689Skan      /* 0 is a register (or a pair of registers) on SPARC.  */
926169689Skan      if (register_or_zero_operand (operands[1], mode))
927169689Skan	return false;
92850397Sobrien
929169689Skan      if (!reload_in_progress)
930169689Skan	{
931169689Skan	  operands[0] = validize_mem (operands[0]);
932169689Skan	  operands[1] = force_reg (mode, operands[1]);
933169689Skan	}
934169689Skan    }
93550397Sobrien
936169689Skan  /* Fixup TLS cases.  */
937169689Skan  if (TARGET_HAVE_TLS
938169689Skan      && CONSTANT_P (operands[1])
939169689Skan      && GET_CODE (operands[1]) != HIGH
940169689Skan      && sparc_tls_referenced_p (operands [1]))
941169689Skan    {
942169689Skan      rtx sym = operands[1];
943169689Skan      rtx addend = NULL;
94450397Sobrien
945169689Skan      if (GET_CODE (sym) == CONST && GET_CODE (XEXP (sym, 0)) == PLUS)
946169689Skan	{
947169689Skan	  addend = XEXP (XEXP (sym, 0), 1);
948169689Skan	  sym = XEXP (XEXP (sym, 0), 0);
949169689Skan	}
95050397Sobrien
951169689Skan      gcc_assert (SPARC_SYMBOL_REF_TLS_P (sym));
95250397Sobrien
953169689Skan      sym = legitimize_tls_address (sym);
954169689Skan      if (addend)
955169689Skan	{
956169689Skan	  sym = gen_rtx_PLUS (mode, sym, addend);
957169689Skan	  sym = force_operand (sym, operands[0]);
958169689Skan	}
959169689Skan      operands[1] = sym;
960169689Skan    }
961169689Skan
962169689Skan  /* Fixup PIC cases.  */
963169689Skan  if (flag_pic && CONSTANT_P (operands[1]))
964169689Skan    {
965169689Skan      if (pic_address_needs_scratch (operands[1]))
966169689Skan	operands[1] = legitimize_pic_address (operands[1], mode, 0);
96796263Sobrien
968169689Skan      if (GET_CODE (operands[1]) == LABEL_REF && mode == SImode)
969169689Skan	{
970169689Skan	  emit_insn (gen_movsi_pic_label_ref (operands[0], operands[1]));
971169689Skan	  return true;
972169689Skan	}
97396263Sobrien
974169689Skan      if (GET_CODE (operands[1]) == LABEL_REF && mode == DImode)
975169689Skan	{
976169689Skan	  gcc_assert (TARGET_ARCH64);
977169689Skan	  emit_insn (gen_movdi_pic_label_ref (operands[0], operands[1]));
978169689Skan	  return true;
979169689Skan	}
98096263Sobrien
981169689Skan      if (symbolic_operand (operands[1], mode))
982169689Skan	{
983169689Skan	  operands[1] = legitimize_pic_address (operands[1],
984169689Skan						mode,
985169689Skan						(reload_in_progress ?
986169689Skan						 operands[0] :
987169689Skan						 NULL_RTX));
988169689Skan	  return false;
989169689Skan	}
99050397Sobrien    }
99150397Sobrien
992169689Skan  /* If we are trying to toss an integer constant into FP registers,
993169689Skan     or loading a FP or vector constant, force it into memory.  */
994169689Skan  if (CONSTANT_P (operands[1])
995169689Skan      && REG_P (operands[0])
996169689Skan      && (SPARC_FP_REG_P (REGNO (operands[0]))
997169689Skan	  || SCALAR_FLOAT_MODE_P (mode)
998169689Skan	  || VECTOR_MODE_P (mode)))
99950397Sobrien    {
1000169689Skan      /* emit_group_store will send such bogosity to us when it is
1001169689Skan         not storing directly into memory.  So fix this up to avoid
1002169689Skan         crashes in output_constant_pool.  */
1003169689Skan      if (operands [1] == const0_rtx)
1004169689Skan	operands[1] = CONST0_RTX (mode);
1005132718Skan
1006169689Skan      /* We can clear FP registers if TARGET_VIS, and always other regs.  */
1007169689Skan      if ((TARGET_VIS || REGNO (operands[0]) < SPARC_FIRST_FP_REG)
1008169689Skan	  && const_zero_operand (operands[1], mode))
1009169689Skan	return false;
101050397Sobrien
1011169689Skan      if (REGNO (operands[0]) < SPARC_FIRST_FP_REG
1012169689Skan	  /* We are able to build any SF constant in integer registers
1013169689Skan	     with at most 2 instructions.  */
1014169689Skan	  && (mode == SFmode
1015169689Skan	      /* And any DF constant in integer registers.  */
1016169689Skan	      || (mode == DFmode
1017169689Skan		  && (reload_completed || reload_in_progress))))
1018169689Skan	return false;
101950397Sobrien
1020169689Skan      operands[1] = force_const_mem (mode, operands[1]);
1021169689Skan      if (!reload_in_progress)
1022169689Skan	operands[1] = validize_mem (operands[1]);
1023169689Skan      return false;
102450397Sobrien    }
102550397Sobrien
1026169689Skan  /* Accept non-constants and valid constants unmodified.  */
1027169689Skan  if (!CONSTANT_P (operands[1])
1028169689Skan      || GET_CODE (operands[1]) == HIGH
1029169689Skan      || input_operand (operands[1], mode))
1030169689Skan    return false;
103150397Sobrien
1032169689Skan  switch (mode)
103350397Sobrien    {
1034169689Skan    case QImode:
1035169689Skan      /* All QImode constants require only one insn, so proceed.  */
1036169689Skan      break;
103750397Sobrien
1038169689Skan    case HImode:
1039169689Skan    case SImode:
1040169689Skan      sparc_emit_set_const32 (operands[0], operands[1]);
1041169689Skan      return true;
104250397Sobrien
1043169689Skan    case DImode:
1044169689Skan      /* input_operand should have filtered out 32-bit mode.  */
1045169689Skan      sparc_emit_set_const64 (operands[0], operands[1]);
1046169689Skan      return true;
1047169689Skan
1048169689Skan    default:
1049169689Skan      gcc_unreachable ();
105050397Sobrien    }
105150397Sobrien
1052169689Skan  return false;
105350397Sobrien}
105450397Sobrien
1055169689Skan/* Load OP1, a 32-bit constant, into OP0, a register.
1056169689Skan   We know it can't be done in one insn when we get
1057169689Skan   here, the move expander guarantees this.  */
105850397Sobrien
105952284Sobrienvoid
1060132718Skansparc_emit_set_const32 (rtx op0, rtx op1)
106152284Sobrien{
106252284Sobrien  enum machine_mode mode = GET_MODE (op0);
106352284Sobrien  rtx temp;
106452284Sobrien
106552284Sobrien  if (reload_in_progress || reload_completed)
106652284Sobrien    temp = op0;
106752284Sobrien  else
106852284Sobrien    temp = gen_reg_rtx (mode);
106952284Sobrien
107052284Sobrien  if (GET_CODE (op1) == CONST_INT)
107152284Sobrien    {
1072169689Skan      gcc_assert (!small_int_operand (op1, mode)
1073169689Skan		  && !const_high_operand (op1, mode));
1074169689Skan
107552284Sobrien      /* Emit them as real moves instead of a HIGH/LO_SUM,
107652284Sobrien	 this way CSE can see everything and reuse intermediate
107752284Sobrien	 values if it wants.  */
1078169689Skan      emit_insn (gen_rtx_SET (VOIDmode, temp,
1079169689Skan			      GEN_INT (INTVAL (op1)
1080169689Skan			        & ~(HOST_WIDE_INT)0x3ff)));
108190075Sobrien
108252284Sobrien      emit_insn (gen_rtx_SET (VOIDmode,
108352284Sobrien			      op0,
108490075Sobrien			      gen_rtx_IOR (mode, temp,
108552284Sobrien					   GEN_INT (INTVAL (op1) & 0x3ff))));
108652284Sobrien    }
108752284Sobrien  else
108852284Sobrien    {
108952284Sobrien      /* A symbol, emit in the traditional way.  */
109090075Sobrien      emit_insn (gen_rtx_SET (VOIDmode, temp,
109190075Sobrien			      gen_rtx_HIGH (mode, op1)));
109252284Sobrien      emit_insn (gen_rtx_SET (VOIDmode,
109390075Sobrien			      op0, gen_rtx_LO_SUM (mode, temp, op1)));
109452284Sobrien    }
109552284Sobrien}
109652284Sobrien
1097132718Skan/* Load OP1, a symbolic 64-bit constant, into OP0, a DImode register.
1098169689Skan   If TEMP is nonzero, we are forbidden to use any other scratch
1099132718Skan   registers.  Otherwise, we are allowed to generate them as needed.
1100132718Skan
1101132718Skan   Note that TEMP may have TImode if the code model is TARGET_CM_MEDANY
1102132718Skan   or TARGET_CM_EMBMEDANY (see the reload_indi and reload_outdi patterns).  */
1103169689Skan
110452284Sobrienvoid
1105132718Skansparc_emit_set_symbolic_const64 (rtx op0, rtx op1, rtx temp)
110652284Sobrien{
1107132718Skan  rtx temp1, temp2, temp3, temp4, temp5;
1108132718Skan  rtx ti_temp = 0;
110996263Sobrien
1110132718Skan  if (temp && GET_MODE (temp) == TImode)
111196263Sobrien    {
1112132718Skan      ti_temp = temp;
1113132718Skan      temp = gen_rtx_REG (DImode, REGNO (temp));
111496263Sobrien    }
111596263Sobrien
1116132718Skan  /* SPARC-V9 code-model support.  */
111752284Sobrien  switch (sparc_cmodel)
111852284Sobrien    {
111952284Sobrien    case CM_MEDLOW:
112052284Sobrien      /* The range spanned by all instructions in the object is less
112152284Sobrien	 than 2^31 bytes (2GB) and the distance from any instruction
112252284Sobrien	 to the location of the label _GLOBAL_OFFSET_TABLE_ is less
112352284Sobrien	 than 2^31 bytes (2GB).
112452284Sobrien
112552284Sobrien	 The executable must be in the low 4TB of the virtual address
112652284Sobrien	 space.
112752284Sobrien
1128132718Skan	 sethi	%hi(symbol), %temp1
1129132718Skan	 or	%temp1, %lo(symbol), %reg  */
1130132718Skan      if (temp)
1131132718Skan	temp1 = temp;  /* op0 is allowed.  */
1132132718Skan      else
1133132718Skan	temp1 = gen_reg_rtx (DImode);
1134132718Skan
113552284Sobrien      emit_insn (gen_rtx_SET (VOIDmode, temp1, gen_rtx_HIGH (DImode, op1)));
113652284Sobrien      emit_insn (gen_rtx_SET (VOIDmode, op0, gen_rtx_LO_SUM (DImode, temp1, op1)));
113752284Sobrien      break;
113852284Sobrien
113952284Sobrien    case CM_MEDMID:
114052284Sobrien      /* The range spanned by all instructions in the object is less
114152284Sobrien	 than 2^31 bytes (2GB) and the distance from any instruction
114252284Sobrien	 to the location of the label _GLOBAL_OFFSET_TABLE_ is less
114352284Sobrien	 than 2^31 bytes (2GB).
114452284Sobrien
114552284Sobrien	 The executable must be in the low 16TB of the virtual address
114652284Sobrien	 space.
114752284Sobrien
114852284Sobrien	 sethi	%h44(symbol), %temp1
114952284Sobrien	 or	%temp1, %m44(symbol), %temp2
115052284Sobrien	 sllx	%temp2, 12, %temp3
115152284Sobrien	 or	%temp3, %l44(symbol), %reg  */
1152132718Skan      if (temp)
1153132718Skan	{
1154132718Skan	  temp1 = op0;
1155132718Skan	  temp2 = op0;
1156132718Skan	  temp3 = temp;  /* op0 is allowed.  */
1157132718Skan	}
1158132718Skan      else
1159132718Skan	{
1160132718Skan	  temp1 = gen_reg_rtx (DImode);
1161132718Skan	  temp2 = gen_reg_rtx (DImode);
1162132718Skan	  temp3 = gen_reg_rtx (DImode);
1163132718Skan	}
1164132718Skan
1165132718Skan      emit_insn (gen_seth44 (temp1, op1));
1166132718Skan      emit_insn (gen_setm44 (temp2, temp1, op1));
1167132718Skan      emit_insn (gen_rtx_SET (VOIDmode, temp3,
1168132718Skan			      gen_rtx_ASHIFT (DImode, temp2, GEN_INT (12))));
1169132718Skan      emit_insn (gen_setl44 (op0, temp3, op1));
117052284Sobrien      break;
117152284Sobrien
117252284Sobrien    case CM_MEDANY:
117352284Sobrien      /* The range spanned by all instructions in the object is less
117452284Sobrien	 than 2^31 bytes (2GB) and the distance from any instruction
117552284Sobrien	 to the location of the label _GLOBAL_OFFSET_TABLE_ is less
117652284Sobrien	 than 2^31 bytes (2GB).
117752284Sobrien
117852284Sobrien	 The executable can be placed anywhere in the virtual address
117952284Sobrien	 space.
118052284Sobrien
118152284Sobrien	 sethi	%hh(symbol), %temp1
118252284Sobrien	 sethi	%lm(symbol), %temp2
118352284Sobrien	 or	%temp1, %hm(symbol), %temp3
1184132718Skan	 sllx	%temp3, 32, %temp4
1185132718Skan	 or	%temp4, %temp2, %temp5
1186132718Skan	 or	%temp5, %lo(symbol), %reg  */
1187132718Skan      if (temp)
118896263Sobrien	{
1189132718Skan	  /* It is possible that one of the registers we got for operands[2]
1190132718Skan	     might coincide with that of operands[0] (which is why we made
1191132718Skan	     it TImode).  Pick the other one to use as our scratch.  */
1192132718Skan	  if (rtx_equal_p (temp, op0))
1193132718Skan	    {
1194169689Skan	      gcc_assert (ti_temp);
1195169689Skan	      temp = gen_rtx_REG (DImode, REGNO (temp) + 1);
1196132718Skan	    }
1197132718Skan	  temp1 = op0;
1198132718Skan	  temp2 = temp;  /* op0 is _not_ allowed, see above.  */
1199132718Skan	  temp3 = op0;
1200132718Skan	  temp4 = op0;
1201132718Skan	  temp5 = op0;
120296263Sobrien	}
1203132718Skan      else
1204132718Skan	{
1205132718Skan	  temp1 = gen_reg_rtx (DImode);
1206132718Skan	  temp2 = gen_reg_rtx (DImode);
1207132718Skan	  temp3 = gen_reg_rtx (DImode);
1208132718Skan	  temp4 = gen_reg_rtx (DImode);
1209132718Skan	  temp5 = gen_reg_rtx (DImode);
1210132718Skan	}
121152284Sobrien
1212132718Skan      emit_insn (gen_sethh (temp1, op1));
1213132718Skan      emit_insn (gen_setlm (temp2, op1));
1214132718Skan      emit_insn (gen_sethm (temp3, temp1, op1));
1215132718Skan      emit_insn (gen_rtx_SET (VOIDmode, temp4,
1216132718Skan			      gen_rtx_ASHIFT (DImode, temp3, GEN_INT (32))));
1217132718Skan      emit_insn (gen_rtx_SET (VOIDmode, temp5,
1218132718Skan			      gen_rtx_PLUS (DImode, temp4, temp2)));
1219132718Skan      emit_insn (gen_setlo (op0, temp5, op1));
122052284Sobrien      break;
122152284Sobrien
122252284Sobrien    case CM_EMBMEDANY:
122352284Sobrien      /* Old old old backwards compatibility kruft here.
122452284Sobrien	 Essentially it is MEDLOW with a fixed 64-bit
122552284Sobrien	 virtual base added to all data segment addresses.
122652284Sobrien	 Text-segment stuff is computed like MEDANY, we can't
122752284Sobrien	 reuse the code above because the relocation knobs
122852284Sobrien	 look different.
122952284Sobrien
123052284Sobrien	 Data segment:	sethi	%hi(symbol), %temp1
1231132718Skan			add	%temp1, EMBMEDANY_BASE_REG, %temp2
1232132718Skan			or	%temp2, %lo(symbol), %reg  */
123352284Sobrien      if (data_segment_operand (op1, GET_MODE (op1)))
123452284Sobrien	{
1235132718Skan	  if (temp)
1236132718Skan	    {
1237132718Skan	      temp1 = temp;  /* op0 is allowed.  */
1238132718Skan	      temp2 = op0;
1239132718Skan	    }
1240132718Skan	  else
1241132718Skan	    {
1242132718Skan	      temp1 = gen_reg_rtx (DImode);
1243132718Skan	      temp2 = gen_reg_rtx (DImode);
1244132718Skan	    }
1245132718Skan
124652284Sobrien	  emit_insn (gen_embmedany_sethi (temp1, op1));
1247132718Skan	  emit_insn (gen_embmedany_brsum (temp2, temp1));
1248132718Skan	  emit_insn (gen_embmedany_losum (op0, temp2, op1));
124952284Sobrien	}
1250132718Skan
1251132718Skan      /* Text segment:	sethi	%uhi(symbol), %temp1
1252132718Skan			sethi	%hi(symbol), %temp2
1253132718Skan			or	%temp1, %ulo(symbol), %temp3
1254132718Skan			sllx	%temp3, 32, %temp4
1255132718Skan			or	%temp4, %temp2, %temp5
1256132718Skan			or	%temp5, %lo(symbol), %reg  */
125752284Sobrien      else
125852284Sobrien	{
1259132718Skan	  if (temp)
126096263Sobrien	    {
1261132718Skan	      /* It is possible that one of the registers we got for operands[2]
1262132718Skan		 might coincide with that of operands[0] (which is why we made
1263132718Skan		 it TImode).  Pick the other one to use as our scratch.  */
1264132718Skan	      if (rtx_equal_p (temp, op0))
1265132718Skan		{
1266169689Skan		  gcc_assert (ti_temp);
1267169689Skan		  temp = gen_rtx_REG (DImode, REGNO (temp) + 1);
1268132718Skan		}
1269132718Skan	      temp1 = op0;
1270132718Skan	      temp2 = temp;  /* op0 is _not_ allowed, see above.  */
1271132718Skan	      temp3 = op0;
1272132718Skan	      temp4 = op0;
1273132718Skan	      temp5 = op0;
127496263Sobrien	    }
1275132718Skan	  else
1276132718Skan	    {
1277132718Skan	      temp1 = gen_reg_rtx (DImode);
1278132718Skan	      temp2 = gen_reg_rtx (DImode);
1279132718Skan	      temp3 = gen_reg_rtx (DImode);
1280132718Skan	      temp4 = gen_reg_rtx (DImode);
1281132718Skan	      temp5 = gen_reg_rtx (DImode);
1282132718Skan	    }
128352284Sobrien
1284132718Skan	  emit_insn (gen_embmedany_textuhi (temp1, op1));
1285132718Skan	  emit_insn (gen_embmedany_texthi  (temp2, op1));
1286132718Skan	  emit_insn (gen_embmedany_textulo (temp3, temp1, op1));
1287132718Skan	  emit_insn (gen_rtx_SET (VOIDmode, temp4,
1288132718Skan				  gen_rtx_ASHIFT (DImode, temp3, GEN_INT (32))));
1289132718Skan	  emit_insn (gen_rtx_SET (VOIDmode, temp5,
1290132718Skan				  gen_rtx_PLUS (DImode, temp4, temp2)));
1291132718Skan	  emit_insn (gen_embmedany_textlo  (op0, temp5, op1));
129252284Sobrien	}
129352284Sobrien      break;
129452284Sobrien
129552284Sobrien    default:
1296169689Skan      gcc_unreachable ();
129752284Sobrien    }
129852284Sobrien}
129952284Sobrien
1300169689Skan#if HOST_BITS_PER_WIDE_INT == 32
1301169689Skanvoid
1302169689Skansparc_emit_set_const64 (rtx op0 ATTRIBUTE_UNUSED, rtx op1 ATTRIBUTE_UNUSED)
1303169689Skan{
1304169689Skan  gcc_unreachable ();
1305169689Skan}
1306169689Skan#else
130752284Sobrien/* These avoid problems when cross compiling.  If we do not
130852284Sobrien   go through all this hair then the optimizer will see
130952284Sobrien   invalid REG_EQUAL notes or in some cases none at all.  */
1310169689Skanstatic rtx gen_safe_HIGH64 (rtx, HOST_WIDE_INT);
1311132718Skanstatic rtx gen_safe_SET64 (rtx, HOST_WIDE_INT);
1312132718Skanstatic rtx gen_safe_OR64 (rtx, HOST_WIDE_INT);
1313132718Skanstatic rtx gen_safe_XOR64 (rtx, HOST_WIDE_INT);
131452284Sobrien
131552284Sobrien/* The optimizer is not to assume anything about exactly
131652284Sobrien   which bits are set for a HIGH, they are unspecified.
131752284Sobrien   Unfortunately this leads to many missed optimizations
131852284Sobrien   during CSE.  We mask out the non-HIGH bits, and matches
131952284Sobrien   a plain movdi, to alleviate this problem.  */
1320169689Skanstatic rtx
1321169689Skangen_safe_HIGH64 (rtx dest, HOST_WIDE_INT val)
132252284Sobrien{
1323169689Skan  return gen_rtx_SET (VOIDmode, dest, GEN_INT (val & ~(HOST_WIDE_INT)0x3ff));
132452284Sobrien}
132552284Sobrien
132652284Sobrienstatic rtx
1327132718Skangen_safe_SET64 (rtx dest, HOST_WIDE_INT val)
132852284Sobrien{
1329169689Skan  return gen_rtx_SET (VOIDmode, dest, GEN_INT (val));
133052284Sobrien}
133152284Sobrien
133252284Sobrienstatic rtx
1333132718Skangen_safe_OR64 (rtx src, HOST_WIDE_INT val)
133452284Sobrien{
1335169689Skan  return gen_rtx_IOR (DImode, src, GEN_INT (val));
133652284Sobrien}
133752284Sobrien
133852284Sobrienstatic rtx
1339132718Skangen_safe_XOR64 (rtx src, HOST_WIDE_INT val)
134052284Sobrien{
1341169689Skan  return gen_rtx_XOR (DImode, src, GEN_INT (val));
134252284Sobrien}
134352284Sobrien
134452284Sobrien/* Worker routines for 64-bit constant formation on arch64.
134552284Sobrien   One of the key things to be doing in these emissions is
134652284Sobrien   to create as many temp REGs as possible.  This makes it
134752284Sobrien   possible for half-built constants to be used later when
134852284Sobrien   such values are similar to something required later on.
134952284Sobrien   Without doing this, the optimizer cannot see such
135052284Sobrien   opportunities.  */
135152284Sobrien
1352132718Skanstatic void sparc_emit_set_const64_quick1 (rtx, rtx,
1353132718Skan					   unsigned HOST_WIDE_INT, int);
135452284Sobrien
135552284Sobrienstatic void
1356132718Skansparc_emit_set_const64_quick1 (rtx op0, rtx temp,
1357132718Skan			       unsigned HOST_WIDE_INT low_bits, int is_neg)
135852284Sobrien{
135952284Sobrien  unsigned HOST_WIDE_INT high_bits;
136052284Sobrien
136152284Sobrien  if (is_neg)
136252284Sobrien    high_bits = (~low_bits) & 0xffffffff;
136352284Sobrien  else
136452284Sobrien    high_bits = low_bits;
136552284Sobrien
1366169689Skan  emit_insn (gen_safe_HIGH64 (temp, high_bits));
136752284Sobrien  if (!is_neg)
136852284Sobrien    {
136952284Sobrien      emit_insn (gen_rtx_SET (VOIDmode, op0,
137052284Sobrien			      gen_safe_OR64 (temp, (high_bits & 0x3ff))));
137152284Sobrien    }
137252284Sobrien  else
137352284Sobrien    {
137452284Sobrien      /* If we are XOR'ing with -1, then we should emit a one's complement
137552284Sobrien	 instead.  This way the combiner will notice logical operations
137652284Sobrien	 such as ANDN later on and substitute.  */
137752284Sobrien      if ((low_bits & 0x3ff) == 0x3ff)
137852284Sobrien	{
137952284Sobrien	  emit_insn (gen_rtx_SET (VOIDmode, op0,
138052284Sobrien				  gen_rtx_NOT (DImode, temp)));
138152284Sobrien	}
138252284Sobrien      else
138352284Sobrien	{
138452284Sobrien	  emit_insn (gen_rtx_SET (VOIDmode, op0,
138552284Sobrien				  gen_safe_XOR64 (temp,
138696263Sobrien						  (-(HOST_WIDE_INT)0x400
138796263Sobrien						   | (low_bits & 0x3ff)))));
138852284Sobrien	}
138952284Sobrien    }
139052284Sobrien}
139152284Sobrien
1392132718Skanstatic void sparc_emit_set_const64_quick2 (rtx, rtx, unsigned HOST_WIDE_INT,
1393132718Skan					   unsigned HOST_WIDE_INT, int);
139452284Sobrien
139552284Sobrienstatic void
1396132718Skansparc_emit_set_const64_quick2 (rtx op0, rtx temp,
1397132718Skan			       unsigned HOST_WIDE_INT high_bits,
1398132718Skan			       unsigned HOST_WIDE_INT low_immediate,
1399132718Skan			       int shift_count)
140052284Sobrien{
140152284Sobrien  rtx temp2 = op0;
140252284Sobrien
140352284Sobrien  if ((high_bits & 0xfffffc00) != 0)
140452284Sobrien    {
1405169689Skan      emit_insn (gen_safe_HIGH64 (temp, high_bits));
140652284Sobrien      if ((high_bits & ~0xfffffc00) != 0)
140752284Sobrien	emit_insn (gen_rtx_SET (VOIDmode, op0,
140852284Sobrien				gen_safe_OR64 (temp, (high_bits & 0x3ff))));
140952284Sobrien      else
141052284Sobrien	temp2 = temp;
141152284Sobrien    }
141252284Sobrien  else
141352284Sobrien    {
141452284Sobrien      emit_insn (gen_safe_SET64 (temp, high_bits));
141552284Sobrien      temp2 = temp;
141652284Sobrien    }
141752284Sobrien
141890075Sobrien  /* Now shift it up into place.  */
141952284Sobrien  emit_insn (gen_rtx_SET (VOIDmode, op0,
142052284Sobrien			  gen_rtx_ASHIFT (DImode, temp2,
142152284Sobrien					  GEN_INT (shift_count))));
142252284Sobrien
142352284Sobrien  /* If there is a low immediate part piece, finish up by
142452284Sobrien     putting that in as well.  */
142552284Sobrien  if (low_immediate != 0)
142652284Sobrien    emit_insn (gen_rtx_SET (VOIDmode, op0,
142752284Sobrien			    gen_safe_OR64 (op0, low_immediate)));
142852284Sobrien}
142952284Sobrien
1430132718Skanstatic void sparc_emit_set_const64_longway (rtx, rtx, unsigned HOST_WIDE_INT,
1431132718Skan					    unsigned HOST_WIDE_INT);
143252284Sobrien
143352284Sobrien/* Full 64-bit constant decomposition.  Even though this is the
143452284Sobrien   'worst' case, we still optimize a few things away.  */
143552284Sobrienstatic void
1436132718Skansparc_emit_set_const64_longway (rtx op0, rtx temp,
1437132718Skan				unsigned HOST_WIDE_INT high_bits,
1438132718Skan				unsigned HOST_WIDE_INT low_bits)
143952284Sobrien{
144052284Sobrien  rtx sub_temp;
144152284Sobrien
144252284Sobrien  if (reload_in_progress || reload_completed)
144352284Sobrien    sub_temp = op0;
144452284Sobrien  else
144552284Sobrien    sub_temp = gen_reg_rtx (DImode);
144652284Sobrien
144752284Sobrien  if ((high_bits & 0xfffffc00) != 0)
144852284Sobrien    {
1449169689Skan      emit_insn (gen_safe_HIGH64 (temp, high_bits));
145052284Sobrien      if ((high_bits & ~0xfffffc00) != 0)
145152284Sobrien	emit_insn (gen_rtx_SET (VOIDmode,
145252284Sobrien				sub_temp,
145352284Sobrien				gen_safe_OR64 (temp, (high_bits & 0x3ff))));
145452284Sobrien      else
145552284Sobrien	sub_temp = temp;
145652284Sobrien    }
145752284Sobrien  else
145852284Sobrien    {
145952284Sobrien      emit_insn (gen_safe_SET64 (temp, high_bits));
146052284Sobrien      sub_temp = temp;
146152284Sobrien    }
146252284Sobrien
146352284Sobrien  if (!reload_in_progress && !reload_completed)
146452284Sobrien    {
146552284Sobrien      rtx temp2 = gen_reg_rtx (DImode);
146652284Sobrien      rtx temp3 = gen_reg_rtx (DImode);
146752284Sobrien      rtx temp4 = gen_reg_rtx (DImode);
146852284Sobrien
146952284Sobrien      emit_insn (gen_rtx_SET (VOIDmode, temp4,
147052284Sobrien			      gen_rtx_ASHIFT (DImode, sub_temp,
147152284Sobrien					      GEN_INT (32))));
147252284Sobrien
1473169689Skan      emit_insn (gen_safe_HIGH64 (temp2, low_bits));
147452284Sobrien      if ((low_bits & ~0xfffffc00) != 0)
147552284Sobrien	{
147652284Sobrien	  emit_insn (gen_rtx_SET (VOIDmode, temp3,
147752284Sobrien				  gen_safe_OR64 (temp2, (low_bits & 0x3ff))));
147852284Sobrien	  emit_insn (gen_rtx_SET (VOIDmode, op0,
147952284Sobrien				  gen_rtx_PLUS (DImode, temp4, temp3)));
148052284Sobrien	}
148152284Sobrien      else
148252284Sobrien	{
148352284Sobrien	  emit_insn (gen_rtx_SET (VOIDmode, op0,
148452284Sobrien				  gen_rtx_PLUS (DImode, temp4, temp2)));
148552284Sobrien	}
148652284Sobrien    }
148752284Sobrien  else
148852284Sobrien    {
148952284Sobrien      rtx low1 = GEN_INT ((low_bits >> (32 - 12))          & 0xfff);
149052284Sobrien      rtx low2 = GEN_INT ((low_bits >> (32 - 12 - 12))     & 0xfff);
149152284Sobrien      rtx low3 = GEN_INT ((low_bits >> (32 - 12 - 12 - 8)) & 0x0ff);
149252284Sobrien      int to_shift = 12;
149352284Sobrien
149452284Sobrien      /* We are in the middle of reload, so this is really
149552284Sobrien	 painful.  However we do still make an attempt to
149652284Sobrien	 avoid emitting truly stupid code.  */
149752284Sobrien      if (low1 != const0_rtx)
149852284Sobrien	{
149952284Sobrien	  emit_insn (gen_rtx_SET (VOIDmode, op0,
150052284Sobrien				  gen_rtx_ASHIFT (DImode, sub_temp,
150152284Sobrien						  GEN_INT (to_shift))));
150252284Sobrien	  emit_insn (gen_rtx_SET (VOIDmode, op0,
150352284Sobrien				  gen_rtx_IOR (DImode, op0, low1)));
150452284Sobrien	  sub_temp = op0;
150552284Sobrien	  to_shift = 12;
150652284Sobrien	}
150752284Sobrien      else
150852284Sobrien	{
150952284Sobrien	  to_shift += 12;
151052284Sobrien	}
151152284Sobrien      if (low2 != const0_rtx)
151252284Sobrien	{
151352284Sobrien	  emit_insn (gen_rtx_SET (VOIDmode, op0,
151452284Sobrien				  gen_rtx_ASHIFT (DImode, sub_temp,
151552284Sobrien						  GEN_INT (to_shift))));
151652284Sobrien	  emit_insn (gen_rtx_SET (VOIDmode, op0,
151752284Sobrien				  gen_rtx_IOR (DImode, op0, low2)));
151852284Sobrien	  sub_temp = op0;
151952284Sobrien	  to_shift = 8;
152052284Sobrien	}
152152284Sobrien      else
152252284Sobrien	{
152352284Sobrien	  to_shift += 8;
152452284Sobrien	}
152552284Sobrien      emit_insn (gen_rtx_SET (VOIDmode, op0,
152652284Sobrien			      gen_rtx_ASHIFT (DImode, sub_temp,
152752284Sobrien					      GEN_INT (to_shift))));
152852284Sobrien      if (low3 != const0_rtx)
152952284Sobrien	emit_insn (gen_rtx_SET (VOIDmode, op0,
153052284Sobrien				gen_rtx_IOR (DImode, op0, low3)));
153190075Sobrien      /* phew...  */
153252284Sobrien    }
153352284Sobrien}
153452284Sobrien
153590075Sobrien/* Analyze a 64-bit constant for certain properties.  */
1536132718Skanstatic void analyze_64bit_constant (unsigned HOST_WIDE_INT,
1537132718Skan				    unsigned HOST_WIDE_INT,
1538132718Skan				    int *, int *, int *);
153952284Sobrien
154052284Sobrienstatic void
1541132718Skananalyze_64bit_constant (unsigned HOST_WIDE_INT high_bits,
1542132718Skan			unsigned HOST_WIDE_INT low_bits,
1543132718Skan			int *hbsp, int *lbsp, int *abbasp)
154452284Sobrien{
154552284Sobrien  int lowest_bit_set, highest_bit_set, all_bits_between_are_set;
154652284Sobrien  int i;
154752284Sobrien
154852284Sobrien  lowest_bit_set = highest_bit_set = -1;
154952284Sobrien  i = 0;
155052284Sobrien  do
155152284Sobrien    {
155252284Sobrien      if ((lowest_bit_set == -1)
155352284Sobrien	  && ((low_bits >> i) & 1))
155452284Sobrien	lowest_bit_set = i;
155552284Sobrien      if ((highest_bit_set == -1)
155652284Sobrien	  && ((high_bits >> (32 - i - 1)) & 1))
155752284Sobrien	highest_bit_set = (64 - i - 1);
155852284Sobrien    }
155952284Sobrien  while (++i < 32
156052284Sobrien	 && ((highest_bit_set == -1)
156152284Sobrien	     || (lowest_bit_set == -1)));
156252284Sobrien  if (i == 32)
156352284Sobrien    {
156452284Sobrien      i = 0;
156552284Sobrien      do
156652284Sobrien	{
156752284Sobrien	  if ((lowest_bit_set == -1)
156852284Sobrien	      && ((high_bits >> i) & 1))
156952284Sobrien	    lowest_bit_set = i + 32;
157052284Sobrien	  if ((highest_bit_set == -1)
157152284Sobrien	      && ((low_bits >> (32 - i - 1)) & 1))
157252284Sobrien	    highest_bit_set = 32 - i - 1;
157352284Sobrien	}
157452284Sobrien      while (++i < 32
157552284Sobrien	     && ((highest_bit_set == -1)
157652284Sobrien		 || (lowest_bit_set == -1)));
157752284Sobrien    }
157852284Sobrien  /* If there are no bits set this should have gone out
157952284Sobrien     as one instruction!  */
1580169689Skan  gcc_assert (lowest_bit_set != -1 && highest_bit_set != -1);
158152284Sobrien  all_bits_between_are_set = 1;
158252284Sobrien  for (i = lowest_bit_set; i <= highest_bit_set; i++)
158352284Sobrien    {
158452284Sobrien      if (i < 32)
158552284Sobrien	{
158652284Sobrien	  if ((low_bits & (1 << i)) != 0)
158752284Sobrien	    continue;
158852284Sobrien	}
158952284Sobrien      else
159052284Sobrien	{
159152284Sobrien	  if ((high_bits & (1 << (i - 32))) != 0)
159252284Sobrien	    continue;
159352284Sobrien	}
159452284Sobrien      all_bits_between_are_set = 0;
159552284Sobrien      break;
159652284Sobrien    }
159752284Sobrien  *hbsp = highest_bit_set;
159852284Sobrien  *lbsp = lowest_bit_set;
159952284Sobrien  *abbasp = all_bits_between_are_set;
160052284Sobrien}
160152284Sobrien
1602132718Skanstatic int const64_is_2insns (unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT);
160352284Sobrien
160452284Sobrienstatic int
1605132718Skanconst64_is_2insns (unsigned HOST_WIDE_INT high_bits,
1606132718Skan		   unsigned HOST_WIDE_INT low_bits)
160752284Sobrien{
160852284Sobrien  int highest_bit_set, lowest_bit_set, all_bits_between_are_set;
160952284Sobrien
161052284Sobrien  if (high_bits == 0
161152284Sobrien      || high_bits == 0xffffffff)
161252284Sobrien    return 1;
161352284Sobrien
161452284Sobrien  analyze_64bit_constant (high_bits, low_bits,
161552284Sobrien			  &highest_bit_set, &lowest_bit_set,
161652284Sobrien			  &all_bits_between_are_set);
161752284Sobrien
161852284Sobrien  if ((highest_bit_set == 63
161952284Sobrien       || lowest_bit_set == 0)
162052284Sobrien      && all_bits_between_are_set != 0)
162152284Sobrien    return 1;
162252284Sobrien
162352284Sobrien  if ((highest_bit_set - lowest_bit_set) < 21)
162452284Sobrien    return 1;
162552284Sobrien
162652284Sobrien  return 0;
162752284Sobrien}
162852284Sobrien
1629132718Skanstatic unsigned HOST_WIDE_INT create_simple_focus_bits (unsigned HOST_WIDE_INT,
1630132718Skan							unsigned HOST_WIDE_INT,
1631132718Skan							int, int);
163252284Sobrien
163352284Sobrienstatic unsigned HOST_WIDE_INT
1634132718Skancreate_simple_focus_bits (unsigned HOST_WIDE_INT high_bits,
1635132718Skan			  unsigned HOST_WIDE_INT low_bits,
1636132718Skan			  int lowest_bit_set, int shift)
163752284Sobrien{
163852284Sobrien  HOST_WIDE_INT hi, lo;
163952284Sobrien
164052284Sobrien  if (lowest_bit_set < 32)
164152284Sobrien    {
164252284Sobrien      lo = (low_bits >> lowest_bit_set) << shift;
164352284Sobrien      hi = ((high_bits << (32 - lowest_bit_set)) << shift);
164452284Sobrien    }
164552284Sobrien  else
164652284Sobrien    {
164752284Sobrien      lo = 0;
164852284Sobrien      hi = ((high_bits >> (lowest_bit_set - 32)) << shift);
164952284Sobrien    }
1650169689Skan  gcc_assert (! (hi & lo));
165152284Sobrien  return (hi | lo);
165252284Sobrien}
165352284Sobrien
165452284Sobrien/* Here we are sure to be arch64 and this is an integer constant
165552284Sobrien   being loaded into a register.  Emit the most efficient
165652284Sobrien   insn sequence possible.  Detection of all the 1-insn cases
165752284Sobrien   has been done already.  */
165852284Sobrienvoid
1659132718Skansparc_emit_set_const64 (rtx op0, rtx op1)
166052284Sobrien{
166152284Sobrien  unsigned HOST_WIDE_INT high_bits, low_bits;
166252284Sobrien  int lowest_bit_set, highest_bit_set;
166352284Sobrien  int all_bits_between_are_set;
1664132718Skan  rtx temp = 0;
166552284Sobrien
166652284Sobrien  /* Sanity check that we know what we are working with.  */
1667169689Skan  gcc_assert (TARGET_ARCH64
1668169689Skan	      && (GET_CODE (op0) == SUBREG
1669169689Skan		  || (REG_P (op0) && ! SPARC_FP_REG_P (REGNO (op0)))));
167052284Sobrien
167152284Sobrien  if (reload_in_progress || reload_completed)
167252284Sobrien    temp = op0;
167352284Sobrien
1674169689Skan  if (GET_CODE (op1) != CONST_INT)
167552284Sobrien    {
167652284Sobrien      sparc_emit_set_symbolic_const64 (op0, op1, temp);
167752284Sobrien      return;
167852284Sobrien    }
167952284Sobrien
1680132718Skan  if (! temp)
1681132718Skan    temp = gen_reg_rtx (DImode);
1682132718Skan
1683169689Skan  high_bits = ((INTVAL (op1) >> 32) & 0xffffffff);
1684169689Skan  low_bits = (INTVAL (op1) & 0xffffffff);
168552284Sobrien
168652284Sobrien  /* low_bits	bits 0  --> 31
168752284Sobrien     high_bits	bits 32 --> 63  */
168852284Sobrien
168952284Sobrien  analyze_64bit_constant (high_bits, low_bits,
169052284Sobrien			  &highest_bit_set, &lowest_bit_set,
169152284Sobrien			  &all_bits_between_are_set);
169252284Sobrien
169352284Sobrien  /* First try for a 2-insn sequence.  */
169452284Sobrien
169552284Sobrien  /* These situations are preferred because the optimizer can
169652284Sobrien   * do more things with them:
169752284Sobrien   * 1) mov	-1, %reg
169852284Sobrien   *    sllx	%reg, shift, %reg
169952284Sobrien   * 2) mov	-1, %reg
170052284Sobrien   *    srlx	%reg, shift, %reg
170152284Sobrien   * 3) mov	some_small_const, %reg
170252284Sobrien   *    sllx	%reg, shift, %reg
170352284Sobrien   */
170452284Sobrien  if (((highest_bit_set == 63
170552284Sobrien	|| lowest_bit_set == 0)
170652284Sobrien       && all_bits_between_are_set != 0)
170752284Sobrien      || ((highest_bit_set - lowest_bit_set) < 12))
170852284Sobrien    {
170952284Sobrien      HOST_WIDE_INT the_const = -1;
171052284Sobrien      int shift = lowest_bit_set;
171152284Sobrien
171252284Sobrien      if ((highest_bit_set != 63
171352284Sobrien	   && lowest_bit_set != 0)
171452284Sobrien	  || all_bits_between_are_set == 0)
171552284Sobrien	{
171652284Sobrien	  the_const =
171752284Sobrien	    create_simple_focus_bits (high_bits, low_bits,
171852284Sobrien				      lowest_bit_set, 0);
171952284Sobrien	}
172052284Sobrien      else if (lowest_bit_set == 0)
172152284Sobrien	shift = -(63 - highest_bit_set);
172252284Sobrien
1723169689Skan      gcc_assert (SPARC_SIMM13_P (the_const));
1724169689Skan      gcc_assert (shift != 0);
172552284Sobrien
172652284Sobrien      emit_insn (gen_safe_SET64 (temp, the_const));
172752284Sobrien      if (shift > 0)
172852284Sobrien	emit_insn (gen_rtx_SET (VOIDmode,
172952284Sobrien				op0,
173052284Sobrien				gen_rtx_ASHIFT (DImode,
173152284Sobrien						temp,
173252284Sobrien						GEN_INT (shift))));
173352284Sobrien      else if (shift < 0)
173452284Sobrien	emit_insn (gen_rtx_SET (VOIDmode,
173552284Sobrien				op0,
173652284Sobrien				gen_rtx_LSHIFTRT (DImode,
173752284Sobrien						  temp,
173852284Sobrien						  GEN_INT (-shift))));
173952284Sobrien      return;
174052284Sobrien    }
174152284Sobrien
174252284Sobrien  /* Now a range of 22 or less bits set somewhere.
174352284Sobrien   * 1) sethi	%hi(focus_bits), %reg
174452284Sobrien   *    sllx	%reg, shift, %reg
174552284Sobrien   * 2) sethi	%hi(focus_bits), %reg
174652284Sobrien   *    srlx	%reg, shift, %reg
174752284Sobrien   */
174852284Sobrien  if ((highest_bit_set - lowest_bit_set) < 21)
174952284Sobrien    {
175052284Sobrien      unsigned HOST_WIDE_INT focus_bits =
175152284Sobrien	create_simple_focus_bits (high_bits, low_bits,
175252284Sobrien				  lowest_bit_set, 10);
175352284Sobrien
1754169689Skan      gcc_assert (SPARC_SETHI_P (focus_bits));
1755169689Skan      gcc_assert (lowest_bit_set != 10);
175652284Sobrien
1757169689Skan      emit_insn (gen_safe_HIGH64 (temp, focus_bits));
175852284Sobrien
175952284Sobrien      /* If lowest_bit_set == 10 then a sethi alone could have done it.  */
176052284Sobrien      if (lowest_bit_set < 10)
176152284Sobrien	emit_insn (gen_rtx_SET (VOIDmode,
176252284Sobrien				op0,
176352284Sobrien				gen_rtx_LSHIFTRT (DImode, temp,
176452284Sobrien						  GEN_INT (10 - lowest_bit_set))));
176552284Sobrien      else if (lowest_bit_set > 10)
176652284Sobrien	emit_insn (gen_rtx_SET (VOIDmode,
176752284Sobrien				op0,
176852284Sobrien				gen_rtx_ASHIFT (DImode, temp,
176952284Sobrien						GEN_INT (lowest_bit_set - 10))));
177052284Sobrien      return;
177152284Sobrien    }
177252284Sobrien
177352284Sobrien  /* 1) sethi	%hi(low_bits), %reg
177452284Sobrien   *    or	%reg, %lo(low_bits), %reg
177552284Sobrien   * 2) sethi	%hi(~low_bits), %reg
177652284Sobrien   *	xor	%reg, %lo(-0x400 | (low_bits & 0x3ff)), %reg
177752284Sobrien   */
177852284Sobrien  if (high_bits == 0
177952284Sobrien      || high_bits == 0xffffffff)
178052284Sobrien    {
178152284Sobrien      sparc_emit_set_const64_quick1 (op0, temp, low_bits,
178252284Sobrien				     (high_bits == 0xffffffff));
178352284Sobrien      return;
178452284Sobrien    }
178552284Sobrien
178652284Sobrien  /* Now, try 3-insn sequences.  */
178752284Sobrien
178852284Sobrien  /* 1) sethi	%hi(high_bits), %reg
178952284Sobrien   *    or	%reg, %lo(high_bits), %reg
179052284Sobrien   *    sllx	%reg, 32, %reg
179152284Sobrien   */
179252284Sobrien  if (low_bits == 0)
179352284Sobrien    {
179452284Sobrien      sparc_emit_set_const64_quick2 (op0, temp, high_bits, 0, 32);
179552284Sobrien      return;
179652284Sobrien    }
179752284Sobrien
179852284Sobrien  /* We may be able to do something quick
179952284Sobrien     when the constant is negated, so try that.  */
180052284Sobrien  if (const64_is_2insns ((~high_bits) & 0xffffffff,
180152284Sobrien			 (~low_bits) & 0xfffffc00))
180252284Sobrien    {
180352284Sobrien      /* NOTE: The trailing bits get XOR'd so we need the
180452284Sobrien	 non-negated bits, not the negated ones.  */
180552284Sobrien      unsigned HOST_WIDE_INT trailing_bits = low_bits & 0x3ff;
180652284Sobrien
180752284Sobrien      if ((((~high_bits) & 0xffffffff) == 0
180852284Sobrien	   && ((~low_bits) & 0x80000000) == 0)
180952284Sobrien	  || (((~high_bits) & 0xffffffff) == 0xffffffff
181052284Sobrien	      && ((~low_bits) & 0x80000000) != 0))
181152284Sobrien	{
1812169689Skan	  unsigned HOST_WIDE_INT fast_int = (~low_bits & 0xffffffff);
181352284Sobrien
181452284Sobrien	  if ((SPARC_SETHI_P (fast_int)
181552284Sobrien	       && (~high_bits & 0xffffffff) == 0)
181652284Sobrien	      || SPARC_SIMM13_P (fast_int))
181752284Sobrien	    emit_insn (gen_safe_SET64 (temp, fast_int));
181852284Sobrien	  else
1819169689Skan	    sparc_emit_set_const64 (temp, GEN_INT (fast_int));
182052284Sobrien	}
182152284Sobrien      else
182252284Sobrien	{
182352284Sobrien	  rtx negated_const;
182452284Sobrien	  negated_const = GEN_INT (((~low_bits) & 0xfffffc00) |
182552284Sobrien				   (((HOST_WIDE_INT)((~high_bits) & 0xffffffff))<<32));
182652284Sobrien	  sparc_emit_set_const64 (temp, negated_const);
182752284Sobrien	}
182852284Sobrien
182952284Sobrien      /* If we are XOR'ing with -1, then we should emit a one's complement
183052284Sobrien	 instead.  This way the combiner will notice logical operations
183152284Sobrien	 such as ANDN later on and substitute.  */
183252284Sobrien      if (trailing_bits == 0x3ff)
183352284Sobrien	{
183452284Sobrien	  emit_insn (gen_rtx_SET (VOIDmode, op0,
183552284Sobrien				  gen_rtx_NOT (DImode, temp)));
183652284Sobrien	}
183752284Sobrien      else
183852284Sobrien	{
183952284Sobrien	  emit_insn (gen_rtx_SET (VOIDmode,
184052284Sobrien				  op0,
184152284Sobrien				  gen_safe_XOR64 (temp,
184252284Sobrien						  (-0x400 | trailing_bits))));
184352284Sobrien	}
184452284Sobrien      return;
184552284Sobrien    }
184652284Sobrien
184752284Sobrien  /* 1) sethi	%hi(xxx), %reg
184852284Sobrien   *    or	%reg, %lo(xxx), %reg
184952284Sobrien   *	sllx	%reg, yyy, %reg
185052284Sobrien   *
185152284Sobrien   * ??? This is just a generalized version of the low_bits==0
185252284Sobrien   * thing above, FIXME...
185352284Sobrien   */
185452284Sobrien  if ((highest_bit_set - lowest_bit_set) < 32)
185552284Sobrien    {
185652284Sobrien      unsigned HOST_WIDE_INT focus_bits =
185752284Sobrien	create_simple_focus_bits (high_bits, low_bits,
185852284Sobrien				  lowest_bit_set, 0);
185952284Sobrien
186052284Sobrien      /* We can't get here in this state.  */
1861169689Skan      gcc_assert (highest_bit_set >= 32 && lowest_bit_set < 32);
186252284Sobrien
186352284Sobrien      /* So what we know is that the set bits straddle the
186452284Sobrien	 middle of the 64-bit word.  */
186552284Sobrien      sparc_emit_set_const64_quick2 (op0, temp,
186652284Sobrien				     focus_bits, 0,
186752284Sobrien				     lowest_bit_set);
186852284Sobrien      return;
186952284Sobrien    }
187052284Sobrien
187152284Sobrien  /* 1) sethi	%hi(high_bits), %reg
187252284Sobrien   *    or	%reg, %lo(high_bits), %reg
187352284Sobrien   *    sllx	%reg, 32, %reg
187452284Sobrien   *	or	%reg, low_bits, %reg
187552284Sobrien   */
187652284Sobrien  if (SPARC_SIMM13_P(low_bits)
187752284Sobrien      && ((int)low_bits > 0))
187852284Sobrien    {
187952284Sobrien      sparc_emit_set_const64_quick2 (op0, temp, high_bits, low_bits, 32);
188052284Sobrien      return;
188152284Sobrien    }
188252284Sobrien
188390075Sobrien  /* The easiest way when all else fails, is full decomposition.  */
188452284Sobrien#if 0
188552284Sobrien  printf ("sparc_emit_set_const64: Hard constant [%08lx%08lx] neg[%08lx%08lx]\n",
188652284Sobrien	  high_bits, low_bits, ~high_bits, ~low_bits);
188752284Sobrien#endif
188852284Sobrien  sparc_emit_set_const64_longway (op0, temp, high_bits, low_bits);
188952284Sobrien}
1890169689Skan#endif /* HOST_BITS_PER_WIDE_INT == 32 */
189152284Sobrien
189290075Sobrien/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
189390075Sobrien   return the mode to be used for the comparison.  For floating-point,
189490075Sobrien   CCFP[E]mode is used.  CC_NOOVmode should be used when the first operand
189590075Sobrien   is a PLUS, MINUS, NEG, or ASHIFT.  CCmode should be used when no special
189690075Sobrien   processing is needed.  */
189790075Sobrien
189890075Sobrienenum machine_mode
1899132718Skanselect_cc_mode (enum rtx_code op, rtx x, rtx y ATTRIBUTE_UNUSED)
190090075Sobrien{
190190075Sobrien  if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
190290075Sobrien    {
190390075Sobrien      switch (op)
190490075Sobrien	{
190590075Sobrien	case EQ:
190690075Sobrien	case NE:
190790075Sobrien	case UNORDERED:
190890075Sobrien	case ORDERED:
190990075Sobrien	case UNLT:
191090075Sobrien	case UNLE:
191190075Sobrien	case UNGT:
191290075Sobrien	case UNGE:
191390075Sobrien	case UNEQ:
191490075Sobrien	case LTGT:
191590075Sobrien	  return CCFPmode;
191690075Sobrien
191790075Sobrien	case LT:
191890075Sobrien	case LE:
191990075Sobrien	case GT:
192090075Sobrien	case GE:
192190075Sobrien	  return CCFPEmode;
192290075Sobrien
192390075Sobrien	default:
1924169689Skan	  gcc_unreachable ();
192590075Sobrien	}
192690075Sobrien    }
192790075Sobrien  else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
192890075Sobrien	   || GET_CODE (x) == NEG || GET_CODE (x) == ASHIFT)
192990075Sobrien    {
193090075Sobrien      if (TARGET_ARCH64 && GET_MODE (x) == DImode)
193190075Sobrien	return CCX_NOOVmode;
193290075Sobrien      else
193390075Sobrien	return CC_NOOVmode;
193490075Sobrien    }
193590075Sobrien  else
193690075Sobrien    {
193790075Sobrien      if (TARGET_ARCH64 && GET_MODE (x) == DImode)
193890075Sobrien	return CCXmode;
193990075Sobrien      else
194090075Sobrien	return CCmode;
194190075Sobrien    }
194290075Sobrien}
194390075Sobrien
194450397Sobrien/* X and Y are two things to compare using CODE.  Emit the compare insn and
194550397Sobrien   return the rtx for the cc reg in the proper mode.  */
194650397Sobrien
194750397Sobrienrtx
1948169689Skangen_compare_reg (enum rtx_code code)
194950397Sobrien{
1950169689Skan  rtx x = sparc_compare_op0;
1951169689Skan  rtx y = sparc_compare_op1;
195250397Sobrien  enum machine_mode mode = SELECT_CC_MODE (code, x, y);
195350397Sobrien  rtx cc_reg;
195450397Sobrien
1955169689Skan  if (sparc_compare_emitted != NULL_RTX)
1956169689Skan    {
1957169689Skan      cc_reg = sparc_compare_emitted;
1958169689Skan      sparc_compare_emitted = NULL_RTX;
1959169689Skan      return cc_reg;
1960169689Skan    }
1961169689Skan
196250397Sobrien  /* ??? We don't have movcc patterns so we cannot generate pseudo regs for the
196350397Sobrien     fcc regs (cse can't tell they're really call clobbered regs and will
196450397Sobrien     remove a duplicate comparison even if there is an intervening function
196550397Sobrien     call - it will then try to reload the cc reg via an int reg which is why
196650397Sobrien     we need the movcc patterns).  It is possible to provide the movcc
196750397Sobrien     patterns by using the ldxfsr/stxfsr v9 insns.  I tried it: you need two
196850397Sobrien     registers (say %g1,%g5) and it takes about 6 insns.  A better fix would be
196950397Sobrien     to tell cse that CCFPE mode registers (even pseudos) are call
197050397Sobrien     clobbered.  */
197150397Sobrien
197250397Sobrien  /* ??? This is an experiment.  Rather than making changes to cse which may
197350397Sobrien     or may not be easy/clean, we do our own cse.  This is possible because
197450397Sobrien     we will generate hard registers.  Cse knows they're call clobbered (it
197550397Sobrien     doesn't know the same thing about pseudos). If we guess wrong, no big
197650397Sobrien     deal, but if we win, great!  */
197750397Sobrien
197850397Sobrien  if (TARGET_V9 && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
197950397Sobrien#if 1 /* experiment */
198050397Sobrien    {
198150397Sobrien      int reg;
198250397Sobrien      /* We cycle through the registers to ensure they're all exercised.  */
198350397Sobrien      static int next_fcc_reg = 0;
198450397Sobrien      /* Previous x,y for each fcc reg.  */
198550397Sobrien      static rtx prev_args[4][2];
198650397Sobrien
198750397Sobrien      /* Scan prev_args for x,y.  */
198850397Sobrien      for (reg = 0; reg < 4; reg++)
198950397Sobrien	if (prev_args[reg][0] == x && prev_args[reg][1] == y)
199050397Sobrien	  break;
199150397Sobrien      if (reg == 4)
199250397Sobrien	{
199350397Sobrien	  reg = next_fcc_reg;
199450397Sobrien	  prev_args[reg][0] = x;
199550397Sobrien	  prev_args[reg][1] = y;
199650397Sobrien	  next_fcc_reg = (next_fcc_reg + 1) & 3;
199750397Sobrien	}
199850397Sobrien      cc_reg = gen_rtx_REG (mode, reg + SPARC_FIRST_V9_FCC_REG);
199950397Sobrien    }
200050397Sobrien#else
200150397Sobrien    cc_reg = gen_reg_rtx (mode);
200250397Sobrien#endif /* ! experiment */
200350397Sobrien  else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
200450397Sobrien    cc_reg = gen_rtx_REG (mode, SPARC_FCC_REG);
200550397Sobrien  else
200650397Sobrien    cc_reg = gen_rtx_REG (mode, SPARC_ICC_REG);
200750397Sobrien
200852284Sobrien  emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
200950397Sobrien			  gen_rtx_COMPARE (mode, x, y)));
201050397Sobrien
201150397Sobrien  return cc_reg;
201250397Sobrien}
201350397Sobrien
201450397Sobrien/* This function is used for v9 only.
201550397Sobrien   CODE is the code for an Scc's comparison.
201650397Sobrien   OPERANDS[0] is the target of the Scc insn.
201750397Sobrien   OPERANDS[1] is the value we compare against const0_rtx (which hasn't
201850397Sobrien   been generated yet).
201950397Sobrien
202050397Sobrien   This function is needed to turn
202150397Sobrien
202250397Sobrien	   (set (reg:SI 110)
202350397Sobrien	       (gt (reg:CCX 100 %icc)
202450397Sobrien	           (const_int 0)))
202550397Sobrien   into
202650397Sobrien	   (set (reg:SI 110)
202750397Sobrien	       (gt:DI (reg:CCX 100 %icc)
202850397Sobrien	           (const_int 0)))
202950397Sobrien
203050397Sobrien   IE: The instruction recognizer needs to see the mode of the comparison to
203150397Sobrien   find the right instruction. We could use "gt:DI" right in the
203250397Sobrien   define_expand, but leaving it out allows us to handle DI, SI, etc.
203350397Sobrien
203450397Sobrien   We refer to the global sparc compare operands sparc_compare_op0 and
203550397Sobrien   sparc_compare_op1.  */
203650397Sobrien
203750397Sobrienint
2038132718Skangen_v9_scc (enum rtx_code compare_code, register rtx *operands)
203950397Sobrien{
204050397Sobrien  if (! TARGET_ARCH64
204150397Sobrien      && (GET_MODE (sparc_compare_op0) == DImode
204250397Sobrien	  || GET_MODE (operands[0]) == DImode))
204350397Sobrien    return 0;
204450397Sobrien
204550397Sobrien  /* Try to use the movrCC insns.  */
204650397Sobrien  if (TARGET_ARCH64
2047169689Skan      && GET_MODE_CLASS (GET_MODE (sparc_compare_op0)) == MODE_INT
2048169689Skan      && sparc_compare_op1 == const0_rtx
204950397Sobrien      && v9_regcmp_p (compare_code))
205050397Sobrien    {
2051169689Skan      rtx op0 = sparc_compare_op0;
2052169689Skan      rtx temp;
2053169689Skan
205450397Sobrien      /* Special case for op0 != 0.  This can be done with one instruction if
205596263Sobrien	 operands[0] == sparc_compare_op0.  */
205650397Sobrien
205750397Sobrien      if (compare_code == NE
205850397Sobrien	  && GET_MODE (operands[0]) == DImode
205996263Sobrien	  && rtx_equal_p (op0, operands[0]))
206050397Sobrien	{
206150397Sobrien	  emit_insn (gen_rtx_SET (VOIDmode, operands[0],
206250397Sobrien			      gen_rtx_IF_THEN_ELSE (DImode,
206350397Sobrien				       gen_rtx_fmt_ee (compare_code, DImode,
206450397Sobrien						       op0, const0_rtx),
206550397Sobrien				       const1_rtx,
206650397Sobrien				       operands[0])));
206750397Sobrien	  return 1;
206850397Sobrien	}
206950397Sobrien
207096263Sobrien      if (reg_overlap_mentioned_p (operands[0], op0))
207196263Sobrien	{
207296263Sobrien	  /* Handle the case where operands[0] == sparc_compare_op0.
207396263Sobrien	     We "early clobber" the result.  */
207496263Sobrien	  op0 = gen_reg_rtx (GET_MODE (sparc_compare_op0));
207596263Sobrien	  emit_move_insn (op0, sparc_compare_op0);
207696263Sobrien	}
207796263Sobrien
207850397Sobrien      emit_insn (gen_rtx_SET (VOIDmode, operands[0], const0_rtx));
207950397Sobrien      if (GET_MODE (op0) != DImode)
208050397Sobrien	{
208150397Sobrien	  temp = gen_reg_rtx (DImode);
208250397Sobrien	  convert_move (temp, op0, 0);
208350397Sobrien	}
208450397Sobrien      else
208550397Sobrien	temp = op0;
208650397Sobrien      emit_insn (gen_rtx_SET (VOIDmode, operands[0],
208750397Sobrien			  gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
208850397Sobrien				   gen_rtx_fmt_ee (compare_code, DImode,
208950397Sobrien						   temp, const0_rtx),
209050397Sobrien				   const1_rtx,
209150397Sobrien				   operands[0])));
209250397Sobrien      return 1;
209350397Sobrien    }
209450397Sobrien  else
209550397Sobrien    {
2096169689Skan      operands[1] = gen_compare_reg (compare_code);
209750397Sobrien
209850397Sobrien      switch (GET_MODE (operands[1]))
209950397Sobrien	{
210050397Sobrien	  case CCmode :
210150397Sobrien	  case CCXmode :
210250397Sobrien	  case CCFPEmode :
210350397Sobrien	  case CCFPmode :
210450397Sobrien	    break;
210550397Sobrien	  default :
2106169689Skan	    gcc_unreachable ();
210750397Sobrien	}
210850397Sobrien      emit_insn (gen_rtx_SET (VOIDmode, operands[0], const0_rtx));
210950397Sobrien      emit_insn (gen_rtx_SET (VOIDmode, operands[0],
211050397Sobrien			  gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
211150397Sobrien				   gen_rtx_fmt_ee (compare_code,
211250397Sobrien						   GET_MODE (operands[1]),
211350397Sobrien						   operands[1], const0_rtx),
211450397Sobrien				    const1_rtx, operands[0])));
211550397Sobrien      return 1;
211650397Sobrien    }
211750397Sobrien}
211850397Sobrien
211950397Sobrien/* Emit a conditional jump insn for the v9 architecture using comparison code
212050397Sobrien   CODE and jump target LABEL.
212150397Sobrien   This function exists to take advantage of the v9 brxx insns.  */
212250397Sobrien
212350397Sobrienvoid
2124132718Skanemit_v9_brxx_insn (enum rtx_code code, rtx op0, rtx label)
212550397Sobrien{
2126169689Skan  gcc_assert (sparc_compare_emitted == NULL_RTX);
212750397Sobrien  emit_jump_insn (gen_rtx_SET (VOIDmode,
212850397Sobrien			   pc_rtx,
212950397Sobrien			   gen_rtx_IF_THEN_ELSE (VOIDmode,
213050397Sobrien				    gen_rtx_fmt_ee (code, GET_MODE (op0),
213150397Sobrien						    op0, const0_rtx),
213250397Sobrien				    gen_rtx_LABEL_REF (VOIDmode, label),
213350397Sobrien				    pc_rtx)));
213450397Sobrien}
213590075Sobrien
213690075Sobrien/* Generate a DFmode part of a hard TFmode register.
213790075Sobrien   REG is the TFmode hard register, LOW is 1 for the
213890075Sobrien   low 64bit of the register and 0 otherwise.
213990075Sobrien */
214090075Sobrienrtx
2141132718Skangen_df_reg (rtx reg, int low)
214290075Sobrien{
214390075Sobrien  int regno = REGNO (reg);
214490075Sobrien
214590075Sobrien  if ((WORDS_BIG_ENDIAN == 0) ^ (low != 0))
214690075Sobrien    regno += (TARGET_ARCH64 && regno < 32) ? 1 : 2;
214790075Sobrien  return gen_rtx_REG (DFmode, regno);
214890075Sobrien}
214950397Sobrien
215096263Sobrien/* Generate a call to FUNC with OPERANDS.  Operand 0 is the return value.
215196263Sobrien   Unlike normal calls, TFmode operands are passed by reference.  It is
215296263Sobrien   assumed that no more than 3 operands are required.  */
215396263Sobrien
215496263Sobrienstatic void
2155132718Skanemit_soft_tfmode_libcall (const char *func_name, int nargs, rtx *operands)
215696263Sobrien{
215796263Sobrien  rtx ret_slot = NULL, arg[3], func_sym;
215896263Sobrien  int i;
215996263Sobrien
216096263Sobrien  /* We only expect to be called for conversions, unary, and binary ops.  */
2161169689Skan  gcc_assert (nargs == 2 || nargs == 3);
216296263Sobrien
216396263Sobrien  for (i = 0; i < nargs; ++i)
216496263Sobrien    {
216596263Sobrien      rtx this_arg = operands[i];
216696263Sobrien      rtx this_slot;
216796263Sobrien
216896263Sobrien      /* TFmode arguments and return values are passed by reference.  */
216996263Sobrien      if (GET_MODE (this_arg) == TFmode)
217096263Sobrien	{
2171102780Skan	  int force_stack_temp;
2172102780Skan
2173102780Skan	  force_stack_temp = 0;
2174102780Skan	  if (TARGET_BUGGY_QP_LIB && i == 0)
2175102780Skan	    force_stack_temp = 1;
2176102780Skan
2177102780Skan	  if (GET_CODE (this_arg) == MEM
2178102780Skan	      && ! force_stack_temp)
217996263Sobrien	    this_arg = XEXP (this_arg, 0);
2180102780Skan	  else if (CONSTANT_P (this_arg)
2181102780Skan		   && ! force_stack_temp)
218296263Sobrien	    {
218396263Sobrien	      this_slot = force_const_mem (TFmode, this_arg);
218496263Sobrien	      this_arg = XEXP (this_slot, 0);
218596263Sobrien	    }
218696263Sobrien	  else
218796263Sobrien	    {
218896263Sobrien	      this_slot = assign_stack_temp (TFmode, GET_MODE_SIZE (TFmode), 0);
218996263Sobrien
219096263Sobrien	      /* Operand 0 is the return value.  We'll copy it out later.  */
219196263Sobrien	      if (i > 0)
219296263Sobrien		emit_move_insn (this_slot, this_arg);
219396263Sobrien	      else
219496263Sobrien		ret_slot = this_slot;
219596263Sobrien
219696263Sobrien	      this_arg = XEXP (this_slot, 0);
219796263Sobrien	    }
219896263Sobrien	}
219996263Sobrien
220096263Sobrien      arg[i] = this_arg;
220196263Sobrien    }
220296263Sobrien
220396263Sobrien  func_sym = gen_rtx_SYMBOL_REF (Pmode, func_name);
220496263Sobrien
220596263Sobrien  if (GET_MODE (operands[0]) == TFmode)
220696263Sobrien    {
220796263Sobrien      if (nargs == 2)
220896263Sobrien	emit_library_call (func_sym, LCT_NORMAL, VOIDmode, 2,
220996263Sobrien			   arg[0], GET_MODE (arg[0]),
221096263Sobrien			   arg[1], GET_MODE (arg[1]));
221196263Sobrien      else
221296263Sobrien	emit_library_call (func_sym, LCT_NORMAL, VOIDmode, 3,
221396263Sobrien			   arg[0], GET_MODE (arg[0]),
221496263Sobrien			   arg[1], GET_MODE (arg[1]),
221596263Sobrien			   arg[2], GET_MODE (arg[2]));
221696263Sobrien
221796263Sobrien      if (ret_slot)
221896263Sobrien	emit_move_insn (operands[0], ret_slot);
221996263Sobrien    }
222096263Sobrien  else
222196263Sobrien    {
222296263Sobrien      rtx ret;
222396263Sobrien
2224169689Skan      gcc_assert (nargs == 2);
222596263Sobrien
222696263Sobrien      ret = emit_library_call_value (func_sym, operands[0], LCT_NORMAL,
222796263Sobrien				     GET_MODE (operands[0]), 1,
222896263Sobrien				     arg[1], GET_MODE (arg[1]));
222996263Sobrien
223096263Sobrien      if (ret != operands[0])
223196263Sobrien	emit_move_insn (operands[0], ret);
223296263Sobrien    }
223396263Sobrien}
223496263Sobrien
223596263Sobrien/* Expand soft-float TFmode calls to sparc abi routines.  */
223696263Sobrien
223796263Sobrienstatic void
2238132718Skanemit_soft_tfmode_binop (enum rtx_code code, rtx *operands)
223996263Sobrien{
224096263Sobrien  const char *func;
224196263Sobrien
224296263Sobrien  switch (code)
224396263Sobrien    {
224496263Sobrien    case PLUS:
224596263Sobrien      func = "_Qp_add";
224696263Sobrien      break;
224796263Sobrien    case MINUS:
224896263Sobrien      func = "_Qp_sub";
224996263Sobrien      break;
225096263Sobrien    case MULT:
225196263Sobrien      func = "_Qp_mul";
225296263Sobrien      break;
225396263Sobrien    case DIV:
225496263Sobrien      func = "_Qp_div";
225596263Sobrien      break;
225696263Sobrien    default:
2257169689Skan      gcc_unreachable ();
225896263Sobrien    }
225996263Sobrien
226096263Sobrien  emit_soft_tfmode_libcall (func, 3, operands);
226196263Sobrien}
226296263Sobrien
226396263Sobrienstatic void
2264132718Skanemit_soft_tfmode_unop (enum rtx_code code, rtx *operands)
226596263Sobrien{
226696263Sobrien  const char *func;
226796263Sobrien
2268169689Skan  gcc_assert (code == SQRT);
2269169689Skan  func = "_Qp_sqrt";
227096263Sobrien
227196263Sobrien  emit_soft_tfmode_libcall (func, 2, operands);
227296263Sobrien}
227396263Sobrien
227496263Sobrienstatic void
2275132718Skanemit_soft_tfmode_cvt (enum rtx_code code, rtx *operands)
227696263Sobrien{
227796263Sobrien  const char *func;
227896263Sobrien
227996263Sobrien  switch (code)
228096263Sobrien    {
228196263Sobrien    case FLOAT_EXTEND:
228296263Sobrien      switch (GET_MODE (operands[1]))
228396263Sobrien	{
228496263Sobrien	case SFmode:
228596263Sobrien	  func = "_Qp_stoq";
228696263Sobrien	  break;
228796263Sobrien	case DFmode:
228896263Sobrien	  func = "_Qp_dtoq";
228996263Sobrien	  break;
229096263Sobrien	default:
2291169689Skan	  gcc_unreachable ();
229296263Sobrien	}
229396263Sobrien      break;
229496263Sobrien
229596263Sobrien    case FLOAT_TRUNCATE:
229696263Sobrien      switch (GET_MODE (operands[0]))
229796263Sobrien	{
229896263Sobrien	case SFmode:
229996263Sobrien	  func = "_Qp_qtos";
230096263Sobrien	  break;
230196263Sobrien	case DFmode:
230296263Sobrien	  func = "_Qp_qtod";
230396263Sobrien	  break;
230496263Sobrien	default:
2305169689Skan	  gcc_unreachable ();
230696263Sobrien	}
230796263Sobrien      break;
230896263Sobrien
230996263Sobrien    case FLOAT:
231096263Sobrien      switch (GET_MODE (operands[1]))
231196263Sobrien	{
231296263Sobrien	case SImode:
231396263Sobrien	  func = "_Qp_itoq";
231496263Sobrien	  break;
231596263Sobrien	case DImode:
231696263Sobrien	  func = "_Qp_xtoq";
231796263Sobrien	  break;
231896263Sobrien	default:
2319169689Skan	  gcc_unreachable ();
232096263Sobrien	}
232196263Sobrien      break;
232296263Sobrien
232396263Sobrien    case UNSIGNED_FLOAT:
232496263Sobrien      switch (GET_MODE (operands[1]))
232596263Sobrien	{
232696263Sobrien	case SImode:
232796263Sobrien	  func = "_Qp_uitoq";
232896263Sobrien	  break;
232996263Sobrien	case DImode:
233096263Sobrien	  func = "_Qp_uxtoq";
233196263Sobrien	  break;
233296263Sobrien	default:
2333169689Skan	  gcc_unreachable ();
233496263Sobrien	}
233596263Sobrien      break;
233696263Sobrien
233796263Sobrien    case FIX:
233896263Sobrien      switch (GET_MODE (operands[0]))
233996263Sobrien	{
234096263Sobrien	case SImode:
234196263Sobrien	  func = "_Qp_qtoi";
234296263Sobrien	  break;
234396263Sobrien	case DImode:
234496263Sobrien	  func = "_Qp_qtox";
234596263Sobrien	  break;
234696263Sobrien	default:
2347169689Skan	  gcc_unreachable ();
234896263Sobrien	}
234996263Sobrien      break;
235096263Sobrien
235196263Sobrien    case UNSIGNED_FIX:
235296263Sobrien      switch (GET_MODE (operands[0]))
235396263Sobrien	{
235496263Sobrien	case SImode:
235596263Sobrien	  func = "_Qp_qtoui";
235696263Sobrien	  break;
235796263Sobrien	case DImode:
235896263Sobrien	  func = "_Qp_qtoux";
235996263Sobrien	  break;
236096263Sobrien	default:
2361169689Skan	  gcc_unreachable ();
236296263Sobrien	}
236396263Sobrien      break;
236496263Sobrien
236596263Sobrien    default:
2366169689Skan      gcc_unreachable ();
236796263Sobrien    }
236896263Sobrien
236996263Sobrien  emit_soft_tfmode_libcall (func, 2, operands);
237096263Sobrien}
237196263Sobrien
237296263Sobrien/* Expand a hard-float tfmode operation.  All arguments must be in
237396263Sobrien   registers.  */
237496263Sobrien
237596263Sobrienstatic void
2376132718Skanemit_hard_tfmode_operation (enum rtx_code code, rtx *operands)
237796263Sobrien{
237896263Sobrien  rtx op, dest;
237996263Sobrien
2380169689Skan  if (GET_RTX_CLASS (code) == RTX_UNARY)
238196263Sobrien    {
238296263Sobrien      operands[1] = force_reg (GET_MODE (operands[1]), operands[1]);
238396263Sobrien      op = gen_rtx_fmt_e (code, GET_MODE (operands[0]), operands[1]);
238496263Sobrien    }
238596263Sobrien  else
238696263Sobrien    {
238796263Sobrien      operands[1] = force_reg (GET_MODE (operands[1]), operands[1]);
238896263Sobrien      operands[2] = force_reg (GET_MODE (operands[2]), operands[2]);
238996263Sobrien      op = gen_rtx_fmt_ee (code, GET_MODE (operands[0]),
239096263Sobrien			   operands[1], operands[2]);
239196263Sobrien    }
239296263Sobrien
239396263Sobrien  if (register_operand (operands[0], VOIDmode))
239496263Sobrien    dest = operands[0];
239596263Sobrien  else
239696263Sobrien    dest = gen_reg_rtx (GET_MODE (operands[0]));
239796263Sobrien
239896263Sobrien  emit_insn (gen_rtx_SET (VOIDmode, dest, op));
239996263Sobrien
240096263Sobrien  if (dest != operands[0])
240196263Sobrien    emit_move_insn (operands[0], dest);
240296263Sobrien}
240396263Sobrien
240496263Sobrienvoid
2405132718Skanemit_tfmode_binop (enum rtx_code code, rtx *operands)
240696263Sobrien{
240796263Sobrien  if (TARGET_HARD_QUAD)
240896263Sobrien    emit_hard_tfmode_operation (code, operands);
240996263Sobrien  else
241096263Sobrien    emit_soft_tfmode_binop (code, operands);
241196263Sobrien}
241296263Sobrien
241396263Sobrienvoid
2414132718Skanemit_tfmode_unop (enum rtx_code code, rtx *operands)
241596263Sobrien{
241696263Sobrien  if (TARGET_HARD_QUAD)
241796263Sobrien    emit_hard_tfmode_operation (code, operands);
241896263Sobrien  else
241996263Sobrien    emit_soft_tfmode_unop (code, operands);
242096263Sobrien}
242196263Sobrien
242296263Sobrienvoid
2423132718Skanemit_tfmode_cvt (enum rtx_code code, rtx *operands)
242496263Sobrien{
242596263Sobrien  if (TARGET_HARD_QUAD)
242696263Sobrien    emit_hard_tfmode_operation (code, operands);
242796263Sobrien  else
242896263Sobrien    emit_soft_tfmode_cvt (code, operands);
242996263Sobrien}
243096263Sobrien
243196263Sobrien/* Return nonzero if a branch/jump/call instruction will be emitting
243296263Sobrien   nop into its delay slot.  */
243396263Sobrien
243496263Sobrienint
2435132718Skanempty_delay_slot (rtx insn)
243696263Sobrien{
243796263Sobrien  rtx seq;
243896263Sobrien
243996263Sobrien  /* If no previous instruction (should not happen), return true.  */
244096263Sobrien  if (PREV_INSN (insn) == NULL)
244196263Sobrien    return 1;
244296263Sobrien
244396263Sobrien  seq = NEXT_INSN (PREV_INSN (insn));
244496263Sobrien  if (GET_CODE (PATTERN (seq)) == SEQUENCE)
244596263Sobrien    return 0;
244696263Sobrien
244796263Sobrien  return 1;
244896263Sobrien}
244996263Sobrien
2450169689Skan/* Return nonzero if TRIAL can go into the call delay slot.  */
245150397Sobrien
245250397Sobrienint
2453169689Skantls_call_delay (rtx trial)
245450397Sobrien{
2455169689Skan  rtx pat;
245650397Sobrien
2457169689Skan  /* Binutils allows
2458169689Skan       call __tls_get_addr, %tgd_call (foo)
2459169689Skan        add %l7, %o0, %o0, %tgd_add (foo)
2460169689Skan     while Sun as/ld does not.  */
2461169689Skan  if (TARGET_GNU_TLS || !TARGET_TLS)
2462169689Skan    return 1;
246350397Sobrien
2464169689Skan  pat = PATTERN (trial);
246550397Sobrien
2466169689Skan  /* We must reject tgd_add{32|64}, i.e.
2467169689Skan       (set (reg) (plus (reg) (unspec [(reg) (symbol_ref)] UNSPEC_TLSGD)))
2468169689Skan     and tldm_add{32|64}, i.e.
2469169689Skan       (set (reg) (plus (reg) (unspec [(reg) (symbol_ref)] UNSPEC_TLSLDM)))
2470169689Skan     for Sun as/ld.  */
2471169689Skan  if (GET_CODE (pat) == SET
2472169689Skan      && GET_CODE (SET_SRC (pat)) == PLUS)
2473169689Skan    {
2474169689Skan      rtx unspec = XEXP (SET_SRC (pat), 1);
247550397Sobrien
2476169689Skan      if (GET_CODE (unspec) == UNSPEC
2477169689Skan	  && (XINT (unspec, 1) == UNSPEC_TLSGD
2478169689Skan	      || XINT (unspec, 1) == UNSPEC_TLSLDM))
2479169689Skan	return 0;
248050397Sobrien    }
248150397Sobrien
2482169689Skan  return 1;
2483169689Skan}
248450397Sobrien
2485169689Skan/* Return nonzero if TRIAL, an insn, can be combined with a 'restore'
2486169689Skan   instruction.  RETURN_P is true if the v9 variant 'return' is to be
2487169689Skan   considered in the test too.
248850397Sobrien
2489169689Skan   TRIAL must be a SET whose destination is a REG appropriate for the
2490169689Skan   'restore' instruction or, if RETURN_P is true, for the 'return'
2491169689Skan   instruction.  */
249290075Sobrien
2493169689Skanstatic int
2494169689Skaneligible_for_restore_insn (rtx trial, bool return_p)
2495169689Skan{
2496169689Skan  rtx pat = PATTERN (trial);
2497169689Skan  rtx src = SET_SRC (pat);
249850397Sobrien
2499169689Skan  /* The 'restore src,%g0,dest' pattern for word mode and below.  */
250090075Sobrien  if (GET_MODE_CLASS (GET_MODE (src)) != MODE_FLOAT
250190075Sobrien      && arith_operand (src, GET_MODE (src)))
250252284Sobrien    {
250352284Sobrien      if (TARGET_ARCH64)
250452284Sobrien        return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
250552284Sobrien      else
250652284Sobrien        return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (SImode);
250752284Sobrien    }
250890075Sobrien
2509169689Skan  /* The 'restore src,%g0,dest' pattern for double-word mode.  */
251090075Sobrien  else if (GET_MODE_CLASS (GET_MODE (src)) != MODE_FLOAT
251190075Sobrien	   && arith_double_operand (src, GET_MODE (src)))
251250397Sobrien    return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
251350397Sobrien
2514169689Skan  /* The 'restore src,%g0,dest' pattern for float if no FPU.  */
2515169689Skan  else if (! TARGET_FPU && register_operand (src, SFmode))
251650397Sobrien    return 1;
251750397Sobrien
2518169689Skan  /* The 'restore src,%g0,dest' pattern for double if no FPU.  */
2519169689Skan  else if (! TARGET_FPU && TARGET_ARCH64 && register_operand (src, DFmode))
2520169689Skan    return 1;
2521169689Skan
2522169689Skan  /* If we have the 'return' instruction, anything that does not use
252390075Sobrien     local or output registers and can go into a delay slot wins.  */
2524169689Skan  else if (return_p && TARGET_V9 && ! epilogue_renumber (&pat, 1)
2525169689Skan	   && (get_attr_in_uncond_branch_delay (trial)
2526169689Skan	       == IN_UNCOND_BRANCH_DELAY_TRUE))
252790075Sobrien    return 1;
252890075Sobrien
2529169689Skan  /* The 'restore src1,src2,dest' pattern for SImode.  */
253050397Sobrien  else if (GET_CODE (src) == PLUS
2531169689Skan	   && register_operand (XEXP (src, 0), SImode)
2532169689Skan	   && arith_operand (XEXP (src, 1), SImode))
253350397Sobrien    return 1;
253450397Sobrien
2535169689Skan  /* The 'restore src1,src2,dest' pattern for DImode.  */
253650397Sobrien  else if (GET_CODE (src) == PLUS
2537169689Skan	   && register_operand (XEXP (src, 0), DImode)
2538169689Skan	   && arith_double_operand (XEXP (src, 1), DImode))
253950397Sobrien    return 1;
254050397Sobrien
2541169689Skan  /* The 'restore src1,%lo(src2),dest' pattern.  */
254290075Sobrien  else if (GET_CODE (src) == LO_SUM
254390075Sobrien	   && ! TARGET_CM_MEDMID
254490075Sobrien	   && ((register_operand (XEXP (src, 0), SImode)
254590075Sobrien	        && immediate_operand (XEXP (src, 1), SImode))
254690075Sobrien	       || (TARGET_ARCH64
254790075Sobrien		   && register_operand (XEXP (src, 0), DImode)
254890075Sobrien		   && immediate_operand (XEXP (src, 1), DImode))))
254990075Sobrien    return 1;
255090075Sobrien
2551169689Skan  /* The 'restore src,src,dest' pattern.  */
255290075Sobrien  else if (GET_CODE (src) == ASHIFT
255390075Sobrien	   && (register_operand (XEXP (src, 0), SImode)
255490075Sobrien	       || register_operand (XEXP (src, 0), DImode))
255590075Sobrien	   && XEXP (src, 1) == const1_rtx)
255690075Sobrien    return 1;
255790075Sobrien
255850397Sobrien  return 0;
255950397Sobrien}
256050397Sobrien
2561169689Skan/* Return nonzero if TRIAL can go into the function return's
2562169689Skan   delay slot.  */
2563169689Skan
2564132718Skanint
2565169689Skaneligible_for_return_delay (rtx trial)
2566132718Skan{
2567161651Skan  rtx pat;
2568132718Skan
2569169689Skan  if (GET_CODE (trial) != INSN || GET_CODE (PATTERN (trial)) != SET)
2570169689Skan    return 0;
2571132718Skan
2572169689Skan  if (get_attr_length (trial) != 1)
2573169689Skan    return 0;
2574169689Skan
2575169689Skan  /* If there are any call-saved registers, we should scan TRIAL if it
2576169689Skan     does not reference them.  For now just make it easy.  */
2577169689Skan  if (num_gfregs)
2578169689Skan    return 0;
2579169689Skan
2580169689Skan  /* If the function uses __builtin_eh_return, the eh_return machinery
2581169689Skan     occupies the delay slot.  */
2582169689Skan  if (current_function_calls_eh_return)
2583169689Skan    return 0;
2584169689Skan
2585169689Skan  /* In the case of a true leaf function, anything can go into the slot.  */
2586169689Skan  if (sparc_leaf_function_p)
2587169689Skan    return get_attr_in_uncond_branch_delay (trial)
2588169689Skan	   == IN_UNCOND_BRANCH_DELAY_TRUE;
2589169689Skan
2590132718Skan  pat = PATTERN (trial);
2591132718Skan
2592169689Skan  /* Otherwise, only operations which can be done in tandem with
2593169689Skan     a `restore' or `return' insn can go into the delay slot.  */
2594169689Skan  if (GET_CODE (SET_DEST (pat)) != REG
2595169689Skan      || (REGNO (SET_DEST (pat)) >= 8 && REGNO (SET_DEST (pat)) < 24))
2596169689Skan    return 0;
2597132718Skan
2598169689Skan  /* If this instruction sets up floating point register and we have a return
2599169689Skan     instruction, it can probably go in.  But restore will not work
2600169689Skan     with FP_REGS.  */
2601169689Skan  if (REGNO (SET_DEST (pat)) >= 32)
2602169689Skan    return (TARGET_V9
2603169689Skan	    && ! epilogue_renumber (&pat, 1)
2604169689Skan	    && (get_attr_in_uncond_branch_delay (trial)
2605169689Skan		== IN_UNCOND_BRANCH_DELAY_TRUE));
2606161651Skan
2607169689Skan  return eligible_for_restore_insn (trial, true);
2608132718Skan}
2609132718Skan
2610169689Skan/* Return nonzero if TRIAL can go into the sibling call's
261190075Sobrien   delay slot.  */
261290075Sobrien
261390075Sobrienint
2614132718Skaneligible_for_sibcall_delay (rtx trial)
261590075Sobrien{
2616169689Skan  rtx pat;
261790075Sobrien
261890075Sobrien  if (GET_CODE (trial) != INSN || GET_CODE (PATTERN (trial)) != SET)
261990075Sobrien    return 0;
262090075Sobrien
262190075Sobrien  if (get_attr_length (trial) != 1)
262290075Sobrien    return 0;
262390075Sobrien
262490075Sobrien  pat = PATTERN (trial);
262590075Sobrien
2626169689Skan  if (sparc_leaf_function_p)
262790075Sobrien    {
262890075Sobrien      /* If the tail call is done using the call instruction,
262990075Sobrien	 we have to restore %o7 in the delay slot.  */
2630169689Skan      if (LEAF_SIBCALL_SLOT_RESERVED_P)
263190075Sobrien	return 0;
263290075Sobrien
263390075Sobrien      /* %g1 is used to build the function address */
263490075Sobrien      if (reg_mentioned_p (gen_rtx_REG (Pmode, 1), pat))
263590075Sobrien	return 0;
263690075Sobrien
263790075Sobrien      return 1;
263890075Sobrien    }
263990075Sobrien
264090075Sobrien  /* Otherwise, only operations which can be done in tandem with
264190075Sobrien     a `restore' insn can go into the delay slot.  */
264290075Sobrien  if (GET_CODE (SET_DEST (pat)) != REG
2643169689Skan      || (REGNO (SET_DEST (pat)) >= 8 && REGNO (SET_DEST (pat)) < 24)
264490075Sobrien      || REGNO (SET_DEST (pat)) >= 32)
264590075Sobrien    return 0;
264690075Sobrien
264790075Sobrien  /* If it mentions %o7, it can't go in, because sibcall will clobber it
264890075Sobrien     in most cases.  */
264990075Sobrien  if (reg_mentioned_p (gen_rtx_REG (Pmode, 15), pat))
265090075Sobrien    return 0;
265190075Sobrien
2652169689Skan  return eligible_for_restore_insn (trial, false);
265390075Sobrien}
265490075Sobrien
265550397Sobrienint
2656132718Skanshort_branch (int uid1, int uid2)
265750397Sobrien{
265890075Sobrien  int delta = INSN_ADDRESSES (uid1) - INSN_ADDRESSES (uid2);
265990075Sobrien
266090075Sobrien  /* Leave a few words of "slop".  */
266190075Sobrien  if (delta >= -1023 && delta <= 1022)
266250397Sobrien    return 1;
266390075Sobrien
266450397Sobrien  return 0;
266550397Sobrien}
266650397Sobrien
2667117395Skan/* Return nonzero if REG is not used after INSN.
266850397Sobrien   We assume REG is a reload reg, and therefore does
266950397Sobrien   not live past labels or calls or jumps.  */
267050397Sobrienint
2671132718Skanreg_unused_after (rtx reg, rtx insn)
267250397Sobrien{
267350397Sobrien  enum rtx_code code, prev_code = UNKNOWN;
267450397Sobrien
267550397Sobrien  while ((insn = NEXT_INSN (insn)))
267650397Sobrien    {
267750397Sobrien      if (prev_code == CALL_INSN && call_used_regs[REGNO (reg)])
267850397Sobrien	return 1;
267950397Sobrien
268050397Sobrien      code = GET_CODE (insn);
268150397Sobrien      if (GET_CODE (insn) == CODE_LABEL)
268250397Sobrien	return 1;
268350397Sobrien
2684169689Skan      if (INSN_P (insn))
268550397Sobrien	{
268650397Sobrien	  rtx set = single_set (insn);
268750397Sobrien	  int in_src = set && reg_overlap_mentioned_p (reg, SET_SRC (set));
268850397Sobrien	  if (set && in_src)
268950397Sobrien	    return 0;
269050397Sobrien	  if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
269150397Sobrien	    return 1;
269250397Sobrien	  if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
269350397Sobrien	    return 0;
269450397Sobrien	}
269550397Sobrien      prev_code = code;
269650397Sobrien    }
269750397Sobrien  return 1;
269850397Sobrien}
269950397Sobrien
2700132718Skan/* Determine if it's legal to put X into the constant pool.  This
2701132718Skan   is not possible if X contains the address of a symbol that is
2702132718Skan   not constant (TLS) or not known at final link time (PIC).  */
2703132718Skan
2704132718Skanstatic bool
2705132718Skansparc_cannot_force_const_mem (rtx x)
2706132718Skan{
2707132718Skan  switch (GET_CODE (x))
2708132718Skan    {
2709132718Skan    case CONST_INT:
2710132718Skan    case CONST_DOUBLE:
2711169689Skan    case CONST_VECTOR:
2712132718Skan      /* Accept all non-symbolic constants.  */
2713132718Skan      return false;
2714132718Skan
2715132718Skan    case LABEL_REF:
2716132718Skan      /* Labels are OK iff we are non-PIC.  */
2717132718Skan      return flag_pic != 0;
2718132718Skan
2719132718Skan    case SYMBOL_REF:
2720132718Skan      /* 'Naked' TLS symbol references are never OK,
2721132718Skan	 non-TLS symbols are OK iff we are non-PIC.  */
2722132718Skan      if (SYMBOL_REF_TLS_MODEL (x))
2723132718Skan	return true;
2724132718Skan      else
2725132718Skan	return flag_pic != 0;
2726132718Skan
2727132718Skan    case CONST:
2728132718Skan      return sparc_cannot_force_const_mem (XEXP (x, 0));
2729132718Skan    case PLUS:
2730132718Skan    case MINUS:
2731132718Skan      return sparc_cannot_force_const_mem (XEXP (x, 0))
2732132718Skan         || sparc_cannot_force_const_mem (XEXP (x, 1));
2733132718Skan    case UNSPEC:
2734132718Skan      return true;
2735132718Skan    default:
2736169689Skan      gcc_unreachable ();
2737132718Skan    }
2738132718Skan}
2739132718Skan
2740169689Skan/* PIC support.  */
2741169689Skanstatic GTY(()) char pic_helper_symbol_name[256];
2742169689Skanstatic GTY(()) rtx pic_helper_symbol;
2743169689Skanstatic GTY(()) bool pic_helper_emitted_p = false;
2744117395Skanstatic GTY(()) rtx global_offset_table;
274550397Sobrien
274650397Sobrien/* Ensure that we are not using patterns that are not OK with PIC.  */
274750397Sobrien
274850397Sobrienint
2749132718Skancheck_pic (int i)
275050397Sobrien{
275150397Sobrien  switch (flag_pic)
275250397Sobrien    {
275350397Sobrien    case 1:
2754169689Skan      gcc_assert (GET_CODE (recog_data.operand[i]) != SYMBOL_REF
2755169689Skan	  	  && (GET_CODE (recog_data.operand[i]) != CONST
2756169689Skan	          || (GET_CODE (XEXP (recog_data.operand[i], 0)) == MINUS
2757169689Skan		      && (XEXP (XEXP (recog_data.operand[i], 0), 0)
2758169689Skan			  == global_offset_table)
2759169689Skan		      && (GET_CODE (XEXP (XEXP (recog_data.operand[i], 0), 1))
2760169689Skan			  == CONST))));
276150397Sobrien    case 2:
276250397Sobrien    default:
276350397Sobrien      return 1;
276450397Sobrien    }
276550397Sobrien}
276650397Sobrien
276750397Sobrien/* Return true if X is an address which needs a temporary register when
276850397Sobrien   reloaded while generating PIC code.  */
276950397Sobrien
277050397Sobrienint
2771132718Skanpic_address_needs_scratch (rtx x)
277250397Sobrien{
277350397Sobrien  /* An address which is a symbolic plus a non SMALL_INT needs a temp reg.  */
277450397Sobrien  if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
277550397Sobrien      && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
277650397Sobrien      && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
277750397Sobrien      && ! SMALL_INT (XEXP (XEXP (x, 0), 1)))
277850397Sobrien    return 1;
277950397Sobrien
278050397Sobrien  return 0;
278150397Sobrien}
278250397Sobrien
2783132718Skan/* Determine if a given RTX is a valid constant.  We already know this
2784132718Skan   satisfies CONSTANT_P.  */
2785132718Skan
2786132718Skanbool
2787132718Skanlegitimate_constant_p (rtx x)
2788132718Skan{
2789132718Skan  rtx inner;
2790132718Skan
2791132718Skan  switch (GET_CODE (x))
2792132718Skan    {
2793132718Skan    case SYMBOL_REF:
2794132718Skan      /* TLS symbols are not constant.  */
2795132718Skan      if (SYMBOL_REF_TLS_MODEL (x))
2796132718Skan	return false;
2797132718Skan      break;
2798132718Skan
2799132718Skan    case CONST:
2800132718Skan      inner = XEXP (x, 0);
2801132718Skan
2802132718Skan      /* Offsets of TLS symbols are never valid.
2803132718Skan	 Discourage CSE from creating them.  */
2804132718Skan      if (GET_CODE (inner) == PLUS
2805169689Skan	  && SPARC_SYMBOL_REF_TLS_P (XEXP (inner, 0)))
2806132718Skan	return false;
2807132718Skan      break;
2808132718Skan
2809132718Skan    case CONST_DOUBLE:
2810132718Skan      if (GET_MODE (x) == VOIDmode)
2811132718Skan        return true;
2812132718Skan
2813132718Skan      /* Floating point constants are generally not ok.
2814132718Skan	 The only exception is 0.0 in VIS.  */
2815132718Skan      if (TARGET_VIS
2816169689Skan	  && SCALAR_FLOAT_MODE_P (GET_MODE (x))
2817169689Skan	  && const_zero_operand (x, GET_MODE (x)))
2818132718Skan	return true;
2819132718Skan
2820132718Skan      return false;
2821132718Skan
2822169689Skan    case CONST_VECTOR:
2823169689Skan      /* Vector constants are generally not ok.
2824169689Skan	 The only exception is 0 in VIS.  */
2825169689Skan      if (TARGET_VIS
2826169689Skan	  && const_zero_operand (x, GET_MODE (x)))
2827169689Skan	return true;
2828169689Skan
2829169689Skan      return false;
2830169689Skan
2831132718Skan    default:
2832132718Skan      break;
2833132718Skan    }
2834132718Skan
2835132718Skan  return true;
2836132718Skan}
2837132718Skan
2838132718Skan/* Determine if a given RTX is a valid constant address.  */
2839132718Skan
2840132718Skanbool
2841132718Skanconstant_address_p (rtx x)
2842132718Skan{
2843132718Skan  switch (GET_CODE (x))
2844132718Skan    {
2845132718Skan    case LABEL_REF:
2846132718Skan    case CONST_INT:
2847132718Skan    case HIGH:
2848132718Skan      return true;
2849132718Skan
2850132718Skan    case CONST:
2851132718Skan      if (flag_pic && pic_address_needs_scratch (x))
2852132718Skan	return false;
2853132718Skan      return legitimate_constant_p (x);
2854132718Skan
2855132718Skan    case SYMBOL_REF:
2856132718Skan      return !flag_pic && legitimate_constant_p (x);
2857132718Skan
2858132718Skan    default:
2859132718Skan      return false;
2860132718Skan    }
2861132718Skan}
2862132718Skan
2863132718Skan/* Nonzero if the constant value X is a legitimate general operand
2864132718Skan   when generating PIC code.  It is given that flag_pic is on and
2865132718Skan   that X satisfies CONSTANT_P or is a CONST_DOUBLE.  */
2866132718Skan
2867132718Skanbool
2868132718Skanlegitimate_pic_operand_p (rtx x)
2869132718Skan{
2870132718Skan  if (pic_address_needs_scratch (x))
2871132718Skan    return false;
2872169689Skan  if (SPARC_SYMBOL_REF_TLS_P (x)
2873132718Skan      || (GET_CODE (x) == CONST
2874132718Skan	  && GET_CODE (XEXP (x, 0)) == PLUS
2875169689Skan	  && SPARC_SYMBOL_REF_TLS_P (XEXP (XEXP (x, 0), 0))))
2876132718Skan    return false;
2877132718Skan  return true;
2878132718Skan}
2879132718Skan
2880132718Skan/* Return nonzero if ADDR is a valid memory address.
2881132718Skan   STRICT specifies whether strict register checking applies.  */
2882132718Skan
2883132718Skanint
2884132718Skanlegitimate_address_p (enum machine_mode mode, rtx addr, int strict)
2885132718Skan{
2886146895Skan  rtx rs1 = NULL, rs2 = NULL, imm1 = NULL;
2887132718Skan
2888132718Skan  if (REG_P (addr) || GET_CODE (addr) == SUBREG)
2889132718Skan    rs1 = addr;
2890132718Skan  else if (GET_CODE (addr) == PLUS)
2891132718Skan    {
2892132718Skan      rs1 = XEXP (addr, 0);
2893132718Skan      rs2 = XEXP (addr, 1);
2894132718Skan
2895132718Skan      /* Canonicalize.  REG comes first, if there are no regs,
2896132718Skan	 LO_SUM comes first.  */
2897132718Skan      if (!REG_P (rs1)
2898132718Skan	  && GET_CODE (rs1) != SUBREG
2899132718Skan	  && (REG_P (rs2)
2900132718Skan	      || GET_CODE (rs2) == SUBREG
2901132718Skan	      || (GET_CODE (rs2) == LO_SUM && GET_CODE (rs1) != LO_SUM)))
2902132718Skan	{
2903132718Skan	  rs1 = XEXP (addr, 1);
2904132718Skan	  rs2 = XEXP (addr, 0);
2905132718Skan	}
2906132718Skan
2907132718Skan      if ((flag_pic == 1
2908132718Skan	   && rs1 == pic_offset_table_rtx
2909132718Skan	   && !REG_P (rs2)
2910132718Skan	   && GET_CODE (rs2) != SUBREG
2911132718Skan	   && GET_CODE (rs2) != LO_SUM
2912132718Skan	   && GET_CODE (rs2) != MEM
2913169689Skan	   && ! SPARC_SYMBOL_REF_TLS_P (rs2)
2914132718Skan	   && (! symbolic_operand (rs2, VOIDmode) || mode == Pmode)
2915132718Skan	   && (GET_CODE (rs2) != CONST_INT || SMALL_INT (rs2)))
2916132718Skan	  || ((REG_P (rs1)
2917132718Skan	       || GET_CODE (rs1) == SUBREG)
2918132718Skan	      && RTX_OK_FOR_OFFSET_P (rs2)))
2919132718Skan	{
2920132718Skan	  imm1 = rs2;
2921132718Skan	  rs2 = NULL;
2922132718Skan	}
2923132718Skan      else if ((REG_P (rs1) || GET_CODE (rs1) == SUBREG)
2924132718Skan	       && (REG_P (rs2) || GET_CODE (rs2) == SUBREG))
2925132718Skan	{
2926146895Skan	  /* We prohibit REG + REG for TFmode when there are no quad move insns
2927146895Skan	     and we consequently need to split.  We do this because REG+REG
2928146895Skan	     is not an offsettable address.  If we get the situation in reload
2929132718Skan	     where source and destination of a movtf pattern are both MEMs with
2930132718Skan	     REG+REG address, then only one of them gets converted to an
2931146895Skan	     offsettable address.  */
2932132718Skan	  if (mode == TFmode
2933146895Skan	      && ! (TARGET_FPU && TARGET_ARCH64 && TARGET_HARD_QUAD))
2934132718Skan	    return 0;
2935132718Skan
2936132718Skan	  /* We prohibit REG + REG on ARCH32 if not optimizing for
2937132718Skan	     DFmode/DImode because then mem_min_alignment is likely to be zero
2938132718Skan	     after reload and the  forced split would lack a matching splitter
2939132718Skan	     pattern.  */
2940132718Skan	  if (TARGET_ARCH32 && !optimize
2941132718Skan	      && (mode == DFmode || mode == DImode))
2942132718Skan	    return 0;
2943132718Skan	}
2944132718Skan      else if (USE_AS_OFFSETABLE_LO10
2945132718Skan	       && GET_CODE (rs1) == LO_SUM
2946132718Skan	       && TARGET_ARCH64
2947132718Skan	       && ! TARGET_CM_MEDMID
2948132718Skan	       && RTX_OK_FOR_OLO10_P (rs2))
2949132718Skan	{
2950132718Skan	  rs2 = NULL;
2951132718Skan	  imm1 = XEXP (rs1, 1);
2952132718Skan	  rs1 = XEXP (rs1, 0);
2953169689Skan	  if (! CONSTANT_P (imm1) || SPARC_SYMBOL_REF_TLS_P (rs1))
2954132718Skan	    return 0;
2955132718Skan	}
2956132718Skan    }
2957132718Skan  else if (GET_CODE (addr) == LO_SUM)
2958132718Skan    {
2959132718Skan      rs1 = XEXP (addr, 0);
2960132718Skan      imm1 = XEXP (addr, 1);
2961132718Skan
2962169689Skan      if (! CONSTANT_P (imm1) || SPARC_SYMBOL_REF_TLS_P (rs1))
2963132718Skan	return 0;
2964132718Skan
2965146895Skan      /* We can't allow TFmode in 32-bit mode, because an offset greater
2966146895Skan	 than the alignment (8) may cause the LO_SUM to overflow.  */
2967146895Skan      if (mode == TFmode && TARGET_ARCH32)
2968132718Skan	return 0;
2969132718Skan    }
2970132718Skan  else if (GET_CODE (addr) == CONST_INT && SMALL_INT (addr))
2971132718Skan    return 1;
2972132718Skan  else
2973132718Skan    return 0;
2974132718Skan
2975132718Skan  if (GET_CODE (rs1) == SUBREG)
2976132718Skan    rs1 = SUBREG_REG (rs1);
2977132718Skan  if (!REG_P (rs1))
2978132718Skan    return 0;
2979132718Skan
2980132718Skan  if (rs2)
2981132718Skan    {
2982132718Skan      if (GET_CODE (rs2) == SUBREG)
2983132718Skan	rs2 = SUBREG_REG (rs2);
2984132718Skan      if (!REG_P (rs2))
2985132718Skan	return 0;
2986132718Skan    }
2987132718Skan
2988132718Skan  if (strict)
2989132718Skan    {
2990132718Skan      if (!REGNO_OK_FOR_BASE_P (REGNO (rs1))
2991132718Skan	  || (rs2 && !REGNO_OK_FOR_BASE_P (REGNO (rs2))))
2992132718Skan	return 0;
2993132718Skan    }
2994132718Skan  else
2995132718Skan    {
2996132718Skan      if ((REGNO (rs1) >= 32
2997132718Skan	   && REGNO (rs1) != FRAME_POINTER_REGNUM
2998132718Skan	   && REGNO (rs1) < FIRST_PSEUDO_REGISTER)
2999132718Skan	  || (rs2
3000132718Skan	      && (REGNO (rs2) >= 32
3001132718Skan		  && REGNO (rs2) != FRAME_POINTER_REGNUM
3002132718Skan		  && REGNO (rs2) < FIRST_PSEUDO_REGISTER)))
3003132718Skan	return 0;
3004132718Skan    }
3005132718Skan  return 1;
3006132718Skan}
3007132718Skan
3008132718Skan/* Construct the SYMBOL_REF for the tls_get_offset function.  */
3009132718Skan
3010132718Skanstatic GTY(()) rtx sparc_tls_symbol;
3011169689Skan
3012132718Skanstatic rtx
3013132718Skansparc_tls_get_addr (void)
3014132718Skan{
3015132718Skan  if (!sparc_tls_symbol)
3016132718Skan    sparc_tls_symbol = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_addr");
3017132718Skan
3018132718Skan  return sparc_tls_symbol;
3019132718Skan}
3020132718Skan
3021132718Skanstatic rtx
3022132718Skansparc_tls_got (void)
3023132718Skan{
3024132718Skan  rtx temp;
3025132718Skan  if (flag_pic)
3026132718Skan    {
3027132718Skan      current_function_uses_pic_offset_table = 1;
3028132718Skan      return pic_offset_table_rtx;
3029132718Skan    }
3030132718Skan
3031132718Skan  if (!global_offset_table)
3032132718Skan    global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
3033132718Skan  temp = gen_reg_rtx (Pmode);
3034132718Skan  emit_move_insn (temp, global_offset_table);
3035132718Skan  return temp;
3036132718Skan}
3037132718Skan
3038169689Skan/* Return 1 if *X is a thread-local symbol.  */
3039132718Skan
3040169689Skanstatic int
3041169689Skansparc_tls_symbol_ref_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
3042169689Skan{
3043169689Skan  return SPARC_SYMBOL_REF_TLS_P (*x);
3044169689Skan}
3045169689Skan
3046169689Skan/* Return 1 if X contains a thread-local symbol.  */
3047169689Skan
3048169689Skanbool
3049169689Skansparc_tls_referenced_p (rtx x)
3050169689Skan{
3051169689Skan  if (!TARGET_HAVE_TLS)
3052169689Skan    return false;
3053169689Skan
3054169689Skan  return for_each_rtx (&x, &sparc_tls_symbol_ref_1, 0);
3055169689Skan}
3056169689Skan
3057132718Skan/* ADDR contains a thread-local SYMBOL_REF.  Generate code to compute
3058132718Skan   this (thread-local) address.  */
3059132718Skan
3060132718Skanrtx
3061132718Skanlegitimize_tls_address (rtx addr)
3062132718Skan{
3063132718Skan  rtx temp1, temp2, temp3, ret, o0, got, insn;
3064132718Skan
3065169689Skan  gcc_assert (! no_new_pseudos);
3066132718Skan
3067132718Skan  if (GET_CODE (addr) == SYMBOL_REF)
3068132718Skan    switch (SYMBOL_REF_TLS_MODEL (addr))
3069132718Skan      {
3070132718Skan      case TLS_MODEL_GLOBAL_DYNAMIC:
3071132718Skan	start_sequence ();
3072132718Skan	temp1 = gen_reg_rtx (SImode);
3073132718Skan	temp2 = gen_reg_rtx (SImode);
3074132718Skan	ret = gen_reg_rtx (Pmode);
3075132718Skan	o0 = gen_rtx_REG (Pmode, 8);
3076132718Skan	got = sparc_tls_got ();
3077132718Skan	emit_insn (gen_tgd_hi22 (temp1, addr));
3078132718Skan	emit_insn (gen_tgd_lo10 (temp2, temp1, addr));
3079132718Skan	if (TARGET_ARCH32)
3080132718Skan	  {
3081132718Skan	    emit_insn (gen_tgd_add32 (o0, got, temp2, addr));
3082132718Skan	    insn = emit_call_insn (gen_tgd_call32 (o0, sparc_tls_get_addr (),
3083132718Skan						   addr, const1_rtx));
3084132718Skan	  }
3085132718Skan	else
3086132718Skan	  {
3087132718Skan	    emit_insn (gen_tgd_add64 (o0, got, temp2, addr));
3088132718Skan	    insn = emit_call_insn (gen_tgd_call64 (o0, sparc_tls_get_addr (),
3089132718Skan						   addr, const1_rtx));
3090132718Skan	  }
3091132718Skan        CALL_INSN_FUNCTION_USAGE (insn)
3092132718Skan	  = gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_USE (VOIDmode, o0),
3093132718Skan			       CALL_INSN_FUNCTION_USAGE (insn));
3094132718Skan	insn = get_insns ();
3095132718Skan	end_sequence ();
3096132718Skan	emit_libcall_block (insn, ret, o0, addr);
3097132718Skan	break;
3098132718Skan
3099132718Skan      case TLS_MODEL_LOCAL_DYNAMIC:
3100132718Skan	start_sequence ();
3101132718Skan	temp1 = gen_reg_rtx (SImode);
3102132718Skan	temp2 = gen_reg_rtx (SImode);
3103132718Skan	temp3 = gen_reg_rtx (Pmode);
3104132718Skan	ret = gen_reg_rtx (Pmode);
3105132718Skan	o0 = gen_rtx_REG (Pmode, 8);
3106132718Skan	got = sparc_tls_got ();
3107132718Skan	emit_insn (gen_tldm_hi22 (temp1));
3108132718Skan	emit_insn (gen_tldm_lo10 (temp2, temp1));
3109132718Skan	if (TARGET_ARCH32)
3110132718Skan	  {
3111132718Skan	    emit_insn (gen_tldm_add32 (o0, got, temp2));
3112132718Skan	    insn = emit_call_insn (gen_tldm_call32 (o0, sparc_tls_get_addr (),
3113132718Skan						    const1_rtx));
3114132718Skan	  }
3115132718Skan	else
3116132718Skan	  {
3117132718Skan	    emit_insn (gen_tldm_add64 (o0, got, temp2));
3118132718Skan	    insn = emit_call_insn (gen_tldm_call64 (o0, sparc_tls_get_addr (),
3119132718Skan						    const1_rtx));
3120132718Skan	  }
3121132718Skan        CALL_INSN_FUNCTION_USAGE (insn)
3122132718Skan	  = gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_USE (VOIDmode, o0),
3123132718Skan			       CALL_INSN_FUNCTION_USAGE (insn));
3124132718Skan	insn = get_insns ();
3125132718Skan	end_sequence ();
3126132718Skan	emit_libcall_block (insn, temp3, o0,
3127132718Skan			    gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
3128132718Skan					    UNSPEC_TLSLD_BASE));
3129132718Skan	temp1 = gen_reg_rtx (SImode);
3130132718Skan	temp2 = gen_reg_rtx (SImode);
3131132718Skan	emit_insn (gen_tldo_hix22 (temp1, addr));
3132132718Skan	emit_insn (gen_tldo_lox10 (temp2, temp1, addr));
3133132718Skan	if (TARGET_ARCH32)
3134132718Skan	  emit_insn (gen_tldo_add32 (ret, temp3, temp2, addr));
3135132718Skan	else
3136132718Skan	  emit_insn (gen_tldo_add64 (ret, temp3, temp2, addr));
3137132718Skan	break;
3138132718Skan
3139132718Skan      case TLS_MODEL_INITIAL_EXEC:
3140132718Skan	temp1 = gen_reg_rtx (SImode);
3141132718Skan	temp2 = gen_reg_rtx (SImode);
3142132718Skan	temp3 = gen_reg_rtx (Pmode);
3143132718Skan	got = sparc_tls_got ();
3144132718Skan	emit_insn (gen_tie_hi22 (temp1, addr));
3145132718Skan	emit_insn (gen_tie_lo10 (temp2, temp1, addr));
3146132718Skan	if (TARGET_ARCH32)
3147132718Skan	  emit_insn (gen_tie_ld32 (temp3, got, temp2, addr));
3148132718Skan	else
3149132718Skan	  emit_insn (gen_tie_ld64 (temp3, got, temp2, addr));
3150132718Skan        if (TARGET_SUN_TLS)
3151132718Skan	  {
3152132718Skan	    ret = gen_reg_rtx (Pmode);
3153132718Skan	    if (TARGET_ARCH32)
3154132718Skan	      emit_insn (gen_tie_add32 (ret, gen_rtx_REG (Pmode, 7),
3155132718Skan					temp3, addr));
3156132718Skan	    else
3157132718Skan	      emit_insn (gen_tie_add64 (ret, gen_rtx_REG (Pmode, 7),
3158132718Skan					temp3, addr));
3159132718Skan	  }
3160132718Skan	else
3161132718Skan	  ret = gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, 7), temp3);
3162132718Skan	break;
3163132718Skan
3164132718Skan      case TLS_MODEL_LOCAL_EXEC:
3165132718Skan	temp1 = gen_reg_rtx (Pmode);
3166132718Skan	temp2 = gen_reg_rtx (Pmode);
3167132718Skan	if (TARGET_ARCH32)
3168132718Skan	  {
3169132718Skan	    emit_insn (gen_tle_hix22_sp32 (temp1, addr));
3170132718Skan	    emit_insn (gen_tle_lox10_sp32 (temp2, temp1, addr));
3171132718Skan	  }
3172132718Skan	else
3173132718Skan	  {
3174132718Skan	    emit_insn (gen_tle_hix22_sp64 (temp1, addr));
3175132718Skan	    emit_insn (gen_tle_lox10_sp64 (temp2, temp1, addr));
3176132718Skan	  }
3177132718Skan	ret = gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, 7), temp2);
3178132718Skan	break;
3179132718Skan
3180132718Skan      default:
3181169689Skan	gcc_unreachable ();
3182132718Skan      }
3183132718Skan
3184132718Skan  else
3185169689Skan    gcc_unreachable ();  /* for now ... */
3186132718Skan
3187132718Skan  return ret;
3188132718Skan}
3189132718Skan
3190132718Skan
319150397Sobrien/* Legitimize PIC addresses.  If the address is already position-independent,
319250397Sobrien   we return ORIG.  Newly generated position-independent addresses go into a
3193117395Skan   reg.  This is REG if nonzero, otherwise we allocate register(s) as
319450397Sobrien   necessary.  */
319550397Sobrien
319650397Sobrienrtx
3197132718Skanlegitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
3198132718Skan			rtx reg)
319950397Sobrien{
320052284Sobrien  if (GET_CODE (orig) == SYMBOL_REF)
320150397Sobrien    {
320250397Sobrien      rtx pic_ref, address;
320350397Sobrien      rtx insn;
320450397Sobrien
320550397Sobrien      if (reg == 0)
320650397Sobrien	{
3207169689Skan	  gcc_assert (! reload_in_progress && ! reload_completed);
3208169689Skan	  reg = gen_reg_rtx (Pmode);
320950397Sobrien	}
321050397Sobrien
321150397Sobrien      if (flag_pic == 2)
321250397Sobrien	{
321350397Sobrien	  /* If not during reload, allocate another temp reg here for loading
321450397Sobrien	     in the address, so that these instructions can be optimized
321550397Sobrien	     properly.  */
321650397Sobrien	  rtx temp_reg = ((reload_in_progress || reload_completed)
321750397Sobrien			  ? reg : gen_reg_rtx (Pmode));
321850397Sobrien
321950397Sobrien	  /* Must put the SYMBOL_REF inside an UNSPEC here so that cse
322050397Sobrien	     won't get confused into thinking that these two instructions
322150397Sobrien	     are loading in the true address of the symbol.  If in the
322250397Sobrien	     future a PIC rtx exists, that should be used instead.  */
3223169689Skan	  if (TARGET_ARCH64)
322452284Sobrien	    {
3225169689Skan	      emit_insn (gen_movdi_high_pic (temp_reg, orig));
3226169689Skan	      emit_insn (gen_movdi_lo_sum_pic (temp_reg, temp_reg, orig));
322752284Sobrien	    }
322852284Sobrien	  else
322952284Sobrien	    {
3230169689Skan	      emit_insn (gen_movsi_high_pic (temp_reg, orig));
3231169689Skan	      emit_insn (gen_movsi_lo_sum_pic (temp_reg, temp_reg, orig));
323252284Sobrien	    }
323350397Sobrien	  address = temp_reg;
323450397Sobrien	}
323550397Sobrien      else
323650397Sobrien	address = orig;
323750397Sobrien
3238169689Skan      pic_ref = gen_const_mem (Pmode,
3239169689Skan			       gen_rtx_PLUS (Pmode,
3240169689Skan					     pic_offset_table_rtx, address));
324150397Sobrien      current_function_uses_pic_offset_table = 1;
324250397Sobrien      insn = emit_move_insn (reg, pic_ref);
324350397Sobrien      /* Put a REG_EQUAL note on this insn, so that it can be optimized
324450397Sobrien	 by loop.  */
324550397Sobrien      REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig,
324650397Sobrien				  REG_NOTES (insn));
324750397Sobrien      return reg;
324850397Sobrien    }
324950397Sobrien  else if (GET_CODE (orig) == CONST)
325050397Sobrien    {
325150397Sobrien      rtx base, offset;
325250397Sobrien
325350397Sobrien      if (GET_CODE (XEXP (orig, 0)) == PLUS
325450397Sobrien	  && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
325550397Sobrien	return orig;
325650397Sobrien
325750397Sobrien      if (reg == 0)
325850397Sobrien	{
3259169689Skan	  gcc_assert (! reload_in_progress && ! reload_completed);
3260169689Skan	  reg = gen_reg_rtx (Pmode);
326150397Sobrien	}
326250397Sobrien
3263169689Skan      gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
3264169689Skan      base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
3265169689Skan      offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
3266169689Skan			 	       base == reg ? 0 : reg);
326750397Sobrien
326850397Sobrien      if (GET_CODE (offset) == CONST_INT)
326950397Sobrien	{
327050397Sobrien	  if (SMALL_INT (offset))
327190075Sobrien	    return plus_constant (base, INTVAL (offset));
327250397Sobrien	  else if (! reload_in_progress && ! reload_completed)
327350397Sobrien	    offset = force_reg (Pmode, offset);
327450397Sobrien	  else
327550397Sobrien	    /* If we reach here, then something is seriously wrong.  */
3276169689Skan	    gcc_unreachable ();
327750397Sobrien	}
327850397Sobrien      return gen_rtx_PLUS (Pmode, base, offset);
327950397Sobrien    }
328052284Sobrien  else if (GET_CODE (orig) == LABEL_REF)
328152284Sobrien    /* ??? Why do we do this?  */
328252284Sobrien    /* Now movsi_pic_label_ref uses it, but we ought to be checking that
328352284Sobrien       the register is live instead, in case it is eliminated.  */
328452284Sobrien    current_function_uses_pic_offset_table = 1;
328550397Sobrien
328650397Sobrien  return orig;
328750397Sobrien}
328850397Sobrien
3289132718Skan/* Try machine-dependent ways of modifying an illegitimate address X
3290132718Skan   to be legitimate.  If we find one, return the new, valid address.
3291132718Skan
3292132718Skan   OLDX is the address as it was before break_out_memory_refs was called.
3293132718Skan   In some cases it is useful to look at this to decide what needs to be done.
3294132718Skan
3295132718Skan   MODE is the mode of the operand pointed to by X.  */
3296132718Skan
3297132718Skanrtx
3298132718Skanlegitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, enum machine_mode mode)
3299132718Skan{
3300132718Skan  rtx orig_x = x;
3301132718Skan
3302132718Skan  if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT)
3303132718Skan    x = gen_rtx_PLUS (Pmode, XEXP (x, 1),
3304132718Skan		      force_operand (XEXP (x, 0), NULL_RTX));
3305132718Skan  if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == MULT)
3306132718Skan    x = gen_rtx_PLUS (Pmode, XEXP (x, 0),
3307132718Skan		      force_operand (XEXP (x, 1), NULL_RTX));
3308132718Skan  if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS)
3309132718Skan    x = gen_rtx_PLUS (Pmode, force_operand (XEXP (x, 0), NULL_RTX),
3310132718Skan		      XEXP (x, 1));
3311132718Skan  if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == PLUS)
3312132718Skan    x = gen_rtx_PLUS (Pmode, XEXP (x, 0),
3313132718Skan		      force_operand (XEXP (x, 1), NULL_RTX));
3314132718Skan
3315132718Skan  if (x != orig_x && legitimate_address_p (mode, x, FALSE))
3316132718Skan    return x;
3317132718Skan
3318169689Skan  if (SPARC_SYMBOL_REF_TLS_P (x))
3319132718Skan    x = legitimize_tls_address (x);
3320132718Skan  else if (flag_pic)
3321132718Skan    x = legitimize_pic_address (x, mode, 0);
3322132718Skan  else if (GET_CODE (x) == PLUS && CONSTANT_ADDRESS_P (XEXP (x, 1)))
3323132718Skan    x = gen_rtx_PLUS (Pmode, XEXP (x, 0),
3324132718Skan		      copy_to_mode_reg (Pmode, XEXP (x, 1)));
3325132718Skan  else if (GET_CODE (x) == PLUS && CONSTANT_ADDRESS_P (XEXP (x, 0)))
3326132718Skan    x = gen_rtx_PLUS (Pmode, XEXP (x, 1),
3327132718Skan		      copy_to_mode_reg (Pmode, XEXP (x, 0)));
3328132718Skan  else if (GET_CODE (x) == SYMBOL_REF
3329132718Skan	   || GET_CODE (x) == CONST
3330132718Skan           || GET_CODE (x) == LABEL_REF)
3331132718Skan    x = copy_to_suggested_reg (x, NULL_RTX, Pmode);
3332132718Skan  return x;
3333132718Skan}
3334132718Skan
3335169689Skan/* Emit the special PIC helper function.  */
333650397Sobrien
3337169689Skanstatic void
3338169689Skanemit_pic_helper (void)
333950397Sobrien{
3340169689Skan  const char *pic_name = reg_names[REGNO (pic_offset_table_rtx)];
3341169689Skan  int align;
334250397Sobrien
3343169689Skan  switch_to_section (text_section);
334450397Sobrien
3345169689Skan  align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
3346169689Skan  if (align > 0)
3347169689Skan    ASM_OUTPUT_ALIGN (asm_out_file, align);
3348169689Skan  ASM_OUTPUT_LABEL (asm_out_file, pic_helper_symbol_name);
3349169689Skan  if (flag_delayed_branch)
3350169689Skan    fprintf (asm_out_file, "\tjmp\t%%o7+8\n\t add\t%%o7, %s, %s\n",
3351169689Skan	    pic_name, pic_name);
3352169689Skan  else
3353169689Skan    fprintf (asm_out_file, "\tadd\t%%o7, %s, %s\n\tjmp\t%%o7+8\n\t nop\n",
3354169689Skan	    pic_name, pic_name);
335552284Sobrien
3356169689Skan  pic_helper_emitted_p = true;
3357169689Skan}
335850397Sobrien
3359169689Skan/* Emit code to load the PIC register.  */
3360169689Skan
3361169689Skanstatic void
3362169689Skanload_pic_register (bool delay_pic_helper)
3363169689Skan{
3364169689Skan  int orig_flag_pic = flag_pic;
3365169689Skan
3366169689Skan  /* If we haven't initialized the special PIC symbols, do so now.  */
3367169689Skan  if (!pic_helper_symbol_name[0])
3368169689Skan    {
3369169689Skan      ASM_GENERATE_INTERNAL_LABEL (pic_helper_symbol_name, "LADDPC", 0);
3370169689Skan      pic_helper_symbol = gen_rtx_SYMBOL_REF (Pmode, pic_helper_symbol_name);
3371169689Skan      global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
337250397Sobrien    }
337350397Sobrien
3374169689Skan  /* If we haven't emitted the special PIC helper function, do so now unless
3375169689Skan     we are requested to delay it.  */
3376169689Skan  if (!delay_pic_helper && !pic_helper_emitted_p)
3377169689Skan    emit_pic_helper ();
3378169689Skan
337950397Sobrien  flag_pic = 0;
3380169689Skan  if (TARGET_ARCH64)
3381169689Skan    emit_insn (gen_load_pcrel_symdi (pic_offset_table_rtx, global_offset_table,
3382169689Skan				     pic_helper_symbol));
3383169689Skan  else
3384169689Skan    emit_insn (gen_load_pcrel_symsi (pic_offset_table_rtx, global_offset_table,
3385169689Skan				     pic_helper_symbol));
338650397Sobrien  flag_pic = orig_flag_pic;
338750397Sobrien
338850397Sobrien  /* Need to emit this whether or not we obey regdecls,
338950397Sobrien     since setjmp/longjmp can cause life info to screw up.
339050397Sobrien     ??? In the case where we don't obey regdecls, this is not sufficient
339150397Sobrien     since we may not fall out the bottom.  */
339250397Sobrien  emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
339350397Sobrien}
339450397Sobrien
339552284Sobrien/* Return 1 if RTX is a MEM which is known to be aligned to at
339696263Sobrien   least a DESIRED byte boundary.  */
339750397Sobrien
339850397Sobrienint
3399132718Skanmem_min_alignment (rtx mem, int desired)
340050397Sobrien{
340152284Sobrien  rtx addr, base, offset;
340250397Sobrien
340352284Sobrien  /* If it's not a MEM we can't accept it.  */
340450397Sobrien  if (GET_CODE (mem) != MEM)
340552284Sobrien    return 0;
340650397Sobrien
3407169689Skan  /* Obviously...  */
3408169689Skan  if (!TARGET_UNALIGNED_DOUBLES
3409169689Skan      && MEM_ALIGN (mem) / BITS_PER_UNIT >= (unsigned)desired)
3410169689Skan    return 1;
3411169689Skan
3412169689Skan  /* ??? The rest of the function predates MEM_ALIGN so
3413169689Skan     there is probably a bit of redundancy.  */
341450397Sobrien  addr = XEXP (mem, 0);
341552284Sobrien  base = offset = NULL_RTX;
341650397Sobrien  if (GET_CODE (addr) == PLUS)
341750397Sobrien    {
341852284Sobrien      if (GET_CODE (XEXP (addr, 0)) == REG)
341950397Sobrien	{
342050397Sobrien	  base = XEXP (addr, 0);
342152284Sobrien
342252284Sobrien	  /* What we are saying here is that if the base
342352284Sobrien	     REG is aligned properly, the compiler will make
342452284Sobrien	     sure any REG based index upon it will be so
342552284Sobrien	     as well.  */
342652284Sobrien	  if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
342752284Sobrien	    offset = XEXP (addr, 1);
342852284Sobrien	  else
342952284Sobrien	    offset = const0_rtx;
343050397Sobrien	}
343150397Sobrien    }
343250397Sobrien  else if (GET_CODE (addr) == REG)
343350397Sobrien    {
343450397Sobrien      base = addr;
343550397Sobrien      offset = const0_rtx;
343650397Sobrien    }
343750397Sobrien
343852284Sobrien  if (base != NULL_RTX)
343950397Sobrien    {
344052284Sobrien      int regno = REGNO (base);
344150397Sobrien
344296263Sobrien      if (regno != HARD_FRAME_POINTER_REGNUM && regno != STACK_POINTER_REGNUM)
344350397Sobrien	{
344452284Sobrien	  /* Check if the compiler has recorded some information
344552284Sobrien	     about the alignment of the base REG.  If reload has
344690075Sobrien	     completed, we already matched with proper alignments.
344790075Sobrien	     If not running global_alloc, reload might give us
344890075Sobrien	     unaligned pointer to local stack though.  */
344990075Sobrien	  if (((cfun != 0
345090075Sobrien		&& REGNO_POINTER_ALIGN (regno) >= desired * BITS_PER_UNIT)
345190075Sobrien	       || (optimize && reload_completed))
345290075Sobrien	      && (INTVAL (offset) & (desired - 1)) == 0)
345352284Sobrien	    return 1;
345450397Sobrien	}
345550397Sobrien      else
345650397Sobrien	{
345752284Sobrien	  if (((INTVAL (offset) - SPARC_STACK_BIAS) & (desired - 1)) == 0)
345852284Sobrien	    return 1;
345950397Sobrien	}
346050397Sobrien    }
346152284Sobrien  else if (! TARGET_UNALIGNED_DOUBLES
346252284Sobrien	   || CONSTANT_P (addr)
346352284Sobrien	   || GET_CODE (addr) == LO_SUM)
346450397Sobrien    {
346552284Sobrien      /* Anything else we know is properly aligned unless TARGET_UNALIGNED_DOUBLES
346652284Sobrien	 is true, in which case we can only assume that an access is aligned if
346752284Sobrien	 it is to a constant address, or the address involves a LO_SUM.  */
346852284Sobrien      return 1;
346950397Sobrien    }
347050397Sobrien
347152284Sobrien  /* An obviously unaligned address.  */
347252284Sobrien  return 0;
347350397Sobrien}
347450397Sobrien
347550397Sobrien
347650397Sobrien/* Vectors to keep interesting information about registers where it can easily
3477117395Skan   be got.  We used to use the actual mode value as the bit number, but there
347850397Sobrien   are more than 32 modes now.  Instead we use two tables: one indexed by
347950397Sobrien   hard register number, and one indexed by mode.  */
348050397Sobrien
348150397Sobrien/* The purpose of sparc_mode_class is to shrink the range of modes so that
348250397Sobrien   they all fit (as bit numbers) in a 32 bit word (again).  Each real mode is
348350397Sobrien   mapped into one sparc_mode_class mode.  */
348450397Sobrien
348550397Sobrienenum sparc_mode_class {
348650397Sobrien  S_MODE, D_MODE, T_MODE, O_MODE,
348750397Sobrien  SF_MODE, DF_MODE, TF_MODE, OF_MODE,
348850397Sobrien  CC_MODE, CCFP_MODE
348950397Sobrien};
349050397Sobrien
349150397Sobrien/* Modes for single-word and smaller quantities.  */
349250397Sobrien#define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))
349350397Sobrien
349450397Sobrien/* Modes for double-word and smaller quantities.  */
349550397Sobrien#define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE))
349650397Sobrien
349750397Sobrien/* Modes for quad-word and smaller quantities.  */
349850397Sobrien#define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE))
349950397Sobrien
350090075Sobrien/* Modes for 8-word and smaller quantities.  */
350190075Sobrien#define O_MODES (T_MODES | (1 << (int) O_MODE) | (1 << (int) OF_MODE))
350290075Sobrien
350350397Sobrien/* Modes for single-float quantities.  We must allow any single word or
350450397Sobrien   smaller quantity.  This is because the fix/float conversion instructions
350550397Sobrien   take integer inputs/outputs from the float registers.  */
350650397Sobrien#define SF_MODES (S_MODES)
350750397Sobrien
350850397Sobrien/* Modes for double-float and smaller quantities.  */
350950397Sobrien#define DF_MODES (S_MODES | D_MODES)
351050397Sobrien
351150397Sobrien/* Modes for double-float only quantities.  */
351290075Sobrien#define DF_MODES_NO_S ((1 << (int) D_MODE) | (1 << (int) DF_MODE))
351350397Sobrien
351450397Sobrien/* Modes for quad-float only quantities.  */
351550397Sobrien#define TF_ONLY_MODES (1 << (int) TF_MODE)
351650397Sobrien
351750397Sobrien/* Modes for quad-float and smaller quantities.  */
351850397Sobrien#define TF_MODES (DF_MODES | TF_ONLY_MODES)
351950397Sobrien
352090075Sobrien/* Modes for quad-float and double-float quantities.  */
352190075Sobrien#define TF_MODES_NO_S (DF_MODES_NO_S | TF_ONLY_MODES)
352250397Sobrien
352390075Sobrien/* Modes for quad-float pair only quantities.  */
352490075Sobrien#define OF_ONLY_MODES (1 << (int) OF_MODE)
352590075Sobrien
352690075Sobrien/* Modes for quad-float pairs and smaller quantities.  */
352790075Sobrien#define OF_MODES (TF_MODES | OF_ONLY_MODES)
352890075Sobrien
352990075Sobrien#define OF_MODES_NO_S (TF_MODES_NO_S | OF_ONLY_MODES)
353090075Sobrien
353150397Sobrien/* Modes for condition codes.  */
353250397Sobrien#define CC_MODES (1 << (int) CC_MODE)
353350397Sobrien#define CCFP_MODES (1 << (int) CCFP_MODE)
353450397Sobrien
353550397Sobrien/* Value is 1 if register/mode pair is acceptable on sparc.
353650397Sobrien   The funny mixture of D and T modes is because integer operations
353750397Sobrien   do not specially operate on tetra quantities, so non-quad-aligned
353850397Sobrien   registers can hold quadword quantities (except %o4 and %i4 because
353950397Sobrien   they cross fixed registers).  */
354050397Sobrien
354150397Sobrien/* This points to either the 32 bit or the 64 bit version.  */
354290075Sobrienconst int *hard_regno_mode_classes;
354350397Sobrien
354490075Sobrienstatic const int hard_32bit_mode_classes[] = {
354550397Sobrien  S_MODES, S_MODES, T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,
354650397Sobrien  T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, D_MODES, S_MODES,
354750397Sobrien  T_MODES, S_MODES, T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,
354850397Sobrien  T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, D_MODES, S_MODES,
354950397Sobrien
355090075Sobrien  OF_MODES, SF_MODES, DF_MODES, SF_MODES, OF_MODES, SF_MODES, DF_MODES, SF_MODES,
355190075Sobrien  OF_MODES, SF_MODES, DF_MODES, SF_MODES, OF_MODES, SF_MODES, DF_MODES, SF_MODES,
355290075Sobrien  OF_MODES, SF_MODES, DF_MODES, SF_MODES, OF_MODES, SF_MODES, DF_MODES, SF_MODES,
355390075Sobrien  OF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,
355450397Sobrien
355550397Sobrien  /* FP regs f32 to f63.  Only the even numbered registers actually exist,
355650397Sobrien     and none can hold SFmode/SImode values.  */
355790075Sobrien  OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, OF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
355890075Sobrien  OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, OF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
355990075Sobrien  OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, OF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
356090075Sobrien  OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, TF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
356150397Sobrien
356250397Sobrien  /* %fcc[0123] */
356350397Sobrien  CCFP_MODES, CCFP_MODES, CCFP_MODES, CCFP_MODES,
356450397Sobrien
356550397Sobrien  /* %icc */
356650397Sobrien  CC_MODES
356750397Sobrien};
356850397Sobrien
356990075Sobrienstatic const int hard_64bit_mode_classes[] = {
357050397Sobrien  D_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES,
357190075Sobrien  O_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES,
357250397Sobrien  T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES,
357390075Sobrien  O_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES,
357450397Sobrien
357590075Sobrien  OF_MODES, SF_MODES, DF_MODES, SF_MODES, OF_MODES, SF_MODES, DF_MODES, SF_MODES,
357690075Sobrien  OF_MODES, SF_MODES, DF_MODES, SF_MODES, OF_MODES, SF_MODES, DF_MODES, SF_MODES,
357790075Sobrien  OF_MODES, SF_MODES, DF_MODES, SF_MODES, OF_MODES, SF_MODES, DF_MODES, SF_MODES,
357890075Sobrien  OF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,
357950397Sobrien
358050397Sobrien  /* FP regs f32 to f63.  Only the even numbered registers actually exist,
358150397Sobrien     and none can hold SFmode/SImode values.  */
358290075Sobrien  OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, OF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
358390075Sobrien  OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, OF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
358490075Sobrien  OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, OF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
358590075Sobrien  OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, TF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
358650397Sobrien
358750397Sobrien  /* %fcc[0123] */
358850397Sobrien  CCFP_MODES, CCFP_MODES, CCFP_MODES, CCFP_MODES,
358950397Sobrien
359050397Sobrien  /* %icc */
359150397Sobrien  CC_MODES
359250397Sobrien};
359350397Sobrien
359450397Sobrienint sparc_mode_class [NUM_MACHINE_MODES];
359550397Sobrien
359650397Sobrienenum reg_class sparc_regno_reg_class[FIRST_PSEUDO_REGISTER];
359750397Sobrien
359850397Sobrienstatic void
3599132718Skansparc_init_modes (void)
360050397Sobrien{
360150397Sobrien  int i;
360250397Sobrien
360350397Sobrien  for (i = 0; i < NUM_MACHINE_MODES; i++)
360450397Sobrien    {
360550397Sobrien      switch (GET_MODE_CLASS (i))
360650397Sobrien	{
360750397Sobrien	case MODE_INT:
360850397Sobrien	case MODE_PARTIAL_INT:
360950397Sobrien	case MODE_COMPLEX_INT:
361050397Sobrien	  if (GET_MODE_SIZE (i) <= 4)
361150397Sobrien	    sparc_mode_class[i] = 1 << (int) S_MODE;
361250397Sobrien	  else if (GET_MODE_SIZE (i) == 8)
361350397Sobrien	    sparc_mode_class[i] = 1 << (int) D_MODE;
361450397Sobrien	  else if (GET_MODE_SIZE (i) == 16)
361550397Sobrien	    sparc_mode_class[i] = 1 << (int) T_MODE;
361650397Sobrien	  else if (GET_MODE_SIZE (i) == 32)
361750397Sobrien	    sparc_mode_class[i] = 1 << (int) O_MODE;
361850397Sobrien	  else
361950397Sobrien	    sparc_mode_class[i] = 0;
362050397Sobrien	  break;
3621169689Skan	case MODE_VECTOR_INT:
3622169689Skan	  if (GET_MODE_SIZE (i) <= 4)
3623169689Skan	    sparc_mode_class[i] = 1 << (int)SF_MODE;
3624169689Skan	  else if (GET_MODE_SIZE (i) == 8)
3625169689Skan	    sparc_mode_class[i] = 1 << (int)DF_MODE;
3626169689Skan	  break;
362750397Sobrien	case MODE_FLOAT:
362850397Sobrien	case MODE_COMPLEX_FLOAT:
362950397Sobrien	  if (GET_MODE_SIZE (i) <= 4)
363050397Sobrien	    sparc_mode_class[i] = 1 << (int) SF_MODE;
363150397Sobrien	  else if (GET_MODE_SIZE (i) == 8)
363250397Sobrien	    sparc_mode_class[i] = 1 << (int) DF_MODE;
363350397Sobrien	  else if (GET_MODE_SIZE (i) == 16)
363450397Sobrien	    sparc_mode_class[i] = 1 << (int) TF_MODE;
363550397Sobrien	  else if (GET_MODE_SIZE (i) == 32)
363650397Sobrien	    sparc_mode_class[i] = 1 << (int) OF_MODE;
363750397Sobrien	  else
363850397Sobrien	    sparc_mode_class[i] = 0;
363950397Sobrien	  break;
364050397Sobrien	case MODE_CC:
364150397Sobrien	  if (i == (int) CCFPmode || i == (int) CCFPEmode)
364250397Sobrien	    sparc_mode_class[i] = 1 << (int) CCFP_MODE;
3643132718Skan	  else
364450397Sobrien	    sparc_mode_class[i] = 1 << (int) CC_MODE;
364550397Sobrien	  break;
3646132718Skan	default:
3647132718Skan	  sparc_mode_class[i] = 0;
3648132718Skan	  break;
364950397Sobrien	}
365050397Sobrien    }
365150397Sobrien
365250397Sobrien  if (TARGET_ARCH64)
365350397Sobrien    hard_regno_mode_classes = hard_64bit_mode_classes;
365450397Sobrien  else
365550397Sobrien    hard_regno_mode_classes = hard_32bit_mode_classes;
365650397Sobrien
365750397Sobrien  /* Initialize the array used by REGNO_REG_CLASS.  */
365850397Sobrien  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
365950397Sobrien    {
366050397Sobrien      if (i < 16 && TARGET_V8PLUS)
366150397Sobrien	sparc_regno_reg_class[i] = I64_REGS;
366296263Sobrien      else if (i < 32 || i == FRAME_POINTER_REGNUM)
366350397Sobrien	sparc_regno_reg_class[i] = GENERAL_REGS;
366450397Sobrien      else if (i < 64)
366550397Sobrien	sparc_regno_reg_class[i] = FP_REGS;
366650397Sobrien      else if (i < 96)
366750397Sobrien	sparc_regno_reg_class[i] = EXTRA_FP_REGS;
366850397Sobrien      else if (i < 100)
366950397Sobrien	sparc_regno_reg_class[i] = FPCC_REGS;
367050397Sobrien      else
367150397Sobrien	sparc_regno_reg_class[i] = NO_REGS;
367250397Sobrien    }
367350397Sobrien}
367450397Sobrien
367550397Sobrien/* Compute the frame size required by the function.  This function is called
3676169689Skan   during the reload pass and also by sparc_expand_prologue.  */
367750397Sobrien
3678132718SkanHOST_WIDE_INT
3679169689Skansparc_compute_frame_size (HOST_WIDE_INT size, int leaf_function_p)
368050397Sobrien{
368150397Sobrien  int outgoing_args_size = (current_function_outgoing_args_size
368250397Sobrien			    + REG_PARM_STACK_SPACE (current_function_decl));
3683169689Skan  int n_regs = 0;  /* N_REGS is the number of 4-byte regs saved thus far.  */
3684169689Skan  int i;
368550397Sobrien
368696263Sobrien  if (TARGET_ARCH64)
368750397Sobrien    {
368896263Sobrien      for (i = 0; i < 8; i++)
368996263Sobrien	if (regs_ever_live[i] && ! call_used_regs[i])
369096263Sobrien	  n_regs += 2;
369196263Sobrien    }
369296263Sobrien  else
369396263Sobrien    {
369496263Sobrien      for (i = 0; i < 8; i += 2)
369550397Sobrien	if ((regs_ever_live[i] && ! call_used_regs[i])
369650397Sobrien	    || (regs_ever_live[i+1] && ! call_used_regs[i+1]))
369750397Sobrien	  n_regs += 2;
369850397Sobrien    }
369950397Sobrien
370096263Sobrien  for (i = 32; i < (TARGET_V9 ? 96 : 64); i += 2)
370196263Sobrien    if ((regs_ever_live[i] && ! call_used_regs[i])
370296263Sobrien	|| (regs_ever_live[i+1] && ! call_used_regs[i+1]))
370396263Sobrien      n_regs += 2;
370496263Sobrien
3705169689Skan  /* Set up values for use in prologue and epilogue.  */
370650397Sobrien  num_gfregs = n_regs;
370750397Sobrien
3708169689Skan  if (leaf_function_p
3709169689Skan      && n_regs == 0
3710169689Skan      && size == 0
3711169689Skan      && current_function_outgoing_args_size == 0)
3712169689Skan    actual_fsize = apparent_fsize = 0;
371350397Sobrien  else
371450397Sobrien    {
371596263Sobrien      /* We subtract STARTING_FRAME_OFFSET, remember it's negative.  */
371696263Sobrien      apparent_fsize = (size - STARTING_FRAME_OFFSET + 7) & -8;
371750397Sobrien      apparent_fsize += n_regs * 4;
371850397Sobrien      actual_fsize = apparent_fsize + ((outgoing_args_size + 7) & -8);
371950397Sobrien    }
372050397Sobrien
372150397Sobrien  /* Make sure nothing can clobber our register windows.
372250397Sobrien     If a SAVE must be done, or there is a stack-local variable,
3723169689Skan     the register window area must be allocated.  */
3724169689Skan  if (! leaf_function_p || size > 0)
3725169689Skan    actual_fsize += FIRST_PARM_OFFSET (current_function_decl);
372650397Sobrien
372750397Sobrien  return SPARC_STACK_ALIGN (actual_fsize);
372850397Sobrien}
372950397Sobrien
3730169689Skan/* Output any necessary .register pseudo-ops.  */
373150397Sobrien
373290075Sobrienvoid
3733132718Skansparc_output_scratch_registers (FILE *file ATTRIBUTE_UNUSED)
373490075Sobrien{
373590075Sobrien#ifdef HAVE_AS_REGISTER_PSEUDO_OP
373690075Sobrien  int i;
373790075Sobrien
373890075Sobrien  if (TARGET_ARCH32)
373990075Sobrien    return;
374090075Sobrien
374190075Sobrien  /* Check if %g[2367] were used without
374290075Sobrien     .register being printed for them already.  */
374390075Sobrien  for (i = 2; i < 8; i++)
374490075Sobrien    {
374590075Sobrien      if (regs_ever_live [i]
374690075Sobrien	  && ! sparc_hard_reg_printed [i])
374790075Sobrien	{
374890075Sobrien	  sparc_hard_reg_printed [i] = 1;
3749169689Skan	  /* %g7 is used as TLS base register, use #ignore
3750169689Skan	     for it instead of #scratch.  */
3751169689Skan	  fprintf (file, "\t.register\t%%g%d, #%s\n", i,
3752169689Skan		   i == 7 ? "ignore" : "scratch");
375390075Sobrien	}
375490075Sobrien      if (i == 3) i = 5;
375590075Sobrien    }
375690075Sobrien#endif
375790075Sobrien}
375890075Sobrien
3759169689Skan/* Save/restore call-saved registers from LOW to HIGH at BASE+OFFSET
3760169689Skan   as needed.  LOW should be double-word aligned for 32-bit registers.
3761169689Skan   Return the new OFFSET.  */
376290075Sobrien
3763169689Skan#define SORR_SAVE    0
3764169689Skan#define SORR_RESTORE 1
376590075Sobrien
3766169689Skanstatic int
3767169689Skansave_or_restore_regs (int low, int high, rtx base, int offset, int action)
3768169689Skan{
3769169689Skan  rtx mem, insn;
3770169689Skan  int i;
377190075Sobrien
3772169689Skan  if (TARGET_ARCH64 && high <= 32)
3773169689Skan    {
3774169689Skan      for (i = low; i < high; i++)
3775169689Skan	{
3776169689Skan	  if (regs_ever_live[i] && ! call_used_regs[i])
3777169689Skan	    {
3778169689Skan	      mem = gen_rtx_MEM (DImode, plus_constant (base, offset));
3779169689Skan	      set_mem_alias_set (mem, sparc_sr_alias_set);
3780169689Skan	      if (action == SORR_SAVE)
3781169689Skan		{
3782169689Skan		  insn = emit_move_insn (mem, gen_rtx_REG (DImode, i));
3783169689Skan		  RTX_FRAME_RELATED_P (insn) = 1;
3784169689Skan		}
3785169689Skan	      else  /* action == SORR_RESTORE */
3786169689Skan		emit_move_insn (gen_rtx_REG (DImode, i), mem);
3787169689Skan	      offset += 8;
3788169689Skan	    }
3789169689Skan	}
3790169689Skan    }
3791169689Skan  else
3792169689Skan    {
3793169689Skan      for (i = low; i < high; i += 2)
3794169689Skan	{
3795169689Skan	  bool reg0 = regs_ever_live[i] && ! call_used_regs[i];
3796169689Skan	  bool reg1 = regs_ever_live[i+1] && ! call_used_regs[i+1];
3797169689Skan	  enum machine_mode mode;
3798169689Skan	  int regno;
3799169689Skan
3800169689Skan	  if (reg0 && reg1)
3801169689Skan	    {
3802169689Skan	      mode = i < 32 ? DImode : DFmode;
3803169689Skan	      regno = i;
3804169689Skan	    }
3805169689Skan	  else if (reg0)
3806169689Skan	    {
3807169689Skan	      mode = i < 32 ? SImode : SFmode;
3808169689Skan	      regno = i;
3809169689Skan	    }
3810169689Skan	  else if (reg1)
3811169689Skan	    {
3812169689Skan	      mode = i < 32 ? SImode : SFmode;
3813169689Skan	      regno = i + 1;
3814169689Skan	      offset += 4;
3815169689Skan	    }
3816169689Skan	  else
3817169689Skan	    continue;
3818169689Skan
3819169689Skan	  mem = gen_rtx_MEM (mode, plus_constant (base, offset));
3820169689Skan	  set_mem_alias_set (mem, sparc_sr_alias_set);
3821169689Skan	  if (action == SORR_SAVE)
3822169689Skan	    {
3823169689Skan	      insn = emit_move_insn (mem, gen_rtx_REG (mode, regno));
3824169689Skan	      RTX_FRAME_RELATED_P (insn) = 1;
3825169689Skan	    }
3826169689Skan	  else  /* action == SORR_RESTORE */
3827169689Skan	    emit_move_insn (gen_rtx_REG (mode, regno), mem);
3828169689Skan
3829169689Skan	  /* Always preserve double-word alignment.  */
3830169689Skan	  offset = (offset + 7) & -8;
3831169689Skan	}
3832169689Skan    }
3833169689Skan
3834169689Skan  return offset;
3835169689Skan}
3836169689Skan
3837169689Skan/* Emit code to save call-saved registers.  */
3838169689Skan
383990075Sobrienstatic void
3840169689Skanemit_save_or_restore_regs (int action)
384190075Sobrien{
3842169689Skan  HOST_WIDE_INT offset;
3843169689Skan  rtx base;
3844169689Skan
3845169689Skan  offset = frame_base_offset - apparent_fsize;
3846169689Skan
3847169689Skan  if (offset < -4096 || offset + num_gfregs * 4 > 4095)
3848169689Skan    {
3849169689Skan      /* ??? This might be optimized a little as %g1 might already have a
3850169689Skan	 value close enough that a single add insn will do.  */
3851169689Skan      /* ??? Although, all of this is probably only a temporary fix
3852169689Skan	 because if %g1 can hold a function result, then
3853169689Skan	 sparc_expand_epilogue will lose (the result will be
3854169689Skan	 clobbered).  */
3855169689Skan      base = gen_rtx_REG (Pmode, 1);
3856169689Skan      emit_move_insn (base, GEN_INT (offset));
3857169689Skan      emit_insn (gen_rtx_SET (VOIDmode,
3858169689Skan			      base,
3859169689Skan			      gen_rtx_PLUS (Pmode, frame_base_reg, base)));
3860169689Skan      offset = 0;
3861169689Skan    }
386290075Sobrien  else
3863169689Skan    base = frame_base_reg;
3864169689Skan
3865169689Skan  offset = save_or_restore_regs (0, 8, base, offset, action);
3866169689Skan  save_or_restore_regs (32, TARGET_V9 ? 96 : 64, base, offset, action);
386790075Sobrien}
386890075Sobrien
3869169689Skan/* Generate a save_register_window insn.  */
387050397Sobrien
3871169689Skanstatic rtx
3872169689Skangen_save_register_window (rtx increment)
387350397Sobrien{
3874169689Skan  if (TARGET_ARCH64)
3875169689Skan    return gen_save_register_windowdi (increment);
3876169689Skan  else
3877169689Skan    return gen_save_register_windowsi (increment);
3878169689Skan}
387990075Sobrien
3880169689Skan/* Generate an increment for the stack pointer.  */
3881169689Skan
3882169689Skanstatic rtx
3883169689Skangen_stack_pointer_inc (rtx increment)
3884169689Skan{
3885169689Skan  return gen_rtx_SET (VOIDmode,
3886169689Skan		      stack_pointer_rtx,
3887169689Skan		      gen_rtx_PLUS (Pmode,
3888169689Skan				    stack_pointer_rtx,
3889169689Skan				    increment));
3890169689Skan}
3891169689Skan
3892169689Skan/* Generate a decrement for the stack pointer.  */
3893169689Skan
3894169689Skanstatic rtx
3895169689Skangen_stack_pointer_dec (rtx decrement)
3896169689Skan{
3897169689Skan  return gen_rtx_SET (VOIDmode,
3898169689Skan		      stack_pointer_rtx,
3899169689Skan		      gen_rtx_MINUS (Pmode,
3900169689Skan				     stack_pointer_rtx,
3901169689Skan				     decrement));
3902169689Skan}
3903169689Skan
3904169689Skan/* Expand the function prologue.  The prologue is responsible for reserving
3905169689Skan   storage for the frame, saving the call-saved registers and loading the
3906169689Skan   PIC register if needed.  */
3907169689Skan
3908169689Skanvoid
3909169689Skansparc_expand_prologue (void)
3910169689Skan{
3911169689Skan  rtx insn;
3912169689Skan  int i;
3913169689Skan
3914169689Skan  /* Compute a snapshot of current_function_uses_only_leaf_regs.  Relying
3915169689Skan     on the final value of the flag means deferring the prologue/epilogue
3916169689Skan     expansion until just before the second scheduling pass, which is too
3917169689Skan     late to emit multiple epilogues or return insns.
3918169689Skan
3919169689Skan     Of course we are making the assumption that the value of the flag
3920169689Skan     will not change between now and its final value.  Of the three parts
3921169689Skan     of the formula, only the last one can reasonably vary.  Let's take a
3922169689Skan     closer look, after assuming that the first two ones are set to true
3923169689Skan     (otherwise the last value is effectively silenced).
3924169689Skan
3925169689Skan     If only_leaf_regs_used returns false, the global predicate will also
3926169689Skan     be false so the actual frame size calculated below will be positive.
3927169689Skan     As a consequence, the save_register_window insn will be emitted in
3928169689Skan     the instruction stream; now this insn explicitly references %fp
3929169689Skan     which is not a leaf register so only_leaf_regs_used will always
3930169689Skan     return false subsequently.
3931169689Skan
3932169689Skan     If only_leaf_regs_used returns true, we hope that the subsequent
3933169689Skan     optimization passes won't cause non-leaf registers to pop up.  For
3934169689Skan     example, the regrename pass has special provisions to not rename to
3935169689Skan     non-leaf registers in a leaf function.  */
3936169689Skan  sparc_leaf_function_p
3937169689Skan    = optimize > 0 && leaf_function_p () && only_leaf_regs_used ();
3938169689Skan
393950397Sobrien  /* Need to use actual_fsize, since we are also allocating
394050397Sobrien     space for our callee (and our own register save area).  */
3941169689Skan  actual_fsize
3942169689Skan    = sparc_compute_frame_size (get_frame_size(), sparc_leaf_function_p);
394350397Sobrien
3944169689Skan  /* Advertise that the data calculated just above are now valid.  */
3945169689Skan  sparc_prologue_data_valid_p = true;
3946169689Skan
3947169689Skan  if (sparc_leaf_function_p)
394850397Sobrien    {
3949169689Skan      frame_base_reg = stack_pointer_rtx;
395050397Sobrien      frame_base_offset = actual_fsize + SPARC_STACK_BIAS;
395150397Sobrien    }
395250397Sobrien  else
395350397Sobrien    {
3954169689Skan      frame_base_reg = hard_frame_pointer_rtx;
395550397Sobrien      frame_base_offset = SPARC_STACK_BIAS;
395650397Sobrien    }
395750397Sobrien
395850397Sobrien  if (actual_fsize == 0)
395950397Sobrien    /* do nothing.  */ ;
3960169689Skan  else if (sparc_leaf_function_p)
396150397Sobrien    {
396250397Sobrien      if (actual_fsize <= 4096)
3963169689Skan	insn = emit_insn (gen_stack_pointer_inc (GEN_INT (-actual_fsize)));
396450397Sobrien      else if (actual_fsize <= 8192)
396550397Sobrien	{
3966169689Skan	  insn = emit_insn (gen_stack_pointer_inc (GEN_INT (-4096)));
3967169689Skan	  /* %sp is still the CFA register.  */
3968169689Skan	  RTX_FRAME_RELATED_P (insn) = 1;
3969169689Skan	  insn
3970169689Skan	    = emit_insn (gen_stack_pointer_inc (GEN_INT (4096-actual_fsize)));
397150397Sobrien	}
397250397Sobrien      else
397350397Sobrien	{
3974169689Skan	  rtx reg = gen_rtx_REG (Pmode, 1);
3975169689Skan	  emit_move_insn (reg, GEN_INT (-actual_fsize));
3976169689Skan	  insn = emit_insn (gen_stack_pointer_inc (reg));
3977169689Skan	  REG_NOTES (insn) =
3978169689Skan	    gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
3979169689Skan			       gen_stack_pointer_inc (GEN_INT (-actual_fsize)),
3980169689Skan			       REG_NOTES (insn));
398150397Sobrien	}
3982169689Skan
3983169689Skan      RTX_FRAME_RELATED_P (insn) = 1;
398450397Sobrien    }
3985169689Skan  else
398650397Sobrien    {
398750397Sobrien      if (actual_fsize <= 4096)
3988169689Skan	insn = emit_insn (gen_save_register_window (GEN_INT (-actual_fsize)));
398950397Sobrien      else if (actual_fsize <= 8192)
399050397Sobrien	{
3991169689Skan	  insn = emit_insn (gen_save_register_window (GEN_INT (-4096)));
3992169689Skan	  /* %sp is not the CFA register anymore.  */
3993169689Skan	  emit_insn (gen_stack_pointer_inc (GEN_INT (4096-actual_fsize)));
399450397Sobrien	}
399550397Sobrien      else
399650397Sobrien	{
3997169689Skan	  rtx reg = gen_rtx_REG (Pmode, 1);
3998169689Skan	  emit_move_insn (reg, GEN_INT (-actual_fsize));
3999169689Skan	  insn = emit_insn (gen_save_register_window (reg));
400050397Sobrien	}
4001169689Skan
4002169689Skan      RTX_FRAME_RELATED_P (insn) = 1;
4003169689Skan      for (i=0; i < XVECLEN (PATTERN (insn), 0); i++)
4004169689Skan        RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn), 0, i)) = 1;
400550397Sobrien    }
400650397Sobrien
4007169689Skan  if (num_gfregs)
4008169689Skan    emit_save_or_restore_regs (SORR_SAVE);
400950397Sobrien
4010169689Skan  /* Load the PIC register if needed.  */
4011169689Skan  if (flag_pic && current_function_uses_pic_offset_table)
4012169689Skan    load_pic_register (false);
4013169689Skan}
4014169689Skan
4015169689Skan/* This function generates the assembly code for function entry, which boils
4016169689Skan   down to emitting the necessary .register directives.  */
401750397Sobrien
4018169689Skanstatic void
4019169689Skansparc_asm_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
4020169689Skan{
4021169689Skan  /* Check that the assumption we made in sparc_expand_prologue is valid.  */
4022169689Skan  gcc_assert (sparc_leaf_function_p == current_function_uses_only_leaf_regs);
402350397Sobrien
4024169689Skan  sparc_output_scratch_registers (file);
4025169689Skan}
402650397Sobrien
4027169689Skan/* Expand the function epilogue, either normal or part of a sibcall.
4028169689Skan   We emit all the instructions except the return or the call.  */
402950397Sobrien
4030169689Skanvoid
4031169689Skansparc_expand_epilogue (void)
4032169689Skan{
403350397Sobrien  if (num_gfregs)
4034169689Skan    emit_save_or_restore_regs (SORR_RESTORE);
4035169689Skan
4036169689Skan  if (actual_fsize == 0)
4037169689Skan    /* do nothing.  */ ;
4038169689Skan  else if (sparc_leaf_function_p)
403950397Sobrien    {
4040169689Skan      if (actual_fsize <= 4096)
4041169689Skan	emit_insn (gen_stack_pointer_dec (GEN_INT (- actual_fsize)));
4042169689Skan      else if (actual_fsize <= 8192)
404350397Sobrien	{
4044169689Skan	  emit_insn (gen_stack_pointer_dec (GEN_INT (-4096)));
4045169689Skan	  emit_insn (gen_stack_pointer_dec (GEN_INT (4096 - actual_fsize)));
404650397Sobrien	}
404750397Sobrien      else
404850397Sobrien	{
4049169689Skan	  rtx reg = gen_rtx_REG (Pmode, 1);
4050169689Skan	  emit_move_insn (reg, GEN_INT (-actual_fsize));
4051169689Skan	  emit_insn (gen_stack_pointer_dec (reg));
405250397Sobrien	}
405350397Sobrien    }
405450397Sobrien}
405550397Sobrien
4056169689Skan/* Return true if it is appropriate to emit `return' instructions in the
4057169689Skan   body of a function.  */
405890075Sobrien
4059169689Skanbool
4060169689Skansparc_can_use_return_insn_p (void)
4061169689Skan{
4062169689Skan  return sparc_prologue_data_valid_p
4063169689Skan	 && (actual_fsize == 0 || !sparc_leaf_function_p);
4064169689Skan}
4065169689Skan
4066169689Skan/* This function generates the assembly code for function exit.  */
4067169689Skan
406890075Sobrienstatic void
4069169689Skansparc_asm_function_epilogue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
407090075Sobrien{
4071169689Skan  /* If code does not drop into the epilogue, we have to still output
4072169689Skan     a dummy nop for the sake of sane backtraces.  Otherwise, if the
4073169689Skan     last two instructions of a function were "call foo; dslot;" this
4074169689Skan     can make the return PC of foo (i.e. address of call instruction
4075169689Skan     plus 8) point to the first instruction in the next function.  */
407690075Sobrien
4077169689Skan  rtx insn, last_real_insn;
407890075Sobrien
4079169689Skan  insn = get_last_insn ();
408090075Sobrien
4081169689Skan  last_real_insn = prev_real_insn (insn);
4082169689Skan  if (last_real_insn
4083169689Skan      && GET_CODE (last_real_insn) == INSN
4084169689Skan      && GET_CODE (PATTERN (last_real_insn)) == SEQUENCE)
4085169689Skan    last_real_insn = XVECEXP (PATTERN (last_real_insn), 0, 0);
408690075Sobrien
4087169689Skan  if (last_real_insn && GET_CODE (last_real_insn) == CALL_INSN)
4088169689Skan    fputs("\tnop\n", file);
408990075Sobrien
4090169689Skan  sparc_output_deferred_case_vectors ();
409190075Sobrien}
4092169689Skan
4093169689Skan/* Output a 'restore' instruction.  */
4094169689Skan
409590075Sobrienstatic void
4096169689Skanoutput_restore (rtx pat)
409750397Sobrien{
4098169689Skan  rtx operands[3];
409950397Sobrien
4100169689Skan  if (! pat)
410150397Sobrien    {
4102169689Skan      fputs ("\t restore\n", asm_out_file);
4103169689Skan      return;
4104169689Skan    }
410596263Sobrien
4106169689Skan  gcc_assert (GET_CODE (pat) == SET);
410796263Sobrien
4108169689Skan  operands[0] = SET_DEST (pat);
4109169689Skan  pat = SET_SRC (pat);
411096263Sobrien
4111169689Skan  switch (GET_CODE (pat))
4112169689Skan    {
4113169689Skan      case PLUS:
4114169689Skan	operands[1] = XEXP (pat, 0);
4115169689Skan	operands[2] = XEXP (pat, 1);
4116169689Skan	output_asm_insn (" restore %r1, %2, %Y0", operands);
4117169689Skan	break;
4118169689Skan      case LO_SUM:
4119169689Skan	operands[1] = XEXP (pat, 0);
4120169689Skan	operands[2] = XEXP (pat, 1);
4121169689Skan	output_asm_insn (" restore %r1, %%lo(%a2), %Y0", operands);
4122169689Skan	break;
4123169689Skan      case ASHIFT:
4124169689Skan	operands[1] = XEXP (pat, 0);
4125169689Skan	gcc_assert (XEXP (pat, 1) == const1_rtx);
4126169689Skan	output_asm_insn (" restore %r1, %r1, %Y0", operands);
4127169689Skan	break;
4128169689Skan      default:
4129169689Skan	operands[1] = pat;
4130169689Skan	output_asm_insn (" restore %%g0, %1, %Y0", operands);
4131169689Skan	break;
4132169689Skan    }
4133169689Skan}
4134169689Skan
4135169689Skan/* Output a return.  */
4136119256Skan
4137169689Skanconst char *
4138169689Skanoutput_return (rtx insn)
4139169689Skan{
4140169689Skan  if (sparc_leaf_function_p)
4141169689Skan    {
4142169689Skan      /* This is a leaf function so we don't have to bother restoring the
4143169689Skan	 register window, which frees us from dealing with the convoluted
4144169689Skan	 semantics of restore/return.  We simply output the jump to the
4145169689Skan	 return address and the insn in the delay slot (if any).  */
4146119256Skan
4147169689Skan      gcc_assert (! current_function_calls_eh_return);
4148169689Skan
4149169689Skan      return "jmp\t%%o7+%)%#";
415050397Sobrien    }
415150397Sobrien  else
4152169689Skan    {
4153169689Skan      /* This is a regular function so we have to restore the register window.
4154169689Skan	 We may have a pending insn for the delay slot, which will be either
4155169689Skan	 combined with the 'restore' instruction or put in the delay slot of
4156169689Skan	 the 'return' instruction.  */
415750397Sobrien
415896263Sobrien      if (current_function_calls_eh_return)
415996263Sobrien	{
4160169689Skan	  /* If the function uses __builtin_eh_return, the eh_return
4161169689Skan	     machinery occupies the delay slot.  */
4162169689Skan	  gcc_assert (! final_sequence);
416350397Sobrien
4164169689Skan	  if (! flag_delayed_branch)
4165169689Skan	    fputs ("\tadd\t%fp, %g1, %fp\n", asm_out_file);
4166169689Skan
4167169689Skan	  if (TARGET_V9)
4168169689Skan	    fputs ("\treturn\t%i7+8\n", asm_out_file);
4169169689Skan	  else
4170169689Skan	    fputs ("\trestore\n\tjmp\t%o7+8\n", asm_out_file);
4171169689Skan
4172169689Skan	  if (flag_delayed_branch)
4173169689Skan	    fputs ("\t add\t%sp, %g1, %sp\n", asm_out_file);
4174169689Skan	  else
4175169689Skan	    fputs ("\t nop\n", asm_out_file);
417696263Sobrien	}
4177169689Skan      else if (final_sequence)
417850397Sobrien	{
4179169689Skan	  rtx delay, pat;
418096263Sobrien
4181169689Skan	  delay = NEXT_INSN (insn);
4182169689Skan	  gcc_assert (delay);
4183169689Skan
4184169689Skan	  pat = PATTERN (delay);
4185169689Skan
4186169689Skan	  if (TARGET_V9 && ! epilogue_renumber (&pat, 1))
418790075Sobrien	    {
4188169689Skan	      epilogue_renumber (&pat, 0);
4189169689Skan	      return "return\t%%i7+%)%#";
419090075Sobrien	    }
419196263Sobrien	  else
419250397Sobrien	    {
4193169689Skan	      output_asm_insn ("jmp\t%%i7+%)", NULL);
4194169689Skan	      output_restore (pat);
4195169689Skan	      PATTERN (delay) = gen_blockage ();
4196169689Skan	      INSN_CODE (delay) = -1;
419750397Sobrien	    }
419850397Sobrien	}
419996263Sobrien      else
4200169689Skan        {
4201169689Skan	  /* The delay slot is empty.  */
4202169689Skan	  if (TARGET_V9)
4203169689Skan	    return "return\t%%i7+%)\n\t nop";
4204169689Skan	  else if (flag_delayed_branch)
4205169689Skan	    return "jmp\t%%i7+%)\n\t restore";
4206169689Skan	  else
4207169689Skan	    return "restore\n\tjmp\t%%o7+%)\n\t nop";
4208169689Skan	}
420996263Sobrien    }
421052284Sobrien
4211169689Skan  return "";
421250397Sobrien}
421390075Sobrien
421490075Sobrien/* Output a sibling call.  */
421590075Sobrien
421690075Sobrienconst char *
4217132718Skanoutput_sibcall (rtx insn, rtx call_operand)
421890075Sobrien{
4219169689Skan  rtx operands[1];
422090075Sobrien
4221169689Skan  gcc_assert (flag_delayed_branch);
4222169689Skan
4223169689Skan  operands[0] = call_operand;
4224169689Skan
4225169689Skan  if (sparc_leaf_function_p)
422690075Sobrien    {
4227169689Skan      /* This is a leaf function so we don't have to bother restoring the
4228169689Skan	 register window.  We simply output the jump to the function and
4229169689Skan	 the insn in the delay slot (if any).  */
423090075Sobrien
4231169689Skan      gcc_assert (!(LEAF_SIBCALL_SLOT_RESERVED_P && final_sequence));
423290075Sobrien
4233169689Skan      if (final_sequence)
4234169689Skan	output_asm_insn ("sethi\t%%hi(%a0), %%g1\n\tjmp\t%%g1 + %%lo(%a0)%#",
4235169689Skan			 operands);
4236169689Skan      else
4237169689Skan	/* Use or with rs2 %%g0 instead of mov, so that as/ld can optimize
4238169689Skan	   it into branch if possible.  */
4239169689Skan	output_asm_insn ("or\t%%o7, %%g0, %%g1\n\tcall\t%a0, 0\n\t or\t%%g1, %%g0, %%o7",
4240169689Skan			 operands);
424190075Sobrien    }
4242169689Skan  else
4243169689Skan    {
4244169689Skan      /* This is a regular function so we have to restore the register window.
4245169689Skan	 We may have a pending insn for the delay slot, which will be combined
4246169689Skan	 with the 'restore' instruction.  */
424790075Sobrien
4248169689Skan      output_asm_insn ("call\t%a0, 0", operands);
424990075Sobrien
4250169689Skan      if (final_sequence)
425190075Sobrien	{
425290075Sobrien	  rtx delay = NEXT_INSN (insn);
4253169689Skan	  gcc_assert (delay);
425490075Sobrien
4255169689Skan	  output_restore (PATTERN (delay));
425690075Sobrien
425790075Sobrien	  PATTERN (delay) = gen_blockage ();
425890075Sobrien	  INSN_CODE (delay) = -1;
425990075Sobrien	}
426090075Sobrien      else
4261169689Skan	output_restore (NULL_RTX);
426290075Sobrien    }
426390075Sobrien
426490075Sobrien  return "";
426590075Sobrien}
426650397Sobrien
426750397Sobrien/* Functions for handling argument passing.
426850397Sobrien
4269169689Skan   For 32-bit, the first 6 args are normally in registers and the rest are
427050397Sobrien   pushed.  Any arg that starts within the first 6 words is at least
427150397Sobrien   partially passed in a register unless its data type forbids.
427250397Sobrien
4273169689Skan   For 64-bit, the argument registers are laid out as an array of 16 elements
427450397Sobrien   and arguments are added sequentially.  The first 6 int args and up to the
427550397Sobrien   first 16 fp args (depending on size) are passed in regs.
427650397Sobrien
427750397Sobrien   Slot    Stack   Integral   Float   Float in structure   Double   Long Double
427850397Sobrien   ----    -----   --------   -----   ------------------   ------   -----------
427950397Sobrien    15   [SP+248]              %f31       %f30,%f31         %d30
428050397Sobrien    14   [SP+240]              %f29       %f28,%f29         %d28       %q28
428150397Sobrien    13   [SP+232]              %f27       %f26,%f27         %d26
428250397Sobrien    12   [SP+224]              %f25       %f24,%f25         %d24       %q24
428350397Sobrien    11   [SP+216]              %f23       %f22,%f23         %d22
428450397Sobrien    10   [SP+208]              %f21       %f20,%f21         %d20       %q20
428550397Sobrien     9   [SP+200]              %f19       %f18,%f19         %d18
428650397Sobrien     8   [SP+192]              %f17       %f16,%f17         %d16       %q16
428750397Sobrien     7   [SP+184]              %f15       %f14,%f15         %d14
428850397Sobrien     6   [SP+176]              %f13       %f12,%f13         %d12       %q12
428950397Sobrien     5   [SP+168]     %o5      %f11       %f10,%f11         %d10
429050397Sobrien     4   [SP+160]     %o4       %f9        %f8,%f9           %d8        %q8
429150397Sobrien     3   [SP+152]     %o3       %f7        %f6,%f7           %d6
429250397Sobrien     2   [SP+144]     %o2       %f5        %f4,%f5           %d4        %q4
429350397Sobrien     1   [SP+136]     %o1       %f3        %f2,%f3           %d2
429450397Sobrien     0   [SP+128]     %o0       %f1        %f0,%f1           %d0        %q0
429550397Sobrien
429650397Sobrien   Here SP = %sp if -mno-stack-bias or %sp+stack_bias otherwise.
429750397Sobrien
4298169689Skan   Integral arguments are always passed as 64-bit quantities appropriately
429950397Sobrien   extended.
430050397Sobrien
430150397Sobrien   Passing of floating point values is handled as follows.
430250397Sobrien   If a prototype is in scope:
430350397Sobrien     If the value is in a named argument (i.e. not a stdarg function or a
430450397Sobrien     value not part of the `...') then the value is passed in the appropriate
430550397Sobrien     fp reg.
430650397Sobrien     If the value is part of the `...' and is passed in one of the first 6
430750397Sobrien     slots then the value is passed in the appropriate int reg.
430850397Sobrien     If the value is part of the `...' and is not passed in one of the first 6
430950397Sobrien     slots then the value is passed in memory.
431050397Sobrien   If a prototype is not in scope:
431150397Sobrien     If the value is one of the first 6 arguments the value is passed in the
431250397Sobrien     appropriate integer reg and the appropriate fp reg.
431350397Sobrien     If the value is not one of the first 6 arguments the value is passed in
431450397Sobrien     the appropriate fp reg and in memory.
431550397Sobrien
4316169689Skan
4317169689Skan   Summary of the calling conventions implemented by GCC on SPARC:
4318169689Skan
4319169689Skan   32-bit ABI:
4320169689Skan                                size      argument     return value
4321169689Skan
4322169689Skan      small integer              <4       int. reg.      int. reg.
4323169689Skan      word                        4       int. reg.      int. reg.
4324169689Skan      double word                 8       int. reg.      int. reg.
4325169689Skan
4326169689Skan      _Complex small integer     <8       int. reg.      int. reg.
4327169689Skan      _Complex word               8       int. reg.      int. reg.
4328169689Skan      _Complex double word       16        memory        int. reg.
4329169689Skan
4330169689Skan      vector integer            <=8       int. reg.       FP reg.
4331169689Skan      vector integer             >8        memory         memory
4332169689Skan
4333169689Skan      float                       4       int. reg.       FP reg.
4334169689Skan      double                      8       int. reg.       FP reg.
4335169689Skan      long double                16        memory         memory
4336169689Skan
4337169689Skan      _Complex float              8        memory         FP reg.
4338169689Skan      _Complex double            16        memory         FP reg.
4339169689Skan      _Complex long double       32        memory         FP reg.
4340169689Skan
4341169689Skan      vector float              any        memory         memory
4342169689Skan
4343169689Skan      aggregate                 any        memory         memory
4344169689Skan
4345169689Skan
4346169689Skan
4347169689Skan    64-bit ABI:
4348169689Skan                                size      argument     return value
4349169689Skan
4350169689Skan      small integer              <8       int. reg.      int. reg.
4351169689Skan      word                        8       int. reg.      int. reg.
4352169689Skan      double word                16       int. reg.      int. reg.
4353169689Skan
4354169689Skan      _Complex small integer    <16       int. reg.      int. reg.
4355169689Skan      _Complex word              16       int. reg.      int. reg.
4356169689Skan      _Complex double word       32        memory        int. reg.
4357169689Skan
4358169689Skan      vector integer           <=16        FP reg.        FP reg.
4359169689Skan      vector integer       16<s<=32        memory         FP reg.
4360169689Skan      vector integer            >32        memory         memory
4361169689Skan
4362169689Skan      float                       4        FP reg.        FP reg.
4363169689Skan      double                      8        FP reg.        FP reg.
4364169689Skan      long double                16        FP reg.        FP reg.
4365169689Skan
4366169689Skan      _Complex float              8        FP reg.        FP reg.
4367169689Skan      _Complex double            16        FP reg.        FP reg.
4368169689Skan      _Complex long double       32        memory         FP reg.
4369169689Skan
4370169689Skan      vector float             <=16        FP reg.        FP reg.
4371169689Skan      vector float         16<s<=32        memory         FP reg.
4372169689Skan      vector float              >32        memory         memory
4373169689Skan
4374169689Skan      aggregate                <=16         reg.           reg.
4375169689Skan      aggregate            16<s<=32        memory          reg.
4376169689Skan      aggregate                 >32        memory         memory
4377169689Skan
4378169689Skan
4379169689Skan
4380169689SkanNote #1: complex floating-point types follow the extended SPARC ABIs as
4381169689Skanimplemented by the Sun compiler.
4382169689Skan
4383169689SkanNote #2: integral vector types follow the scalar floating-point types
4384169689Skanconventions to match what is implemented by the Sun VIS SDK.
4385169689Skan
4386169689SkanNote #3: floating-point vector types follow the aggregate types
4387169689Skanconventions.  */
4388169689Skan
4389169689Skan
439050397Sobrien/* Maximum number of int regs for args.  */
439150397Sobrien#define SPARC_INT_ARG_MAX 6
439250397Sobrien/* Maximum number of fp regs for args.  */
439350397Sobrien#define SPARC_FP_ARG_MAX 16
439450397Sobrien
439550397Sobrien#define ROUND_ADVANCE(SIZE) (((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
439650397Sobrien
439750397Sobrien/* Handle the INIT_CUMULATIVE_ARGS macro.
439850397Sobrien   Initialize a variable CUM of type CUMULATIVE_ARGS
439950397Sobrien   for a call to a function whose data type is FNTYPE.
440050397Sobrien   For a library call, FNTYPE is 0.  */
440150397Sobrien
440250397Sobrienvoid
4403132718Skaninit_cumulative_args (struct sparc_args *cum, tree fntype,
4404132718Skan		      rtx libname ATTRIBUTE_UNUSED,
4405132718Skan		      tree fndecl ATTRIBUTE_UNUSED)
440650397Sobrien{
440750397Sobrien  cum->words = 0;
440850397Sobrien  cum->prototype_p = fntype && TYPE_ARG_TYPES (fntype);
440950397Sobrien  cum->libcall_p = fntype == 0;
441050397Sobrien}
441150397Sobrien
4412169689Skan/* Handle the TARGET_PROMOTE_PROTOTYPES target hook.
4413169689Skan   When a prototype says `char' or `short', really pass an `int'.  */
4414169689Skan
4415169689Skanstatic bool
4416169689Skansparc_promote_prototypes (tree fntype ATTRIBUTE_UNUSED)
4417169689Skan{
4418169689Skan  return TARGET_ARCH32 ? true : false;
4419169689Skan}
4420169689Skan
4421169689Skan/* Handle the TARGET_STRICT_ARGUMENT_NAMING target hook.  */
4422169689Skan
4423169689Skanstatic bool
4424169689Skansparc_strict_argument_naming (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED)
4425169689Skan{
4426169689Skan  return TARGET_ARCH64 ? true : false;
4427169689Skan}
4428169689Skan
4429132718Skan/* Scan the record type TYPE and return the following predicates:
4430132718Skan    - INTREGS_P: the record contains at least one field or sub-field
4431132718Skan      that is eligible for promotion in integer registers.
4432132718Skan    - FP_REGS_P: the record contains at least one field or sub-field
4433132718Skan      that is eligible for promotion in floating-point registers.
4434132718Skan    - PACKED_P: the record contains at least one field that is packed.
4435132718Skan
4436132718Skan   Sub-fields are not taken into account for the PACKED_P predicate.  */
4437132718Skan
4438132718Skanstatic void
4439132718Skanscan_record_type (tree type, int *intregs_p, int *fpregs_p, int *packed_p)
4440132718Skan{
4441132718Skan  tree field;
4442132718Skan
4443132718Skan  for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
4444132718Skan    {
4445132718Skan      if (TREE_CODE (field) == FIELD_DECL)
4446132718Skan	{
4447132718Skan	  if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
4448132718Skan	    scan_record_type (TREE_TYPE (field), intregs_p, fpregs_p, 0);
4449169689Skan	  else if ((FLOAT_TYPE_P (TREE_TYPE (field))
4450169689Skan		   || TREE_CODE (TREE_TYPE (field)) == VECTOR_TYPE)
4451169689Skan		  && TARGET_FPU)
4452132718Skan	    *fpregs_p = 1;
4453132718Skan	  else
4454132718Skan	    *intregs_p = 1;
4455132718Skan
4456132718Skan	  if (packed_p && DECL_PACKED (field))
4457132718Skan	    *packed_p = 1;
4458132718Skan	}
4459132718Skan    }
4460132718Skan}
4461132718Skan
446250397Sobrien/* Compute the slot number to pass an argument in.
4463132718Skan   Return the slot number or -1 if passing on the stack.
446450397Sobrien
446550397Sobrien   CUM is a variable of type CUMULATIVE_ARGS which gives info about
446650397Sobrien    the preceding args and about the function being called.
446750397Sobrien   MODE is the argument's machine mode.
446850397Sobrien   TYPE is the data type of the argument (as a tree).
446950397Sobrien    This is null for libcalls where that information may
447050397Sobrien    not be available.
447150397Sobrien   NAMED is nonzero if this argument is a named parameter
447250397Sobrien    (otherwise it is an extra parameter matching an ellipsis).
447350397Sobrien   INCOMING_P is zero for FUNCTION_ARG, nonzero for FUNCTION_INCOMING_ARG.
447450397Sobrien   *PREGNO records the register number to use if scalar type.
447550397Sobrien   *PPADDING records the amount of padding needed in words.  */
447650397Sobrien
447750397Sobrienstatic int
4478132718Skanfunction_arg_slotno (const struct sparc_args *cum, enum machine_mode mode,
4479132718Skan		     tree type, int named, int incoming_p,
4480132718Skan		     int *pregno, int *ppadding)
448150397Sobrien{
448250397Sobrien  int regbase = (incoming_p
448350397Sobrien		 ? SPARC_INCOMING_INT_ARG_FIRST
448450397Sobrien		 : SPARC_OUTGOING_INT_ARG_FIRST);
448550397Sobrien  int slotno = cum->words;
4486169689Skan  enum mode_class mclass;
448750397Sobrien  int regno;
448850397Sobrien
448950397Sobrien  *ppadding = 0;
449050397Sobrien
4491169689Skan  if (type && TREE_ADDRESSABLE (type))
449250397Sobrien    return -1;
4493169689Skan
449450397Sobrien  if (TARGET_ARCH32
4495169689Skan      && mode == BLKmode
4496169689Skan      && type
449750397Sobrien      && TYPE_ALIGN (type) % PARM_BOUNDARY != 0)
449850397Sobrien    return -1;
449950397Sobrien
4500169689Skan  /* For SPARC64, objects requiring 16-byte alignment get it.  */
4501169689Skan  if (TARGET_ARCH64
4502169689Skan      && (type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode)) >= 128
4503169689Skan      && (slotno & 1) != 0)
4504169689Skan    slotno++, *ppadding = 1;
4505169689Skan
4506169689Skan  mclass = GET_MODE_CLASS (mode);
4507169689Skan  if (type && TREE_CODE (type) == VECTOR_TYPE)
450850397Sobrien    {
4509169689Skan      /* Vector types deserve special treatment because they are
4510169689Skan	 polymorphic wrt their mode, depending upon whether VIS
4511169689Skan	 instructions are enabled.  */
4512169689Skan      if (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE)
4513169689Skan	{
4514169689Skan	  /* The SPARC port defines no floating-point vector modes.  */
4515169689Skan	  gcc_assert (mode == BLKmode);
4516169689Skan	}
4517169689Skan      else
4518169689Skan	{
4519169689Skan	  /* Integral vector types should either have a vector
4520169689Skan	     mode or an integral mode, because we are guaranteed
4521169689Skan	     by pass_by_reference that their size is not greater
4522169689Skan	     than 16 bytes and TImode is 16-byte wide.  */
4523169689Skan	  gcc_assert (mode != BLKmode);
452450397Sobrien
4525169689Skan	  /* Vector integers are handled like floats according to
4526169689Skan	     the Sun VIS SDK.  */
4527169689Skan	  mclass = MODE_FLOAT;
4528169689Skan	}
4529169689Skan    }
4530169689Skan
4531169689Skan  switch (mclass)
4532169689Skan    {
4533169689Skan    case MODE_FLOAT:
4534169689Skan    case MODE_COMPLEX_FLOAT:
4535169689Skan      if (TARGET_ARCH64 && TARGET_FPU && named)
4536169689Skan	{
4537169689Skan	  if (slotno >= SPARC_FP_ARG_MAX)
4538169689Skan	    return -1;
4539169689Skan	  regno = SPARC_FP_ARG_FIRST + slotno * 2;
4540169689Skan	  /* Arguments filling only one single FP register are
4541169689Skan	     right-justified in the outer double FP register.  */
4542169689Skan	  if (GET_MODE_SIZE (mode) <= 4)
4543169689Skan	    regno++;
4544169689Skan	  break;
4545169689Skan	}
4546132718Skan      /* fallthrough */
4547132718Skan
4548169689Skan    case MODE_INT:
4549169689Skan    case MODE_COMPLEX_INT:
455050397Sobrien      if (slotno >= SPARC_INT_ARG_MAX)
455150397Sobrien	return -1;
455250397Sobrien      regno = regbase + slotno;
455350397Sobrien      break;
455450397Sobrien
4555169689Skan    case MODE_RANDOM:
4556169689Skan      if (mode == VOIDmode)
4557169689Skan	/* MODE is VOIDmode when generating the actual call.  */
4558169689Skan	return -1;
4559132718Skan
4560169689Skan      gcc_assert (mode == BLKmode);
456150397Sobrien
456250397Sobrien      if (TARGET_ARCH32
4563169689Skan	  || !type
4564169689Skan	  || (TREE_CODE (type) != VECTOR_TYPE
4565169689Skan	      && TREE_CODE (type) != RECORD_TYPE))
456650397Sobrien	{
456750397Sobrien	  if (slotno >= SPARC_INT_ARG_MAX)
456850397Sobrien	    return -1;
456950397Sobrien	  regno = regbase + slotno;
457050397Sobrien	}
4571169689Skan      else  /* TARGET_ARCH64 && type */
457250397Sobrien	{
4573132718Skan	  int intregs_p = 0, fpregs_p = 0, packed_p = 0;
457450397Sobrien
4575132718Skan	  /* First see what kinds of registers we would need.  */
4576169689Skan	  if (TREE_CODE (type) == VECTOR_TYPE)
4577169689Skan	    fpregs_p = 1;
4578169689Skan	  else
4579169689Skan	    scan_record_type (type, &intregs_p, &fpregs_p, &packed_p);
4580132718Skan
4581132718Skan	  /* The ABI obviously doesn't specify how packed structures
4582132718Skan	     are passed.  These are defined to be passed in int regs
4583132718Skan	     if possible, otherwise memory.  */
458450397Sobrien	  if (packed_p || !named)
458550397Sobrien	    fpregs_p = 0, intregs_p = 1;
458650397Sobrien
458750397Sobrien	  /* If all arg slots are filled, then must pass on stack.  */
458850397Sobrien	  if (fpregs_p && slotno >= SPARC_FP_ARG_MAX)
458950397Sobrien	    return -1;
4590169689Skan
459150397Sobrien	  /* If there are only int args and all int arg slots are filled,
459250397Sobrien	     then must pass on stack.  */
459350397Sobrien	  if (!fpregs_p && intregs_p && slotno >= SPARC_INT_ARG_MAX)
459450397Sobrien	    return -1;
4595169689Skan
459650397Sobrien	  /* Note that even if all int arg slots are filled, fp members may
459750397Sobrien	     still be passed in regs if such regs are available.
459850397Sobrien	     *PREGNO isn't set because there may be more than one, it's up
459950397Sobrien	     to the caller to compute them.  */
460050397Sobrien	  return slotno;
460150397Sobrien	}
460250397Sobrien      break;
460350397Sobrien
460450397Sobrien    default :
4605169689Skan      gcc_unreachable ();
460650397Sobrien    }
460750397Sobrien
460850397Sobrien  *pregno = regno;
460950397Sobrien  return slotno;
461050397Sobrien}
461150397Sobrien
461250397Sobrien/* Handle recursive register counting for structure field layout.  */
461350397Sobrien
461450397Sobrienstruct function_arg_record_value_parms
461550397Sobrien{
4616117395Skan  rtx ret;		/* return expression being built.  */
4617117395Skan  int slotno;		/* slot number of the argument.  */
4618117395Skan  int named;		/* whether the argument is named.  */
4619117395Skan  int regbase;		/* regno of the base register.  */
4620117395Skan  int stack;		/* 1 if part of the argument is on the stack.  */
4621132718Skan  int intoffset;	/* offset of the first pending integer field.  */
4622117395Skan  unsigned int nregs;	/* number of words passed in registers.  */
462350397Sobrien};
462450397Sobrien
462552284Sobrienstatic void function_arg_record_value_3
4626132718Skan (HOST_WIDE_INT, struct function_arg_record_value_parms *);
462752284Sobrienstatic void function_arg_record_value_2
4628132718Skan (tree, HOST_WIDE_INT, struct function_arg_record_value_parms *, bool);
462990075Sobrienstatic void function_arg_record_value_1
4630132718Skan (tree, HOST_WIDE_INT, struct function_arg_record_value_parms *, bool);
4631132718Skanstatic rtx function_arg_record_value (tree, enum machine_mode, int, int, int);
4632146895Skanstatic rtx function_arg_union_value (int, enum machine_mode, int, int);
463352284Sobrien
463490075Sobrien/* A subroutine of function_arg_record_value.  Traverse the structure
4635132718Skan   recursively and determine how many registers will be required.  */
463690075Sobrien
463750397Sobrienstatic void
4638132718Skanfunction_arg_record_value_1 (tree type, HOST_WIDE_INT startbitpos,
4639132718Skan			     struct function_arg_record_value_parms *parms,
4640132718Skan			     bool packed_p)
464150397Sobrien{
464250397Sobrien  tree field;
464350397Sobrien
464450397Sobrien  /* We need to compute how many registers are needed so we can
464550397Sobrien     allocate the PARALLEL but before we can do that we need to know
4646132718Skan     whether there are any packed fields.  The ABI obviously doesn't
4647132718Skan     specify how structures are passed in this case, so they are
4648132718Skan     defined to be passed in int regs if possible, otherwise memory,
4649132718Skan     regardless of whether there are fp values present.  */
465050397Sobrien
4651132718Skan  if (! packed_p)
4652132718Skan    for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
4653132718Skan      {
4654132718Skan	if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field))
4655132718Skan	  {
4656132718Skan	    packed_p = true;
4657132718Skan	    break;
4658132718Skan	  }
4659132718Skan      }
4660132718Skan
466150397Sobrien  /* Compute how many registers we need.  */
466250397Sobrien  for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
466350397Sobrien    {
466450397Sobrien      if (TREE_CODE (field) == FIELD_DECL)
466550397Sobrien	{
466690075Sobrien	  HOST_WIDE_INT bitpos = startbitpos;
466790075Sobrien
4668169689Skan	  if (DECL_SIZE (field) != 0)
4669169689Skan	    {
4670169689Skan	      if (integer_zerop (DECL_SIZE (field)))
4671169689Skan		continue;
467290075Sobrien
4673169689Skan	      if (host_integerp (bit_position (field), 1))
4674169689Skan		bitpos += int_bit_position (field);
4675169689Skan	    }
4676169689Skan
467750397Sobrien	  /* ??? FIXME: else assume zero offset.  */
467850397Sobrien
467950397Sobrien	  if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
4680132718Skan	    function_arg_record_value_1 (TREE_TYPE (field),
4681132718Skan	    				 bitpos,
4682132718Skan					 parms,
4683132718Skan					 packed_p);
4684169689Skan	  else if ((FLOAT_TYPE_P (TREE_TYPE (field))
4685169689Skan		    || TREE_CODE (TREE_TYPE (field)) == VECTOR_TYPE)
4686132718Skan		   && TARGET_FPU
4687132718Skan		   && parms->named
4688132718Skan		   && ! packed_p)
468950397Sobrien	    {
469050397Sobrien	      if (parms->intoffset != -1)
469150397Sobrien		{
4692132718Skan		  unsigned int startbit, endbit;
469350397Sobrien		  int intslots, this_slotno;
469450397Sobrien
4695132718Skan		  startbit = parms->intoffset & -BITS_PER_WORD;
4696132718Skan		  endbit   = (bitpos + BITS_PER_WORD - 1) & -BITS_PER_WORD;
4697132718Skan
4698132718Skan		  intslots = (endbit - startbit) / BITS_PER_WORD;
469950397Sobrien		  this_slotno = parms->slotno + parms->intoffset
470050397Sobrien		    / BITS_PER_WORD;
470150397Sobrien
4702117395Skan		  if (intslots > 0 && intslots > SPARC_INT_ARG_MAX - this_slotno)
4703117395Skan		    {
4704117395Skan		      intslots = MAX (0, SPARC_INT_ARG_MAX - this_slotno);
4705117395Skan		      /* We need to pass this field on the stack.  */
4706117395Skan		      parms->stack = 1;
4707117395Skan		    }
4708117395Skan
470950397Sobrien		  parms->nregs += intslots;
471050397Sobrien		  parms->intoffset = -1;
471150397Sobrien		}
471250397Sobrien
471350397Sobrien	      /* There's no need to check this_slotno < SPARC_FP_ARG MAX.
471450397Sobrien		 If it wasn't true we wouldn't be here.  */
4715169689Skan	      if (TREE_CODE (TREE_TYPE (field)) == VECTOR_TYPE
4716169689Skan		  && DECL_MODE (field) == BLKmode)
4717169689Skan		parms->nregs += TYPE_VECTOR_SUBPARTS (TREE_TYPE (field));
4718169689Skan	      else if (TREE_CODE (TREE_TYPE (field)) == COMPLEX_TYPE)
4719169689Skan		parms->nregs += 2;
4720169689Skan	      else
472196263Sobrien		parms->nregs += 1;
472250397Sobrien	    }
472350397Sobrien	  else
472450397Sobrien	    {
472550397Sobrien	      if (parms->intoffset == -1)
472650397Sobrien		parms->intoffset = bitpos;
472750397Sobrien	    }
472850397Sobrien	}
472950397Sobrien    }
473050397Sobrien}
473150397Sobrien
473290075Sobrien/* A subroutine of function_arg_record_value.  Assign the bits of the
473390075Sobrien   structure between parms->intoffset and bitpos to integer registers.  */
473450397Sobrien
473550397Sobrienstatic void
4736132718Skanfunction_arg_record_value_3 (HOST_WIDE_INT bitpos,
4737132718Skan			     struct function_arg_record_value_parms *parms)
473850397Sobrien{
473950397Sobrien  enum machine_mode mode;
474090075Sobrien  unsigned int regno;
474190075Sobrien  unsigned int startbit, endbit;
474290075Sobrien  int this_slotno, intslots, intoffset;
474350397Sobrien  rtx reg;
474450397Sobrien
474550397Sobrien  if (parms->intoffset == -1)
474650397Sobrien    return;
474790075Sobrien
474850397Sobrien  intoffset = parms->intoffset;
474950397Sobrien  parms->intoffset = -1;
475050397Sobrien
475190075Sobrien  startbit = intoffset & -BITS_PER_WORD;
475290075Sobrien  endbit = (bitpos + BITS_PER_WORD - 1) & -BITS_PER_WORD;
475390075Sobrien  intslots = (endbit - startbit) / BITS_PER_WORD;
475450397Sobrien  this_slotno = parms->slotno + intoffset / BITS_PER_WORD;
475550397Sobrien
475650397Sobrien  intslots = MIN (intslots, SPARC_INT_ARG_MAX - this_slotno);
475750397Sobrien  if (intslots <= 0)
475850397Sobrien    return;
475950397Sobrien
476050397Sobrien  /* If this is the trailing part of a word, only load that much into
476150397Sobrien     the register.  Otherwise load the whole register.  Note that in
476250397Sobrien     the latter case we may pick up unwanted bits.  It's not a problem
476350397Sobrien     at the moment but may wish to revisit.  */
476450397Sobrien
476550397Sobrien  if (intoffset % BITS_PER_WORD != 0)
4766169689Skan    mode = smallest_mode_for_size (BITS_PER_WORD - intoffset % BITS_PER_WORD,
4767169689Skan			  	   MODE_INT);
476850397Sobrien  else
476950397Sobrien    mode = word_mode;
477050397Sobrien
477150397Sobrien  intoffset /= BITS_PER_UNIT;
477250397Sobrien  do
477350397Sobrien    {
477450397Sobrien      regno = parms->regbase + this_slotno;
477550397Sobrien      reg = gen_rtx_REG (mode, regno);
4776117395Skan      XVECEXP (parms->ret, 0, parms->stack + parms->nregs)
477750397Sobrien	= gen_rtx_EXPR_LIST (VOIDmode, reg, GEN_INT (intoffset));
477850397Sobrien
477950397Sobrien      this_slotno += 1;
478050397Sobrien      intoffset = (intoffset | (UNITS_PER_WORD-1)) + 1;
4781132718Skan      mode = word_mode;
478250397Sobrien      parms->nregs += 1;
478350397Sobrien      intslots -= 1;
478450397Sobrien    }
478550397Sobrien  while (intslots > 0);
478650397Sobrien}
478750397Sobrien
478890075Sobrien/* A subroutine of function_arg_record_value.  Traverse the structure
478990075Sobrien   recursively and assign bits to floating point registers.  Track which
479090075Sobrien   bits in between need integer registers; invoke function_arg_record_value_3
479190075Sobrien   to make that happen.  */
479290075Sobrien
479350397Sobrienstatic void
4794132718Skanfunction_arg_record_value_2 (tree type, HOST_WIDE_INT startbitpos,
4795132718Skan			     struct function_arg_record_value_parms *parms,
4796132718Skan			     bool packed_p)
479750397Sobrien{
479850397Sobrien  tree field;
479950397Sobrien
4800132718Skan  if (! packed_p)
4801132718Skan    for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
4802132718Skan      {
4803132718Skan	if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field))
4804132718Skan	  {
4805132718Skan	    packed_p = true;
4806132718Skan	    break;
4807132718Skan	  }
4808132718Skan      }
480950397Sobrien
481050397Sobrien  for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
481150397Sobrien    {
481250397Sobrien      if (TREE_CODE (field) == FIELD_DECL)
481350397Sobrien	{
481490075Sobrien	  HOST_WIDE_INT bitpos = startbitpos;
481590075Sobrien
4816169689Skan	  if (DECL_SIZE (field) != 0)
4817169689Skan	    {
4818169689Skan	      if (integer_zerop (DECL_SIZE (field)))
4819169689Skan		continue;
482090075Sobrien
4821169689Skan	      if (host_integerp (bit_position (field), 1))
4822169689Skan		bitpos += int_bit_position (field);
4823169689Skan	    }
4824169689Skan
482550397Sobrien	  /* ??? FIXME: else assume zero offset.  */
482650397Sobrien
482750397Sobrien	  if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
4828132718Skan	    function_arg_record_value_2 (TREE_TYPE (field),
4829132718Skan	    				 bitpos,
4830132718Skan					 parms,
4831132718Skan					 packed_p);
4832169689Skan	  else if ((FLOAT_TYPE_P (TREE_TYPE (field))
4833169689Skan		    || TREE_CODE (TREE_TYPE (field)) == VECTOR_TYPE)
4834132718Skan		   && TARGET_FPU
4835132718Skan		   && parms->named
4836132718Skan		   && ! packed_p)
483750397Sobrien	    {
483850397Sobrien	      int this_slotno = parms->slotno + bitpos / BITS_PER_WORD;
4839169689Skan	      int regno, nregs, pos;
484096263Sobrien	      enum machine_mode mode = DECL_MODE (field);
484150397Sobrien	      rtx reg;
484250397Sobrien
484350397Sobrien	      function_arg_record_value_3 (bitpos, parms);
4844169689Skan
4845169689Skan	      if (TREE_CODE (TREE_TYPE (field)) == VECTOR_TYPE
4846169689Skan		  && mode == BLKmode)
4847169689Skan	        {
4848169689Skan		  mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (field)));
4849169689Skan		  nregs = TYPE_VECTOR_SUBPARTS (TREE_TYPE (field));
485096263Sobrien		}
4851169689Skan	      else if (TREE_CODE (TREE_TYPE (field)) == COMPLEX_TYPE)
4852169689Skan	        {
4853169689Skan		  mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (field)));
4854169689Skan		  nregs = 2;
4855169689Skan		}
4856169689Skan	      else
4857169689Skan	        nregs = 1;
4858169689Skan
4859169689Skan	      regno = SPARC_FP_ARG_FIRST + this_slotno * 2;
4860169689Skan	      if (GET_MODE_SIZE (mode) <= 4 && (bitpos & 32) != 0)
4861169689Skan		regno++;
486296263Sobrien	      reg = gen_rtx_REG (mode, regno);
4863169689Skan	      pos = bitpos / BITS_PER_UNIT;
4864117395Skan	      XVECEXP (parms->ret, 0, parms->stack + parms->nregs)
4865169689Skan		= gen_rtx_EXPR_LIST (VOIDmode, reg, GEN_INT (pos));
486650397Sobrien	      parms->nregs += 1;
4867169689Skan	      while (--nregs > 0)
486896263Sobrien		{
486996263Sobrien		  regno += GET_MODE_SIZE (mode) / 4;
487096263Sobrien	  	  reg = gen_rtx_REG (mode, regno);
4871169689Skan		  pos += GET_MODE_SIZE (mode);
4872117395Skan		  XVECEXP (parms->ret, 0, parms->stack + parms->nregs)
4873169689Skan		    = gen_rtx_EXPR_LIST (VOIDmode, reg, GEN_INT (pos));
487496263Sobrien		  parms->nregs += 1;
487596263Sobrien		}
487650397Sobrien	    }
487750397Sobrien	  else
487850397Sobrien	    {
487950397Sobrien	      if (parms->intoffset == -1)
488050397Sobrien		parms->intoffset = bitpos;
488150397Sobrien	    }
488250397Sobrien	}
488350397Sobrien    }
488450397Sobrien}
488550397Sobrien
488690075Sobrien/* Used by function_arg and function_value to implement the complex
4887117395Skan   conventions of the 64-bit ABI for passing and returning structures.
4888117395Skan   Return an expression valid as a return value for the two macros
4889117395Skan   FUNCTION_ARG and FUNCTION_VALUE.
489090075Sobrien
4891117395Skan   TYPE is the data type of the argument (as a tree).
4892117395Skan    This is null for libcalls where that information may
4893117395Skan    not be available.
4894117395Skan   MODE is the argument's machine mode.
4895117395Skan   SLOTNO is the index number of the argument's slot in the parameter array.
4896117395Skan   NAMED is nonzero if this argument is a named parameter
4897117395Skan    (otherwise it is an extra parameter matching an ellipsis).
4898117395Skan   REGBASE is the regno of the base register for the parameter array.  */
4899117395Skan
490050397Sobrienstatic rtx
4901132718Skanfunction_arg_record_value (tree type, enum machine_mode mode,
4902132718Skan			   int slotno, int named, int regbase)
490350397Sobrien{
490450397Sobrien  HOST_WIDE_INT typesize = int_size_in_bytes (type);
490550397Sobrien  struct function_arg_record_value_parms parms;
490690075Sobrien  unsigned int nregs;
490750397Sobrien
490850397Sobrien  parms.ret = NULL_RTX;
490950397Sobrien  parms.slotno = slotno;
491050397Sobrien  parms.named = named;
491150397Sobrien  parms.regbase = regbase;
4912117395Skan  parms.stack = 0;
491350397Sobrien
491450397Sobrien  /* Compute how many registers we need.  */
491550397Sobrien  parms.nregs = 0;
491650397Sobrien  parms.intoffset = 0;
4917132718Skan  function_arg_record_value_1 (type, 0, &parms, false);
491850397Sobrien
4919132718Skan  /* Take into account pending integer fields.  */
492050397Sobrien  if (parms.intoffset != -1)
492150397Sobrien    {
492290075Sobrien      unsigned int startbit, endbit;
492350397Sobrien      int intslots, this_slotno;
492450397Sobrien
492590075Sobrien      startbit = parms.intoffset & -BITS_PER_WORD;
492690075Sobrien      endbit = (typesize*BITS_PER_UNIT + BITS_PER_WORD - 1) & -BITS_PER_WORD;
492790075Sobrien      intslots = (endbit - startbit) / BITS_PER_WORD;
492850397Sobrien      this_slotno = slotno + parms.intoffset / BITS_PER_WORD;
492950397Sobrien
4930117395Skan      if (intslots > 0 && intslots > SPARC_INT_ARG_MAX - this_slotno)
4931117395Skan        {
4932117395Skan	  intslots = MAX (0, SPARC_INT_ARG_MAX - this_slotno);
4933117395Skan	  /* We need to pass this field on the stack.  */
4934117395Skan	  parms.stack = 1;
4935117395Skan        }
493650397Sobrien
493750397Sobrien      parms.nregs += intslots;
493850397Sobrien    }
493950397Sobrien  nregs = parms.nregs;
494050397Sobrien
494150397Sobrien  /* Allocate the vector and handle some annoying special cases.  */
494250397Sobrien  if (nregs == 0)
494350397Sobrien    {
494450397Sobrien      /* ??? Empty structure has no value?  Duh?  */
494550397Sobrien      if (typesize <= 0)
494650397Sobrien	{
494750397Sobrien	  /* Though there's nothing really to store, return a word register
494850397Sobrien	     anyway so the rest of gcc doesn't go nuts.  Returning a PARALLEL
494950397Sobrien	     leads to breakage due to the fact that there are zero bytes to
495050397Sobrien	     load.  */
495150397Sobrien	  return gen_rtx_REG (mode, regbase);
495250397Sobrien	}
495350397Sobrien      else
495450397Sobrien	{
495550397Sobrien	  /* ??? C++ has structures with no fields, and yet a size.  Give up
495650397Sobrien	     for now and pass everything back in integer registers.  */
495750397Sobrien	  nregs = (typesize + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
495850397Sobrien	}
495950397Sobrien      if (nregs + slotno > SPARC_INT_ARG_MAX)
496050397Sobrien	nregs = SPARC_INT_ARG_MAX - slotno;
496150397Sobrien    }
4962169689Skan  gcc_assert (nregs != 0);
496350397Sobrien
4964117395Skan  parms.ret = gen_rtx_PARALLEL (mode, rtvec_alloc (parms.stack + nregs));
496550397Sobrien
4966117395Skan  /* If at least one field must be passed on the stack, generate
4967117395Skan     (parallel [(expr_list (nil) ...) ...]) so that all fields will
4968117395Skan     also be passed on the stack.  We can't do much better because the
4969169689Skan     semantics of TARGET_ARG_PARTIAL_BYTES doesn't handle the case
4970117395Skan     of structures for which the fields passed exclusively in registers
4971117395Skan     are not at the beginning of the structure.  */
4972117395Skan  if (parms.stack)
4973117395Skan    XVECEXP (parms.ret, 0, 0)
4974117395Skan      = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx);
4975117395Skan
497650397Sobrien  /* Fill in the entries.  */
497750397Sobrien  parms.nregs = 0;
497850397Sobrien  parms.intoffset = 0;
4979132718Skan  function_arg_record_value_2 (type, 0, &parms, false);
498050397Sobrien  function_arg_record_value_3 (typesize * BITS_PER_UNIT, &parms);
498150397Sobrien
4982169689Skan  gcc_assert (parms.nregs == nregs);
498350397Sobrien
498450397Sobrien  return parms.ret;
498550397Sobrien}
498650397Sobrien
4987132718Skan/* Used by function_arg and function_value to implement the conventions
4988132718Skan   of the 64-bit ABI for passing and returning unions.
4989132718Skan   Return an expression valid as a return value for the two macros
4990132718Skan   FUNCTION_ARG and FUNCTION_VALUE.
4991132718Skan
4992132718Skan   SIZE is the size in bytes of the union.
4993132718Skan   MODE is the argument's machine mode.
4994132718Skan   REGNO is the hard register the union will be passed in.  */
4995132718Skan
4996132718Skanstatic rtx
4997146895Skanfunction_arg_union_value (int size, enum machine_mode mode, int slotno,
4998146895Skan			  int regno)
4999132718Skan{
5000132718Skan  int nwords = ROUND_ADVANCE (size), i;
5001132718Skan  rtx regs;
5002132718Skan
5003146895Skan  /* See comment in previous function for empty structures.  */
5004146895Skan  if (nwords == 0)
5005146895Skan    return gen_rtx_REG (mode, regno);
5006146895Skan
5007146895Skan  if (slotno == SPARC_INT_ARG_MAX - 1)
5008146895Skan    nwords = 1;
5009146895Skan
5010132718Skan  regs = gen_rtx_PARALLEL (mode, rtvec_alloc (nwords));
5011132718Skan
5012132718Skan  for (i = 0; i < nwords; i++)
5013169689Skan    {
5014169689Skan      /* Unions are passed left-justified.  */
5015169689Skan      XVECEXP (regs, 0, i)
5016169689Skan	= gen_rtx_EXPR_LIST (VOIDmode,
5017169689Skan			     gen_rtx_REG (word_mode, regno),
5018169689Skan			     GEN_INT (UNITS_PER_WORD * i));
5019169689Skan      regno++;
5020169689Skan    }
5021132718Skan
5022132718Skan  return regs;
5023132718Skan}
5024132718Skan
5025169689Skan/* Used by function_arg and function_value to implement the conventions
5026169689Skan   for passing and returning large (BLKmode) vectors.
5027169689Skan   Return an expression valid as a return value for the two macros
5028169689Skan   FUNCTION_ARG and FUNCTION_VALUE.
5029169689Skan
5030169689Skan   SIZE is the size in bytes of the vector.
5031169689Skan   BASE_MODE is the argument's base machine mode.
5032169689Skan   REGNO is the FP hard register the vector will be passed in.  */
5033169689Skan
5034169689Skanstatic rtx
5035169689Skanfunction_arg_vector_value (int size, enum machine_mode base_mode, int regno)
5036169689Skan{
5037169689Skan  unsigned short base_mode_size = GET_MODE_SIZE (base_mode);
5038169689Skan  int nregs = size / base_mode_size, i;
5039169689Skan  rtx regs;
5040169689Skan
5041169689Skan  regs = gen_rtx_PARALLEL (BLKmode, rtvec_alloc (nregs));
5042169689Skan
5043169689Skan  for (i = 0; i < nregs; i++)
5044169689Skan    {
5045169689Skan      XVECEXP (regs, 0, i)
5046169689Skan	= gen_rtx_EXPR_LIST (VOIDmode,
5047169689Skan			     gen_rtx_REG (base_mode, regno),
5048169689Skan			     GEN_INT (base_mode_size * i));
5049169689Skan      regno += base_mode_size / 4;
5050169689Skan    }
5051169689Skan
5052169689Skan  return regs;
5053169689Skan}
5054169689Skan
505550397Sobrien/* Handle the FUNCTION_ARG macro.
505650397Sobrien   Determine where to put an argument to a function.
505750397Sobrien   Value is zero to push the argument on the stack,
505850397Sobrien   or a hard register in which to store the argument.
505950397Sobrien
506050397Sobrien   CUM is a variable of type CUMULATIVE_ARGS which gives info about
506150397Sobrien    the preceding args and about the function being called.
506250397Sobrien   MODE is the argument's machine mode.
506350397Sobrien   TYPE is the data type of the argument (as a tree).
506450397Sobrien    This is null for libcalls where that information may
506550397Sobrien    not be available.
506650397Sobrien   NAMED is nonzero if this argument is a named parameter
506750397Sobrien    (otherwise it is an extra parameter matching an ellipsis).
506850397Sobrien   INCOMING_P is zero for FUNCTION_ARG, nonzero for FUNCTION_INCOMING_ARG.  */
506950397Sobrien
507050397Sobrienrtx
5071132718Skanfunction_arg (const struct sparc_args *cum, enum machine_mode mode,
5072132718Skan	      tree type, int named, int incoming_p)
507350397Sobrien{
507450397Sobrien  int regbase = (incoming_p
507550397Sobrien		 ? SPARC_INCOMING_INT_ARG_FIRST
507650397Sobrien		 : SPARC_OUTGOING_INT_ARG_FIRST);
507750397Sobrien  int slotno, regno, padding;
5078169689Skan  enum mode_class mclass = GET_MODE_CLASS (mode);
507950397Sobrien
508050397Sobrien  slotno = function_arg_slotno (cum, mode, type, named, incoming_p,
508150397Sobrien				&regno, &padding);
508250397Sobrien  if (slotno == -1)
508350397Sobrien    return 0;
508450397Sobrien
5085169689Skan  /* Vector types deserve special treatment because they are polymorphic wrt
5086169689Skan     their mode, depending upon whether VIS instructions are enabled.  */
5087169689Skan  if (type && TREE_CODE (type) == VECTOR_TYPE)
508850397Sobrien    {
5089169689Skan      HOST_WIDE_INT size = int_size_in_bytes (type);
5090169689Skan      gcc_assert ((TARGET_ARCH32 && size <= 8)
5091169689Skan		  || (TARGET_ARCH64 && size <= 16));
5092169689Skan
5093169689Skan      if (mode == BLKmode)
5094169689Skan	return function_arg_vector_value (size,
5095169689Skan					  TYPE_MODE (TREE_TYPE (type)),
5096169689Skan					  SPARC_FP_ARG_FIRST + 2*slotno);
5097169689Skan      else
5098169689Skan	mclass = MODE_FLOAT;
509950397Sobrien    }
5100169689Skan
5101169689Skan  if (TARGET_ARCH32)
5102169689Skan    return gen_rtx_REG (mode, regno);
5103169689Skan
5104169689Skan  /* Structures up to 16 bytes in size are passed in arg slots on the stack
5105169689Skan     and are promoted to registers if possible.  */
5106132718Skan  if (type && TREE_CODE (type) == RECORD_TYPE)
5107132718Skan    {
5108169689Skan      HOST_WIDE_INT size = int_size_in_bytes (type);
5109169689Skan      gcc_assert (size <= 16);
511050397Sobrien
5111132718Skan      return function_arg_record_value (type, mode, slotno, named, regbase);
5112132718Skan    }
5113169689Skan
5114169689Skan  /* Unions up to 16 bytes in size are passed in integer registers.  */
5115132718Skan  else if (type && TREE_CODE (type) == UNION_TYPE)
5116132718Skan    {
5117132718Skan      HOST_WIDE_INT size = int_size_in_bytes (type);
5118169689Skan      gcc_assert (size <= 16);
5119132718Skan
5120146895Skan      return function_arg_union_value (size, mode, slotno, regno);
5121132718Skan    }
5122169689Skan
512350397Sobrien  /* v9 fp args in reg slots beyond the int reg slots get passed in regs
512450397Sobrien     but also have the slot allocated for them.
512550397Sobrien     If no prototype is in scope fp values in register slots get passed
512650397Sobrien     in two places, either fp regs and int regs or fp regs and memory.  */
5127169689Skan  else if ((mclass == MODE_FLOAT || mclass == MODE_COMPLEX_FLOAT)
5128169689Skan	   && SPARC_FP_REG_P (regno))
512950397Sobrien    {
5130169689Skan      rtx reg = gen_rtx_REG (mode, regno);
513150397Sobrien      if (cum->prototype_p || cum->libcall_p)
513250397Sobrien	{
513350397Sobrien	  /* "* 2" because fp reg numbers are recorded in 4 byte
513450397Sobrien	     quantities.  */
513550397Sobrien#if 0
513650397Sobrien	  /* ??? This will cause the value to be passed in the fp reg and
513750397Sobrien	     in the stack.  When a prototype exists we want to pass the
513850397Sobrien	     value in the reg but reserve space on the stack.  That's an
513950397Sobrien	     optimization, and is deferred [for a bit].  */
514050397Sobrien	  if ((regno - SPARC_FP_ARG_FIRST) >= SPARC_INT_ARG_MAX * 2)
514150397Sobrien	    return gen_rtx_PARALLEL (mode,
514250397Sobrien			    gen_rtvec (2,
514350397Sobrien				       gen_rtx_EXPR_LIST (VOIDmode,
514450397Sobrien						NULL_RTX, const0_rtx),
514550397Sobrien				       gen_rtx_EXPR_LIST (VOIDmode,
514650397Sobrien						reg, const0_rtx)));
514750397Sobrien	  else
514850397Sobrien#else
514950397Sobrien	  /* ??? It seems that passing back a register even when past
515050397Sobrien	     the area declared by REG_PARM_STACK_SPACE will allocate
515150397Sobrien	     space appropriately, and will not copy the data onto the
515250397Sobrien	     stack, exactly as we desire.
515350397Sobrien
515450397Sobrien	     This is due to locate_and_pad_parm being called in
515550397Sobrien	     expand_call whenever reg_parm_stack_space > 0, which
5156132718Skan	     while beneficial to our example here, would seem to be
515750397Sobrien	     in error from what had been intended.  Ho hum...  -- r~ */
515850397Sobrien#endif
515950397Sobrien	    return reg;
516050397Sobrien	}
516150397Sobrien      else
516250397Sobrien	{
516350397Sobrien	  rtx v0, v1;
516450397Sobrien
516550397Sobrien	  if ((regno - SPARC_FP_ARG_FIRST) < SPARC_INT_ARG_MAX * 2)
516650397Sobrien	    {
516750397Sobrien	      int intreg;
516850397Sobrien
516950397Sobrien	      /* On incoming, we don't need to know that the value
517050397Sobrien		 is passed in %f0 and %i0, and it confuses other parts
517150397Sobrien		 causing needless spillage even on the simplest cases.  */
517250397Sobrien	      if (incoming_p)
517350397Sobrien		return reg;
517450397Sobrien
517550397Sobrien	      intreg = (SPARC_OUTGOING_INT_ARG_FIRST
517650397Sobrien			+ (regno - SPARC_FP_ARG_FIRST) / 2);
517750397Sobrien
517850397Sobrien	      v0 = gen_rtx_EXPR_LIST (VOIDmode, reg, const0_rtx);
517950397Sobrien	      v1 = gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_REG (mode, intreg),
518050397Sobrien				      const0_rtx);
518150397Sobrien	      return gen_rtx_PARALLEL (mode, gen_rtvec (2, v0, v1));
518250397Sobrien	    }
518350397Sobrien	  else
518450397Sobrien	    {
518550397Sobrien	      v0 = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx);
518650397Sobrien	      v1 = gen_rtx_EXPR_LIST (VOIDmode, reg, const0_rtx);
518750397Sobrien	      return gen_rtx_PARALLEL (mode, gen_rtvec (2, v0, v1));
518850397Sobrien	    }
518950397Sobrien	}
519050397Sobrien    }
5191169689Skan
5192169689Skan  /* All other aggregate types are passed in an integer register in a mode
5193169689Skan     corresponding to the size of the type.  */
5194169689Skan  else if (type && AGGREGATE_TYPE_P (type))
519550397Sobrien    {
5196169689Skan      HOST_WIDE_INT size = int_size_in_bytes (type);
5197169689Skan      gcc_assert (size <= 16);
5198169689Skan
5199169689Skan      mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
520050397Sobrien    }
520150397Sobrien
5202169689Skan  return gen_rtx_REG (mode, regno);
520350397Sobrien}
520450397Sobrien
5205169689Skan/* For an arg passed partly in registers and partly in memory,
5206169689Skan   this is the number of bytes of registers used.
520750397Sobrien   For args passed entirely in registers or entirely in memory, zero.
520850397Sobrien
520950397Sobrien   Any arg that starts in the first 6 regs but won't entirely fit in them
521050397Sobrien   needs partial registers on v8.  On v9, structures with integer
521150397Sobrien   values in arg slots 5,6 will be passed in %o5 and SP+176, and complex fp
521250397Sobrien   values that begin in the last fp reg [where "last fp reg" varies with the
521350397Sobrien   mode] will be split between that reg and memory.  */
521450397Sobrien
5215169689Skanstatic int
5216169689Skansparc_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
5217169689Skan			 tree type, bool named)
521850397Sobrien{
521950397Sobrien  int slotno, regno, padding;
522050397Sobrien
522150397Sobrien  /* We pass 0 for incoming_p here, it doesn't matter.  */
522250397Sobrien  slotno = function_arg_slotno (cum, mode, type, named, 0, &regno, &padding);
522350397Sobrien
522450397Sobrien  if (slotno == -1)
522550397Sobrien    return 0;
522650397Sobrien
522750397Sobrien  if (TARGET_ARCH32)
522850397Sobrien    {
522950397Sobrien      if ((slotno + (mode == BLKmode
523050397Sobrien		     ? ROUND_ADVANCE (int_size_in_bytes (type))
523150397Sobrien		     : ROUND_ADVANCE (GET_MODE_SIZE (mode))))
5232169689Skan	  > SPARC_INT_ARG_MAX)
5233169689Skan	return (SPARC_INT_ARG_MAX - slotno) * UNITS_PER_WORD;
523450397Sobrien    }
523550397Sobrien  else
523650397Sobrien    {
5237169689Skan      /* We are guaranteed by pass_by_reference that the size of the
5238169689Skan	 argument is not greater than 16 bytes, so we only need to return
5239169689Skan	 one word if the argument is partially passed in registers.  */
5240169689Skan
524150397Sobrien      if (type && AGGREGATE_TYPE_P (type))
524250397Sobrien	{
524350397Sobrien	  int size = int_size_in_bytes (type);
524450397Sobrien
5245169689Skan	  if (size > UNITS_PER_WORD
524650397Sobrien	      && slotno == SPARC_INT_ARG_MAX - 1)
5247169689Skan	    return UNITS_PER_WORD;
524850397Sobrien	}
524950397Sobrien      else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
525050397Sobrien	       || (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
5251132718Skan		   && ! (TARGET_FPU && named)))
525250397Sobrien	{
5253132718Skan	  /* The complex types are passed as packed types.  */
5254169689Skan	  if (GET_MODE_SIZE (mode) > UNITS_PER_WORD
5255169689Skan	      && slotno == SPARC_INT_ARG_MAX - 1)
5256169689Skan	    return UNITS_PER_WORD;
525750397Sobrien	}
525850397Sobrien      else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
525950397Sobrien	{
526050397Sobrien	  if ((slotno + GET_MODE_SIZE (mode) / UNITS_PER_WORD)
526150397Sobrien	      > SPARC_FP_ARG_MAX)
5262169689Skan	    return UNITS_PER_WORD;
526350397Sobrien	}
526450397Sobrien    }
5265169689Skan
5266169689Skan  return 0;
526750397Sobrien}
526850397Sobrien
5269169689Skan/* Handle the TARGET_PASS_BY_REFERENCE target hook.
5270169689Skan   Specify whether to pass the argument by reference.  */
527150397Sobrien
5272169689Skanstatic bool
5273169689Skansparc_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
5274169689Skan			 enum machine_mode mode, tree type,
5275169689Skan			 bool named ATTRIBUTE_UNUSED)
527650397Sobrien{
527750397Sobrien  if (TARGET_ARCH32)
5278169689Skan    /* Original SPARC 32-bit ABI says that structures and unions,
5279169689Skan       and quad-precision floats are passed by reference.  For Pascal,
5280169689Skan       also pass arrays by reference.  All other base types are passed
5281169689Skan       in registers.
5282169689Skan
5283169689Skan       Extended ABI (as implemented by the Sun compiler) says that all
5284169689Skan       complex floats are passed by reference.  Pass complex integers
5285169689Skan       in registers up to 8 bytes.  More generally, enforce the 2-word
5286169689Skan       cap for passing arguments in registers.
5287169689Skan
5288169689Skan       Vector ABI (as implemented by the Sun VIS SDK) says that vector
5289169689Skan       integers are passed like floats of the same size, that is in
5290169689Skan       registers up to 8 bytes.  Pass all vector floats by reference
5291169689Skan       like structure and unions.  */
5292169689Skan    return ((type && (AGGREGATE_TYPE_P (type) || VECTOR_FLOAT_TYPE_P (type)))
5293169689Skan	    || mode == SCmode
5294169689Skan	    /* Catch CDImode, TFmode, DCmode and TCmode.  */
5295169689Skan	    || GET_MODE_SIZE (mode) > 8
5296169689Skan	    || (type
5297169689Skan		&& TREE_CODE (type) == VECTOR_TYPE
5298169689Skan		&& (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 8));
529950397Sobrien  else
5300169689Skan    /* Original SPARC 64-bit ABI says that structures and unions
5301169689Skan       smaller than 16 bytes are passed in registers, as well as
5302169689Skan       all other base types.
5303169689Skan
5304169689Skan       Extended ABI (as implemented by the Sun compiler) says that
5305169689Skan       complex floats are passed in registers up to 16 bytes.  Pass
5306169689Skan       all complex integers in registers up to 16 bytes.  More generally,
5307169689Skan       enforce the 2-word cap for passing arguments in registers.
5308169689Skan
5309169689Skan       Vector ABI (as implemented by the Sun VIS SDK) says that vector
5310169689Skan       integers are passed like floats of the same size, that is in
5311169689Skan       registers (up to 16 bytes).  Pass all vector floats like structure
5312169689Skan       and unions.  */
5313169689Skan    return ((type
5314169689Skan	     && (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == VECTOR_TYPE)
5315169689Skan	     && (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 16)
5316169689Skan	    /* Catch CTImode and TCmode.  */
5317169689Skan	    || GET_MODE_SIZE (mode) > 16);
531850397Sobrien}
531950397Sobrien
532050397Sobrien/* Handle the FUNCTION_ARG_ADVANCE macro.
532150397Sobrien   Update the data in CUM to advance over an argument
532250397Sobrien   of mode MODE and data type TYPE.
532350397Sobrien   TYPE is null for libcalls where that information may not be available.  */
532450397Sobrien
532550397Sobrienvoid
5326132718Skanfunction_arg_advance (struct sparc_args *cum, enum machine_mode mode,
5327132718Skan		      tree type, int named)
532850397Sobrien{
532950397Sobrien  int slotno, regno, padding;
533050397Sobrien
533150397Sobrien  /* We pass 0 for incoming_p here, it doesn't matter.  */
533250397Sobrien  slotno = function_arg_slotno (cum, mode, type, named, 0, &regno, &padding);
533350397Sobrien
533450397Sobrien  /* If register required leading padding, add it.  */
533550397Sobrien  if (slotno != -1)
533650397Sobrien    cum->words += padding;
533750397Sobrien
533850397Sobrien  if (TARGET_ARCH32)
533950397Sobrien    {
534050397Sobrien      cum->words += (mode != BLKmode
534150397Sobrien		     ? ROUND_ADVANCE (GET_MODE_SIZE (mode))
534250397Sobrien		     : ROUND_ADVANCE (int_size_in_bytes (type)));
534350397Sobrien    }
534450397Sobrien  else
534550397Sobrien    {
534650397Sobrien      if (type && AGGREGATE_TYPE_P (type))
534750397Sobrien	{
534850397Sobrien	  int size = int_size_in_bytes (type);
534950397Sobrien
535050397Sobrien	  if (size <= 8)
535150397Sobrien	    ++cum->words;
535250397Sobrien	  else if (size <= 16)
535350397Sobrien	    cum->words += 2;
535450397Sobrien	  else /* passed by reference */
535550397Sobrien	    ++cum->words;
535650397Sobrien	}
535750397Sobrien      else
535850397Sobrien	{
535950397Sobrien	  cum->words += (mode != BLKmode
536050397Sobrien			 ? ROUND_ADVANCE (GET_MODE_SIZE (mode))
536150397Sobrien			 : ROUND_ADVANCE (int_size_in_bytes (type)));
536250397Sobrien	}
536350397Sobrien    }
536450397Sobrien}
536550397Sobrien
536650397Sobrien/* Handle the FUNCTION_ARG_PADDING macro.
536750397Sobrien   For the 64 bit ABI structs are always stored left shifted in their
536850397Sobrien   argument slot.  */
536950397Sobrien
537050397Sobrienenum direction
5371132718Skanfunction_arg_padding (enum machine_mode mode, tree type)
537250397Sobrien{
537350397Sobrien  if (TARGET_ARCH64 && type != 0 && AGGREGATE_TYPE_P (type))
537450397Sobrien    return upward;
537550397Sobrien
5376132718Skan  /* Fall back to the default.  */
5377132718Skan  return DEFAULT_FUNCTION_ARG_PADDING (mode, type);
537850397Sobrien}
537950397Sobrien
5380169689Skan/* Handle the TARGET_RETURN_IN_MEMORY target hook.
5381169689Skan   Specify whether to return the return value in memory.  */
5382169689Skan
5383169689Skanstatic bool
5384169689Skansparc_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
5385169689Skan{
5386169689Skan  if (TARGET_ARCH32)
5387169689Skan    /* Original SPARC 32-bit ABI says that structures and unions,
5388169689Skan       and quad-precision floats are returned in memory.  All other
5389169689Skan       base types are returned in registers.
5390169689Skan
5391169689Skan       Extended ABI (as implemented by the Sun compiler) says that
5392169689Skan       all complex floats are returned in registers (8 FP registers
5393169689Skan       at most for '_Complex long double').  Return all complex integers
5394169689Skan       in registers (4 at most for '_Complex long long').
5395169689Skan
5396169689Skan       Vector ABI (as implemented by the Sun VIS SDK) says that vector
5397169689Skan       integers are returned like floats of the same size, that is in
5398169689Skan       registers up to 8 bytes and in memory otherwise.  Return all
5399169689Skan       vector floats in memory like structure and unions; note that
5400169689Skan       they always have BLKmode like the latter.  */
5401169689Skan    return (TYPE_MODE (type) == BLKmode
5402169689Skan	    || TYPE_MODE (type) == TFmode
5403169689Skan	    || (TREE_CODE (type) == VECTOR_TYPE
5404169689Skan		&& (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 8));
5405169689Skan  else
5406169689Skan    /* Original SPARC 64-bit ABI says that structures and unions
5407169689Skan       smaller than 32 bytes are returned in registers, as well as
5408169689Skan       all other base types.
5409169689Skan
5410169689Skan       Extended ABI (as implemented by the Sun compiler) says that all
5411169689Skan       complex floats are returned in registers (8 FP registers at most
5412169689Skan       for '_Complex long double').  Return all complex integers in
5413169689Skan       registers (4 at most for '_Complex TItype').
5414169689Skan
5415169689Skan       Vector ABI (as implemented by the Sun VIS SDK) says that vector
5416169689Skan       integers are returned like floats of the same size, that is in
5417169689Skan       registers.  Return all vector floats like structure and unions;
5418169689Skan       note that they always have BLKmode like the latter.  */
5419169689Skan    return ((TYPE_MODE (type) == BLKmode
5420169689Skan	     && (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 32));
5421169689Skan}
5422169689Skan
5423169689Skan/* Handle the TARGET_STRUCT_VALUE target hook.
5424169689Skan   Return where to find the structure return value address.  */
5425169689Skan
5426169689Skanstatic rtx
5427169689Skansparc_struct_value_rtx (tree fndecl, int incoming)
5428169689Skan{
5429169689Skan  if (TARGET_ARCH64)
5430169689Skan    return 0;
5431169689Skan  else
5432169689Skan    {
5433169689Skan      rtx mem;
5434169689Skan
5435169689Skan      if (incoming)
5436169689Skan	mem = gen_rtx_MEM (Pmode, plus_constant (frame_pointer_rtx,
5437169689Skan						 STRUCT_VALUE_OFFSET));
5438169689Skan      else
5439169689Skan	mem = gen_rtx_MEM (Pmode, plus_constant (stack_pointer_rtx,
5440169689Skan						 STRUCT_VALUE_OFFSET));
5441169689Skan
5442169689Skan      /* Only follow the SPARC ABI for fixed-size structure returns.
5443169689Skan         Variable size structure returns are handled per the normal
5444169689Skan         procedures in GCC. This is enabled by -mstd-struct-return */
5445169689Skan      if (incoming == 2
5446169689Skan	  && sparc_std_struct_return
5447169689Skan	  && TYPE_SIZE_UNIT (TREE_TYPE (fndecl))
5448169689Skan	  && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (fndecl))) == INTEGER_CST)
5449169689Skan	{
5450169689Skan	  /* We must check and adjust the return address, as it is
5451169689Skan	     optional as to whether the return object is really
5452169689Skan	     provided.  */
5453169689Skan	  rtx ret_rtx = gen_rtx_REG (Pmode, 31);
5454169689Skan	  rtx scratch = gen_reg_rtx (SImode);
5455169689Skan	  rtx endlab = gen_label_rtx ();
5456169689Skan
5457169689Skan	  /* Calculate the return object size */
5458169689Skan	  tree size = TYPE_SIZE_UNIT (TREE_TYPE (fndecl));
5459169689Skan	  rtx size_rtx = GEN_INT (TREE_INT_CST_LOW (size) & 0xfff);
5460169689Skan	  /* Construct a temporary return value */
5461169689Skan	  rtx temp_val = assign_stack_local (Pmode, TREE_INT_CST_LOW (size), 0);
5462169689Skan
5463169689Skan	  /* Implement SPARC 32-bit psABI callee returns struck checking
5464169689Skan	     requirements:
5465169689Skan
5466169689Skan	      Fetch the instruction where we will return to and see if
5467169689Skan	     it's an unimp instruction (the most significant 10 bits
5468169689Skan	     will be zero).  */
5469169689Skan	  emit_move_insn (scratch, gen_rtx_MEM (SImode,
5470169689Skan						plus_constant (ret_rtx, 8)));
5471169689Skan	  /* Assume the size is valid and pre-adjust */
5472169689Skan	  emit_insn (gen_add3_insn (ret_rtx, ret_rtx, GEN_INT (4)));
5473169689Skan	  emit_cmp_and_jump_insns (scratch, size_rtx, EQ, const0_rtx, SImode, 0, endlab);
5474169689Skan	  emit_insn (gen_sub3_insn (ret_rtx, ret_rtx, GEN_INT (4)));
5475169689Skan	  /* Assign stack temp:
5476169689Skan	     Write the address of the memory pointed to by temp_val into
5477169689Skan	     the memory pointed to by mem */
5478169689Skan	  emit_move_insn (mem, XEXP (temp_val, 0));
5479169689Skan	  emit_label (endlab);
5480169689Skan	}
5481169689Skan
5482169689Skan      set_mem_alias_set (mem, struct_value_alias_set);
5483169689Skan      return mem;
5484169689Skan    }
5485169689Skan}
5486169689Skan
548750397Sobrien/* Handle FUNCTION_VALUE, FUNCTION_OUTGOING_VALUE, and LIBCALL_VALUE macros.
548850397Sobrien   For v9, function return values are subject to the same rules as arguments,
5489169689Skan   except that up to 32 bytes may be returned in registers.  */
549050397Sobrien
549150397Sobrienrtx
5492132718Skanfunction_value (tree type, enum machine_mode mode, int incoming_p)
549350397Sobrien{
5494169689Skan  /* Beware that the two values are swapped here wrt function_arg.  */
5495169689Skan  int regbase = (incoming_p
5496169689Skan		 ? SPARC_OUTGOING_INT_ARG_FIRST
5497169689Skan		 : SPARC_INCOMING_INT_ARG_FIRST);
5498169689Skan  enum mode_class mclass = GET_MODE_CLASS (mode);
549950397Sobrien  int regno;
550050397Sobrien
5501169689Skan  /* Vector types deserve special treatment because they are polymorphic wrt
5502169689Skan     their mode, depending upon whether VIS instructions are enabled.  */
5503169689Skan  if (type && TREE_CODE (type) == VECTOR_TYPE)
5504169689Skan    {
5505169689Skan      HOST_WIDE_INT size = int_size_in_bytes (type);
5506169689Skan      gcc_assert ((TARGET_ARCH32 && size <= 8)
5507169689Skan		  || (TARGET_ARCH64 && size <= 32));
5508169689Skan
5509169689Skan      if (mode == BLKmode)
5510169689Skan	return function_arg_vector_value (size,
5511169689Skan					  TYPE_MODE (TREE_TYPE (type)),
5512169689Skan					  SPARC_FP_ARG_FIRST);
5513169689Skan      else
5514169689Skan	mclass = MODE_FLOAT;
5515169689Skan    }
5516169689Skan
551750397Sobrien  if (TARGET_ARCH64 && type)
551850397Sobrien    {
5519169689Skan      /* Structures up to 32 bytes in size are returned in registers.  */
552050397Sobrien      if (TREE_CODE (type) == RECORD_TYPE)
552150397Sobrien	{
5522169689Skan	  HOST_WIDE_INT size = int_size_in_bytes (type);
5523169689Skan	  gcc_assert (size <= 32);
552450397Sobrien
552550397Sobrien	  return function_arg_record_value (type, mode, 0, 1, regbase);
552650397Sobrien	}
5527169689Skan
5528169689Skan      /* Unions up to 32 bytes in size are returned in integer registers.  */
5529132718Skan      else if (TREE_CODE (type) == UNION_TYPE)
5530132718Skan	{
5531132718Skan	  HOST_WIDE_INT size = int_size_in_bytes (type);
5532169689Skan	  gcc_assert (size <= 32);
5533132718Skan
5534146895Skan	  return function_arg_union_value (size, mode, 0, regbase);
5535132718Skan	}
5536169689Skan
5537169689Skan      /* Objects that require it are returned in FP registers.  */
5538169689Skan      else if (mclass == MODE_FLOAT || mclass == MODE_COMPLEX_FLOAT)
5539169689Skan	;
5540169689Skan
5541169689Skan      /* All other aggregate types are returned in an integer register in a
5542169689Skan	 mode corresponding to the size of the type.  */
554390075Sobrien      else if (AGGREGATE_TYPE_P (type))
554450397Sobrien	{
554590075Sobrien	  /* All other aggregate types are passed in an integer register
554690075Sobrien	     in a mode corresponding to the size of the type.  */
5547169689Skan	  HOST_WIDE_INT size = int_size_in_bytes (type);
5548169689Skan	  gcc_assert (size <= 32);
554950397Sobrien
5550169689Skan	  mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
555150397Sobrien
5552132718Skan	  /* ??? We probably should have made the same ABI change in
5553132718Skan	     3.4.0 as the one we made for unions.   The latter was
5554132718Skan	     required by the SCD though, while the former is not
5555132718Skan	     specified, so we favored compatibility and efficiency.
5556132718Skan
5557132718Skan	     Now we're stuck for aggregates larger than 16 bytes,
5558132718Skan	     because OImode vanished in the meantime.  Let's not
5559132718Skan	     try to be unduly clever, and simply follow the ABI
5560132718Skan	     for unions in that case.  */
5561132718Skan	  if (mode == BLKmode)
5562169689Skan	    return function_arg_union_value (size, mode, 0, regbase);
5563169689Skan	  else
5564169689Skan	    mclass = MODE_INT;
556550397Sobrien	}
5566169689Skan
5567169689Skan      /* This must match PROMOTE_FUNCTION_MODE.  */
5568169689Skan      else if (mclass == MODE_INT && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
5569132718Skan	mode = word_mode;
557050397Sobrien    }
557150397Sobrien
5572169689Skan  if ((mclass == MODE_FLOAT || mclass == MODE_COMPLEX_FLOAT) && TARGET_FPU)
5573169689Skan    regno = SPARC_FP_ARG_FIRST;
557450397Sobrien  else
5575169689Skan    regno = regbase;
557650397Sobrien
557750397Sobrien  return gen_rtx_REG (mode, regno);
557850397Sobrien}
557950397Sobrien
558090075Sobrien/* Do what is necessary for `va_start'.  We look at the current function
558190075Sobrien   to determine if stdarg or varargs is used and return the address of
558290075Sobrien   the first unnamed parameter.  */
558350397Sobrien
5584169689Skanstatic rtx
5585132718Skansparc_builtin_saveregs (void)
558650397Sobrien{
558750397Sobrien  int first_reg = current_function_args_info.words;
558850397Sobrien  rtx address;
558950397Sobrien  int regno;
559050397Sobrien
5591169689Skan  for (regno = first_reg; regno < SPARC_INT_ARG_MAX; regno++)
559250397Sobrien    emit_move_insn (gen_rtx_MEM (word_mode,
559390075Sobrien				 gen_rtx_PLUS (Pmode,
559490075Sobrien					       frame_pointer_rtx,
559596263Sobrien					       GEN_INT (FIRST_PARM_OFFSET (0)
559690075Sobrien							+ (UNITS_PER_WORD
559790075Sobrien							   * regno)))),
559850397Sobrien		    gen_rtx_REG (word_mode,
5599169689Skan				 SPARC_INCOMING_INT_ARG_FIRST + regno));
560050397Sobrien
560150397Sobrien  address = gen_rtx_PLUS (Pmode,
560290075Sobrien			  frame_pointer_rtx,
560396263Sobrien			  GEN_INT (FIRST_PARM_OFFSET (0)
560490075Sobrien				   + UNITS_PER_WORD * first_reg));
560550397Sobrien
560650397Sobrien  return address;
560750397Sobrien}
560890075Sobrien
5609169689Skan/* Implement `va_start' for stdarg.  */
561090075Sobrien
561190075Sobrienvoid
5612132718Skansparc_va_start (tree valist, rtx nextarg)
561390075Sobrien{
561490075Sobrien  nextarg = expand_builtin_saveregs ();
5615117395Skan  std_expand_builtin_va_start (valist, nextarg);
561690075Sobrien}
561790075Sobrien
5618169689Skan/* Implement `va_arg' for stdarg.  */
561990075Sobrien
5620169689Skanstatic tree
5621169689Skansparc_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
562290075Sobrien{
562390075Sobrien  HOST_WIDE_INT size, rsize, align;
562490075Sobrien  tree addr, incr;
5625169689Skan  bool indirect;
5626169689Skan  tree ptrtype = build_pointer_type (type);
562790075Sobrien
5628169689Skan  if (pass_by_reference (NULL, TYPE_MODE (type), type, false))
562990075Sobrien    {
5630169689Skan      indirect = true;
5631169689Skan      size = rsize = UNITS_PER_WORD;
5632169689Skan      align = 0;
563390075Sobrien    }
563490075Sobrien  else
563590075Sobrien    {
5636169689Skan      indirect = false;
5637169689Skan      size = int_size_in_bytes (type);
5638169689Skan      rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
5639169689Skan      align = 0;
5640169689Skan
5641169689Skan      if (TARGET_ARCH64)
564290075Sobrien	{
5643169689Skan	  /* For SPARC64, objects requiring 16-byte alignment get it.  */
5644169689Skan	  if (TYPE_ALIGN (type) >= 2 * (unsigned) BITS_PER_WORD)
5645169689Skan	    align = 2 * UNITS_PER_WORD;
5646169689Skan
5647169689Skan	  /* SPARC-V9 ABI states that structures up to 16 bytes in size
5648169689Skan	     are left-justified in their slots.  */
5649169689Skan	  if (AGGREGATE_TYPE_P (type))
5650169689Skan	    {
5651169689Skan	      if (size == 0)
5652169689Skan		size = rsize = UNITS_PER_WORD;
5653169689Skan	      else
5654169689Skan		size = rsize;
5655169689Skan	    }
565690075Sobrien	}
565790075Sobrien    }
565890075Sobrien
565990075Sobrien  incr = valist;
566090075Sobrien  if (align)
566190075Sobrien    {
5662169689Skan      incr = fold (build2 (PLUS_EXPR, ptr_type_node, incr,
5663169689Skan			   ssize_int (align - 1)));
5664169689Skan      incr = fold (build2 (BIT_AND_EXPR, ptr_type_node, incr,
5665169689Skan			   ssize_int (-align)));
566690075Sobrien    }
566790075Sobrien
5668169689Skan  gimplify_expr (&incr, pre_p, post_p, is_gimple_val, fb_rvalue);
5669169689Skan  addr = incr;
5670169689Skan
567190075Sobrien  if (BYTES_BIG_ENDIAN && size < rsize)
5672169689Skan    addr = fold (build2 (PLUS_EXPR, ptr_type_node, incr,
5673169689Skan			 ssize_int (rsize - size)));
5674169689Skan
5675169689Skan  if (indirect)
567690075Sobrien    {
5677169689Skan      addr = fold_convert (build_pointer_type (ptrtype), addr);
5678169689Skan      addr = build_va_arg_indirect_ref (addr);
567990075Sobrien    }
568090075Sobrien  /* If the address isn't aligned properly for the type,
568190075Sobrien     we may need to copy to a temporary.
568290075Sobrien     FIXME: This is inefficient.  Usually we can do this
568390075Sobrien     in registers.  */
5684169689Skan  else if (align == 0
5685169689Skan	   && TYPE_ALIGN (type) > BITS_PER_WORD)
568690075Sobrien    {
5687169689Skan      tree tmp = create_tmp_var (type, "va_arg_tmp");
5688169689Skan      tree dest_addr = build_fold_addr_expr (tmp);
568990075Sobrien
5690169689Skan      tree copy = build_function_call_expr
5691169689Skan	(implicit_built_in_decls[BUILT_IN_MEMCPY],
5692169689Skan	 tree_cons (NULL_TREE, dest_addr,
5693169689Skan		    tree_cons (NULL_TREE, addr,
5694169689Skan			       tree_cons (NULL_TREE, size_int (rsize),
5695169689Skan					  NULL_TREE))));
569690075Sobrien
5697169689Skan      gimplify_and_add (copy, pre_p);
5698169689Skan      addr = dest_addr;
569990075Sobrien    }
5700169689Skan  else
5701169689Skan    addr = fold_convert (ptrtype, addr);
570290075Sobrien
5703169689Skan  incr = fold (build2 (PLUS_EXPR, ptr_type_node, incr, ssize_int (rsize)));
5704169689Skan  incr = build2 (MODIFY_EXPR, ptr_type_node, valist, incr);
5705169689Skan  gimplify_and_add (incr, post_p);
5706169689Skan
5707169689Skan  return build_va_arg_indirect_ref (addr);
570890075Sobrien}
570950397Sobrien
5710169689Skan/* Implement the TARGET_VECTOR_MODE_SUPPORTED_P target hook.
5711169689Skan   Specify whether the vector mode is supported by the hardware.  */
5712169689Skan
5713169689Skanstatic bool
5714169689Skansparc_vector_mode_supported_p (enum machine_mode mode)
5715169689Skan{
5716169689Skan  return TARGET_VIS && VECTOR_MODE_P (mode) ? true : false;
5717169689Skan}
5718169689Skan
5719132718Skan/* Return the string to output an unconditional branch to LABEL, which is
5720132718Skan   the operand number of the label.
5721132718Skan
5722132718Skan   DEST is the destination insn (i.e. the label), INSN is the source.  */
5723132718Skan
5724132718Skanconst char *
5725132718Skanoutput_ubranch (rtx dest, int label, rtx insn)
5726132718Skan{
5727132718Skan  static char string[64];
5728169689Skan  bool v9_form = false;
5729132718Skan  char *p;
5730132718Skan
5731169689Skan  if (TARGET_V9 && INSN_ADDRESSES_SET_P ())
5732132718Skan    {
5733169689Skan      int delta = (INSN_ADDRESSES (INSN_UID (dest))
5734169689Skan		   - INSN_ADDRESSES (INSN_UID (insn)));
5735169689Skan      /* Leave some instructions for "slop".  */
5736169689Skan      if (delta >= -260000 && delta < 260000)
5737169689Skan	v9_form = true;
5738132718Skan    }
5739169689Skan
5740169689Skan  if (v9_form)
5741169689Skan    strcpy (string, "ba%*,pt\t%%xcc, ");
5742132718Skan  else
5743169689Skan    strcpy (string, "b%*\t");
5744132718Skan
5745132718Skan  p = strchr (string, '\0');
5746132718Skan  *p++ = '%';
5747132718Skan  *p++ = 'l';
5748132718Skan  *p++ = '0' + label;
5749132718Skan  *p++ = '%';
5750169689Skan  *p++ = '(';
5751132718Skan  *p = '\0';
5752132718Skan
5753132718Skan  return string;
5754132718Skan}
5755132718Skan
575650397Sobrien/* Return the string to output a conditional branch to LABEL, which is
575750397Sobrien   the operand number of the label.  OP is the conditional expression.
575850397Sobrien   XEXP (OP, 0) is assumed to be a condition code register (integer or
575950397Sobrien   floating point) and its mode specifies what kind of comparison we made.
576050397Sobrien
5761132718Skan   DEST is the destination insn (i.e. the label), INSN is the source.
5762132718Skan
5763117395Skan   REVERSED is nonzero if we should reverse the sense of the comparison.
576450397Sobrien
5765169689Skan   ANNUL is nonzero if we should generate an annulling branch.  */
576650397Sobrien
5767169689Skanconst char *
5768132718Skanoutput_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
5769169689Skan		rtx insn)
577050397Sobrien{
5771169689Skan  static char string[64];
577250397Sobrien  enum rtx_code code = GET_CODE (op);
577350397Sobrien  rtx cc_reg = XEXP (op, 0);
577450397Sobrien  enum machine_mode mode = GET_MODE (cc_reg);
577596263Sobrien  const char *labelno, *branch;
577696263Sobrien  int spaces = 8, far;
577796263Sobrien  char *p;
577850397Sobrien
577996263Sobrien  /* v9 branches are limited to +-1MB.  If it is too far away,
578096263Sobrien     change
578196263Sobrien
578296263Sobrien     bne,pt %xcc, .LC30
578396263Sobrien
578496263Sobrien     to
578596263Sobrien
578696263Sobrien     be,pn %xcc, .+12
5787169689Skan      nop
578896263Sobrien     ba .LC30
578996263Sobrien
579096263Sobrien     and
579196263Sobrien
579296263Sobrien     fbne,a,pn %fcc2, .LC29
579396263Sobrien
579496263Sobrien     to
579596263Sobrien
579696263Sobrien     fbe,pt %fcc2, .+16
5797169689Skan      nop
579896263Sobrien     ba .LC29  */
579996263Sobrien
5800132718Skan  far = TARGET_V9 && (get_attr_length (insn) >= 3);
580196263Sobrien  if (reversed ^ far)
580250397Sobrien    {
580390075Sobrien      /* Reversal of FP compares takes care -- an ordered compare
580490075Sobrien	 becomes an unordered compare and vice versa.  */
580550397Sobrien      if (mode == CCFPmode || mode == CCFPEmode)
580690075Sobrien	code = reverse_condition_maybe_unordered (code);
580750397Sobrien      else
580890075Sobrien	code = reverse_condition (code);
580990075Sobrien    }
581050397Sobrien
581190075Sobrien  /* Start by writing the branch condition.  */
581290075Sobrien  if (mode == CCFPmode || mode == CCFPEmode)
581390075Sobrien    {
581490075Sobrien      switch (code)
581552284Sobrien	{
581690075Sobrien	case NE:
581790075Sobrien	  branch = "fbne";
581890075Sobrien	  break;
581990075Sobrien	case EQ:
582090075Sobrien	  branch = "fbe";
582190075Sobrien	  break;
582290075Sobrien	case GE:
582390075Sobrien	  branch = "fbge";
582490075Sobrien	  break;
582590075Sobrien	case GT:
582690075Sobrien	  branch = "fbg";
582790075Sobrien	  break;
582890075Sobrien	case LE:
582990075Sobrien	  branch = "fble";
583090075Sobrien	  break;
583190075Sobrien	case LT:
583290075Sobrien	  branch = "fbl";
583390075Sobrien	  break;
583490075Sobrien	case UNORDERED:
583590075Sobrien	  branch = "fbu";
583690075Sobrien	  break;
583790075Sobrien	case ORDERED:
583890075Sobrien	  branch = "fbo";
583990075Sobrien	  break;
584090075Sobrien	case UNGT:
584190075Sobrien	  branch = "fbug";
584290075Sobrien	  break;
584390075Sobrien	case UNLT:
584490075Sobrien	  branch = "fbul";
584590075Sobrien	  break;
584690075Sobrien	case UNEQ:
584790075Sobrien	  branch = "fbue";
584890075Sobrien	  break;
584990075Sobrien	case UNGE:
585090075Sobrien	  branch = "fbuge";
585190075Sobrien	  break;
585290075Sobrien	case UNLE:
585390075Sobrien	  branch = "fbule";
585490075Sobrien	  break;
585590075Sobrien	case LTGT:
585690075Sobrien	  branch = "fblg";
585790075Sobrien	  break;
585850397Sobrien
585990075Sobrien	default:
5860169689Skan	  gcc_unreachable ();
586150397Sobrien	}
586250397Sobrien
586390075Sobrien      /* ??? !v9: FP branches cannot be preceded by another floating point
586490075Sobrien	 insn.  Because there is currently no concept of pre-delay slots,
586590075Sobrien	 we can fix this only by always emitting a nop before a floating
586690075Sobrien	 point branch.  */
586750397Sobrien
586890075Sobrien      string[0] = '\0';
586990075Sobrien      if (! TARGET_V9)
587090075Sobrien	strcpy (string, "nop\n\t");
587190075Sobrien      strcat (string, branch);
587290075Sobrien    }
587390075Sobrien  else
587490075Sobrien    {
587590075Sobrien      switch (code)
587650397Sobrien	{
587790075Sobrien	case NE:
587890075Sobrien	  branch = "bne";
587990075Sobrien	  break;
588090075Sobrien	case EQ:
588190075Sobrien	  branch = "be";
588290075Sobrien	  break;
588390075Sobrien	case GE:
588496263Sobrien	  if (mode == CC_NOOVmode || mode == CCX_NOOVmode)
588590075Sobrien	    branch = "bpos";
588650397Sobrien	  else
588790075Sobrien	    branch = "bge";
588890075Sobrien	  break;
588990075Sobrien	case GT:
589090075Sobrien	  branch = "bg";
589190075Sobrien	  break;
589290075Sobrien	case LE:
589390075Sobrien	  branch = "ble";
589490075Sobrien	  break;
589590075Sobrien	case LT:
589696263Sobrien	  if (mode == CC_NOOVmode || mode == CCX_NOOVmode)
589790075Sobrien	    branch = "bneg";
589890075Sobrien	  else
589990075Sobrien	    branch = "bl";
590090075Sobrien	  break;
590190075Sobrien	case GEU:
590290075Sobrien	  branch = "bgeu";
590390075Sobrien	  break;
590490075Sobrien	case GTU:
590590075Sobrien	  branch = "bgu";
590690075Sobrien	  break;
590790075Sobrien	case LEU:
590890075Sobrien	  branch = "bleu";
590990075Sobrien	  break;
591090075Sobrien	case LTU:
591190075Sobrien	  branch = "blu";
591290075Sobrien	  break;
591350397Sobrien
591490075Sobrien	default:
5915169689Skan	  gcc_unreachable ();
591650397Sobrien	}
591790075Sobrien      strcpy (string, branch);
591850397Sobrien    }
591990075Sobrien  spaces -= strlen (branch);
592096263Sobrien  p = strchr (string, '\0');
592150397Sobrien
592250397Sobrien  /* Now add the annulling, the label, and a possible noop.  */
592396263Sobrien  if (annul && ! far)
592452284Sobrien    {
592596263Sobrien      strcpy (p, ",a");
592696263Sobrien      p += 2;
592752284Sobrien      spaces -= 2;
592852284Sobrien    }
592950397Sobrien
5930132718Skan  if (TARGET_V9)
593150397Sobrien    {
593250397Sobrien      rtx note;
593396263Sobrien      int v8 = 0;
593450397Sobrien
593596263Sobrien      if (! far && insn && INSN_ADDRESSES_SET_P ())
593652284Sobrien	{
593796263Sobrien	  int delta = (INSN_ADDRESSES (INSN_UID (dest))
593896263Sobrien		       - INSN_ADDRESSES (INSN_UID (insn)));
593996263Sobrien	  /* Leave some instructions for "slop".  */
594096263Sobrien	  if (delta < -260000 || delta >= 260000)
594196263Sobrien	    v8 = 1;
594252284Sobrien	}
594350397Sobrien
594450397Sobrien      if (mode == CCFPmode || mode == CCFPEmode)
594550397Sobrien	{
594696263Sobrien	  static char v9_fcc_labelno[] = "%%fccX, ";
594796263Sobrien	  /* Set the char indicating the number of the fcc reg to use.  */
594896263Sobrien	  v9_fcc_labelno[5] = REGNO (cc_reg) - SPARC_FIRST_V9_FCC_REG + '0';
594950397Sobrien	  labelno = v9_fcc_labelno;
595096263Sobrien	  if (v8)
595196263Sobrien	    {
5952169689Skan	      gcc_assert (REGNO (cc_reg) == SPARC_FCC_REG);
5953169689Skan	      labelno = "";
595496263Sobrien	    }
595550397Sobrien	}
595650397Sobrien      else if (mode == CCXmode || mode == CCX_NOOVmode)
595796263Sobrien	{
595896263Sobrien	  labelno = "%%xcc, ";
5959169689Skan	  gcc_assert (! v8);
596096263Sobrien	}
596150397Sobrien      else
596296263Sobrien	{
596396263Sobrien	  labelno = "%%icc, ";
596496263Sobrien	  if (v8)
596596263Sobrien	    labelno = "";
596696263Sobrien	}
596796263Sobrien
596896263Sobrien      if (*labelno && insn && (note = find_reg_note (insn, REG_BR_PROB, NULL_RTX)))
596996263Sobrien	{
597096263Sobrien	  strcpy (p,
597196263Sobrien		  ((INTVAL (XEXP (note, 0)) >= REG_BR_PROB_BASE / 2) ^ far)
597296263Sobrien		  ? ",pt" : ",pn");
597396263Sobrien	  p += 3;
597496263Sobrien	  spaces -= 3;
597596263Sobrien	}
597650397Sobrien    }
5977132718Skan  else
5978132718Skan    labelno = "";
5979132718Skan
598096263Sobrien  if (spaces > 0)
598196263Sobrien    *p++ = '\t';
598296263Sobrien  else
598396263Sobrien    *p++ = ' ';
598496263Sobrien  strcpy (p, labelno);
598596263Sobrien  p = strchr (p, '\0');
598696263Sobrien  if (far)
598796263Sobrien    {
5988169689Skan      strcpy (p, ".+12\n\t nop\n\tb\t");
5989169689Skan      /* Skip the next insn if requested or
5990169689Skan	 if we know that it will be a nop.  */
5991169689Skan      if (annul || ! final_sequence)
599296263Sobrien        p[3] = '6';
5993169689Skan      p += 14;
599496263Sobrien    }
599596263Sobrien  *p++ = '%';
599696263Sobrien  *p++ = 'l';
599796263Sobrien  *p++ = label + '0';
5998169689Skan  *p++ = '%';
5999169689Skan  *p++ = '#';
600096263Sobrien  *p = '\0';
600150397Sobrien
600250397Sobrien  return string;
600350397Sobrien}
600450397Sobrien
600590075Sobrien/* Emit a library call comparison between floating point X and Y.
600690075Sobrien   COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
600790075Sobrien   TARGET_ARCH64 uses _Qp_* functions, which use pointers to TFmode
600890075Sobrien   values as arguments instead of the TFmode registers themselves,
600990075Sobrien   that's why we cannot call emit_float_lib_cmp.  */
601090075Sobrienvoid
6011132718Skansparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison)
601290075Sobrien{
601390075Sobrien  const char *qpfunc;
601490075Sobrien  rtx slot0, slot1, result, tem, tem2;
601590075Sobrien  enum machine_mode mode;
601690075Sobrien
601790075Sobrien  switch (comparison)
601890075Sobrien    {
601990075Sobrien    case EQ:
602090075Sobrien      qpfunc = (TARGET_ARCH64) ? "_Qp_feq" : "_Q_feq";
602190075Sobrien      break;
602290075Sobrien
602390075Sobrien    case NE:
602490075Sobrien      qpfunc = (TARGET_ARCH64) ? "_Qp_fne" : "_Q_fne";
602590075Sobrien      break;
602690075Sobrien
602790075Sobrien    case GT:
602890075Sobrien      qpfunc = (TARGET_ARCH64) ? "_Qp_fgt" : "_Q_fgt";
602990075Sobrien      break;
603090075Sobrien
603190075Sobrien    case GE:
603290075Sobrien      qpfunc = (TARGET_ARCH64) ? "_Qp_fge" : "_Q_fge";
603390075Sobrien      break;
603490075Sobrien
603590075Sobrien    case LT:
603690075Sobrien      qpfunc = (TARGET_ARCH64) ? "_Qp_flt" : "_Q_flt";
603790075Sobrien      break;
603890075Sobrien
603990075Sobrien    case LE:
604090075Sobrien      qpfunc = (TARGET_ARCH64) ? "_Qp_fle" : "_Q_fle";
604190075Sobrien      break;
604290075Sobrien
604390075Sobrien    case ORDERED:
604490075Sobrien    case UNORDERED:
604590075Sobrien    case UNGT:
604690075Sobrien    case UNLT:
604790075Sobrien    case UNEQ:
604890075Sobrien    case UNGE:
604990075Sobrien    case UNLE:
605090075Sobrien    case LTGT:
605190075Sobrien      qpfunc = (TARGET_ARCH64) ? "_Qp_cmp" : "_Q_cmp";
605290075Sobrien      break;
605390075Sobrien
605490075Sobrien    default:
6055169689Skan      gcc_unreachable ();
605690075Sobrien    }
605790075Sobrien
605890075Sobrien  if (TARGET_ARCH64)
605990075Sobrien    {
606090075Sobrien      if (GET_CODE (x) != MEM)
606190075Sobrien	{
606290075Sobrien	  slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
6063169689Skan	  emit_move_insn (slot0, x);
606490075Sobrien	}
606590075Sobrien      else
606690075Sobrien	slot0 = x;
606790075Sobrien
606890075Sobrien      if (GET_CODE (y) != MEM)
606990075Sobrien	{
607090075Sobrien	  slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
6071169689Skan	  emit_move_insn (slot1, y);
607290075Sobrien	}
607390075Sobrien      else
607490075Sobrien	slot1 = y;
607590075Sobrien
607696263Sobrien      emit_library_call (gen_rtx_SYMBOL_REF (Pmode, qpfunc), LCT_NORMAL,
607790075Sobrien			 DImode, 2,
607890075Sobrien			 XEXP (slot0, 0), Pmode,
607990075Sobrien			 XEXP (slot1, 0), Pmode);
608090075Sobrien
608190075Sobrien      mode = DImode;
608290075Sobrien    }
608390075Sobrien  else
608490075Sobrien    {
608596263Sobrien      emit_library_call (gen_rtx_SYMBOL_REF (Pmode, qpfunc), LCT_NORMAL,
608690075Sobrien			 SImode, 2,
608790075Sobrien			 x, TFmode, y, TFmode);
608890075Sobrien
608990075Sobrien      mode = SImode;
609090075Sobrien    }
609190075Sobrien
609290075Sobrien
609390075Sobrien  /* Immediately move the result of the libcall into a pseudo
609490075Sobrien     register so reload doesn't clobber the value if it needs
609590075Sobrien     the return register for a spill reg.  */
609690075Sobrien  result = gen_reg_rtx (mode);
609790075Sobrien  emit_move_insn (result, hard_libcall_value (mode));
609890075Sobrien
609990075Sobrien  switch (comparison)
610090075Sobrien    {
610190075Sobrien    default:
610290075Sobrien      emit_cmp_insn (result, const0_rtx, NE, NULL_RTX, mode, 0);
610390075Sobrien      break;
610490075Sobrien    case ORDERED:
610590075Sobrien    case UNORDERED:
610690075Sobrien      emit_cmp_insn (result, GEN_INT(3), comparison == UNORDERED ? EQ : NE,
610790075Sobrien		     NULL_RTX, mode, 0);
610890075Sobrien      break;
610990075Sobrien    case UNGT:
611090075Sobrien    case UNGE:
611190075Sobrien      emit_cmp_insn (result, const1_rtx,
611290075Sobrien		     comparison == UNGT ? GT : NE, NULL_RTX, mode, 0);
611390075Sobrien      break;
611490075Sobrien    case UNLE:
611590075Sobrien      emit_cmp_insn (result, const2_rtx, NE, NULL_RTX, mode, 0);
611690075Sobrien      break;
611790075Sobrien    case UNLT:
611890075Sobrien      tem = gen_reg_rtx (mode);
611990075Sobrien      if (TARGET_ARCH32)
612090075Sobrien	emit_insn (gen_andsi3 (tem, result, const1_rtx));
612190075Sobrien      else
612290075Sobrien	emit_insn (gen_anddi3 (tem, result, const1_rtx));
612390075Sobrien      emit_cmp_insn (tem, const0_rtx, NE, NULL_RTX, mode, 0);
612490075Sobrien      break;
612590075Sobrien    case UNEQ:
612690075Sobrien    case LTGT:
612790075Sobrien      tem = gen_reg_rtx (mode);
612890075Sobrien      if (TARGET_ARCH32)
612990075Sobrien	emit_insn (gen_addsi3 (tem, result, const1_rtx));
613090075Sobrien      else
613190075Sobrien	emit_insn (gen_adddi3 (tem, result, const1_rtx));
613290075Sobrien      tem2 = gen_reg_rtx (mode);
613390075Sobrien      if (TARGET_ARCH32)
613490075Sobrien	emit_insn (gen_andsi3 (tem2, tem, const2_rtx));
613590075Sobrien      else
613690075Sobrien	emit_insn (gen_anddi3 (tem2, tem, const2_rtx));
613790075Sobrien      emit_cmp_insn (tem2, const0_rtx, comparison == UNEQ ? EQ : NE,
613890075Sobrien		     NULL_RTX, mode, 0);
613990075Sobrien      break;
614090075Sobrien    }
614190075Sobrien}
614290075Sobrien
614396263Sobrien/* Generate an unsigned DImode to FP conversion.  This is the same code
614496263Sobrien   optabs would emit if we didn't have TFmode patterns.  */
614596263Sobrien
614696263Sobrienvoid
6147169689Skansparc_emit_floatunsdi (rtx *operands, enum machine_mode mode)
614896263Sobrien{
614996263Sobrien  rtx neglab, donelab, i0, i1, f0, in, out;
615096263Sobrien
615196263Sobrien  out = operands[0];
615296263Sobrien  in = force_reg (DImode, operands[1]);
615396263Sobrien  neglab = gen_label_rtx ();
615496263Sobrien  donelab = gen_label_rtx ();
615596263Sobrien  i0 = gen_reg_rtx (DImode);
615696263Sobrien  i1 = gen_reg_rtx (DImode);
615796263Sobrien  f0 = gen_reg_rtx (mode);
615896263Sobrien
615996263Sobrien  emit_cmp_and_jump_insns (in, const0_rtx, LT, const0_rtx, DImode, 0, neglab);
616096263Sobrien
616196263Sobrien  emit_insn (gen_rtx_SET (VOIDmode, out, gen_rtx_FLOAT (mode, in)));
616296263Sobrien  emit_jump_insn (gen_jump (donelab));
616396263Sobrien  emit_barrier ();
616496263Sobrien
616596263Sobrien  emit_label (neglab);
616696263Sobrien
616796263Sobrien  emit_insn (gen_lshrdi3 (i0, in, const1_rtx));
616896263Sobrien  emit_insn (gen_anddi3 (i1, in, const1_rtx));
616996263Sobrien  emit_insn (gen_iordi3 (i0, i0, i1));
617096263Sobrien  emit_insn (gen_rtx_SET (VOIDmode, f0, gen_rtx_FLOAT (mode, i0)));
617196263Sobrien  emit_insn (gen_rtx_SET (VOIDmode, out, gen_rtx_PLUS (mode, f0, f0)));
617296263Sobrien
617396263Sobrien  emit_label (donelab);
617496263Sobrien}
617596263Sobrien
6176169689Skan/* Generate an FP to unsigned DImode conversion.  This is the same code
6177169689Skan   optabs would emit if we didn't have TFmode patterns.  */
6178169689Skan
6179169689Skanvoid
6180169689Skansparc_emit_fixunsdi (rtx *operands, enum machine_mode mode)
6181169689Skan{
6182169689Skan  rtx neglab, donelab, i0, i1, f0, in, out, limit;
6183169689Skan
6184169689Skan  out = operands[0];
6185169689Skan  in = force_reg (mode, operands[1]);
6186169689Skan  neglab = gen_label_rtx ();
6187169689Skan  donelab = gen_label_rtx ();
6188169689Skan  i0 = gen_reg_rtx (DImode);
6189169689Skan  i1 = gen_reg_rtx (DImode);
6190169689Skan  limit = gen_reg_rtx (mode);
6191169689Skan  f0 = gen_reg_rtx (mode);
6192169689Skan
6193169689Skan  emit_move_insn (limit,
6194169689Skan		  CONST_DOUBLE_FROM_REAL_VALUE (
6195169689Skan		    REAL_VALUE_ATOF ("9223372036854775808.0", mode), mode));
6196169689Skan  emit_cmp_and_jump_insns (in, limit, GE, NULL_RTX, mode, 0, neglab);
6197169689Skan
6198169689Skan  emit_insn (gen_rtx_SET (VOIDmode,
6199169689Skan			  out,
6200169689Skan			  gen_rtx_FIX (DImode, gen_rtx_FIX (mode, in))));
6201169689Skan  emit_jump_insn (gen_jump (donelab));
6202169689Skan  emit_barrier ();
6203169689Skan
6204169689Skan  emit_label (neglab);
6205169689Skan
6206169689Skan  emit_insn (gen_rtx_SET (VOIDmode, f0, gen_rtx_MINUS (mode, in, limit)));
6207169689Skan  emit_insn (gen_rtx_SET (VOIDmode,
6208169689Skan			  i0,
6209169689Skan			  gen_rtx_FIX (DImode, gen_rtx_FIX (mode, f0))));
6210169689Skan  emit_insn (gen_movdi (i1, const1_rtx));
6211169689Skan  emit_insn (gen_ashldi3 (i1, i1, GEN_INT (63)));
6212169689Skan  emit_insn (gen_xordi3 (out, i0, i1));
6213169689Skan
6214169689Skan  emit_label (donelab);
6215169689Skan}
6216169689Skan
621750397Sobrien/* Return the string to output a conditional branch to LABEL, testing
621850397Sobrien   register REG.  LABEL is the operand number of the label; REG is the
621950397Sobrien   operand number of the reg.  OP is the conditional expression.  The mode
622050397Sobrien   of REG says what kind of comparison we made.
622150397Sobrien
6222132718Skan   DEST is the destination insn (i.e. the label), INSN is the source.
6223132718Skan
6224117395Skan   REVERSED is nonzero if we should reverse the sense of the comparison.
622550397Sobrien
6226169689Skan   ANNUL is nonzero if we should generate an annulling branch.  */
622750397Sobrien
6228169689Skanconst char *
6229132718Skanoutput_v9branch (rtx op, rtx dest, int reg, int label, int reversed,
6230169689Skan		 int annul, rtx insn)
623150397Sobrien{
6232169689Skan  static char string[64];
623350397Sobrien  enum rtx_code code = GET_CODE (op);
623450397Sobrien  enum machine_mode mode = GET_MODE (XEXP (op, 0));
623552284Sobrien  rtx note;
623696263Sobrien  int far;
623796263Sobrien  char *p;
623850397Sobrien
623996263Sobrien  /* branch on register are limited to +-128KB.  If it is too far away,
624096263Sobrien     change
624196263Sobrien
624296263Sobrien     brnz,pt %g1, .LC30
624396263Sobrien
624496263Sobrien     to
624596263Sobrien
624696263Sobrien     brz,pn %g1, .+12
6247169689Skan      nop
624896263Sobrien     ba,pt %xcc, .LC30
624996263Sobrien
625096263Sobrien     and
625196263Sobrien
625296263Sobrien     brgez,a,pn %o1, .LC29
625396263Sobrien
625496263Sobrien     to
625596263Sobrien
625696263Sobrien     brlz,pt %o1, .+16
6257169689Skan      nop
625896263Sobrien     ba,pt %xcc, .LC29  */
625996263Sobrien
626096263Sobrien  far = get_attr_length (insn) >= 3;
626196263Sobrien
626250397Sobrien  /* If not floating-point or if EQ or NE, we can just reverse the code.  */
626396263Sobrien  if (reversed ^ far)
626496263Sobrien    code = reverse_condition (code);
626550397Sobrien
626650397Sobrien  /* Only 64 bit versions of these instructions exist.  */
6267169689Skan  gcc_assert (mode == DImode);
626850397Sobrien
626950397Sobrien  /* Start by writing the branch condition.  */
627050397Sobrien
627150397Sobrien  switch (code)
627250397Sobrien    {
627350397Sobrien    case NE:
627450397Sobrien      strcpy (string, "brnz");
627550397Sobrien      break;
627650397Sobrien
627750397Sobrien    case EQ:
627850397Sobrien      strcpy (string, "brz");
627950397Sobrien      break;
628050397Sobrien
628150397Sobrien    case GE:
628250397Sobrien      strcpy (string, "brgez");
628350397Sobrien      break;
628450397Sobrien
628550397Sobrien    case LT:
628650397Sobrien      strcpy (string, "brlz");
628750397Sobrien      break;
628850397Sobrien
628950397Sobrien    case LE:
629050397Sobrien      strcpy (string, "brlez");
629150397Sobrien      break;
629250397Sobrien
629350397Sobrien    case GT:
629450397Sobrien      strcpy (string, "brgz");
629550397Sobrien      break;
629650397Sobrien
629750397Sobrien    default:
6298169689Skan      gcc_unreachable ();
629950397Sobrien    }
630050397Sobrien
630196263Sobrien  p = strchr (string, '\0');
630296263Sobrien
630350397Sobrien  /* Now add the annulling, reg, label, and nop.  */
630496263Sobrien  if (annul && ! far)
630552284Sobrien    {
630696263Sobrien      strcpy (p, ",a");
630796263Sobrien      p += 2;
630852284Sobrien    }
630950397Sobrien
631096263Sobrien  if (insn && (note = find_reg_note (insn, REG_BR_PROB, NULL_RTX)))
631152284Sobrien    {
631296263Sobrien      strcpy (p,
631396263Sobrien	      ((INTVAL (XEXP (note, 0)) >= REG_BR_PROB_BASE / 2) ^ far)
631496263Sobrien	      ? ",pt" : ",pn");
631596263Sobrien      p += 3;
631652284Sobrien    }
631750397Sobrien
631896263Sobrien  *p = p < string + 8 ? '\t' : ' ';
631996263Sobrien  p++;
632096263Sobrien  *p++ = '%';
632196263Sobrien  *p++ = '0' + reg;
632296263Sobrien  *p++ = ',';
632396263Sobrien  *p++ = ' ';
632496263Sobrien  if (far)
632596263Sobrien    {
632696263Sobrien      int veryfar = 1, delta;
632750397Sobrien
632896263Sobrien      if (INSN_ADDRESSES_SET_P ())
632996263Sobrien	{
633096263Sobrien	  delta = (INSN_ADDRESSES (INSN_UID (dest))
633196263Sobrien		   - INSN_ADDRESSES (INSN_UID (insn)));
633296263Sobrien	  /* Leave some instructions for "slop".  */
633396263Sobrien	  if (delta >= -260000 && delta < 260000)
633496263Sobrien	    veryfar = 0;
633596263Sobrien	}
633696263Sobrien
6337169689Skan      strcpy (p, ".+12\n\t nop\n\t");
6338169689Skan      /* Skip the next insn if requested or
6339169689Skan	 if we know that it will be a nop.  */
6340169689Skan      if (annul || ! final_sequence)
634196263Sobrien        p[3] = '6';
6342169689Skan      p += 12;
634396263Sobrien      if (veryfar)
634496263Sobrien	{
634596263Sobrien	  strcpy (p, "b\t");
634696263Sobrien	  p += 2;
634796263Sobrien	}
634896263Sobrien      else
634996263Sobrien	{
635096263Sobrien	  strcpy (p, "ba,pt\t%%xcc, ");
635196263Sobrien	  p += 13;
635296263Sobrien	}
635396263Sobrien    }
635496263Sobrien  *p++ = '%';
635596263Sobrien  *p++ = 'l';
635696263Sobrien  *p++ = '0' + label;
6357169689Skan  *p++ = '%';
6358169689Skan  *p++ = '#';
635996263Sobrien  *p = '\0';
636096263Sobrien
636150397Sobrien  return string;
636250397Sobrien}
636350397Sobrien
636490075Sobrien/* Return 1, if any of the registers of the instruction are %l[0-7] or %o[0-7].
636590075Sobrien   Such instructions cannot be used in the delay slot of return insn on v9.
636690075Sobrien   If TEST is 0, also rename all %i[0-7] registers to their %o[0-7] counterparts.
636790075Sobrien */
636850397Sobrien
636990075Sobrienstatic int
6370132718Skanepilogue_renumber (register rtx *where, int test)
637150397Sobrien{
637290075Sobrien  register const char *fmt;
637390075Sobrien  register int i;
637490075Sobrien  register enum rtx_code code;
637550397Sobrien
637690075Sobrien  if (*where == 0)
637790075Sobrien    return 0;
637890075Sobrien
637990075Sobrien  code = GET_CODE (*where);
638090075Sobrien
638150397Sobrien  switch (code)
638250397Sobrien    {
638350397Sobrien    case REG:
638490075Sobrien      if (REGNO (*where) >= 8 && REGNO (*where) < 24)      /* oX or lX */
638590075Sobrien	return 1;
638690075Sobrien      if (! test && REGNO (*where) >= 24 && REGNO (*where) < 32)
6387169689Skan	*where = gen_rtx_REG (GET_MODE (*where), OUTGOING_REGNO (REGNO(*where)));
638890075Sobrien    case SCRATCH:
638990075Sobrien    case CC0:
639090075Sobrien    case PC:
639150397Sobrien    case CONST_INT:
639250397Sobrien    case CONST_DOUBLE:
639390075Sobrien      return 0;
639450397Sobrien
639590075Sobrien      /* Do not replace the frame pointer with the stack pointer because
639690075Sobrien	 it can cause the delayed instruction to load below the stack.
639790075Sobrien	 This occurs when instructions like:
639890075Sobrien
639990075Sobrien	 (set (reg/i:SI 24 %i0)
640090075Sobrien	     (mem/f:SI (plus:SI (reg/f:SI 30 %fp)
640190075Sobrien                       (const_int -20 [0xffffffec])) 0))
640290075Sobrien
640390075Sobrien	 are in the return delayed slot.  */
640450397Sobrien    case PLUS:
640590075Sobrien      if (GET_CODE (XEXP (*where, 0)) == REG
640696263Sobrien	  && REGNO (XEXP (*where, 0)) == HARD_FRAME_POINTER_REGNUM
640790075Sobrien	  && (GET_CODE (XEXP (*where, 1)) != CONST_INT
640890075Sobrien	      || INTVAL (XEXP (*where, 1)) < SPARC_STACK_BIAS))
640990075Sobrien	return 1;
641090075Sobrien      break;
641150397Sobrien
641290075Sobrien    case MEM:
641390075Sobrien      if (SPARC_STACK_BIAS
641490075Sobrien	  && GET_CODE (XEXP (*where, 0)) == REG
641596263Sobrien	  && REGNO (XEXP (*where, 0)) == HARD_FRAME_POINTER_REGNUM)
641690075Sobrien	return 1;
641790075Sobrien      break;
641890075Sobrien
641950397Sobrien    default:
642090075Sobrien      break;
642150397Sobrien    }
642290075Sobrien
642390075Sobrien  fmt = GET_RTX_FORMAT (code);
642490075Sobrien
642590075Sobrien  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
642690075Sobrien    {
642790075Sobrien      if (fmt[i] == 'E')
642890075Sobrien	{
642990075Sobrien	  register int j;
643090075Sobrien	  for (j = XVECLEN (*where, i) - 1; j >= 0; j--)
643190075Sobrien	    if (epilogue_renumber (&(XVECEXP (*where, i, j)), test))
643290075Sobrien	      return 1;
643390075Sobrien	}
643490075Sobrien      else if (fmt[i] == 'e'
643590075Sobrien	       && epilogue_renumber (&(XEXP (*where, i)), test))
643690075Sobrien	return 1;
643790075Sobrien    }
643890075Sobrien  return 0;
643950397Sobrien}
644050397Sobrien
644150397Sobrien/* Leaf functions and non-leaf functions have different needs.  */
644250397Sobrien
644390075Sobrienstatic const int
644450397Sobrienreg_leaf_alloc_order[] = REG_LEAF_ALLOC_ORDER;
644550397Sobrien
644690075Sobrienstatic const int
644750397Sobrienreg_nonleaf_alloc_order[] = REG_ALLOC_ORDER;
644850397Sobrien
644990075Sobrienstatic const int *const reg_alloc_orders[] = {
645050397Sobrien  reg_leaf_alloc_order,
645150397Sobrien  reg_nonleaf_alloc_order};
645250397Sobrien
645350397Sobrienvoid
6454132718Skanorder_regs_for_local_alloc (void)
645550397Sobrien{
645650397Sobrien  static int last_order_nonleaf = 1;
645750397Sobrien
645850397Sobrien  if (regs_ever_live[15] != last_order_nonleaf)
645950397Sobrien    {
646050397Sobrien      last_order_nonleaf = !last_order_nonleaf;
646190075Sobrien      memcpy ((char *) reg_alloc_order,
646290075Sobrien	      (const char *) reg_alloc_orders[last_order_nonleaf],
646390075Sobrien	      FIRST_PSEUDO_REGISTER * sizeof (int));
646450397Sobrien    }
646550397Sobrien}
646650397Sobrien
646752284Sobrien/* Return 1 if REG and MEM are legitimate enough to allow the various
646852284Sobrien   mem<-->reg splits to be run.  */
646952284Sobrien
647052284Sobrienint
6471132718Skansparc_splitdi_legitimate (rtx reg, rtx mem)
647252284Sobrien{
647352284Sobrien  /* Punt if we are here by mistake.  */
6474169689Skan  gcc_assert (reload_completed);
647552284Sobrien
647652284Sobrien  /* We must have an offsettable memory reference.  */
647752284Sobrien  if (! offsettable_memref_p (mem))
647852284Sobrien    return 0;
647952284Sobrien
648052284Sobrien  /* If we have legitimate args for ldd/std, we do not want
648152284Sobrien     the split to happen.  */
648252284Sobrien  if ((REGNO (reg) % 2) == 0
648352284Sobrien      && mem_min_alignment (mem, 8))
648452284Sobrien    return 0;
648552284Sobrien
648652284Sobrien  /* Success.  */
648752284Sobrien  return 1;
648852284Sobrien}
648952284Sobrien
649052284Sobrien/* Return 1 if x and y are some kind of REG and they refer to
6491132718Skan   different hard registers.  This test is guaranteed to be
649252284Sobrien   run after reload.  */
649352284Sobrien
649452284Sobrienint
6495132718Skansparc_absnegfloat_split_legitimate (rtx x, rtx y)
649652284Sobrien{
649752284Sobrien  if (GET_CODE (x) != REG)
649852284Sobrien    return 0;
649952284Sobrien  if (GET_CODE (y) != REG)
650052284Sobrien    return 0;
650152284Sobrien  if (REGNO (x) == REGNO (y))
650252284Sobrien    return 0;
650352284Sobrien  return 1;
650452284Sobrien}
650552284Sobrien
650650397Sobrien/* Return 1 if REGNO (reg1) is even and REGNO (reg1) == REGNO (reg2) - 1.
650750397Sobrien   This makes them candidates for using ldd and std insns.
650850397Sobrien
650950397Sobrien   Note reg1 and reg2 *must* be hard registers.  */
651050397Sobrien
651150397Sobrienint
6512132718Skanregisters_ok_for_ldd_peep (rtx reg1, rtx reg2)
651350397Sobrien{
651450397Sobrien  /* We might have been passed a SUBREG.  */
651550397Sobrien  if (GET_CODE (reg1) != REG || GET_CODE (reg2) != REG)
651650397Sobrien    return 0;
651750397Sobrien
651850397Sobrien  if (REGNO (reg1) % 2 != 0)
651950397Sobrien    return 0;
652050397Sobrien
652150397Sobrien  /* Integer ldd is deprecated in SPARC V9 */
652250397Sobrien  if (TARGET_V9 && REGNO (reg1) < 32)
652350397Sobrien    return 0;
652450397Sobrien
652550397Sobrien  return (REGNO (reg1) == REGNO (reg2) - 1);
652650397Sobrien}
652750397Sobrien
652890075Sobrien/* Return 1 if the addresses in mem1 and mem2 are suitable for use in
652990075Sobrien   an ldd or std insn.
653090075Sobrien
653190075Sobrien   This can only happen when addr1 and addr2, the addresses in mem1
653290075Sobrien   and mem2, are consecutive memory locations (addr1 + 4 == addr2).
653390075Sobrien   addr1 must also be aligned on a 64-bit boundary.
653450397Sobrien
653590075Sobrien   Also iff dependent_reg_rtx is not null it should not be used to
653690075Sobrien   compute the address for mem1, i.e. we cannot optimize a sequence
653790075Sobrien   like:
653890075Sobrien   	ld [%o0], %o0
653990075Sobrien	ld [%o0 + 4], %o1
654090075Sobrien   to
654190075Sobrien   	ldd [%o0], %o0
654296263Sobrien   nor:
654396263Sobrien	ld [%g3 + 4], %g3
654496263Sobrien	ld [%g3], %g2
654596263Sobrien   to
654696263Sobrien        ldd [%g3], %g2
654796263Sobrien
654896263Sobrien   But, note that the transformation from:
654996263Sobrien	ld [%g2 + 4], %g3
655096263Sobrien        ld [%g2], %g2
655196263Sobrien   to
655296263Sobrien	ldd [%g2], %g2
655396263Sobrien   is perfectly fine.  Thus, the peephole2 patterns always pass us
655496263Sobrien   the destination register of the first load, never the second one.
655596263Sobrien
655690075Sobrien   For stores we don't have a similar problem, so dependent_reg_rtx is
655790075Sobrien   NULL_RTX.  */
655850397Sobrien
655950397Sobrienint
6560132718Skanmems_ok_for_ldd_peep (rtx mem1, rtx mem2, rtx dependent_reg_rtx)
656150397Sobrien{
656290075Sobrien  rtx addr1, addr2;
656390075Sobrien  unsigned int reg1;
6564132718Skan  HOST_WIDE_INT offset1;
656550397Sobrien
656690075Sobrien  /* The mems cannot be volatile.  */
656790075Sobrien  if (MEM_VOLATILE_P (mem1) || MEM_VOLATILE_P (mem2))
656890075Sobrien    return 0;
656990075Sobrien
657090075Sobrien  /* MEM1 should be aligned on a 64-bit boundary.  */
657190075Sobrien  if (MEM_ALIGN (mem1) < 64)
657290075Sobrien    return 0;
657390075Sobrien
657490075Sobrien  addr1 = XEXP (mem1, 0);
657590075Sobrien  addr2 = XEXP (mem2, 0);
657690075Sobrien
657750397Sobrien  /* Extract a register number and offset (if used) from the first addr.  */
657850397Sobrien  if (GET_CODE (addr1) == PLUS)
657950397Sobrien    {
658050397Sobrien      /* If not a REG, return zero.  */
658150397Sobrien      if (GET_CODE (XEXP (addr1, 0)) != REG)
658250397Sobrien	return 0;
658350397Sobrien      else
658450397Sobrien	{
658550397Sobrien          reg1 = REGNO (XEXP (addr1, 0));
658650397Sobrien	  /* The offset must be constant!  */
658750397Sobrien	  if (GET_CODE (XEXP (addr1, 1)) != CONST_INT)
658850397Sobrien            return 0;
658950397Sobrien          offset1 = INTVAL (XEXP (addr1, 1));
659050397Sobrien	}
659150397Sobrien    }
659250397Sobrien  else if (GET_CODE (addr1) != REG)
659350397Sobrien    return 0;
659450397Sobrien  else
659550397Sobrien    {
659650397Sobrien      reg1 = REGNO (addr1);
659750397Sobrien      /* This was a simple (mem (reg)) expression.  Offset is 0.  */
659850397Sobrien      offset1 = 0;
659950397Sobrien    }
660050397Sobrien
660150397Sobrien  /* Make sure the second address is a (mem (plus (reg) (const_int).  */
660250397Sobrien  if (GET_CODE (addr2) != PLUS)
660350397Sobrien    return 0;
660450397Sobrien
660550397Sobrien  if (GET_CODE (XEXP (addr2, 0)) != REG
660650397Sobrien      || GET_CODE (XEXP (addr2, 1)) != CONST_INT)
660750397Sobrien    return 0;
660850397Sobrien
660990075Sobrien  if (reg1 != REGNO (XEXP (addr2, 0)))
661050397Sobrien    return 0;
661150397Sobrien
661290075Sobrien  if (dependent_reg_rtx != NULL_RTX && reg1 == REGNO (dependent_reg_rtx))
661350397Sobrien    return 0;
661490075Sobrien
661550397Sobrien  /* The first offset must be evenly divisible by 8 to ensure the
661650397Sobrien     address is 64 bit aligned.  */
661750397Sobrien  if (offset1 % 8 != 0)
661850397Sobrien    return 0;
661950397Sobrien
662050397Sobrien  /* The offset for the second addr must be 4 more than the first addr.  */
662150397Sobrien  if (INTVAL (XEXP (addr2, 1)) != offset1 + 4)
662250397Sobrien    return 0;
662350397Sobrien
662450397Sobrien  /* All the tests passed.  addr1 and addr2 are valid for ldd and std
662550397Sobrien     instructions.  */
662650397Sobrien  return 1;
662750397Sobrien}
662850397Sobrien
662950397Sobrien/* Return 1 if reg is a pseudo, or is the first register in
663050397Sobrien   a hard register pair.  This makes it a candidate for use in
663150397Sobrien   ldd and std insns.  */
663250397Sobrien
663350397Sobrienint
6634132718Skanregister_ok_for_ldd (rtx reg)
663550397Sobrien{
663650397Sobrien  /* We might have been passed a SUBREG.  */
663750397Sobrien  if (GET_CODE (reg) != REG)
663850397Sobrien    return 0;
663950397Sobrien
664050397Sobrien  if (REGNO (reg) < FIRST_PSEUDO_REGISTER)
664150397Sobrien    return (REGNO (reg) % 2 == 0);
664250397Sobrien  else
664350397Sobrien    return 1;
664450397Sobrien}
664550397Sobrien
664650397Sobrien/* Print operand X (an rtx) in assembler syntax to file FILE.
664750397Sobrien   CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
664850397Sobrien   For `%' followed by punctuation, CODE is the punctuation and X is null.  */
664950397Sobrien
665050397Sobrienvoid
6651132718Skanprint_operand (FILE *file, rtx x, int code)
665250397Sobrien{
665350397Sobrien  switch (code)
665450397Sobrien    {
665550397Sobrien    case '#':
6656169689Skan      /* Output an insn in a delay slot.  */
6657169689Skan      if (final_sequence)
6658169689Skan        sparc_indent_opcode = 1;
6659169689Skan      else
666052284Sobrien	fputs ("\n\t nop", file);
666150397Sobrien      return;
666250397Sobrien    case '*':
666350397Sobrien      /* Output an annul flag if there's nothing for the delay slot and we
6664169689Skan	 are optimizing.  This is always used with '(' below.
6665169689Skan         Sun OS 4.1.1 dbx can't handle an annulled unconditional branch;
6666169689Skan	 this is a dbx bug.  So, we only do this when optimizing.
6667169689Skan         On UltraSPARC, a branch in a delay slot causes a pipeline flush.
666850397Sobrien	 Always emit a nop in case the next instruction is a branch.  */
6669169689Skan      if (! final_sequence && (optimize && (int)sparc_cpu < PROCESSOR_V9))
667050397Sobrien	fputs (",a", file);
667150397Sobrien      return;
667250397Sobrien    case '(':
667350397Sobrien      /* Output a 'nop' if there's nothing for the delay slot and we are
667450397Sobrien	 not optimizing.  This is always used with '*' above.  */
6675169689Skan      if (! final_sequence && ! (optimize && (int)sparc_cpu < PROCESSOR_V9))
667652284Sobrien	fputs ("\n\t nop", file);
6677169689Skan      else if (final_sequence)
6678169689Skan        sparc_indent_opcode = 1;
667950397Sobrien      return;
6680169689Skan    case ')':
6681169689Skan      /* Output the right displacement from the saved PC on function return.
6682169689Skan	 The caller may have placed an "unimp" insn immediately after the call
6683169689Skan	 so we have to account for it.  This insn is used in the 32-bit ABI
6684169689Skan	 when calling a function that returns a non zero-sized structure. The
6685169689Skan	 64-bit ABI doesn't have it.  Be careful to have this test be the same
6686169689Skan	 as that used on the call. The exception here is that when
6687169689Skan	 sparc_std_struct_return is enabled, the psABI is followed exactly
6688169689Skan	 and the adjustment is made by the code in sparc_struct_value_rtx.
6689169689Skan	 The call emitted is the same when sparc_std_struct_return is
6690169689Skan	 present. */
6691169689Skan     if (! TARGET_ARCH64
6692169689Skan	 && current_function_returns_struct
6693169689Skan	 && ! sparc_std_struct_return
6694169689Skan	 && (TREE_CODE (DECL_SIZE (DECL_RESULT (current_function_decl)))
6695169689Skan	     == INTEGER_CST)
6696169689Skan	 && ! integer_zerop (DECL_SIZE (DECL_RESULT (current_function_decl))))
6697169689Skan	fputs ("12", file);
6698169689Skan      else
6699169689Skan        fputc ('8', file);
6700169689Skan      return;
670150397Sobrien    case '_':
670250397Sobrien      /* Output the Embedded Medium/Anywhere code model base register.  */
670350397Sobrien      fputs (EMBMEDANY_BASE_REG, file);
670450397Sobrien      return;
6705132718Skan    case '&':
6706132718Skan      /* Print some local dynamic TLS name.  */
6707132718Skan      assemble_name (file, get_some_local_dynamic_name ());
6708132718Skan      return;
6709169689Skan
671050397Sobrien    case 'Y':
671150397Sobrien      /* Adjust the operand to take into account a RESTORE operation.  */
671250397Sobrien      if (GET_CODE (x) == CONST_INT)
671350397Sobrien	break;
671450397Sobrien      else if (GET_CODE (x) != REG)
671590075Sobrien	output_operand_lossage ("invalid %%Y operand");
671650397Sobrien      else if (REGNO (x) < 8)
671750397Sobrien	fputs (reg_names[REGNO (x)], file);
671850397Sobrien      else if (REGNO (x) >= 24 && REGNO (x) < 32)
671950397Sobrien	fputs (reg_names[REGNO (x)-16], file);
672050397Sobrien      else
672190075Sobrien	output_operand_lossage ("invalid %%Y operand");
672250397Sobrien      return;
672350397Sobrien    case 'L':
672450397Sobrien      /* Print out the low order register name of a register pair.  */
672550397Sobrien      if (WORDS_BIG_ENDIAN)
672650397Sobrien	fputs (reg_names[REGNO (x)+1], file);
672750397Sobrien      else
672850397Sobrien	fputs (reg_names[REGNO (x)], file);
672950397Sobrien      return;
673050397Sobrien    case 'H':
673150397Sobrien      /* Print out the high order register name of a register pair.  */
673250397Sobrien      if (WORDS_BIG_ENDIAN)
673350397Sobrien	fputs (reg_names[REGNO (x)], file);
673450397Sobrien      else
673550397Sobrien	fputs (reg_names[REGNO (x)+1], file);
673650397Sobrien      return;
673750397Sobrien    case 'R':
673850397Sobrien      /* Print out the second register name of a register pair or quad.
673950397Sobrien	 I.e., R (%o0) => %o1.  */
674050397Sobrien      fputs (reg_names[REGNO (x)+1], file);
674150397Sobrien      return;
674250397Sobrien    case 'S':
674350397Sobrien      /* Print out the third register name of a register quad.
674450397Sobrien	 I.e., S (%o0) => %o2.  */
674550397Sobrien      fputs (reg_names[REGNO (x)+2], file);
674650397Sobrien      return;
674750397Sobrien    case 'T':
674850397Sobrien      /* Print out the fourth register name of a register quad.
674950397Sobrien	 I.e., T (%o0) => %o3.  */
675050397Sobrien      fputs (reg_names[REGNO (x)+3], file);
675150397Sobrien      return;
675250397Sobrien    case 'x':
675350397Sobrien      /* Print a condition code register.  */
675450397Sobrien      if (REGNO (x) == SPARC_ICC_REG)
675550397Sobrien	{
675650397Sobrien	  /* We don't handle CC[X]_NOOVmode because they're not supposed
675750397Sobrien	     to occur here.  */
675850397Sobrien	  if (GET_MODE (x) == CCmode)
675950397Sobrien	    fputs ("%icc", file);
676050397Sobrien	  else if (GET_MODE (x) == CCXmode)
676150397Sobrien	    fputs ("%xcc", file);
676250397Sobrien	  else
6763169689Skan	    gcc_unreachable ();
676450397Sobrien	}
676550397Sobrien      else
676650397Sobrien	/* %fccN register */
676750397Sobrien	fputs (reg_names[REGNO (x)], file);
676850397Sobrien      return;
676950397Sobrien    case 'm':
677050397Sobrien      /* Print the operand's address only.  */
677150397Sobrien      output_address (XEXP (x, 0));
677250397Sobrien      return;
677350397Sobrien    case 'r':
677450397Sobrien      /* In this case we need a register.  Use %g0 if the
677550397Sobrien	 operand is const0_rtx.  */
677650397Sobrien      if (x == const0_rtx
677750397Sobrien	  || (GET_MODE (x) != VOIDmode && x == CONST0_RTX (GET_MODE (x))))
677850397Sobrien	{
677950397Sobrien	  fputs ("%g0", file);
678050397Sobrien	  return;
678150397Sobrien	}
678250397Sobrien      else
678350397Sobrien	break;
678450397Sobrien
678550397Sobrien    case 'A':
678650397Sobrien      switch (GET_CODE (x))
678750397Sobrien	{
678850397Sobrien	case IOR: fputs ("or", file); break;
678950397Sobrien	case AND: fputs ("and", file); break;
679050397Sobrien	case XOR: fputs ("xor", file); break;
679190075Sobrien	default: output_operand_lossage ("invalid %%A operand");
679250397Sobrien	}
679350397Sobrien      return;
679450397Sobrien
679550397Sobrien    case 'B':
679650397Sobrien      switch (GET_CODE (x))
679750397Sobrien	{
679850397Sobrien	case IOR: fputs ("orn", file); break;
679950397Sobrien	case AND: fputs ("andn", file); break;
680050397Sobrien	case XOR: fputs ("xnor", file); break;
680190075Sobrien	default: output_operand_lossage ("invalid %%B operand");
680250397Sobrien	}
680350397Sobrien      return;
680450397Sobrien
680550397Sobrien      /* These are used by the conditional move instructions.  */
680650397Sobrien    case 'c' :
680750397Sobrien    case 'C':
680850397Sobrien      {
680990075Sobrien	enum rtx_code rc = GET_CODE (x);
681090075Sobrien
681190075Sobrien	if (code == 'c')
681290075Sobrien	  {
681390075Sobrien	    enum machine_mode mode = GET_MODE (XEXP (x, 0));
681490075Sobrien	    if (mode == CCFPmode || mode == CCFPEmode)
681590075Sobrien	      rc = reverse_condition_maybe_unordered (GET_CODE (x));
681690075Sobrien	    else
681790075Sobrien	      rc = reverse_condition (GET_CODE (x));
681890075Sobrien	  }
681950397Sobrien	switch (rc)
682050397Sobrien	  {
682150397Sobrien	  case NE: fputs ("ne", file); break;
682250397Sobrien	  case EQ: fputs ("e", file); break;
682350397Sobrien	  case GE: fputs ("ge", file); break;
682450397Sobrien	  case GT: fputs ("g", file); break;
682550397Sobrien	  case LE: fputs ("le", file); break;
682650397Sobrien	  case LT: fputs ("l", file); break;
682750397Sobrien	  case GEU: fputs ("geu", file); break;
682850397Sobrien	  case GTU: fputs ("gu", file); break;
682950397Sobrien	  case LEU: fputs ("leu", file); break;
683050397Sobrien	  case LTU: fputs ("lu", file); break;
683190075Sobrien	  case LTGT: fputs ("lg", file); break;
683290075Sobrien	  case UNORDERED: fputs ("u", file); break;
683390075Sobrien	  case ORDERED: fputs ("o", file); break;
683490075Sobrien	  case UNLT: fputs ("ul", file); break;
683590075Sobrien	  case UNLE: fputs ("ule", file); break;
683690075Sobrien	  case UNGT: fputs ("ug", file); break;
683790075Sobrien	  case UNGE: fputs ("uge", file); break;
683890075Sobrien	  case UNEQ: fputs ("ue", file); break;
683950397Sobrien	  default: output_operand_lossage (code == 'c'
684090075Sobrien					   ? "invalid %%c operand"
684190075Sobrien					   : "invalid %%C operand");
684250397Sobrien	  }
684350397Sobrien	return;
684450397Sobrien      }
684550397Sobrien
684650397Sobrien      /* These are used by the movr instruction pattern.  */
684750397Sobrien    case 'd':
684850397Sobrien    case 'D':
684950397Sobrien      {
685050397Sobrien	enum rtx_code rc = (code == 'd'
685150397Sobrien			    ? reverse_condition (GET_CODE (x))
685250397Sobrien			    : GET_CODE (x));
685350397Sobrien	switch (rc)
685450397Sobrien	  {
685550397Sobrien	  case NE: fputs ("ne", file); break;
685650397Sobrien	  case EQ: fputs ("e", file); break;
685750397Sobrien	  case GE: fputs ("gez", file); break;
685850397Sobrien	  case LT: fputs ("lz", file); break;
685950397Sobrien	  case LE: fputs ("lez", file); break;
686050397Sobrien	  case GT: fputs ("gz", file); break;
686150397Sobrien	  default: output_operand_lossage (code == 'd'
686290075Sobrien					   ? "invalid %%d operand"
686390075Sobrien					   : "invalid %%D operand");
686450397Sobrien	  }
686550397Sobrien	return;
686650397Sobrien      }
686750397Sobrien
686850397Sobrien    case 'b':
686950397Sobrien      {
687050397Sobrien	/* Print a sign-extended character.  */
687196263Sobrien	int i = trunc_int_for_mode (INTVAL (x), QImode);
687250397Sobrien	fprintf (file, "%d", i);
687350397Sobrien	return;
687450397Sobrien      }
687550397Sobrien
687650397Sobrien    case 'f':
687750397Sobrien      /* Operand must be a MEM; write its address.  */
687850397Sobrien      if (GET_CODE (x) != MEM)
687990075Sobrien	output_operand_lossage ("invalid %%f operand");
688050397Sobrien      output_address (XEXP (x, 0));
688150397Sobrien      return;
688250397Sobrien
6883117395Skan    case 's':
6884117395Skan      {
6885117395Skan	/* Print a sign-extended 32-bit value.  */
6886117395Skan	HOST_WIDE_INT i;
6887117395Skan	if (GET_CODE(x) == CONST_INT)
6888117395Skan	  i = INTVAL (x);
6889117395Skan	else if (GET_CODE(x) == CONST_DOUBLE)
6890117395Skan	  i = CONST_DOUBLE_LOW (x);
6891117395Skan	else
6892117395Skan	  {
6893117395Skan	    output_operand_lossage ("invalid %%s operand");
6894117395Skan	    return;
6895117395Skan	  }
6896117395Skan	i = trunc_int_for_mode (i, SImode);
6897117395Skan	fprintf (file, HOST_WIDE_INT_PRINT_DEC, i);
6898117395Skan	return;
6899117395Skan      }
6900117395Skan
690150397Sobrien    case 0:
690250397Sobrien      /* Do nothing special.  */
690350397Sobrien      break;
690450397Sobrien
690550397Sobrien    default:
690650397Sobrien      /* Undocumented flag.  */
690750397Sobrien      output_operand_lossage ("invalid operand output code");
690850397Sobrien    }
690950397Sobrien
691050397Sobrien  if (GET_CODE (x) == REG)
691150397Sobrien    fputs (reg_names[REGNO (x)], file);
691250397Sobrien  else if (GET_CODE (x) == MEM)
691350397Sobrien    {
691450397Sobrien      fputc ('[', file);
691550397Sobrien	/* Poor Sun assembler doesn't understand absolute addressing.  */
691690075Sobrien      if (CONSTANT_P (XEXP (x, 0)))
691750397Sobrien	fputs ("%g0+", file);
691850397Sobrien      output_address (XEXP (x, 0));
691950397Sobrien      fputc (']', file);
692050397Sobrien    }
692150397Sobrien  else if (GET_CODE (x) == HIGH)
692250397Sobrien    {
692350397Sobrien      fputs ("%hi(", file);
692450397Sobrien      output_addr_const (file, XEXP (x, 0));
692550397Sobrien      fputc (')', file);
692650397Sobrien    }
692750397Sobrien  else if (GET_CODE (x) == LO_SUM)
692850397Sobrien    {
692950397Sobrien      print_operand (file, XEXP (x, 0), 0);
693052284Sobrien      if (TARGET_CM_MEDMID)
693152284Sobrien	fputs ("+%l44(", file);
693252284Sobrien      else
693352284Sobrien	fputs ("+%lo(", file);
693450397Sobrien      output_addr_const (file, XEXP (x, 1));
693550397Sobrien      fputc (')', file);
693650397Sobrien    }
693750397Sobrien  else if (GET_CODE (x) == CONST_DOUBLE
693850397Sobrien	   && (GET_MODE (x) == VOIDmode
693950397Sobrien	       || GET_MODE_CLASS (GET_MODE (x)) == MODE_INT))
694050397Sobrien    {
694150397Sobrien      if (CONST_DOUBLE_HIGH (x) == 0)
694290075Sobrien	fprintf (file, "%u", (unsigned int) CONST_DOUBLE_LOW (x));
694350397Sobrien      else if (CONST_DOUBLE_HIGH (x) == -1
694450397Sobrien	       && CONST_DOUBLE_LOW (x) < 0)
694590075Sobrien	fprintf (file, "%d", (int) CONST_DOUBLE_LOW (x));
694650397Sobrien      else
694750397Sobrien	output_operand_lossage ("long long constant not a valid immediate operand");
694850397Sobrien    }
694950397Sobrien  else if (GET_CODE (x) == CONST_DOUBLE)
695050397Sobrien    output_operand_lossage ("floating point constant not a valid immediate operand");
695150397Sobrien  else { output_addr_const (file, x); }
695250397Sobrien}
695350397Sobrien
695490075Sobrien/* Target hook for assembling integer objects.  The sparc version has
695590075Sobrien   special handling for aligned DI-mode objects.  */
695650397Sobrien
695790075Sobrienstatic bool
6958132718Skansparc_assemble_integer (rtx x, unsigned int size, int aligned_p)
695950397Sobrien{
696090075Sobrien  /* ??? We only output .xword's for symbols and only then in environments
696190075Sobrien     where the assembler can handle them.  */
696290075Sobrien  if (aligned_p && size == 8
696390075Sobrien      && (GET_CODE (x) != CONST_INT && GET_CODE (x) != CONST_DOUBLE))
696450397Sobrien    {
696590075Sobrien      if (TARGET_V9)
696650397Sobrien	{
696790075Sobrien	  assemble_integer_with_op ("\t.xword\t", x);
696890075Sobrien	  return true;
696950397Sobrien	}
697050397Sobrien      else
697150397Sobrien	{
697290075Sobrien	  assemble_aligned_integer (4, const0_rtx);
697390075Sobrien	  assemble_aligned_integer (4, x);
697490075Sobrien	  return true;
697550397Sobrien	}
697650397Sobrien    }
697790075Sobrien  return default_assemble_integer (x, size, aligned_p);
697850397Sobrien}
697950397Sobrien
698050397Sobrien/* Return the value of a code used in the .proc pseudo-op that says
698150397Sobrien   what kind of result this function returns.  For non-C types, we pick
698250397Sobrien   the closest C type.  */
698350397Sobrien
698450397Sobrien#ifndef SHORT_TYPE_SIZE
698550397Sobrien#define SHORT_TYPE_SIZE (BITS_PER_UNIT * 2)
698650397Sobrien#endif
698750397Sobrien
698850397Sobrien#ifndef INT_TYPE_SIZE
698950397Sobrien#define INT_TYPE_SIZE BITS_PER_WORD
699050397Sobrien#endif
699150397Sobrien
699250397Sobrien#ifndef LONG_TYPE_SIZE
699350397Sobrien#define LONG_TYPE_SIZE BITS_PER_WORD
699450397Sobrien#endif
699550397Sobrien
699650397Sobrien#ifndef LONG_LONG_TYPE_SIZE
699750397Sobrien#define LONG_LONG_TYPE_SIZE (BITS_PER_WORD * 2)
699850397Sobrien#endif
699950397Sobrien
700050397Sobrien#ifndef FLOAT_TYPE_SIZE
700150397Sobrien#define FLOAT_TYPE_SIZE BITS_PER_WORD
700250397Sobrien#endif
700350397Sobrien
700450397Sobrien#ifndef DOUBLE_TYPE_SIZE
700550397Sobrien#define DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
700650397Sobrien#endif
700750397Sobrien
700850397Sobrien#ifndef LONG_DOUBLE_TYPE_SIZE
700950397Sobrien#define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
701050397Sobrien#endif
701150397Sobrien
701250397Sobrienunsigned long
7013132718Skansparc_type_code (register tree type)
701450397Sobrien{
701550397Sobrien  register unsigned long qualifiers = 0;
701650397Sobrien  register unsigned shift;
701750397Sobrien
701850397Sobrien  /* Only the first 30 bits of the qualifier are valid.  We must refrain from
701950397Sobrien     setting more, since some assemblers will give an error for this.  Also,
702050397Sobrien     we must be careful to avoid shifts of 32 bits or more to avoid getting
702150397Sobrien     unpredictable results.  */
702250397Sobrien
702350397Sobrien  for (shift = 6; shift < 30; shift += 2, type = TREE_TYPE (type))
702450397Sobrien    {
702550397Sobrien      switch (TREE_CODE (type))
702650397Sobrien	{
702750397Sobrien	case ERROR_MARK:
702850397Sobrien	  return qualifiers;
702950397Sobrien
703050397Sobrien	case ARRAY_TYPE:
703150397Sobrien	  qualifiers |= (3 << shift);
703250397Sobrien	  break;
703350397Sobrien
703450397Sobrien	case FUNCTION_TYPE:
703550397Sobrien	case METHOD_TYPE:
703650397Sobrien	  qualifiers |= (2 << shift);
703750397Sobrien	  break;
703850397Sobrien
703950397Sobrien	case POINTER_TYPE:
704050397Sobrien	case REFERENCE_TYPE:
704150397Sobrien	case OFFSET_TYPE:
704250397Sobrien	  qualifiers |= (1 << shift);
704350397Sobrien	  break;
704450397Sobrien
704550397Sobrien	case RECORD_TYPE:
704650397Sobrien	  return (qualifiers | 8);
704750397Sobrien
704850397Sobrien	case UNION_TYPE:
704950397Sobrien	case QUAL_UNION_TYPE:
705050397Sobrien	  return (qualifiers | 9);
705150397Sobrien
705250397Sobrien	case ENUMERAL_TYPE:
705350397Sobrien	  return (qualifiers | 10);
705450397Sobrien
705550397Sobrien	case VOID_TYPE:
705650397Sobrien	  return (qualifiers | 16);
705750397Sobrien
705850397Sobrien	case INTEGER_TYPE:
705950397Sobrien	  /* If this is a range type, consider it to be the underlying
706050397Sobrien	     type.  */
706150397Sobrien	  if (TREE_TYPE (type) != 0)
706250397Sobrien	    break;
706350397Sobrien
706450397Sobrien	  /* Carefully distinguish all the standard types of C,
706550397Sobrien	     without messing up if the language is not C.  We do this by
7066169689Skan	     testing TYPE_PRECISION and TYPE_UNSIGNED.  The old code used to
706750397Sobrien	     look at both the names and the above fields, but that's redundant.
706850397Sobrien	     Any type whose size is between two C types will be considered
706950397Sobrien	     to be the wider of the two types.  Also, we do not have a
707050397Sobrien	     special code to use for "long long", so anything wider than
707150397Sobrien	     long is treated the same.  Note that we can't distinguish
707250397Sobrien	     between "int" and "long" in this code if they are the same
707350397Sobrien	     size, but that's fine, since neither can the assembler.  */
707450397Sobrien
707550397Sobrien	  if (TYPE_PRECISION (type) <= CHAR_TYPE_SIZE)
7076169689Skan	    return (qualifiers | (TYPE_UNSIGNED (type) ? 12 : 2));
707750397Sobrien
707850397Sobrien	  else if (TYPE_PRECISION (type) <= SHORT_TYPE_SIZE)
7079169689Skan	    return (qualifiers | (TYPE_UNSIGNED (type) ? 13 : 3));
708050397Sobrien
708150397Sobrien	  else if (TYPE_PRECISION (type) <= INT_TYPE_SIZE)
7082169689Skan	    return (qualifiers | (TYPE_UNSIGNED (type) ? 14 : 4));
708350397Sobrien
708450397Sobrien	  else
7085169689Skan	    return (qualifiers | (TYPE_UNSIGNED (type) ? 15 : 5));
708650397Sobrien
708750397Sobrien	case REAL_TYPE:
708850397Sobrien	  /* If this is a range type, consider it to be the underlying
708950397Sobrien	     type.  */
709050397Sobrien	  if (TREE_TYPE (type) != 0)
709150397Sobrien	    break;
709250397Sobrien
709350397Sobrien	  /* Carefully distinguish all the standard types of C,
709450397Sobrien	     without messing up if the language is not C.  */
709550397Sobrien
709650397Sobrien	  if (TYPE_PRECISION (type) == FLOAT_TYPE_SIZE)
709750397Sobrien	    return (qualifiers | 6);
709850397Sobrien
709950397Sobrien	  else
710050397Sobrien	    return (qualifiers | 7);
710150397Sobrien
710250397Sobrien	case COMPLEX_TYPE:	/* GNU Fortran COMPLEX type.  */
710350397Sobrien	  /* ??? We need to distinguish between double and float complex types,
710450397Sobrien	     but I don't know how yet because I can't reach this code from
710550397Sobrien	     existing front-ends.  */
710650397Sobrien	  return (qualifiers | 7);	/* Who knows? */
710750397Sobrien
7108169689Skan	case VECTOR_TYPE:
7109169689Skan	case BOOLEAN_TYPE:	/* Boolean truth value type.  */
711050397Sobrien	case LANG_TYPE:		/* ? */
711150397Sobrien	  return qualifiers;
711250397Sobrien
711350397Sobrien	default:
7114169689Skan	  gcc_unreachable ();		/* Not a type! */
711550397Sobrien        }
711650397Sobrien    }
711750397Sobrien
711850397Sobrien  return qualifiers;
711950397Sobrien}
712050397Sobrien
712150397Sobrien/* Nested function support.  */
712250397Sobrien
712350397Sobrien/* Emit RTL insns to initialize the variable parts of a trampoline.
712450397Sobrien   FNADDR is an RTX for the address of the function's pure code.
712550397Sobrien   CXT is an RTX for the static chain value for the function.
712650397Sobrien
712750397Sobrien   This takes 16 insns: 2 shifts & 2 ands (to split up addresses), 4 sethi
712850397Sobrien   (to load in opcodes), 4 iors (to merge address and opcodes), and 4 writes
712950397Sobrien   (to store insns).  This is a bit excessive.  Perhaps a different
713050397Sobrien   mechanism would be better here.
713150397Sobrien
713250397Sobrien   Emit enough FLUSH insns to synchronize the data and instruction caches.  */
713350397Sobrien
713450397Sobrienvoid
7135132718Skansparc_initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt)
713650397Sobrien{
7137132718Skan  /* SPARC 32-bit trampoline:
713850397Sobrien
713952284Sobrien 	sethi	%hi(fn), %g1
714052284Sobrien 	sethi	%hi(static), %g2
714152284Sobrien 	jmp	%g1+%lo(fn)
714252284Sobrien 	or	%g2, %lo(static), %g2
714350397Sobrien
714450397Sobrien    SETHI i,r  = 00rr rrr1 00ii iiii iiii iiii iiii iiii
714550397Sobrien    JMPL r+i,d = 10dd ddd1 1100 0rrr rr1i iiii iiii iiii
714650397Sobrien   */
714750397Sobrien
714896263Sobrien  emit_move_insn
714996263Sobrien    (gen_rtx_MEM (SImode, plus_constant (tramp, 0)),
715096263Sobrien     expand_binop (SImode, ior_optab,
715196263Sobrien		   expand_shift (RSHIFT_EXPR, SImode, fnaddr,
715296263Sobrien				 size_int (10), 0, 1),
715396263Sobrien		   GEN_INT (trunc_int_for_mode (0x03000000, SImode)),
715496263Sobrien		   NULL_RTX, 1, OPTAB_DIRECT));
715550397Sobrien
715696263Sobrien  emit_move_insn
715796263Sobrien    (gen_rtx_MEM (SImode, plus_constant (tramp, 4)),
715896263Sobrien     expand_binop (SImode, ior_optab,
715996263Sobrien		   expand_shift (RSHIFT_EXPR, SImode, cxt,
716096263Sobrien				 size_int (10), 0, 1),
716196263Sobrien		   GEN_INT (trunc_int_for_mode (0x05000000, SImode)),
716296263Sobrien		   NULL_RTX, 1, OPTAB_DIRECT));
716350397Sobrien
716496263Sobrien  emit_move_insn
716596263Sobrien    (gen_rtx_MEM (SImode, plus_constant (tramp, 8)),
716696263Sobrien     expand_binop (SImode, ior_optab,
716796263Sobrien		   expand_and (SImode, fnaddr, GEN_INT (0x3ff), NULL_RTX),
716896263Sobrien		   GEN_INT (trunc_int_for_mode (0x81c06000, SImode)),
716996263Sobrien		   NULL_RTX, 1, OPTAB_DIRECT));
717050397Sobrien
717196263Sobrien  emit_move_insn
717296263Sobrien    (gen_rtx_MEM (SImode, plus_constant (tramp, 12)),
717396263Sobrien     expand_binop (SImode, ior_optab,
717496263Sobrien		   expand_and (SImode, cxt, GEN_INT (0x3ff), NULL_RTX),
717596263Sobrien		   GEN_INT (trunc_int_for_mode (0x8410a000, SImode)),
717696263Sobrien		   NULL_RTX, 1, OPTAB_DIRECT));
717750397Sobrien
717850397Sobrien  /* On UltraSPARC a flush flushes an entire cache line.  The trampoline is
717950397Sobrien     aligned on a 16 byte boundary so one flush clears it all.  */
718096263Sobrien  emit_insn (gen_flush (validize_mem (gen_rtx_MEM (SImode, tramp))));
7181117395Skan  if (sparc_cpu != PROCESSOR_ULTRASPARC
7182169689Skan      && sparc_cpu != PROCESSOR_ULTRASPARC3
7183169689Skan      && sparc_cpu != PROCESSOR_NIAGARA)
718450397Sobrien    emit_insn (gen_flush (validize_mem (gen_rtx_MEM (SImode,
718550397Sobrien						     plus_constant (tramp, 8)))));
7186132718Skan
7187132718Skan  /* Call __enable_execute_stack after writing onto the stack to make sure
7188132718Skan     the stack address is accessible.  */
7189132718Skan#ifdef ENABLE_EXECUTE_STACK
7190169689Skan  emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__enable_execute_stack"),
7191132718Skan                     LCT_NORMAL, VOIDmode, 1, tramp, Pmode);
7192132718Skan#endif
7193132718Skan
719450397Sobrien}
719550397Sobrien
7196132718Skan/* The 64-bit version is simpler because it makes more sense to load the
719750397Sobrien   values as "immediate" data out of the trampoline.  It's also easier since
719850397Sobrien   we can read the PC without clobbering a register.  */
719950397Sobrien
720050397Sobrienvoid
7201132718Skansparc64_initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt)
720250397Sobrien{
7203132718Skan  /* SPARC 64-bit trampoline:
720452284Sobrien
720552284Sobrien	rd	%pc, %g1
720652284Sobrien	ldx	[%g1+24], %g5
720752284Sobrien	jmp	%g5
720852284Sobrien	ldx	[%g1+16], %g5
720950397Sobrien	+16 bytes data
721050397Sobrien   */
721150397Sobrien
721250397Sobrien  emit_move_insn (gen_rtx_MEM (SImode, tramp),
721396263Sobrien		  GEN_INT (trunc_int_for_mode (0x83414000, SImode)));
721450397Sobrien  emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 4)),
721596263Sobrien		  GEN_INT (trunc_int_for_mode (0xca586018, SImode)));
721650397Sobrien  emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 8)),
721796263Sobrien		  GEN_INT (trunc_int_for_mode (0x81c14000, SImode)));
721850397Sobrien  emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 12)),
721996263Sobrien		  GEN_INT (trunc_int_for_mode (0xca586010, SImode)));
722050397Sobrien  emit_move_insn (gen_rtx_MEM (DImode, plus_constant (tramp, 16)), cxt);
722152284Sobrien  emit_move_insn (gen_rtx_MEM (DImode, plus_constant (tramp, 24)), fnaddr);
722290075Sobrien  emit_insn (gen_flushdi (validize_mem (gen_rtx_MEM (DImode, tramp))));
722352284Sobrien
7224117395Skan  if (sparc_cpu != PROCESSOR_ULTRASPARC
7225169689Skan      && sparc_cpu != PROCESSOR_ULTRASPARC3
7226169689Skan      && sparc_cpu != PROCESSOR_NIAGARA)
722790075Sobrien    emit_insn (gen_flushdi (validize_mem (gen_rtx_MEM (DImode, plus_constant (tramp, 8)))));
7228132718Skan
7229132718Skan  /* Call __enable_execute_stack after writing onto the stack to make sure
7230132718Skan     the stack address is accessible.  */
7231132718Skan#ifdef ENABLE_EXECUTE_STACK
7232169689Skan  emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__enable_execute_stack"),
7233132718Skan                     LCT_NORMAL, VOIDmode, 1, tramp, Pmode);
7234132718Skan#endif
723550397Sobrien}
723650397Sobrien
723750397Sobrien/* Adjust the cost of a scheduling dependency.  Return the new cost of
723850397Sobrien   a dependency LINK or INSN on DEP_INSN.  COST is the current cost.  */
723950397Sobrien
724052284Sobrienstatic int
7241132718Skansupersparc_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
724250397Sobrien{
724350397Sobrien  enum attr_type insn_type;
724450397Sobrien
724550397Sobrien  if (! recog_memoized (insn))
724650397Sobrien    return 0;
724750397Sobrien
724850397Sobrien  insn_type = get_attr_type (insn);
724950397Sobrien
725050397Sobrien  if (REG_NOTE_KIND (link) == 0)
725150397Sobrien    {
725250397Sobrien      /* Data dependency; DEP_INSN writes a register that INSN reads some
725350397Sobrien	 cycles later.  */
725450397Sobrien
725550397Sobrien      /* if a load, then the dependence must be on the memory address;
725652284Sobrien	 add an extra "cycle".  Note that the cost could be two cycles
725752284Sobrien	 if the reg was written late in an instruction group; we ca not tell
725850397Sobrien	 here.  */
725950397Sobrien      if (insn_type == TYPE_LOAD || insn_type == TYPE_FPLOAD)
726050397Sobrien	return cost + 3;
726150397Sobrien
726250397Sobrien      /* Get the delay only if the address of the store is the dependence.  */
726350397Sobrien      if (insn_type == TYPE_STORE || insn_type == TYPE_FPSTORE)
726450397Sobrien	{
726550397Sobrien	  rtx pat = PATTERN(insn);
726650397Sobrien	  rtx dep_pat = PATTERN (dep_insn);
726750397Sobrien
726850397Sobrien	  if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
726952284Sobrien	    return cost;  /* This should not happen!  */
727050397Sobrien
727150397Sobrien	  /* The dependency between the two instructions was on the data that
727250397Sobrien	     is being stored.  Assume that this implies that the address of the
727350397Sobrien	     store is not dependent.  */
727450397Sobrien	  if (rtx_equal_p (SET_DEST (dep_pat), SET_SRC (pat)))
727550397Sobrien	    return cost;
727650397Sobrien
727750397Sobrien	  return cost + 3;  /* An approximation.  */
727850397Sobrien	}
727950397Sobrien
728050397Sobrien      /* A shift instruction cannot receive its data from an instruction
728150397Sobrien	 in the same cycle; add a one cycle penalty.  */
728250397Sobrien      if (insn_type == TYPE_SHIFT)
728350397Sobrien	return cost + 3;   /* Split before cascade into shift.  */
728450397Sobrien    }
728550397Sobrien  else
728650397Sobrien    {
728750397Sobrien      /* Anti- or output- dependency; DEP_INSN reads/writes a register that
728850397Sobrien	 INSN writes some cycles later.  */
728950397Sobrien
729050397Sobrien      /* These are only significant for the fpu unit; writing a fp reg before
729150397Sobrien         the fpu has finished with it stalls the processor.  */
729250397Sobrien
729350397Sobrien      /* Reusing an integer register causes no problems.  */
729450397Sobrien      if (insn_type == TYPE_IALU || insn_type == TYPE_SHIFT)
729550397Sobrien	return 0;
729650397Sobrien    }
729750397Sobrien
729850397Sobrien  return cost;
729950397Sobrien}
730050397Sobrien
730152284Sobrienstatic int
7302132718Skanhypersparc_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
730352284Sobrien{
730452284Sobrien  enum attr_type insn_type, dep_type;
730552284Sobrien  rtx pat = PATTERN(insn);
730652284Sobrien  rtx dep_pat = PATTERN (dep_insn);
730752284Sobrien
730852284Sobrien  if (recog_memoized (insn) < 0 || recog_memoized (dep_insn) < 0)
730952284Sobrien    return cost;
731052284Sobrien
731152284Sobrien  insn_type = get_attr_type (insn);
731252284Sobrien  dep_type = get_attr_type (dep_insn);
731352284Sobrien
731452284Sobrien  switch (REG_NOTE_KIND (link))
731552284Sobrien    {
731652284Sobrien    case 0:
731752284Sobrien      /* Data dependency; DEP_INSN writes a register that INSN reads some
731852284Sobrien	 cycles later.  */
731952284Sobrien
732052284Sobrien      switch (insn_type)
732152284Sobrien	{
732252284Sobrien	case TYPE_STORE:
732352284Sobrien	case TYPE_FPSTORE:
732490075Sobrien	  /* Get the delay iff the address of the store is the dependence.  */
732552284Sobrien	  if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
732652284Sobrien	    return cost;
732752284Sobrien
732852284Sobrien	  if (rtx_equal_p (SET_DEST (dep_pat), SET_SRC (pat)))
732952284Sobrien	    return cost;
733052284Sobrien	  return cost + 3;
733152284Sobrien
733252284Sobrien	case TYPE_LOAD:
733352284Sobrien	case TYPE_SLOAD:
733452284Sobrien	case TYPE_FPLOAD:
733552284Sobrien	  /* If a load, then the dependence must be on the memory address.  If
733652284Sobrien	     the addresses aren't equal, then it might be a false dependency */
733752284Sobrien	  if (dep_type == TYPE_STORE || dep_type == TYPE_FPSTORE)
733852284Sobrien	    {
733952284Sobrien	      if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET
734052284Sobrien		  || GET_CODE (SET_DEST (dep_pat)) != MEM
734152284Sobrien		  || GET_CODE (SET_SRC (pat)) != MEM
734252284Sobrien		  || ! rtx_equal_p (XEXP (SET_DEST (dep_pat), 0),
734352284Sobrien				    XEXP (SET_SRC (pat), 0)))
734452284Sobrien		return cost + 2;
734552284Sobrien
734652284Sobrien	      return cost + 8;
734752284Sobrien	    }
734852284Sobrien	  break;
734952284Sobrien
735052284Sobrien	case TYPE_BRANCH:
735152284Sobrien	  /* Compare to branch latency is 0.  There is no benefit from
735252284Sobrien	     separating compare and branch.  */
735352284Sobrien	  if (dep_type == TYPE_COMPARE)
735452284Sobrien	    return 0;
735552284Sobrien	  /* Floating point compare to branch latency is less than
735652284Sobrien	     compare to conditional move.  */
735752284Sobrien	  if (dep_type == TYPE_FPCMP)
735852284Sobrien	    return cost - 1;
735952284Sobrien	  break;
736052284Sobrien	default:
736152284Sobrien	  break;
736252284Sobrien	}
736352284Sobrien	break;
736452284Sobrien
736552284Sobrien    case REG_DEP_ANTI:
736690075Sobrien      /* Anti-dependencies only penalize the fpu unit.  */
736752284Sobrien      if (insn_type == TYPE_IALU || insn_type == TYPE_SHIFT)
736852284Sobrien        return 0;
736952284Sobrien      break;
737052284Sobrien
737152284Sobrien    default:
737252284Sobrien      break;
737352284Sobrien    }
737452284Sobrien
737552284Sobrien  return cost;
737652284Sobrien}
737752284Sobrien
737852284Sobrienstatic int
7379132718Skansparc_adjust_cost(rtx insn, rtx link, rtx dep, int cost)
738052284Sobrien{
738152284Sobrien  switch (sparc_cpu)
738252284Sobrien    {
738352284Sobrien    case PROCESSOR_SUPERSPARC:
738452284Sobrien      cost = supersparc_adjust_cost (insn, link, dep, cost);
738552284Sobrien      break;
738652284Sobrien    case PROCESSOR_HYPERSPARC:
738752284Sobrien    case PROCESSOR_SPARCLITE86X:
738852284Sobrien      cost = hypersparc_adjust_cost (insn, link, dep, cost);
738952284Sobrien      break;
739052284Sobrien    default:
739152284Sobrien      break;
739252284Sobrien    }
739352284Sobrien  return cost;
739452284Sobrien}
739552284Sobrien
739652284Sobrienstatic void
7397132718Skansparc_sched_init (FILE *dump ATTRIBUTE_UNUSED,
7398132718Skan		  int sched_verbose ATTRIBUTE_UNUSED,
7399132718Skan		  int max_ready ATTRIBUTE_UNUSED)
740090075Sobrien{
740190075Sobrien}
740290075Sobrien
740390075Sobrienstatic int
7404132718Skansparc_use_sched_lookahead (void)
740590075Sobrien{
7406169689Skan  if (sparc_cpu == PROCESSOR_NIAGARA)
7407169689Skan    return 0;
7408117395Skan  if (sparc_cpu == PROCESSOR_ULTRASPARC
7409117395Skan      || sparc_cpu == PROCESSOR_ULTRASPARC3)
7410117395Skan    return 4;
7411117395Skan  if ((1 << sparc_cpu) &
7412117395Skan      ((1 << PROCESSOR_SUPERSPARC) | (1 << PROCESSOR_HYPERSPARC) |
7413117395Skan       (1 << PROCESSOR_SPARCLITE86X)))
7414117395Skan    return 3;
7415117395Skan  return 0;
741690075Sobrien}
741790075Sobrien
741890075Sobrienstatic int
7419132718Skansparc_issue_rate (void)
742050397Sobrien{
742150397Sobrien  switch (sparc_cpu)
742250397Sobrien    {
7423169689Skan    case PROCESSOR_NIAGARA:
7424117395Skan    default:
7425117395Skan      return 1;
7426117395Skan    case PROCESSOR_V9:
742750397Sobrien      /* Assume V9 processors are capable of at least dual-issue.  */
742850397Sobrien      return 2;
7429117395Skan    case PROCESSOR_SUPERSPARC:
7430117395Skan      return 3;
743152284Sobrien    case PROCESSOR_HYPERSPARC:
743252284Sobrien    case PROCESSOR_SPARCLITE86X:
743352284Sobrien      return 2;
7434117395Skan    case PROCESSOR_ULTRASPARC:
7435117395Skan    case PROCESSOR_ULTRASPARC3:
7436117395Skan      return 4;
743750397Sobrien    }
743850397Sobrien}
743950397Sobrien
744050397Sobrienstatic int
7441132718Skanset_extends (rtx insn)
744250397Sobrien{
744350397Sobrien  register rtx pat = PATTERN (insn);
744450397Sobrien
744550397Sobrien  switch (GET_CODE (SET_SRC (pat)))
744650397Sobrien    {
744790075Sobrien      /* Load and some shift instructions zero extend.  */
744850397Sobrien    case MEM:
744950397Sobrien    case ZERO_EXTEND:
745050397Sobrien      /* sethi clears the high bits */
745150397Sobrien    case HIGH:
745250397Sobrien      /* LO_SUM is used with sethi.  sethi cleared the high
745350397Sobrien	 bits and the values used with lo_sum are positive */
745450397Sobrien    case LO_SUM:
745550397Sobrien      /* Store flag stores 0 or 1 */
745650397Sobrien    case LT: case LTU:
745750397Sobrien    case GT: case GTU:
745850397Sobrien    case LE: case LEU:
745950397Sobrien    case GE: case GEU:
746050397Sobrien    case EQ:
746150397Sobrien    case NE:
746250397Sobrien      return 1;
746350397Sobrien    case AND:
746450397Sobrien      {
746590075Sobrien	rtx op0 = XEXP (SET_SRC (pat), 0);
746650397Sobrien	rtx op1 = XEXP (SET_SRC (pat), 1);
746750397Sobrien	if (GET_CODE (op1) == CONST_INT)
746850397Sobrien	  return INTVAL (op1) >= 0;
746990075Sobrien	if (GET_CODE (op0) != REG)
747090075Sobrien	  return 0;
747190075Sobrien	if (sparc_check_64 (op0, insn) == 1)
747250397Sobrien	  return 1;
747390075Sobrien	return (GET_CODE (op1) == REG && sparc_check_64 (op1, insn) == 1);
747450397Sobrien      }
747590075Sobrien    case IOR:
747690075Sobrien    case XOR:
747790075Sobrien      {
747890075Sobrien	rtx op0 = XEXP (SET_SRC (pat), 0);
747990075Sobrien	rtx op1 = XEXP (SET_SRC (pat), 1);
748090075Sobrien	if (GET_CODE (op0) != REG || sparc_check_64 (op0, insn) <= 0)
748190075Sobrien	  return 0;
748290075Sobrien	if (GET_CODE (op1) == CONST_INT)
748390075Sobrien	  return INTVAL (op1) >= 0;
748490075Sobrien	return (GET_CODE (op1) == REG && sparc_check_64 (op1, insn) == 1);
748590075Sobrien      }
748650397Sobrien    case LSHIFTRT:
748750397Sobrien      return GET_MODE (SET_SRC (pat)) == SImode;
748890075Sobrien      /* Positive integers leave the high bits zero.  */
748950397Sobrien    case CONST_DOUBLE:
749090075Sobrien      return ! (CONST_DOUBLE_LOW (SET_SRC (pat)) & 0x80000000);
749150397Sobrien    case CONST_INT:
749290075Sobrien      return ! (INTVAL (SET_SRC (pat)) & 0x80000000);
749350397Sobrien    case ASHIFTRT:
749450397Sobrien    case SIGN_EXTEND:
749550397Sobrien      return - (GET_MODE (SET_SRC (pat)) == SImode);
749690075Sobrien    case REG:
749790075Sobrien      return sparc_check_64 (SET_SRC (pat), insn);
749850397Sobrien    default:
749950397Sobrien      return 0;
750050397Sobrien    }
750150397Sobrien}
750250397Sobrien
750390075Sobrien/* We _ought_ to have only one kind per function, but...  */
7504117395Skanstatic GTY(()) rtx sparc_addr_diff_list;
7505117395Skanstatic GTY(()) rtx sparc_addr_list;
750652284Sobrien
750752284Sobrienvoid
7508132718Skansparc_defer_case_vector (rtx lab, rtx vec, int diff)
750952284Sobrien{
751052284Sobrien  vec = gen_rtx_EXPR_LIST (VOIDmode, lab, vec);
751152284Sobrien  if (diff)
751252284Sobrien    sparc_addr_diff_list
751352284Sobrien      = gen_rtx_EXPR_LIST (VOIDmode, vec, sparc_addr_diff_list);
751452284Sobrien  else
751552284Sobrien    sparc_addr_list = gen_rtx_EXPR_LIST (VOIDmode, vec, sparc_addr_list);
751652284Sobrien}
751752284Sobrien
751852284Sobrienstatic void
7519132718Skansparc_output_addr_vec (rtx vec)
752052284Sobrien{
752152284Sobrien  rtx lab = XEXP (vec, 0), body = XEXP (vec, 1);
752252284Sobrien  int idx, vlen = XVECLEN (body, 0);
752352284Sobrien
752452284Sobrien#ifdef ASM_OUTPUT_ADDR_VEC_START
752552284Sobrien  ASM_OUTPUT_ADDR_VEC_START (asm_out_file);
752652284Sobrien#endif
752752284Sobrien
752852284Sobrien#ifdef ASM_OUTPUT_CASE_LABEL
752952284Sobrien  ASM_OUTPUT_CASE_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (lab),
753052284Sobrien			 NEXT_INSN (lab));
753152284Sobrien#else
7532132718Skan  (*targetm.asm_out.internal_label) (asm_out_file, "L", CODE_LABEL_NUMBER (lab));
753352284Sobrien#endif
753452284Sobrien
753552284Sobrien  for (idx = 0; idx < vlen; idx++)
753652284Sobrien    {
753752284Sobrien      ASM_OUTPUT_ADDR_VEC_ELT
753852284Sobrien	(asm_out_file, CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0)));
753952284Sobrien    }
754052284Sobrien
754152284Sobrien#ifdef ASM_OUTPUT_ADDR_VEC_END
754252284Sobrien  ASM_OUTPUT_ADDR_VEC_END (asm_out_file);
754352284Sobrien#endif
754452284Sobrien}
754552284Sobrien
754652284Sobrienstatic void
7547132718Skansparc_output_addr_diff_vec (rtx vec)
754852284Sobrien{
754952284Sobrien  rtx lab = XEXP (vec, 0), body = XEXP (vec, 1);
755052284Sobrien  rtx base = XEXP (XEXP (body, 0), 0);
755152284Sobrien  int idx, vlen = XVECLEN (body, 1);
755252284Sobrien
755352284Sobrien#ifdef ASM_OUTPUT_ADDR_VEC_START
755452284Sobrien  ASM_OUTPUT_ADDR_VEC_START (asm_out_file);
755552284Sobrien#endif
755652284Sobrien
755752284Sobrien#ifdef ASM_OUTPUT_CASE_LABEL
755852284Sobrien  ASM_OUTPUT_CASE_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (lab),
755952284Sobrien			 NEXT_INSN (lab));
756052284Sobrien#else
7561132718Skan  (*targetm.asm_out.internal_label) (asm_out_file, "L", CODE_LABEL_NUMBER (lab));
756252284Sobrien#endif
756352284Sobrien
756452284Sobrien  for (idx = 0; idx < vlen; idx++)
756552284Sobrien    {
756652284Sobrien      ASM_OUTPUT_ADDR_DIFF_ELT
756752284Sobrien        (asm_out_file,
756852284Sobrien         body,
756952284Sobrien         CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 1, idx), 0)),
757052284Sobrien         CODE_LABEL_NUMBER (base));
757152284Sobrien    }
757252284Sobrien
757352284Sobrien#ifdef ASM_OUTPUT_ADDR_VEC_END
757452284Sobrien  ASM_OUTPUT_ADDR_VEC_END (asm_out_file);
757552284Sobrien#endif
757652284Sobrien}
757752284Sobrien
757852284Sobrienstatic void
7579132718Skansparc_output_deferred_case_vectors (void)
758052284Sobrien{
758152284Sobrien  rtx t;
758252284Sobrien  int align;
758352284Sobrien
758452284Sobrien  if (sparc_addr_list == NULL_RTX
758552284Sobrien      && sparc_addr_diff_list == NULL_RTX)
758652284Sobrien    return;
758752284Sobrien
758852284Sobrien  /* Align to cache line in the function's code section.  */
7589169689Skan  switch_to_section (current_function_section ());
759052284Sobrien
759152284Sobrien  align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
759252284Sobrien  if (align > 0)
759352284Sobrien    ASM_OUTPUT_ALIGN (asm_out_file, align);
759452284Sobrien
759552284Sobrien  for (t = sparc_addr_list; t ; t = XEXP (t, 1))
759652284Sobrien    sparc_output_addr_vec (XEXP (t, 0));
759752284Sobrien  for (t = sparc_addr_diff_list; t ; t = XEXP (t, 1))
759852284Sobrien    sparc_output_addr_diff_vec (XEXP (t, 0));
759952284Sobrien
760052284Sobrien  sparc_addr_list = sparc_addr_diff_list = NULL_RTX;
760152284Sobrien}
760252284Sobrien
760350397Sobrien/* Return 0 if the high 32 bits of X (the low word of X, if DImode) are
760450397Sobrien   unknown.  Return 1 if the high bits are zero, -1 if the register is
760550397Sobrien   sign extended.  */
760650397Sobrienint
7607132718Skansparc_check_64 (rtx x, rtx insn)
760850397Sobrien{
760950397Sobrien  /* If a register is set only once it is safe to ignore insns this
761050397Sobrien     code does not know how to handle.  The loop will either recognize
761150397Sobrien     the single set and return the correct value or fail to recognize
761250397Sobrien     it and return 0.  */
761350397Sobrien  int set_once = 0;
761490075Sobrien  rtx y = x;
761550397Sobrien
7616169689Skan  gcc_assert (GET_CODE (x) == REG);
761790075Sobrien
761890075Sobrien  if (GET_MODE (x) == DImode)
761990075Sobrien    y = gen_rtx_REG (SImode, REGNO (x) + WORDS_BIG_ENDIAN);
762090075Sobrien
762190075Sobrien  if (flag_expensive_optimizations
762290075Sobrien      && REG_N_SETS (REGNO (y)) == 1)
762350397Sobrien    set_once = 1;
762450397Sobrien
762550397Sobrien  if (insn == 0)
762650397Sobrien    {
762750397Sobrien      if (set_once)
762850397Sobrien	insn = get_last_insn_anywhere ();
762950397Sobrien      else
763050397Sobrien	return 0;
763150397Sobrien    }
763250397Sobrien
763350397Sobrien  while ((insn = PREV_INSN (insn)))
763450397Sobrien    {
763550397Sobrien      switch (GET_CODE (insn))
763650397Sobrien	{
763750397Sobrien	case JUMP_INSN:
763850397Sobrien	case NOTE:
763950397Sobrien	  break;
764050397Sobrien	case CODE_LABEL:
764150397Sobrien	case CALL_INSN:
764250397Sobrien	default:
764350397Sobrien	  if (! set_once)
764450397Sobrien	    return 0;
764550397Sobrien	  break;
764650397Sobrien	case INSN:
764750397Sobrien	  {
764850397Sobrien	    rtx pat = PATTERN (insn);
764950397Sobrien	    if (GET_CODE (pat) != SET)
765050397Sobrien	      return 0;
765150397Sobrien	    if (rtx_equal_p (x, SET_DEST (pat)))
765290075Sobrien	      return set_extends (insn);
765390075Sobrien	    if (y && rtx_equal_p (y, SET_DEST (pat)))
765490075Sobrien	      return set_extends (insn);
765590075Sobrien	    if (reg_overlap_mentioned_p (SET_DEST (pat), y))
765650397Sobrien	      return 0;
765750397Sobrien	  }
765850397Sobrien	}
765950397Sobrien    }
766050397Sobrien  return 0;
766150397Sobrien}
766250397Sobrien
7663117395Skan/* Returns assembly code to perform a DImode shift using
7664117395Skan   a 64-bit global or out register on SPARC-V8+.  */
7665169689Skanconst char *
7666169689Skanoutput_v8plus_shift (rtx *operands, rtx insn, const char *opcode)
766750397Sobrien{
766850397Sobrien  static char asm_code[60];
766950397Sobrien
7670117395Skan  /* The scratch register is only required when the destination
7671117395Skan     register is not a 64-bit global or out register.  */
7672117395Skan  if (which_alternative != 2)
767350397Sobrien    operands[3] = operands[0];
7674117395Skan
7675122180Skan  /* We can only shift by constants <= 63. */
7676122180Skan  if (GET_CODE (operands[2]) == CONST_INT)
7677122180Skan    operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
7678122180Skan
767950397Sobrien  if (GET_CODE (operands[1]) == CONST_INT)
768050397Sobrien    {
768190075Sobrien      output_asm_insn ("mov\t%1, %3", operands);
768250397Sobrien    }
768350397Sobrien  else
768450397Sobrien    {
768590075Sobrien      output_asm_insn ("sllx\t%H1, 32, %3", operands);
768650397Sobrien      if (sparc_check_64 (operands[1], insn) <= 0)
768790075Sobrien	output_asm_insn ("srl\t%L1, 0, %L1", operands);
768890075Sobrien      output_asm_insn ("or\t%L1, %3, %3", operands);
768950397Sobrien    }
769050397Sobrien
769150397Sobrien  strcpy(asm_code, opcode);
7692117395Skan
769350397Sobrien  if (which_alternative != 2)
769490075Sobrien    return strcat (asm_code, "\t%0, %2, %L0\n\tsrlx\t%L0, 32, %H0");
769550397Sobrien  else
769690075Sobrien    return strcat (asm_code, "\t%3, %2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0");
769750397Sobrien}
769852284Sobrien
769996263Sobrien/* Output rtl to increment the profiler label LABELNO
770096263Sobrien   for profiling a function entry.  */
770152284Sobrien
770252284Sobrienvoid
7703132718Skansparc_profile_hook (int labelno)
770452284Sobrien{
770552284Sobrien  char buf[32];
770696263Sobrien  rtx lab, fun;
770796263Sobrien
770852284Sobrien  ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
770996263Sobrien  lab = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
771096263Sobrien  fun = gen_rtx_SYMBOL_REF (Pmode, MCOUNT_FUNCTION);
771152284Sobrien
771296263Sobrien  emit_library_call (fun, LCT_NORMAL, VOIDmode, 1, lab, Pmode);
771352284Sobrien}
771496263Sobrien
771590075Sobrien#ifdef OBJECT_FORMAT_ELF
771690075Sobrienstatic void
7717169689Skansparc_elf_asm_named_section (const char *name, unsigned int flags,
7718169689Skan			     tree decl)
771952284Sobrien{
772090075Sobrien  if (flags & SECTION_MERGE)
772152284Sobrien    {
772290075Sobrien      /* entsize cannot be expressed in this section attributes
772390075Sobrien	 encoding style.  */
7724169689Skan      default_elf_asm_named_section (name, flags, decl);
772590075Sobrien      return;
772652284Sobrien    }
772752284Sobrien
772890075Sobrien  fprintf (asm_out_file, "\t.section\t\"%s\"", name);
772952284Sobrien
773090075Sobrien  if (!(flags & SECTION_DEBUG))
773190075Sobrien    fputs (",#alloc", asm_out_file);
773290075Sobrien  if (flags & SECTION_WRITE)
773390075Sobrien    fputs (",#write", asm_out_file);
7734132718Skan  if (flags & SECTION_TLS)
7735132718Skan    fputs (",#tls", asm_out_file);
773690075Sobrien  if (flags & SECTION_CODE)
773790075Sobrien    fputs (",#execinstr", asm_out_file);
773852284Sobrien
773990075Sobrien  /* ??? Handle SECTION_BSS.  */
774052284Sobrien
774190075Sobrien  fputc ('\n', asm_out_file);
774252284Sobrien}
774390075Sobrien#endif /* OBJECT_FORMAT_ELF */
774496263Sobrien
7745169689Skan/* We do not allow indirect calls to be optimized into sibling calls.
7746169689Skan
7747169689Skan   We cannot use sibling calls when delayed branches are disabled
7748169689Skan   because they will likely require the call delay slot to be filled.
7749169689Skan
7750169689Skan   Also, on SPARC 32-bit we cannot emit a sibling call when the
7751132718Skan   current function returns a structure.  This is because the "unimp
7752132718Skan   after call" convention would cause the callee to return to the
7753132718Skan   wrong place.  The generic code already disallows cases where the
7754132718Skan   function being called returns a structure.
7755132718Skan
7756132718Skan   It may seem strange how this last case could occur.  Usually there
7757132718Skan   is code after the call which jumps to epilogue code which dumps the
7758132718Skan   return value into the struct return area.  That ought to invalidate
7759169689Skan   the sibling call right?  Well, in the C++ case we can end up passing
7760132718Skan   the pointer to the struct return area to a constructor (which returns
7761132718Skan   void) and then nothing else happens.  Such a sibling call would look
7762132718Skan   valid without the added check here.  */
7763132718Skanstatic bool
7764132718Skansparc_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
7765132718Skan{
7766132718Skan  return (decl
7767169689Skan	  && flag_delayed_branch
7768132718Skan	  && (TARGET_ARCH64 || ! current_function_returns_struct));
7769132718Skan}
7770132718Skan
7771132718Skan/* libfunc renaming.  */
7772132718Skan#include "config/gofast.h"
7773132718Skan
7774132718Skanstatic void
7775132718Skansparc_init_libfuncs (void)
7776132718Skan{
7777132718Skan  if (TARGET_ARCH32)
7778132718Skan    {
7779132718Skan      /* Use the subroutines that Sun's library provides for integer
7780132718Skan	 multiply and divide.  The `*' prevents an underscore from
7781132718Skan	 being prepended by the compiler. .umul is a little faster
7782169689Skan	 than .mul.  */
7783132718Skan      set_optab_libfunc (smul_optab, SImode, "*.umul");
7784132718Skan      set_optab_libfunc (sdiv_optab, SImode, "*.div");
7785132718Skan      set_optab_libfunc (udiv_optab, SImode, "*.udiv");
7786132718Skan      set_optab_libfunc (smod_optab, SImode, "*.rem");
7787132718Skan      set_optab_libfunc (umod_optab, SImode, "*.urem");
7788132718Skan
7789132718Skan      /* TFmode arithmetic.  These names are part of the SPARC 32bit ABI.  */
7790132718Skan      set_optab_libfunc (add_optab, TFmode, "_Q_add");
7791132718Skan      set_optab_libfunc (sub_optab, TFmode, "_Q_sub");
7792132718Skan      set_optab_libfunc (neg_optab, TFmode, "_Q_neg");
7793132718Skan      set_optab_libfunc (smul_optab, TFmode, "_Q_mul");
7794132718Skan      set_optab_libfunc (sdiv_optab, TFmode, "_Q_div");
7795132718Skan
7796132718Skan      /* We can define the TFmode sqrt optab only if TARGET_FPU.  This
7797132718Skan	 is because with soft-float, the SFmode and DFmode sqrt
7798132718Skan	 instructions will be absent, and the compiler will notice and
7799132718Skan	 try to use the TFmode sqrt instruction for calls to the
7800132718Skan	 builtin function sqrt, but this fails.  */
7801132718Skan      if (TARGET_FPU)
7802132718Skan	set_optab_libfunc (sqrt_optab, TFmode, "_Q_sqrt");
7803132718Skan
7804132718Skan      set_optab_libfunc (eq_optab, TFmode, "_Q_feq");
7805132718Skan      set_optab_libfunc (ne_optab, TFmode, "_Q_fne");
7806132718Skan      set_optab_libfunc (gt_optab, TFmode, "_Q_fgt");
7807132718Skan      set_optab_libfunc (ge_optab, TFmode, "_Q_fge");
7808132718Skan      set_optab_libfunc (lt_optab, TFmode, "_Q_flt");
7809132718Skan      set_optab_libfunc (le_optab, TFmode, "_Q_fle");
7810132718Skan
7811132718Skan      set_conv_libfunc (sext_optab,   TFmode, SFmode, "_Q_stoq");
7812132718Skan      set_conv_libfunc (sext_optab,   TFmode, DFmode, "_Q_dtoq");
7813132718Skan      set_conv_libfunc (trunc_optab,  SFmode, TFmode, "_Q_qtos");
7814132718Skan      set_conv_libfunc (trunc_optab,  DFmode, TFmode, "_Q_qtod");
7815132718Skan
7816132718Skan      set_conv_libfunc (sfix_optab,   SImode, TFmode, "_Q_qtoi");
7817132718Skan      set_conv_libfunc (ufix_optab,   SImode, TFmode, "_Q_qtou");
7818132718Skan      set_conv_libfunc (sfloat_optab, TFmode, SImode, "_Q_itoq");
7819169689Skan      set_conv_libfunc (ufloat_optab, TFmode, SImode, "_Q_utoq");
7820132718Skan
7821132718Skan      if (DITF_CONVERSION_LIBFUNCS)
7822132718Skan	{
7823132718Skan	  set_conv_libfunc (sfix_optab,   DImode, TFmode, "_Q_qtoll");
7824132718Skan	  set_conv_libfunc (ufix_optab,   DImode, TFmode, "_Q_qtoull");
7825132718Skan	  set_conv_libfunc (sfloat_optab, TFmode, DImode, "_Q_lltoq");
7826169689Skan	  set_conv_libfunc (ufloat_optab, TFmode, DImode, "_Q_ulltoq");
7827132718Skan	}
7828132718Skan
7829132718Skan      if (SUN_CONVERSION_LIBFUNCS)
7830132718Skan	{
7831132718Skan	  set_conv_libfunc (sfix_optab, DImode, SFmode, "__ftoll");
7832132718Skan	  set_conv_libfunc (ufix_optab, DImode, SFmode, "__ftoull");
7833132718Skan	  set_conv_libfunc (sfix_optab, DImode, DFmode, "__dtoll");
7834132718Skan	  set_conv_libfunc (ufix_optab, DImode, DFmode, "__dtoull");
7835132718Skan	}
7836132718Skan    }
7837132718Skan  if (TARGET_ARCH64)
7838132718Skan    {
7839132718Skan      /* In the SPARC 64bit ABI, SImode multiply and divide functions
7840132718Skan	 do not exist in the library.  Make sure the compiler does not
7841132718Skan	 emit calls to them by accident.  (It should always use the
7842132718Skan         hardware instructions.)  */
7843132718Skan      set_optab_libfunc (smul_optab, SImode, 0);
7844132718Skan      set_optab_libfunc (sdiv_optab, SImode, 0);
7845132718Skan      set_optab_libfunc (udiv_optab, SImode, 0);
7846132718Skan      set_optab_libfunc (smod_optab, SImode, 0);
7847132718Skan      set_optab_libfunc (umod_optab, SImode, 0);
7848132718Skan
7849132718Skan      if (SUN_INTEGER_MULTIPLY_64)
7850132718Skan	{
7851132718Skan	  set_optab_libfunc (smul_optab, DImode, "__mul64");
7852132718Skan	  set_optab_libfunc (sdiv_optab, DImode, "__div64");
7853132718Skan	  set_optab_libfunc (udiv_optab, DImode, "__udiv64");
7854132718Skan	  set_optab_libfunc (smod_optab, DImode, "__rem64");
7855132718Skan	  set_optab_libfunc (umod_optab, DImode, "__urem64");
7856132718Skan	}
7857132718Skan
7858132718Skan      if (SUN_CONVERSION_LIBFUNCS)
7859132718Skan	{
7860132718Skan	  set_conv_libfunc (sfix_optab, DImode, SFmode, "__ftol");
7861132718Skan	  set_conv_libfunc (ufix_optab, DImode, SFmode, "__ftoul");
7862132718Skan	  set_conv_libfunc (sfix_optab, DImode, DFmode, "__dtol");
7863132718Skan	  set_conv_libfunc (ufix_optab, DImode, DFmode, "__dtoul");
7864132718Skan	}
7865132718Skan    }
7866132718Skan
7867132718Skan  gofast_maybe_init_libfuncs ();
7868132718Skan}
7869132718Skan
7870169689Skan#define def_builtin(NAME, CODE, TYPE) \
7871169689Skan  lang_hooks.builtin_function((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL, \
7872169689Skan                              NULL_TREE)
7873117395Skan
7874169689Skan/* Implement the TARGET_INIT_BUILTINS target hook.
7875169689Skan   Create builtin functions for special SPARC instructions.  */
7876169689Skan
7877117395Skanstatic void
7878169689Skansparc_init_builtins (void)
7879117395Skan{
7880169689Skan  if (TARGET_VIS)
7881169689Skan    sparc_vis_init_builtins ();
7882117395Skan}
7883117395Skan
7884169689Skan/* Create builtin functions for VIS 1.0 instructions.  */
7885117395Skan
7886117395Skanstatic void
7887169689Skansparc_vis_init_builtins (void)
7888117395Skan{
7889169689Skan  tree v4qi = build_vector_type (unsigned_intQI_type_node, 4);
7890169689Skan  tree v8qi = build_vector_type (unsigned_intQI_type_node, 8);
7891169689Skan  tree v4hi = build_vector_type (intHI_type_node, 4);
7892169689Skan  tree v2hi = build_vector_type (intHI_type_node, 2);
7893169689Skan  tree v2si = build_vector_type (intSI_type_node, 2);
7894169689Skan
7895169689Skan  tree v4qi_ftype_v4hi = build_function_type_list (v4qi, v4hi, 0);
7896169689Skan  tree v8qi_ftype_v2si_v8qi = build_function_type_list (v8qi, v2si, v8qi, 0);
7897169689Skan  tree v2hi_ftype_v2si = build_function_type_list (v2hi, v2si, 0);
7898169689Skan  tree v4hi_ftype_v4qi = build_function_type_list (v4hi, v4qi, 0);
7899169689Skan  tree v8qi_ftype_v4qi_v4qi = build_function_type_list (v8qi, v4qi, v4qi, 0);
7900169689Skan  tree v4hi_ftype_v4qi_v4hi = build_function_type_list (v4hi, v4qi, v4hi, 0);
7901169689Skan  tree v4hi_ftype_v4qi_v2hi = build_function_type_list (v4hi, v4qi, v2hi, 0);
7902169689Skan  tree v2si_ftype_v4qi_v2hi = build_function_type_list (v2si, v4qi, v2hi, 0);
7903169689Skan  tree v4hi_ftype_v8qi_v4hi = build_function_type_list (v4hi, v8qi, v4hi, 0);
7904169689Skan  tree v4hi_ftype_v4hi_v4hi = build_function_type_list (v4hi, v4hi, v4hi, 0);
7905169689Skan  tree v2si_ftype_v2si_v2si = build_function_type_list (v2si, v2si, v2si, 0);
7906169689Skan  tree v8qi_ftype_v8qi_v8qi = build_function_type_list (v8qi, v8qi, v8qi, 0);
7907169689Skan  tree di_ftype_v8qi_v8qi_di = build_function_type_list (intDI_type_node,
7908169689Skan							 v8qi, v8qi,
7909169689Skan							 intDI_type_node, 0);
7910169689Skan  tree di_ftype_di_di = build_function_type_list (intDI_type_node,
7911169689Skan						  intDI_type_node,
7912169689Skan						  intDI_type_node, 0);
7913169689Skan  tree ptr_ftype_ptr_si = build_function_type_list (ptr_type_node,
7914169689Skan		        			    ptr_type_node,
7915169689Skan					            intSI_type_node, 0);
7916169689Skan  tree ptr_ftype_ptr_di = build_function_type_list (ptr_type_node,
7917169689Skan		        			    ptr_type_node,
7918169689Skan					            intDI_type_node, 0);
7919169689Skan
7920169689Skan  /* Packing and expanding vectors.  */
7921169689Skan  def_builtin ("__builtin_vis_fpack16", CODE_FOR_fpack16_vis, v4qi_ftype_v4hi);
7922169689Skan  def_builtin ("__builtin_vis_fpack32", CODE_FOR_fpack32_vis,
7923169689Skan	       v8qi_ftype_v2si_v8qi);
7924169689Skan  def_builtin ("__builtin_vis_fpackfix", CODE_FOR_fpackfix_vis,
7925169689Skan	       v2hi_ftype_v2si);
7926169689Skan  def_builtin ("__builtin_vis_fexpand", CODE_FOR_fexpand_vis, v4hi_ftype_v4qi);
7927169689Skan  def_builtin ("__builtin_vis_fpmerge", CODE_FOR_fpmerge_vis,
7928169689Skan	       v8qi_ftype_v4qi_v4qi);
7929169689Skan
7930169689Skan  /* Multiplications.  */
7931169689Skan  def_builtin ("__builtin_vis_fmul8x16", CODE_FOR_fmul8x16_vis,
7932169689Skan	       v4hi_ftype_v4qi_v4hi);
7933169689Skan  def_builtin ("__builtin_vis_fmul8x16au", CODE_FOR_fmul8x16au_vis,
7934169689Skan	       v4hi_ftype_v4qi_v2hi);
7935169689Skan  def_builtin ("__builtin_vis_fmul8x16al", CODE_FOR_fmul8x16al_vis,
7936169689Skan	       v4hi_ftype_v4qi_v2hi);
7937169689Skan  def_builtin ("__builtin_vis_fmul8sux16", CODE_FOR_fmul8sux16_vis,
7938169689Skan	       v4hi_ftype_v8qi_v4hi);
7939169689Skan  def_builtin ("__builtin_vis_fmul8ulx16", CODE_FOR_fmul8ulx16_vis,
7940169689Skan	       v4hi_ftype_v8qi_v4hi);
7941169689Skan  def_builtin ("__builtin_vis_fmuld8sux16", CODE_FOR_fmuld8sux16_vis,
7942169689Skan	       v2si_ftype_v4qi_v2hi);
7943169689Skan  def_builtin ("__builtin_vis_fmuld8ulx16", CODE_FOR_fmuld8ulx16_vis,
7944169689Skan	       v2si_ftype_v4qi_v2hi);
7945169689Skan
7946169689Skan  /* Data aligning.  */
7947169689Skan  def_builtin ("__builtin_vis_faligndatav4hi", CODE_FOR_faligndatav4hi_vis,
7948169689Skan	       v4hi_ftype_v4hi_v4hi);
7949169689Skan  def_builtin ("__builtin_vis_faligndatav8qi", CODE_FOR_faligndatav8qi_vis,
7950169689Skan	       v8qi_ftype_v8qi_v8qi);
7951169689Skan  def_builtin ("__builtin_vis_faligndatav2si", CODE_FOR_faligndatav2si_vis,
7952169689Skan	       v2si_ftype_v2si_v2si);
7953169689Skan  def_builtin ("__builtin_vis_faligndatadi", CODE_FOR_faligndatadi_vis,
7954169689Skan               di_ftype_di_di);
7955169689Skan  if (TARGET_ARCH64)
7956169689Skan    def_builtin ("__builtin_vis_alignaddr", CODE_FOR_alignaddrdi_vis,
7957169689Skan	         ptr_ftype_ptr_di);
7958117395Skan  else
7959169689Skan    def_builtin ("__builtin_vis_alignaddr", CODE_FOR_alignaddrsi_vis,
7960169689Skan	         ptr_ftype_ptr_si);
7961169689Skan
7962169689Skan  /* Pixel distance.  */
7963169689Skan  def_builtin ("__builtin_vis_pdist", CODE_FOR_pdist_vis,
7964169689Skan	       di_ftype_v8qi_v8qi_di);
7965117395Skan}
7966117395Skan
7967169689Skan/* Handle TARGET_EXPAND_BUILTIN target hook.
7968169689Skan   Expand builtin functions for sparc intrinsics.  */
7969169689Skan
7970169689Skanstatic rtx
7971171825Skansparc_expand_builtin (tree exp, rtx target,
7972171825Skan		      rtx subtarget ATTRIBUTE_UNUSED,
7973171825Skan		      enum machine_mode tmode ATTRIBUTE_UNUSED,
7974171825Skan		      int ignore ATTRIBUTE_UNUSED)
7975169689Skan{
7976169689Skan  tree arglist;
7977169689Skan  tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
7978169689Skan  unsigned int icode = DECL_FUNCTION_CODE (fndecl);
7979169689Skan  rtx pat, op[4];
7980169689Skan  enum machine_mode mode[4];
7981169689Skan  int arg_count = 0;
7982169689Skan
7983171825Skan  mode[0] = insn_data[icode].operand[0].mode;
7984171825Skan  if (!target
7985171825Skan      || GET_MODE (target) != mode[0]
7986171825Skan      || ! (*insn_data[icode].operand[0].predicate) (target, mode[0]))
7987171825Skan    op[0] = gen_reg_rtx (mode[0]);
7988169689Skan  else
7989171825Skan    op[0] = target;
7990169689Skan
7991169689Skan  for (arglist = TREE_OPERAND (exp, 1); arglist;
7992169689Skan       arglist = TREE_CHAIN (arglist))
7993169689Skan    {
7994169689Skan      tree arg = TREE_VALUE (arglist);
7995169689Skan
7996169689Skan      arg_count++;
7997169689Skan      mode[arg_count] = insn_data[icode].operand[arg_count].mode;
7998169689Skan      op[arg_count] = expand_normal (arg);
7999169689Skan
8000169689Skan      if (! (*insn_data[icode].operand[arg_count].predicate) (op[arg_count],
8001169689Skan							      mode[arg_count]))
8002169689Skan	op[arg_count] = copy_to_mode_reg (mode[arg_count], op[arg_count]);
8003169689Skan    }
8004169689Skan
8005169689Skan  switch (arg_count)
8006169689Skan    {
8007169689Skan    case 1:
8008169689Skan      pat = GEN_FCN (icode) (op[0], op[1]);
8009169689Skan      break;
8010169689Skan    case 2:
8011169689Skan      pat = GEN_FCN (icode) (op[0], op[1], op[2]);
8012169689Skan      break;
8013169689Skan    case 3:
8014169689Skan      pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
8015169689Skan      break;
8016169689Skan    default:
8017169689Skan      gcc_unreachable ();
8018169689Skan    }
8019169689Skan
8020169689Skan  if (!pat)
8021169689Skan    return NULL_RTX;
8022169689Skan
8023169689Skan  emit_insn (pat);
8024169689Skan
8025169689Skan  return op[0];
8026169689Skan}
8027169689Skan
8028169689Skanstatic int
8029169689Skansparc_vis_mul8x16 (int e8, int e16)
8030169689Skan{
8031169689Skan  return (e8 * e16 + 128) / 256;
8032169689Skan}
8033169689Skan
8034169689Skan/* Multiply the vector elements in ELTS0 to the elements in ELTS1 as specified
8035169689Skan   by FNCODE.  All of the elements in ELTS0 and ELTS1 lists must be integer
8036169689Skan   constants.  A tree list with the results of the multiplications is returned,
8037169689Skan   and each element in the list is of INNER_TYPE.  */
8038169689Skan
8039169689Skanstatic tree
8040169689Skansparc_handle_vis_mul8x16 (int fncode, tree inner_type, tree elts0, tree elts1)
8041169689Skan{
8042169689Skan  tree n_elts = NULL_TREE;
8043169689Skan  int scale;
8044169689Skan
8045169689Skan  switch (fncode)
8046169689Skan    {
8047169689Skan    case CODE_FOR_fmul8x16_vis:
8048169689Skan      for (; elts0 && elts1;
8049169689Skan	   elts0 = TREE_CHAIN (elts0), elts1 = TREE_CHAIN (elts1))
8050169689Skan	{
8051169689Skan	  int val
8052169689Skan	    = sparc_vis_mul8x16 (TREE_INT_CST_LOW (TREE_VALUE (elts0)),
8053169689Skan				 TREE_INT_CST_LOW (TREE_VALUE (elts1)));
8054169689Skan	  n_elts = tree_cons (NULL_TREE,
8055169689Skan			      build_int_cst (inner_type, val),
8056169689Skan			      n_elts);
8057169689Skan	}
8058169689Skan      break;
8059169689Skan
8060169689Skan    case CODE_FOR_fmul8x16au_vis:
8061169689Skan      scale = TREE_INT_CST_LOW (TREE_VALUE (elts1));
8062169689Skan
8063169689Skan      for (; elts0; elts0 = TREE_CHAIN (elts0))
8064169689Skan	{
8065169689Skan	  int val
8066169689Skan	    = sparc_vis_mul8x16 (TREE_INT_CST_LOW (TREE_VALUE (elts0)),
8067169689Skan				 scale);
8068169689Skan	  n_elts = tree_cons (NULL_TREE,
8069169689Skan			      build_int_cst (inner_type, val),
8070169689Skan			      n_elts);
8071169689Skan	}
8072169689Skan      break;
8073169689Skan
8074169689Skan    case CODE_FOR_fmul8x16al_vis:
8075169689Skan      scale = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (elts1)));
8076169689Skan
8077169689Skan      for (; elts0; elts0 = TREE_CHAIN (elts0))
8078169689Skan	{
8079169689Skan	  int val
8080169689Skan	    = sparc_vis_mul8x16 (TREE_INT_CST_LOW (TREE_VALUE (elts0)),
8081169689Skan				 scale);
8082169689Skan	  n_elts = tree_cons (NULL_TREE,
8083169689Skan			      build_int_cst (inner_type, val),
8084169689Skan			      n_elts);
8085169689Skan	}
8086169689Skan      break;
8087169689Skan
8088169689Skan    default:
8089169689Skan      gcc_unreachable ();
8090169689Skan    }
8091169689Skan
8092169689Skan  return nreverse (n_elts);
8093169689Skan
8094169689Skan}
8095169689Skan/* Handle TARGET_FOLD_BUILTIN target hook.
8096169689Skan   Fold builtin functions for SPARC intrinsics.  If IGNORE is true the
8097169689Skan   result of the function call is ignored.  NULL_TREE is returned if the
8098169689Skan   function could not be folded.  */
8099169689Skan
8100169689Skanstatic tree
8101169689Skansparc_fold_builtin (tree fndecl, tree arglist, bool ignore)
8102169689Skan{
8103169689Skan  tree arg0, arg1, arg2;
8104169689Skan  tree rtype = TREE_TYPE (TREE_TYPE (fndecl));
8105169689Skan
8106171825Skan  if (ignore
8107171825Skan      && DECL_FUNCTION_CODE (fndecl) != CODE_FOR_alignaddrsi_vis
8108169689Skan      && DECL_FUNCTION_CODE (fndecl) != CODE_FOR_alignaddrdi_vis)
8109171825Skan    return fold_convert (rtype, integer_zero_node);
8110169689Skan
8111169689Skan  switch (DECL_FUNCTION_CODE (fndecl))
8112169689Skan    {
8113169689Skan    case CODE_FOR_fexpand_vis:
8114169689Skan      arg0 = TREE_VALUE (arglist);
8115169689Skan      STRIP_NOPS (arg0);
8116169689Skan
8117169689Skan      if (TREE_CODE (arg0) == VECTOR_CST)
8118169689Skan	{
8119169689Skan	  tree inner_type = TREE_TYPE (rtype);
8120169689Skan	  tree elts = TREE_VECTOR_CST_ELTS (arg0);
8121169689Skan	  tree n_elts = NULL_TREE;
8122169689Skan
8123169689Skan	  for (; elts; elts = TREE_CHAIN (elts))
8124169689Skan	    {
8125169689Skan	      unsigned int val = TREE_INT_CST_LOW (TREE_VALUE (elts)) << 4;
8126169689Skan	      n_elts = tree_cons (NULL_TREE,
8127169689Skan				  build_int_cst (inner_type, val),
8128169689Skan				  n_elts);
8129169689Skan	    }
8130169689Skan	  return build_vector (rtype, nreverse (n_elts));
8131169689Skan	}
8132169689Skan      break;
8133169689Skan
8134169689Skan    case CODE_FOR_fmul8x16_vis:
8135169689Skan    case CODE_FOR_fmul8x16au_vis:
8136169689Skan    case CODE_FOR_fmul8x16al_vis:
8137169689Skan      arg0 = TREE_VALUE (arglist);
8138169689Skan      arg1 = TREE_VALUE (TREE_CHAIN (arglist));
8139169689Skan      STRIP_NOPS (arg0);
8140169689Skan      STRIP_NOPS (arg1);
8141169689Skan
8142169689Skan      if (TREE_CODE (arg0) == VECTOR_CST && TREE_CODE (arg1) == VECTOR_CST)
8143169689Skan	{
8144169689Skan	  tree inner_type = TREE_TYPE (rtype);
8145169689Skan	  tree elts0 = TREE_VECTOR_CST_ELTS (arg0);
8146169689Skan	  tree elts1 = TREE_VECTOR_CST_ELTS (arg1);
8147169689Skan	  tree n_elts = sparc_handle_vis_mul8x16 (DECL_FUNCTION_CODE (fndecl),
8148169689Skan						  inner_type, elts0, elts1);
8149169689Skan
8150169689Skan	  return build_vector (rtype, n_elts);
8151169689Skan	}
8152169689Skan      break;
8153169689Skan
8154169689Skan    case CODE_FOR_fpmerge_vis:
8155169689Skan      arg0 = TREE_VALUE (arglist);
8156169689Skan      arg1 = TREE_VALUE (TREE_CHAIN (arglist));
8157169689Skan      STRIP_NOPS (arg0);
8158169689Skan      STRIP_NOPS (arg1);
8159169689Skan
8160169689Skan      if (TREE_CODE (arg0) == VECTOR_CST && TREE_CODE (arg1) == VECTOR_CST)
8161169689Skan	{
8162169689Skan	  tree elts0 = TREE_VECTOR_CST_ELTS (arg0);
8163169689Skan	  tree elts1 = TREE_VECTOR_CST_ELTS (arg1);
8164169689Skan	  tree n_elts = NULL_TREE;
8165169689Skan
8166169689Skan	  for (; elts0 && elts1;
8167169689Skan	       elts0 = TREE_CHAIN (elts0), elts1 = TREE_CHAIN (elts1))
8168169689Skan	    {
8169169689Skan	      n_elts = tree_cons (NULL_TREE, TREE_VALUE (elts0), n_elts);
8170169689Skan	      n_elts = tree_cons (NULL_TREE, TREE_VALUE (elts1), n_elts);
8171169689Skan	    }
8172169689Skan
8173169689Skan	  return build_vector (rtype, nreverse (n_elts));
8174169689Skan	}
8175169689Skan      break;
8176169689Skan
8177169689Skan    case CODE_FOR_pdist_vis:
8178169689Skan      arg0 = TREE_VALUE (arglist);
8179169689Skan      arg1 = TREE_VALUE (TREE_CHAIN (arglist));
8180169689Skan      arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
8181169689Skan      STRIP_NOPS (arg0);
8182169689Skan      STRIP_NOPS (arg1);
8183169689Skan      STRIP_NOPS (arg2);
8184169689Skan
8185169689Skan      if (TREE_CODE (arg0) == VECTOR_CST
8186169689Skan	  && TREE_CODE (arg1) == VECTOR_CST
8187169689Skan	  && TREE_CODE (arg2) == INTEGER_CST)
8188169689Skan	{
8189169689Skan	  int overflow = 0;
8190169689Skan	  unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (arg2);
8191169689Skan	  HOST_WIDE_INT high = TREE_INT_CST_HIGH (arg2);
8192169689Skan	  tree elts0 = TREE_VECTOR_CST_ELTS (arg0);
8193169689Skan	  tree elts1 = TREE_VECTOR_CST_ELTS (arg1);
8194169689Skan
8195169689Skan	  for (; elts0 && elts1;
8196169689Skan	       elts0 = TREE_CHAIN (elts0), elts1 = TREE_CHAIN (elts1))
8197169689Skan	    {
8198169689Skan	      unsigned HOST_WIDE_INT
8199169689Skan		low0 = TREE_INT_CST_LOW (TREE_VALUE (elts0)),
8200169689Skan		low1 = TREE_INT_CST_LOW (TREE_VALUE (elts1));
8201169689Skan	      HOST_WIDE_INT high0 = TREE_INT_CST_HIGH (TREE_VALUE (elts0));
8202169689Skan	      HOST_WIDE_INT high1 = TREE_INT_CST_HIGH (TREE_VALUE (elts1));
8203169689Skan
8204169689Skan	      unsigned HOST_WIDE_INT l;
8205169689Skan	      HOST_WIDE_INT h;
8206169689Skan
8207169689Skan	      overflow |= neg_double (low1, high1, &l, &h);
8208169689Skan	      overflow |= add_double (low0, high0, l, h, &l, &h);
8209169689Skan	      if (h < 0)
8210169689Skan		overflow |= neg_double (l, h, &l, &h);
8211169689Skan
8212169689Skan	      overflow |= add_double (low, high, l, h, &low, &high);
8213169689Skan	    }
8214169689Skan
8215169689Skan	  gcc_assert (overflow == 0);
8216169689Skan
8217169689Skan	  return build_int_cst_wide (rtype, low, high);
8218169689Skan	}
8219169689Skan
8220169689Skan    default:
8221169689Skan      break;
8222169689Skan    }
8223171825Skan
8224169689Skan  return NULL_TREE;
8225169689Skan}
8226169689Skan
822796263Sobrienint
8228132718Skansparc_extra_constraint_check (rtx op, int c, int strict)
822996263Sobrien{
823096263Sobrien  int reload_ok_mem;
823196263Sobrien
823296263Sobrien  if (TARGET_ARCH64
823396263Sobrien      && (c == 'T' || c == 'U'))
823496263Sobrien    return 0;
823596263Sobrien
823696263Sobrien  switch (c)
823796263Sobrien    {
823896263Sobrien    case 'Q':
823996263Sobrien      return fp_sethi_p (op);
824096263Sobrien
824196263Sobrien    case 'R':
824296263Sobrien      return fp_mov_p (op);
824396263Sobrien
824496263Sobrien    case 'S':
824596263Sobrien      return fp_high_losum_p (op);
824696263Sobrien
824796263Sobrien    case 'U':
824896263Sobrien      if (! strict
824996263Sobrien	  || (GET_CODE (op) == REG
825096263Sobrien	      && (REGNO (op) < FIRST_PSEUDO_REGISTER
825196263Sobrien		  || reg_renumber[REGNO (op)] >= 0)))
825296263Sobrien	return register_ok_for_ldd (op);
825396263Sobrien
825496263Sobrien      return 0;
825596263Sobrien
825696263Sobrien    case 'W':
825796263Sobrien    case 'T':
825896263Sobrien      break;
825996263Sobrien
8260169689Skan    case 'Y':
8261169689Skan      return const_zero_operand (op, GET_MODE (op));
8262169689Skan
826396263Sobrien    default:
826496263Sobrien      return 0;
826596263Sobrien    }
826696263Sobrien
826796263Sobrien  /* Our memory extra constraints have to emulate the
826896263Sobrien     behavior of 'm' and 'o' in order for reload to work
826996263Sobrien     correctly.  */
827096263Sobrien  if (GET_CODE (op) == MEM)
827196263Sobrien    {
827296263Sobrien      reload_ok_mem = 0;
827396263Sobrien      if ((TARGET_ARCH64 || mem_min_alignment (op, 8))
827496263Sobrien	  && (! strict
827596263Sobrien	      || strict_memory_address_p (Pmode, XEXP (op, 0))))
827696263Sobrien	reload_ok_mem = 1;
827796263Sobrien    }
827896263Sobrien  else
827996263Sobrien    {
828096263Sobrien      reload_ok_mem = (reload_in_progress
828196263Sobrien		       && GET_CODE (op) == REG
828296263Sobrien		       && REGNO (op) >= FIRST_PSEUDO_REGISTER
828396263Sobrien		       && reg_renumber [REGNO (op)] < 0);
828496263Sobrien    }
828596263Sobrien
828696263Sobrien  return reload_ok_mem;
828796263Sobrien}
8288102780Skan
8289117395Skan/* ??? This duplicates information provided to the compiler by the
8290117395Skan   ??? scheduler description.  Some day, teach genautomata to output
8291117395Skan   ??? the latencies and then CSE will just use that.  */
8292117395Skan
8293132718Skanstatic bool
8294132718Skansparc_rtx_costs (rtx x, int code, int outer_code, int *total)
8295117395Skan{
8296169689Skan  enum machine_mode mode = GET_MODE (x);
8297169689Skan  bool float_mode_p = FLOAT_MODE_P (mode);
8298169689Skan
8299117395Skan  switch (code)
8300117395Skan    {
8301169689Skan    case CONST_INT:
8302169689Skan      if (INTVAL (x) < 0x1000 && INTVAL (x) >= -0x1000)
8303117395Skan	{
8304169689Skan	  *total = 0;
8305169689Skan	  return true;
8306169689Skan	}
8307169689Skan      /* FALLTHRU */
8308117395Skan
8309169689Skan    case HIGH:
8310169689Skan      *total = 2;
8311169689Skan      return true;
8312117395Skan
8313169689Skan    case CONST:
8314169689Skan    case LABEL_REF:
8315169689Skan    case SYMBOL_REF:
8316169689Skan      *total = 4;
8317169689Skan      return true;
8318117395Skan
8319169689Skan    case CONST_DOUBLE:
8320169689Skan      if (GET_MODE (x) == VOIDmode
8321169689Skan	  && ((CONST_DOUBLE_HIGH (x) == 0
8322169689Skan	       && CONST_DOUBLE_LOW (x) < 0x1000)
8323169689Skan	      || (CONST_DOUBLE_HIGH (x) == -1
8324169689Skan		  && CONST_DOUBLE_LOW (x) < 0
8325169689Skan		  && CONST_DOUBLE_LOW (x) >= -0x1000)))
8326169689Skan	*total = 0;
8327169689Skan      else
8328169689Skan	*total = 8;
8329132718Skan      return true;
8330117395Skan
8331169689Skan    case MEM:
8332169689Skan      /* If outer-code was a sign or zero extension, a cost
8333169689Skan	 of COSTS_N_INSNS (1) was already added in.  This is
8334169689Skan	 why we are subtracting it back out.  */
8335169689Skan      if (outer_code == ZERO_EXTEND)
8336117395Skan	{
8337169689Skan	  *total = sparc_costs->int_zload - COSTS_N_INSNS (1);
8338117395Skan	}
8339169689Skan      else if (outer_code == SIGN_EXTEND)
8340117395Skan	{
8341169689Skan	  *total = sparc_costs->int_sload - COSTS_N_INSNS (1);
8342117395Skan	}
8343169689Skan      else if (float_mode_p)
8344169689Skan	{
8345169689Skan	  *total = sparc_costs->float_load;
8346169689Skan	}
8347169689Skan      else
8348169689Skan	{
8349169689Skan	  *total = sparc_costs->int_load;
8350169689Skan	}
8351117395Skan
8352132718Skan      return true;
8353117395Skan
8354169689Skan    case PLUS:
8355169689Skan    case MINUS:
8356169689Skan      if (float_mode_p)
8357169689Skan	*total = sparc_costs->float_plusminus;
8358169689Skan      else
8359169689Skan	*total = COSTS_N_INSNS (1);
8360169689Skan      return false;
8361169689Skan
8362117395Skan    case MULT:
8363169689Skan      if (float_mode_p)
8364169689Skan	*total = sparc_costs->float_mul;
8365169689Skan      else if (! TARGET_HARD_MUL)
8366169689Skan	*total = COSTS_N_INSNS (25);
8367169689Skan      else
8368117395Skan	{
8369169689Skan	  int bit_cost;
8370169689Skan
8371169689Skan	  bit_cost = 0;
8372169689Skan	  if (sparc_costs->int_mul_bit_factor)
8373117395Skan	    {
8374169689Skan	      int nbits;
8375117395Skan
8376169689Skan	      if (GET_CODE (XEXP (x, 1)) == CONST_INT)
8377169689Skan		{
8378169689Skan		  unsigned HOST_WIDE_INT value = INTVAL (XEXP (x, 1));
8379169689Skan		  for (nbits = 0; value != 0; value &= value - 1)
8380169689Skan		    nbits++;
8381169689Skan		}
8382169689Skan	      else if (GET_CODE (XEXP (x, 1)) == CONST_DOUBLE
8383169689Skan		       && GET_MODE (XEXP (x, 1)) == VOIDmode)
8384169689Skan		{
8385169689Skan		  rtx x1 = XEXP (x, 1);
8386169689Skan		  unsigned HOST_WIDE_INT value1 = CONST_DOUBLE_LOW (x1);
8387169689Skan		  unsigned HOST_WIDE_INT value2 = CONST_DOUBLE_HIGH (x1);
8388117395Skan
8389169689Skan		  for (nbits = 0; value1 != 0; value1 &= value1 - 1)
8390169689Skan		    nbits++;
8391169689Skan		  for (; value2 != 0; value2 &= value2 - 1)
8392169689Skan		    nbits++;
8393169689Skan		}
8394169689Skan	      else
8395169689Skan		nbits = 7;
8396117395Skan
8397169689Skan	      if (nbits < 3)
8398169689Skan		nbits = 3;
8399169689Skan	      bit_cost = (nbits - 3) / sparc_costs->int_mul_bit_factor;
8400169689Skan	      bit_cost = COSTS_N_INSNS (bit_cost);
8401117395Skan	    }
8402117395Skan
8403169689Skan	  if (mode == DImode)
8404169689Skan	    *total = sparc_costs->int_mulX + bit_cost;
8405169689Skan	  else
8406169689Skan	    *total = sparc_costs->int_mul + bit_cost;
8407132718Skan	}
8408169689Skan      return false;
8409117395Skan
8410169689Skan    case ASHIFT:
8411169689Skan    case ASHIFTRT:
8412169689Skan    case LSHIFTRT:
8413169689Skan      *total = COSTS_N_INSNS (1) + sparc_costs->shift_penalty;
8414169689Skan      return false;
8415117395Skan
8416117395Skan    case DIV:
8417117395Skan    case UDIV:
8418117395Skan    case MOD:
8419117395Skan    case UMOD:
8420169689Skan      if (float_mode_p)
8421117395Skan	{
8422169689Skan	  if (mode == DFmode)
8423169689Skan	    *total = sparc_costs->float_div_df;
8424169689Skan	  else
8425169689Skan	    *total = sparc_costs->float_div_sf;
8426117395Skan	}
8427132718Skan      else
8428117395Skan	{
8429169689Skan	  if (mode == DImode)
8430169689Skan	    *total = sparc_costs->int_divX;
8431117395Skan	  else
8432169689Skan	    *total = sparc_costs->int_div;
8433169689Skan	}
8434169689Skan      return false;
8435117395Skan
8436169689Skan    case NEG:
8437169689Skan      if (! float_mode_p)
8438169689Skan	{
8439132718Skan	  *total = COSTS_N_INSNS (1);
8440169689Skan	  return false;
8441117395Skan	}
8442169689Skan      /* FALLTHRU */
8443117395Skan
8444169689Skan    case ABS:
8445169689Skan    case FLOAT:
8446169689Skan    case UNSIGNED_FLOAT:
8447169689Skan    case FIX:
8448169689Skan    case UNSIGNED_FIX:
8449169689Skan    case FLOAT_EXTEND:
8450169689Skan    case FLOAT_TRUNCATE:
8451169689Skan      *total = sparc_costs->float_move;
8452169689Skan      return false;
8453117395Skan
8454169689Skan    case SQRT:
8455169689Skan      if (mode == DFmode)
8456169689Skan	*total = sparc_costs->float_sqrt_df;
8457169689Skan      else
8458169689Skan	*total = sparc_costs->float_sqrt_sf;
8459169689Skan      return false;
8460117395Skan
8461169689Skan    case COMPARE:
8462169689Skan      if (float_mode_p)
8463169689Skan	*total = sparc_costs->float_cmp;
8464169689Skan      else
8465169689Skan	*total = COSTS_N_INSNS (1);
8466169689Skan      return false;
8467117395Skan
8468169689Skan    case IF_THEN_ELSE:
8469169689Skan      if (float_mode_p)
8470169689Skan	*total = sparc_costs->float_cmove;
8471169689Skan      else
8472169689Skan	*total = sparc_costs->int_cmove;
8473169689Skan      return false;
8474117395Skan
8475169689Skan    case IOR:
8476169689Skan      /* Handle the NAND vector patterns.  */
8477169689Skan      if (sparc_vector_mode_supported_p (GET_MODE (x))
8478169689Skan	  && GET_CODE (XEXP (x, 0)) == NOT
8479169689Skan	  && GET_CODE (XEXP (x, 1)) == NOT)
8480132718Skan	{
8481169689Skan	  *total = COSTS_N_INSNS (1);
8482132718Skan	  return true;
8483132718Skan	}
8484132718Skan      else
8485169689Skan        return false;
8486117395Skan
8487117395Skan    default:
8488132718Skan      return false;
8489132718Skan    }
8490117395Skan}
8491117395Skan
8492169689Skan/* Emit the sequence of insns SEQ while preserving the registers REG and REG2.
8493169689Skan   This is achieved by means of a manual dynamic stack space allocation in
8494169689Skan   the current frame.  We make the assumption that SEQ doesn't contain any
8495169689Skan   function calls, with the possible exception of calls to the PIC helper.  */
8496169689Skan
8497169689Skanstatic void
8498169689Skanemit_and_preserve (rtx seq, rtx reg, rtx reg2)
8499169689Skan{
8500169689Skan  /* We must preserve the lowest 16 words for the register save area.  */
8501169689Skan  HOST_WIDE_INT offset = 16*UNITS_PER_WORD;
8502169689Skan  /* We really need only 2 words of fresh stack space.  */
8503169689Skan  HOST_WIDE_INT size = SPARC_STACK_ALIGN (offset + 2*UNITS_PER_WORD);
8504169689Skan
8505169689Skan  rtx slot
8506169689Skan    = gen_rtx_MEM (word_mode, plus_constant (stack_pointer_rtx,
8507169689Skan					     SPARC_STACK_BIAS + offset));
8508169689Skan
8509169689Skan  emit_insn (gen_stack_pointer_dec (GEN_INT (size)));
8510169689Skan  emit_insn (gen_rtx_SET (VOIDmode, slot, reg));
8511169689Skan  if (reg2)
8512169689Skan    emit_insn (gen_rtx_SET (VOIDmode,
8513169689Skan			    adjust_address (slot, word_mode, UNITS_PER_WORD),
8514169689Skan			    reg2));
8515169689Skan  emit_insn (seq);
8516169689Skan  if (reg2)
8517169689Skan    emit_insn (gen_rtx_SET (VOIDmode,
8518169689Skan			    reg2,
8519169689Skan			    adjust_address (slot, word_mode, UNITS_PER_WORD)));
8520169689Skan  emit_insn (gen_rtx_SET (VOIDmode, reg, slot));
8521169689Skan  emit_insn (gen_stack_pointer_inc (GEN_INT (size)));
8522169689Skan}
8523169689Skan
8524146895Skan/* Output the assembler code for a thunk function.  THUNK_DECL is the
8525146895Skan   declaration for the thunk function itself, FUNCTION is the decl for
8526146895Skan   the target function.  DELTA is an immediate constant offset to be
8527146895Skan   added to THIS.  If VCALL_OFFSET is nonzero, the word at address
8528146895Skan   (*THIS + VCALL_OFFSET) should be additionally added to THIS.  */
8529102780Skan
8530117395Skanstatic void
8531132718Skansparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
8532146895Skan		       HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
8533132718Skan		       tree function)
8534102780Skan{
8535146895Skan  rtx this, insn, funexp;
8536169689Skan  unsigned int int_arg_first;
8537102780Skan
8538102780Skan  reload_completed = 1;
8539132718Skan  epilogue_completed = 1;
8540102780Skan  no_new_pseudos = 1;
8541169689Skan  reset_block_changes ();
8542102780Skan
8543132718Skan  emit_note (NOTE_INSN_PROLOGUE_END);
8544102780Skan
8545169689Skan  if (flag_delayed_branch)
8546169689Skan    {
8547169689Skan      /* We will emit a regular sibcall below, so we need to instruct
8548169689Skan	 output_sibcall that we are in a leaf function.  */
8549169689Skan      sparc_leaf_function_p = current_function_uses_only_leaf_regs = 1;
8550169689Skan
8551169689Skan      /* This will cause final.c to invoke leaf_renumber_regs so we
8552169689Skan	 must behave as if we were in a not-yet-leafified function.  */
8553169689Skan      int_arg_first = SPARC_INCOMING_INT_ARG_FIRST;
8554169689Skan    }
8555169689Skan  else
8556169689Skan    {
8557169689Skan      /* We will emit the sibcall manually below, so we will need to
8558169689Skan	 manually spill non-leaf registers.  */
8559169689Skan      sparc_leaf_function_p = current_function_uses_only_leaf_regs = 0;
8560169689Skan
8561169689Skan      /* We really are in a leaf function.  */
8562169689Skan      int_arg_first = SPARC_OUTGOING_INT_ARG_FIRST;
8563169689Skan    }
8564169689Skan
8565102780Skan  /* Find the "this" pointer.  Normally in %o0, but in ARCH64 if the function
8566102780Skan     returns a structure, the structure return pointer is there instead.  */
8567132718Skan  if (TARGET_ARCH64 && aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
8568169689Skan    this = gen_rtx_REG (Pmode, int_arg_first + 1);
8569102780Skan  else
8570169689Skan    this = gen_rtx_REG (Pmode, int_arg_first);
8571102780Skan
8572102780Skan  /* Add DELTA.  When possible use a plain add, otherwise load it into
8573102780Skan     a register first.  */
8574146895Skan  if (delta)
8575102780Skan    {
8576146895Skan      rtx delta_rtx = GEN_INT (delta);
8577146895Skan
8578146895Skan      if (! SPARC_SIMM13_P (delta))
8579146895Skan	{
8580146895Skan	  rtx scratch = gen_rtx_REG (Pmode, 1);
8581146895Skan	  emit_move_insn (scratch, delta_rtx);
8582146895Skan	  delta_rtx = scratch;
8583146895Skan	}
8584146895Skan
8585146895Skan      /* THIS += DELTA.  */
8586146895Skan      emit_insn (gen_add2_insn (this, delta_rtx));
8587146895Skan    }
8588146895Skan
8589146895Skan  /* Add the word at address (*THIS + VCALL_OFFSET).  */
8590146895Skan  if (vcall_offset)
8591146895Skan    {
8592146895Skan      rtx vcall_offset_rtx = GEN_INT (vcall_offset);
8593102780Skan      rtx scratch = gen_rtx_REG (Pmode, 1);
8594132718Skan
8595169689Skan      gcc_assert (vcall_offset < 0);
8596146895Skan
8597146895Skan      /* SCRATCH = *THIS.  */
8598146895Skan      emit_move_insn (scratch, gen_rtx_MEM (Pmode, this));
8599146895Skan
8600146895Skan      /* Prepare for adding VCALL_OFFSET.  The difficulty is that we
8601146895Skan	 may not have any available scratch register at this point.  */
8602146895Skan      if (SPARC_SIMM13_P (vcall_offset))
8603146895Skan	;
8604146895Skan      /* This is the case if ARCH64 (unless -ffixed-g5 is passed).  */
8605146895Skan      else if (! fixed_regs[5]
8606146895Skan	       /* The below sequence is made up of at least 2 insns,
8607146895Skan		  while the default method may need only one.  */
8608146895Skan	       && vcall_offset < -8192)
8609146895Skan	{
8610146895Skan	  rtx scratch2 = gen_rtx_REG (Pmode, 5);
8611146895Skan	  emit_move_insn (scratch2, vcall_offset_rtx);
8612146895Skan	  vcall_offset_rtx = scratch2;
8613146895Skan	}
8614102780Skan      else
8615132718Skan	{
8616146895Skan	  rtx increment = GEN_INT (-4096);
8617146895Skan
8618146895Skan	  /* VCALL_OFFSET is a negative number whose typical range can be
8619146895Skan	     estimated as -32768..0 in 32-bit mode.  In almost all cases
8620146895Skan	     it is therefore cheaper to emit multiple add insns than
8621146895Skan	     spilling and loading the constant into a register (at least
8622146895Skan	     6 insns).  */
8623146895Skan	  while (! SPARC_SIMM13_P (vcall_offset))
8624146895Skan	    {
8625146895Skan	      emit_insn (gen_add2_insn (scratch, increment));
8626146895Skan	      vcall_offset += 4096;
8627146895Skan	    }
8628146895Skan	  vcall_offset_rtx = GEN_INT (vcall_offset); /* cannot be 0 */
8629132718Skan	}
8630132718Skan
8631146895Skan      /* SCRATCH = *(*THIS + VCALL_OFFSET).  */
8632146895Skan      emit_move_insn (scratch, gen_rtx_MEM (Pmode,
8633146895Skan					    gen_rtx_PLUS (Pmode,
8634146895Skan							  scratch,
8635146895Skan							  vcall_offset_rtx)));
8636146895Skan
8637146895Skan      /* THIS += *(*THIS + VCALL_OFFSET).  */
8638146895Skan      emit_insn (gen_add2_insn (this, scratch));
8639102780Skan    }
8640102780Skan
8641102780Skan  /* Generate a tail call to the target function.  */
8642102780Skan  if (! TREE_USED (function))
8643102780Skan    {
8644102780Skan      assemble_external (function);
8645102780Skan      TREE_USED (function) = 1;
8646102780Skan    }
8647102780Skan  funexp = XEXP (DECL_RTL (function), 0);
8648169689Skan
8649169689Skan  if (flag_delayed_branch)
8650169689Skan    {
8651169689Skan      funexp = gen_rtx_MEM (FUNCTION_MODE, funexp);
8652169689Skan      insn = emit_call_insn (gen_sibcall (funexp));
8653169689Skan      SIBLING_CALL_P (insn) = 1;
8654169689Skan    }
8655169689Skan  else
8656169689Skan    {
8657169689Skan      /* The hoops we have to jump through in order to generate a sibcall
8658169689Skan	 without using delay slots...  */
8659169689Skan      rtx spill_reg, spill_reg2, seq, scratch = gen_rtx_REG (Pmode, 1);
8660169689Skan
8661169689Skan      if (flag_pic)
8662169689Skan        {
8663169689Skan	  spill_reg = gen_rtx_REG (word_mode, 15);  /* %o7 */
8664169689Skan	  spill_reg2 = gen_rtx_REG (word_mode, PIC_OFFSET_TABLE_REGNUM);
8665169689Skan	  start_sequence ();
8666169689Skan	  /* Delay emitting the PIC helper function because it needs to
8667169689Skan	     change the section and we are emitting assembly code.  */
8668169689Skan	  load_pic_register (true);  /* clobbers %o7 */
8669169689Skan	  scratch = legitimize_pic_address (funexp, Pmode, scratch);
8670169689Skan	  seq = get_insns ();
8671169689Skan	  end_sequence ();
8672169689Skan	  emit_and_preserve (seq, spill_reg, spill_reg2);
8673169689Skan	}
8674169689Skan      else if (TARGET_ARCH32)
8675169689Skan	{
8676169689Skan	  emit_insn (gen_rtx_SET (VOIDmode,
8677169689Skan				  scratch,
8678169689Skan				  gen_rtx_HIGH (SImode, funexp)));
8679169689Skan	  emit_insn (gen_rtx_SET (VOIDmode,
8680169689Skan				  scratch,
8681169689Skan				  gen_rtx_LO_SUM (SImode, scratch, funexp)));
8682169689Skan	}
8683169689Skan      else  /* TARGET_ARCH64 */
8684169689Skan        {
8685169689Skan	  switch (sparc_cmodel)
8686169689Skan	    {
8687169689Skan	    case CM_MEDLOW:
8688169689Skan	    case CM_MEDMID:
8689169689Skan	      /* The destination can serve as a temporary.  */
8690169689Skan	      sparc_emit_set_symbolic_const64 (scratch, funexp, scratch);
8691169689Skan	      break;
8692169689Skan
8693169689Skan	    case CM_MEDANY:
8694169689Skan	    case CM_EMBMEDANY:
8695169689Skan	      /* The destination cannot serve as a temporary.  */
8696169689Skan	      spill_reg = gen_rtx_REG (DImode, 15);  /* %o7 */
8697169689Skan	      start_sequence ();
8698169689Skan	      sparc_emit_set_symbolic_const64 (scratch, funexp, spill_reg);
8699169689Skan	      seq = get_insns ();
8700169689Skan	      end_sequence ();
8701169689Skan	      emit_and_preserve (seq, spill_reg, 0);
8702169689Skan	      break;
8703169689Skan
8704169689Skan	    default:
8705169689Skan	      gcc_unreachable ();
8706169689Skan	    }
8707169689Skan	}
8708169689Skan
8709169689Skan      emit_jump_insn (gen_indirect_jump (scratch));
8710169689Skan    }
8711169689Skan
8712102780Skan  emit_barrier ();
8713102780Skan
8714102780Skan  /* Run just enough of rest_of_compilation to get the insns emitted.
8715102780Skan     There's not really enough bulk here to make other passes such as
8716102780Skan     instruction scheduling worth while.  Note that use_thunk calls
8717102780Skan     assemble_start_function and assemble_end_function.  */
8718102780Skan  insn = get_insns ();
8719132718Skan  insn_locators_initialize ();
8720102780Skan  shorten_branches (insn);
8721102780Skan  final_start_function (insn, file, 1);
8722169689Skan  final (insn, file, 1);
8723102780Skan  final_end_function ();
8724102780Skan
8725102780Skan  reload_completed = 0;
8726132718Skan  epilogue_completed = 0;
8727102780Skan  no_new_pseudos = 0;
8728102780Skan}
8729117395Skan
8730146895Skan/* Return true if sparc_output_mi_thunk would be able to output the
8731146895Skan   assembler code for the thunk function specified by the arguments
8732146895Skan   it is passed, and false otherwise.  */
8733146895Skanstatic bool
8734146895Skansparc_can_output_mi_thunk (tree thunk_fndecl ATTRIBUTE_UNUSED,
8735146895Skan			   HOST_WIDE_INT delta ATTRIBUTE_UNUSED,
8736146895Skan			   HOST_WIDE_INT vcall_offset,
8737146895Skan			   tree function ATTRIBUTE_UNUSED)
8738146895Skan{
8739146895Skan  /* Bound the loop used in the default method above.  */
8740146895Skan  return (vcall_offset >= -32768 || ! fixed_regs[5]);
8741146895Skan}
8742146895Skan
8743132718Skan/* How to allocate a 'struct machine_function'.  */
8744132718Skan
8745132718Skanstatic struct machine_function *
8746132718Skansparc_init_machine_status (void)
8747132718Skan{
8748132718Skan  return ggc_alloc_cleared (sizeof (struct machine_function));
8749132718Skan}
8750132718Skan
8751132718Skan/* Locate some local-dynamic symbol still in use by this function
8752132718Skan   so that we can print its name in local-dynamic base patterns.  */
8753132718Skan
8754132718Skanstatic const char *
8755132718Skanget_some_local_dynamic_name (void)
8756132718Skan{
8757132718Skan  rtx insn;
8758132718Skan
8759132718Skan  if (cfun->machine->some_ld_name)
8760132718Skan    return cfun->machine->some_ld_name;
8761132718Skan
8762132718Skan  for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
8763132718Skan    if (INSN_P (insn)
8764132718Skan	&& for_each_rtx (&PATTERN (insn), get_some_local_dynamic_name_1, 0))
8765132718Skan      return cfun->machine->some_ld_name;
8766132718Skan
8767169689Skan  gcc_unreachable ();
8768132718Skan}
8769132718Skan
8770132718Skanstatic int
8771132718Skanget_some_local_dynamic_name_1 (rtx *px, void *data ATTRIBUTE_UNUSED)
8772132718Skan{
8773132718Skan  rtx x = *px;
8774132718Skan
8775132718Skan  if (x
8776132718Skan      && GET_CODE (x) == SYMBOL_REF
8777132718Skan      && SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_LOCAL_DYNAMIC)
8778132718Skan    {
8779132718Skan      cfun->machine->some_ld_name = XSTR (x, 0);
8780132718Skan      return 1;
8781132718Skan    }
8782132718Skan
8783132718Skan  return 0;
8784132718Skan}
8785132718Skan
8786169689Skan/* Handle the TARGET_DWARF_HANDLE_FRAME_UNSPEC hook.
8787169689Skan   This is called from dwarf2out.c to emit call frame instructions
8788169689Skan   for frame-related insns containing UNSPECs and UNSPEC_VOLATILEs. */
8789169689Skanstatic void
8790169689Skansparc_dwarf_handle_frame_unspec (const char *label,
8791169689Skan				 rtx pattern ATTRIBUTE_UNUSED,
8792169689Skan				 int index ATTRIBUTE_UNUSED)
8793169689Skan{
8794169689Skan  gcc_assert (index == UNSPECV_SAVEW);
8795169689Skan  dwarf2out_window_save (label);
8796169689Skan}
8797169689Skan
8798169689Skan/* This is called from dwarf2out.c via TARGET_ASM_OUTPUT_DWARF_DTPREL.
8799132718Skan   We need to emit DTP-relative relocations.  */
8800132718Skan
8801169689Skanstatic void
8802132718Skansparc_output_dwarf_dtprel (FILE *file, int size, rtx x)
8803132718Skan{
8804132718Skan  switch (size)
8805132718Skan    {
8806132718Skan    case 4:
8807132718Skan      fputs ("\t.word\t%r_tls_dtpoff32(", file);
8808132718Skan      break;
8809132718Skan    case 8:
8810132718Skan      fputs ("\t.xword\t%r_tls_dtpoff64(", file);
8811132718Skan      break;
8812132718Skan    default:
8813169689Skan      gcc_unreachable ();
8814132718Skan    }
8815132718Skan  output_addr_const (file, x);
8816132718Skan  fputs (")", file);
8817132718Skan}
8818132718Skan
8819169689Skan/* Do whatever processing is required at the end of a file.  */
8820169689Skan
8821169689Skanstatic void
8822169689Skansparc_file_end (void)
8823169689Skan{
8824169689Skan  /* If we haven't emitted the special PIC helper function, do so now.  */
8825169689Skan  if (pic_helper_symbol_name[0] && !pic_helper_emitted_p)
8826169689Skan    emit_pic_helper ();
8827169689Skan
8828169689Skan  if (NEED_INDICATE_EXEC_STACK)
8829169689Skan    file_end_indicate_exec_stack ();
8830169689Skan}
8831169689Skan
8832169689Skan#ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
8833169689Skan/* Implement TARGET_MANGLE_FUNDAMENTAL_TYPE.  */
8834169689Skan
8835169689Skanstatic const char *
8836169689Skansparc_mangle_fundamental_type (tree type)
8837169689Skan{
8838169689Skan  if (!TARGET_64BIT
8839169689Skan      && TYPE_MAIN_VARIANT (type) == long_double_type_node
8840169689Skan      && TARGET_LONG_DOUBLE_128)
8841169689Skan    return "g";
8842169689Skan
8843169689Skan  /* For all other types, use normal C++ mangling.  */
8844169689Skan  return NULL;
8845169689Skan}
8846169689Skan#endif
8847169689Skan
8848169689Skan/* Expand code to perform a 8 or 16-bit compare and swap by doing 32-bit
8849169689Skan   compare and swap on the word containing the byte or half-word.  */
8850169689Skan
8851169689Skanvoid
8852169689Skansparc_expand_compare_and_swap_12 (rtx result, rtx mem, rtx oldval, rtx newval)
8853169689Skan{
8854169689Skan  rtx addr1 = force_reg (Pmode, XEXP (mem, 0));
8855169689Skan  rtx addr = gen_reg_rtx (Pmode);
8856169689Skan  rtx off = gen_reg_rtx (SImode);
8857169689Skan  rtx oldv = gen_reg_rtx (SImode);
8858169689Skan  rtx newv = gen_reg_rtx (SImode);
8859169689Skan  rtx oldvalue = gen_reg_rtx (SImode);
8860169689Skan  rtx newvalue = gen_reg_rtx (SImode);
8861169689Skan  rtx res = gen_reg_rtx (SImode);
8862169689Skan  rtx resv = gen_reg_rtx (SImode);
8863169689Skan  rtx memsi, val, mask, end_label, loop_label, cc;
8864169689Skan
8865169689Skan  emit_insn (gen_rtx_SET (VOIDmode, addr,
8866169689Skan			  gen_rtx_AND (Pmode, addr1, GEN_INT (-4))));
8867169689Skan
8868169689Skan  if (Pmode != SImode)
8869169689Skan    addr1 = gen_lowpart (SImode, addr1);
8870169689Skan  emit_insn (gen_rtx_SET (VOIDmode, off,
8871169689Skan			  gen_rtx_AND (SImode, addr1, GEN_INT (3))));
8872169689Skan
8873169689Skan  memsi = gen_rtx_MEM (SImode, addr);
8874169689Skan  set_mem_alias_set (memsi, ALIAS_SET_MEMORY_BARRIER);
8875169689Skan  MEM_VOLATILE_P (memsi) = MEM_VOLATILE_P (mem);
8876169689Skan
8877169689Skan  val = force_reg (SImode, memsi);
8878169689Skan
8879169689Skan  emit_insn (gen_rtx_SET (VOIDmode, off,
8880169689Skan			  gen_rtx_XOR (SImode, off,
8881169689Skan				       GEN_INT (GET_MODE (mem) == QImode
8882169689Skan						? 3 : 2))));
8883169689Skan
8884169689Skan  emit_insn (gen_rtx_SET (VOIDmode, off,
8885169689Skan			  gen_rtx_ASHIFT (SImode, off, GEN_INT (3))));
8886169689Skan
8887169689Skan  if (GET_MODE (mem) == QImode)
8888169689Skan    mask = force_reg (SImode, GEN_INT (0xff));
8889169689Skan  else
8890169689Skan    mask = force_reg (SImode, GEN_INT (0xffff));
8891169689Skan
8892169689Skan  emit_insn (gen_rtx_SET (VOIDmode, mask,
8893169689Skan			  gen_rtx_ASHIFT (SImode, mask, off)));
8894169689Skan
8895169689Skan  emit_insn (gen_rtx_SET (VOIDmode, val,
8896169689Skan			  gen_rtx_AND (SImode, gen_rtx_NOT (SImode, mask),
8897169689Skan				       val)));
8898169689Skan
8899169689Skan  oldval = gen_lowpart (SImode, oldval);
8900169689Skan  emit_insn (gen_rtx_SET (VOIDmode, oldv,
8901169689Skan			  gen_rtx_ASHIFT (SImode, oldval, off)));
8902169689Skan
8903169689Skan  newval = gen_lowpart_common (SImode, newval);
8904169689Skan  emit_insn (gen_rtx_SET (VOIDmode, newv,
8905169689Skan			  gen_rtx_ASHIFT (SImode, newval, off)));
8906169689Skan
8907169689Skan  emit_insn (gen_rtx_SET (VOIDmode, oldv,
8908169689Skan			  gen_rtx_AND (SImode, oldv, mask)));
8909169689Skan
8910169689Skan  emit_insn (gen_rtx_SET (VOIDmode, newv,
8911169689Skan			  gen_rtx_AND (SImode, newv, mask)));
8912169689Skan
8913169689Skan  end_label = gen_label_rtx ();
8914169689Skan  loop_label = gen_label_rtx ();
8915169689Skan  emit_label (loop_label);
8916169689Skan
8917169689Skan  emit_insn (gen_rtx_SET (VOIDmode, oldvalue,
8918169689Skan			  gen_rtx_IOR (SImode, oldv, val)));
8919169689Skan
8920169689Skan  emit_insn (gen_rtx_SET (VOIDmode, newvalue,
8921169689Skan			  gen_rtx_IOR (SImode, newv, val)));
8922169689Skan
8923169689Skan  emit_insn (gen_sync_compare_and_swapsi (res, memsi, oldvalue, newvalue));
8924169689Skan
8925169689Skan  emit_cmp_and_jump_insns (res, oldvalue, EQ, NULL, SImode, 0, end_label);
8926169689Skan
8927169689Skan  emit_insn (gen_rtx_SET (VOIDmode, resv,
8928169689Skan			  gen_rtx_AND (SImode, gen_rtx_NOT (SImode, mask),
8929169689Skan				       res)));
8930169689Skan
8931169689Skan  sparc_compare_op0 = resv;
8932169689Skan  sparc_compare_op1 = val;
8933169689Skan  cc = gen_compare_reg (NE);
8934169689Skan
8935169689Skan  emit_insn (gen_rtx_SET (VOIDmode, val, resv));
8936169689Skan
8937169689Skan  sparc_compare_emitted = cc;
8938169689Skan  emit_jump_insn (gen_bne (loop_label));
8939169689Skan
8940169689Skan  emit_label (end_label);
8941169689Skan
8942169689Skan  emit_insn (gen_rtx_SET (VOIDmode, res,
8943169689Skan			  gen_rtx_AND (SImode, res, mask)));
8944169689Skan
8945169689Skan  emit_insn (gen_rtx_SET (VOIDmode, res,
8946169689Skan			  gen_rtx_LSHIFTRT (SImode, res, off)));
8947169689Skan
8948169689Skan  emit_move_insn (result, gen_lowpart (GET_MODE (result), res));
8949169689Skan}
8950169689Skan
8951117395Skan#include "gt-sparc.h"
8952