Fix dupplicate declaration of ggc_realloc in gencondmd
[platform/upstream/gcc.git] / gcc / config / score / score.c
1 /* Output routines for Sunplus S+CORE processor
2    Copyright (C) 2005-2014 Free Software Foundation, Inc.
3    Contributed by Sunnorth.
4
5    This file is part of GCC.
6
7    GCC is free software; you can redistribute it and/or modify it
8    under the terms of the GNU General Public License as published
9    by the Free Software Foundation; either version 3, or (at your
10    option) any later version.
11
12    GCC is distributed in the hope that it will be useful, but WITHOUT
13    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15    License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GCC; see the file COPYING3.  If not see
19    <http://www.gnu.org/licenses/>.  */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "rtl.h"
26 #include "regs.h"
27 #include "hard-reg-set.h"
28 #include "insn-config.h"
29 #include "conditions.h"
30 #include "insn-attr.h"
31 #include "recog.h"
32 #include "diagnostic-core.h"
33 #include "output.h"
34 #include "tree.h"
35 #include "stringpool.h"
36 #include "calls.h"
37 #include "varasm.h"
38 #include "stor-layout.h"
39 #include "function.h"
40 #include "expr.h"
41 #include "optabs.h"
42 #include "flags.h"
43 #include "reload.h"
44 #include "tm_p.h"
45 #include "ggc.h"
46 #include "gstab.h"
47 #include "hashtab.h"
48 #include "debug.h"
49 #include "target.h"
50 #include "target-def.h"
51 #include "langhooks.h"
52 #include "df.h"
53 #include "opts.h"
54 #include "builtins.h"
55
56 #define SCORE_SDATA_MAX                score_sdata_max
57 #define SCORE_STACK_ALIGN(LOC)         (((LOC) + 3) & ~3)
58 #define SCORE_PROLOGUE_TEMP_REGNUM     (GP_REG_FIRST + 8)
59 #define SCORE_EPILOGUE_TEMP_REGNUM     (GP_REG_FIRST + 8)
60 #define SCORE_DEFAULT_SDATA_MAX        8
61
62 #define BITSET_P(VALUE, BIT)           (((VALUE) & (1L << (BIT))) != 0)
63 #define INS_BUF_SZ                     128
64
65 enum score_address_type
66 {
67   SCORE_ADD_REG,
68   SCORE_ADD_CONST_INT,
69   SCORE_ADD_SYMBOLIC
70 };
71
72 struct score_frame_info
73 {
74   HOST_WIDE_INT total_size;       /* bytes that the entire frame takes up  */
75   HOST_WIDE_INT var_size;         /* bytes that variables take up  */
76   HOST_WIDE_INT args_size;        /* bytes that outgoing arguments take up  */
77   HOST_WIDE_INT gp_reg_size;      /* bytes needed to store gp regs  */
78   HOST_WIDE_INT gp_sp_offset;     /* offset from new sp to store gp registers  */
79   HOST_WIDE_INT cprestore_size;   /* # bytes that the .cprestore slot takes up  */
80   unsigned int  mask;             /* mask of saved gp registers  */
81   int num_gp;                     /* number of gp registers saved  */
82 };
83
84 struct score_arg_info
85 {
86   unsigned int num_bytes;     /* The argument's size in bytes  */
87   unsigned int reg_words;     /* The number of words passed in registers  */
88   unsigned int reg_offset;    /* The offset of the first register from  */
89                               /* GP_ARG_FIRST or FP_ARG_FIRST etc  */
90   unsigned int stack_words;   /* The number of words that must be passed  */
91                               /* on the stack  */
92   unsigned int stack_offset;  /* The offset from the start of the stack  */
93                               /* overflow area  */
94 };
95
96 #ifdef RTX_CODE
97 struct score_address_info
98 {
99   enum score_address_type type;
100   rtx reg;
101   rtx offset;
102   enum rtx_code code;
103   enum score_symbol_type symbol_type;
104 };
105 #endif
106
107 static int score_sdata_max;
108 static char score_ins[INS_BUF_SZ + 8];
109
110 struct extern_list *extern_head = 0;
111
112 #undef  TARGET_ASM_FILE_START
113 #define TARGET_ASM_FILE_START           score_asm_file_start
114
115 #undef  TARGET_ASM_FILE_END
116 #define TARGET_ASM_FILE_END             score_asm_file_end
117
118 #undef  TARGET_ASM_FUNCTION_PROLOGUE
119 #define TARGET_ASM_FUNCTION_PROLOGUE    score_function_prologue
120
121 #undef  TARGET_ASM_FUNCTION_EPILOGUE
122 #define TARGET_ASM_FUNCTION_EPILOGUE    score_function_epilogue
123
124 #undef TARGET_OPTION_OVERRIDE
125 #define TARGET_OPTION_OVERRIDE          score_option_override
126
127 #undef  TARGET_SCHED_ISSUE_RATE
128 #define TARGET_SCHED_ISSUE_RATE         score_issue_rate
129
130 #undef TARGET_ASM_SELECT_RTX_SECTION
131 #define TARGET_ASM_SELECT_RTX_SECTION   score_select_rtx_section
132
133 #undef  TARGET_IN_SMALL_DATA_P
134 #define TARGET_IN_SMALL_DATA_P          score_in_small_data_p
135
136 #undef  TARGET_FUNCTION_OK_FOR_SIBCALL
137 #define TARGET_FUNCTION_OK_FOR_SIBCALL  score_function_ok_for_sibcall
138
139 #undef TARGET_STRICT_ARGUMENT_NAMING
140 #define TARGET_STRICT_ARGUMENT_NAMING   hook_bool_CUMULATIVE_ARGS_true
141
142 #undef TARGET_ASM_OUTPUT_MI_THUNK
143 #define TARGET_ASM_OUTPUT_MI_THUNK      score_output_mi_thunk
144
145 #undef TARGET_PROMOTE_FUNCTION_MODE
146 #define TARGET_PROMOTE_FUNCTION_MODE    default_promote_function_mode_always_promote
147
148 #undef TARGET_PROMOTE_PROTOTYPES
149 #define TARGET_PROMOTE_PROTOTYPES       hook_bool_const_tree_true
150
151 #undef TARGET_MUST_PASS_IN_STACK
152 #define TARGET_MUST_PASS_IN_STACK       must_pass_in_stack_var_size
153
154 #undef TARGET_ARG_PARTIAL_BYTES
155 #define TARGET_ARG_PARTIAL_BYTES        score_arg_partial_bytes
156
157 #undef TARGET_FUNCTION_ARG
158 #define TARGET_FUNCTION_ARG             score_function_arg
159
160 #undef TARGET_FUNCTION_ARG_ADVANCE
161 #define TARGET_FUNCTION_ARG_ADVANCE     score_function_arg_advance
162
163 #undef TARGET_PASS_BY_REFERENCE
164 #define TARGET_PASS_BY_REFERENCE        score_pass_by_reference
165
166 #undef TARGET_RETURN_IN_MEMORY
167 #define TARGET_RETURN_IN_MEMORY         score_return_in_memory
168
169 #undef TARGET_RTX_COSTS
170 #define TARGET_RTX_COSTS                score_rtx_costs
171
172 #undef TARGET_ADDRESS_COST
173 #define TARGET_ADDRESS_COST             score_address_cost
174
175 #undef TARGET_LEGITIMATE_ADDRESS_P
176 #define TARGET_LEGITIMATE_ADDRESS_P     score_legitimate_address_p
177
178 #undef TARGET_CAN_ELIMINATE
179 #define TARGET_CAN_ELIMINATE            score_can_eliminate
180
181 #undef TARGET_CONDITIONAL_REGISTER_USAGE
182 #define TARGET_CONDITIONAL_REGISTER_USAGE score_conditional_register_usage
183
184 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
185 #define TARGET_ASM_TRAMPOLINE_TEMPLATE  score_asm_trampoline_template
186 #undef TARGET_TRAMPOLINE_INIT
187 #define TARGET_TRAMPOLINE_INIT          score_trampoline_init
188
189 #undef TARGET_REGISTER_MOVE_COST
190 #define TARGET_REGISTER_MOVE_COST       score_register_move_cost
191
192 /* Return true if SYMBOL is a SYMBOL_REF and OFFSET + SYMBOL points
193    to the same object as SYMBOL.  */
194 static int
195 score_offset_within_object_p (rtx symbol, HOST_WIDE_INT offset)
196 {
197   if (GET_CODE (symbol) != SYMBOL_REF)
198     return 0;
199
200   if (CONSTANT_POOL_ADDRESS_P (symbol)
201       && offset >= 0
202       && offset < (int)GET_MODE_SIZE (get_pool_mode (symbol)))
203     return 1;
204
205   if (SYMBOL_REF_DECL (symbol) != 0
206       && offset >= 0
207       && offset < int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (symbol))))
208     return 1;
209
210   return 0;
211 }
212
213 /* Split X into a base and a constant offset, storing them in *BASE
214    and *OFFSET respectively.  */
215 static void
216 score_split_const (rtx x, rtx *base, HOST_WIDE_INT *offset)
217 {
218   *offset = 0;
219
220   if (GET_CODE (x) == CONST)
221     x = XEXP (x, 0);
222
223   if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT)
224     {
225       *offset += INTVAL (XEXP (x, 1));
226       x = XEXP (x, 0);
227     }
228
229   *base = x;
230 }
231
232 /* Classify symbol X, which must be a SYMBOL_REF or a LABEL_REF.  */
233 static enum score_symbol_type
234 score_classify_symbol (rtx x)
235 {
236   if (GET_CODE (x) == LABEL_REF)
237     return SYMBOL_GENERAL;
238
239   gcc_assert (GET_CODE (x) == SYMBOL_REF);
240
241   if (CONSTANT_POOL_ADDRESS_P (x))
242     {
243       if (GET_MODE_SIZE (get_pool_mode (x)) <= SCORE_SDATA_MAX)
244         return SYMBOL_SMALL_DATA;
245       return SYMBOL_GENERAL;
246     }
247   if (SYMBOL_REF_SMALL_P (x))
248     return SYMBOL_SMALL_DATA;
249   return SYMBOL_GENERAL;
250 }
251
252 /* Return true if the current function must save REGNO.  */
253 static int
254 score_save_reg_p (unsigned int regno)
255 {
256   /* Check call-saved registers.  */
257   if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
258     return 1;
259
260   /* We need to save the old frame pointer before setting up a new one.  */
261   if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)
262     return 1;
263
264   /* We need to save the incoming return address if it is ever clobbered
265      within the function.  */
266   if (regno == RA_REGNUM && df_regs_ever_live_p (regno))
267     return 1;
268
269   return 0;
270 }
271
272 /* Return one word of double-word value OP, taking into account the fixed
273    endianness of certain registers.  HIGH_P is true to select the high part,
274    false to select the low part.  */
275 static rtx
276 score_subw (rtx op, int high_p)
277 {
278   unsigned int byte;
279   enum machine_mode mode = GET_MODE (op);
280
281   if (mode == VOIDmode)
282     mode = DImode;
283
284   byte = (TARGET_LITTLE_ENDIAN ? high_p : !high_p) ? UNITS_PER_WORD : 0;
285
286   if (GET_CODE (op) == REG && REGNO (op) == HI_REGNUM)
287     return gen_rtx_REG (SImode, high_p ? HI_REGNUM : LO_REGNUM);
288
289   if (GET_CODE (op) == MEM)
290     return adjust_address (op, SImode, byte);
291
292   return simplify_gen_subreg (SImode, op, mode, byte);
293 }
294
295 static struct score_frame_info *
296 score_cached_frame (void)
297 {
298   static struct score_frame_info _frame_info;
299   return &_frame_info;
300 }
301
302 /* Return the bytes needed to compute the frame pointer from the current
303    stack pointer.  SIZE is the size (in bytes) of the local variables.  */
304 static struct score_frame_info *
305 score_compute_frame_size (HOST_WIDE_INT size)
306 {
307   unsigned int regno;
308   struct score_frame_info *f = score_cached_frame ();
309
310   memset (f, 0, sizeof (struct score_frame_info));
311   f->gp_reg_size = 0;
312   f->mask = 0;
313   f->var_size = SCORE_STACK_ALIGN (size);
314   f->args_size = crtl->outgoing_args_size;
315   f->cprestore_size = flag_pic ? UNITS_PER_WORD : 0;
316   if (f->var_size == 0 && crtl->is_leaf)
317     f->args_size = f->cprestore_size = 0;
318
319   if (f->args_size == 0 && cfun->calls_alloca)
320     f->args_size = UNITS_PER_WORD;
321
322   f->total_size = f->var_size + f->args_size + f->cprestore_size;
323   for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
324     {
325       if (score_save_reg_p (regno))
326         {
327           f->gp_reg_size += GET_MODE_SIZE (SImode);
328           f->mask |= 1 << (regno - GP_REG_FIRST);
329         }
330     }
331
332   if (crtl->calls_eh_return)
333     {
334       unsigned int i;
335       for (i = 0;; ++i)
336         {
337           regno = EH_RETURN_DATA_REGNO (i);
338           if (regno == INVALID_REGNUM)
339             break;
340           f->gp_reg_size += GET_MODE_SIZE (SImode);
341           f->mask |= 1 << (regno - GP_REG_FIRST);
342         }
343     }
344
345   f->total_size += f->gp_reg_size;
346   f->num_gp = f->gp_reg_size / UNITS_PER_WORD;
347
348   if (f->mask)
349     {
350       HOST_WIDE_INT offset;
351       offset = (f->args_size + f->cprestore_size + f->var_size
352                 + f->gp_reg_size - GET_MODE_SIZE (SImode));
353       f->gp_sp_offset = offset;
354     }
355   else
356     f->gp_sp_offset = 0;
357
358   return f;
359 }
360
361 /* Return true if X is a valid base register for the given mode.
362    Allow only hard registers if STRICT.  */
363 static int
364 score_valid_base_register_p (rtx x, int strict)
365 {
366   if (!strict && GET_CODE (x) == SUBREG)
367     x = SUBREG_REG (x);
368
369   return (GET_CODE (x) == REG
370           && score_regno_mode_ok_for_base_p (REGNO (x), strict));
371 }
372
373 /* Return true if X is a valid address for machine mode MODE.  If it is,
374    fill in INFO appropriately.  STRICT is true if we should only accept
375    hard base registers.  */
376 static int
377 score_classify_address (struct score_address_info *info,
378                         enum machine_mode mode, rtx x, int strict)
379 {
380   info->code = GET_CODE (x);
381
382   switch (info->code)
383     {
384     case REG:
385     case SUBREG:
386       info->type = SCORE_ADD_REG;
387       info->reg = x;
388       info->offset = const0_rtx;
389       return score_valid_base_register_p (info->reg, strict);
390     case PLUS:
391       info->type = SCORE_ADD_REG;
392       info->reg = XEXP (x, 0);
393       info->offset = XEXP (x, 1);
394       return (score_valid_base_register_p (info->reg, strict)
395               && GET_CODE (info->offset) == CONST_INT
396               && IMM_IN_RANGE (INTVAL (info->offset), 15, 1));
397     case PRE_DEC:
398     case POST_DEC:
399     case PRE_INC:
400     case POST_INC:
401       if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (SImode))
402         return false;
403       info->type = SCORE_ADD_REG;
404       info->reg = XEXP (x, 0);
405       info->offset = GEN_INT (GET_MODE_SIZE (mode));
406       return score_valid_base_register_p (info->reg, strict);
407     case CONST_INT:
408       info->type = SCORE_ADD_CONST_INT;
409       return IMM_IN_RANGE (INTVAL (x), 15, 1);
410     case CONST:
411     case LABEL_REF:
412     case SYMBOL_REF:
413       info->type = SCORE_ADD_SYMBOLIC;
414       return (score_symbolic_constant_p (x, &info->symbol_type)
415               && (info->symbol_type == SYMBOL_GENERAL
416                   || info->symbol_type == SYMBOL_SMALL_DATA));
417     default:
418       return 0;
419     }
420 }
421
422 /* Implement TARGET_RETURN_IN_MEMORY.  In S+core,
423    small structures are returned in a register.
424    Objects with varying size must still be returned in memory.  */
425 static bool
426 score_return_in_memory (const_tree type, const_tree fndecl ATTRIBUTE_UNUSED)
427 {
428     return ((TYPE_MODE (type) == BLKmode)
429             || (int_size_in_bytes (type) > 2 * UNITS_PER_WORD)
430             || (int_size_in_bytes (type) == -1));
431 }
432
433 /* Return a legitimate address for REG + OFFSET.  */
434 static rtx
435 score_add_offset (rtx reg, HOST_WIDE_INT offset)
436 {
437   if (!IMM_IN_RANGE (offset, 15, 1))
438     {
439       reg = expand_simple_binop (GET_MODE (reg), PLUS,
440                                  gen_int_mode (offset & 0xffffc000,
441                                                GET_MODE (reg)),
442                                  reg, NULL, 0, OPTAB_WIDEN);
443       offset &= 0x3fff;
444     }
445
446   return plus_constant (GET_MODE (reg), reg, offset);
447 }
448
449 /* Implement TARGET_ASM_OUTPUT_MI_THUNK.  Generate rtl rather than asm text
450    in order to avoid duplicating too much logic from elsewhere.  */
451 static void
452 score_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
453                        HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
454                        tree function)
455 {
456   rtx this_rtx, temp1, fnaddr;
457   rtx_insn *insn;
458
459   /* Pretend to be a post-reload pass while generating rtl.  */
460   reload_completed = 1;
461
462   /* Mark the end of the (empty) prologue.  */
463   emit_note (NOTE_INSN_PROLOGUE_END);
464
465   /* We need two temporary registers in some cases.  */
466   temp1 = gen_rtx_REG (Pmode, 8);
467
468   /* Find out which register contains the "this" pointer.  */
469   if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
470     this_rtx = gen_rtx_REG (Pmode, ARG_REG_FIRST + 1);
471   else
472     this_rtx = gen_rtx_REG (Pmode, ARG_REG_FIRST);
473
474   /* Add DELTA to THIS_RTX.  */
475   if (delta != 0)
476     {
477       rtx offset = GEN_INT (delta);
478       if (!(delta >= -32768 && delta <= 32767))
479         {
480           emit_move_insn (temp1, offset);
481           offset = temp1;
482         }
483       emit_insn (gen_add3_insn (this_rtx, this_rtx, offset));
484     }
485
486   /* If needed, add *(*THIS_RTX + VCALL_OFFSET) to THIS_RTX.  */
487   if (vcall_offset != 0)
488     {
489       rtx addr;
490
491       /* Set TEMP1 to *THIS_RTX.  */
492       emit_move_insn (temp1, gen_rtx_MEM (Pmode, this_rtx));
493
494       /* Set ADDR to a legitimate address for *THIS_RTX + VCALL_OFFSET.  */
495       addr = score_add_offset (temp1, vcall_offset);
496
497       /* Load the offset and add it to THIS_RTX.  */
498       emit_move_insn (temp1, gen_rtx_MEM (Pmode, addr));
499       emit_insn (gen_add3_insn (this_rtx, this_rtx, temp1));
500     }
501
502   /* Jump to the target function.  */
503   fnaddr = XEXP (DECL_RTL (function), 0);
504   insn = emit_call_insn (gen_sibcall_internal_score7 (fnaddr, const0_rtx));
505   SIBLING_CALL_P (insn) = 1;
506
507   /* Run just enough of rest_of_compilation.  This sequence was
508      "borrowed" from alpha.c.  */
509   insn = get_insns ();
510   split_all_insns_noflow ();
511   shorten_branches (insn);
512   final_start_function (insn, file, 1);
513   final (insn, file, 1);
514   final_end_function ();
515
516   /* Clean up the vars set above.  Note that final_end_function resets
517      the global pointer for us.  */
518   reload_completed = 0;
519 }
520
521 /* Fill INFO with information about a single argument.  CUM is the
522    cumulative state for earlier arguments.  MODE is the mode of this
523    argument and TYPE is its type (if known).  NAMED is true if this
524    is a named (fixed) argument rather than a variable one.  */
525 static void
526 score_classify_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
527                     const_tree type, bool named, struct score_arg_info *info)
528 {
529   int even_reg_p;
530   unsigned int num_words, max_regs;
531
532   even_reg_p = 0;
533   if (GET_MODE_CLASS (mode) == MODE_INT
534       || GET_MODE_CLASS (mode) == MODE_FLOAT)
535     even_reg_p = (GET_MODE_SIZE (mode) > UNITS_PER_WORD);
536   else
537     if (type != NULL_TREE && TYPE_ALIGN (type) > BITS_PER_WORD && named)
538       even_reg_p = 1;
539
540   if (TARGET_MUST_PASS_IN_STACK (mode, type))
541     info->reg_offset = ARG_REG_NUM;
542   else
543     {
544       info->reg_offset = cum->num_gprs;
545       if (even_reg_p)
546         info->reg_offset += info->reg_offset & 1;
547     }
548
549   if (mode == BLKmode)
550     info->num_bytes = int_size_in_bytes (type);
551   else
552     info->num_bytes = GET_MODE_SIZE (mode);
553
554   num_words = (info->num_bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
555   max_regs = ARG_REG_NUM - info->reg_offset;
556
557   /* Partition the argument between registers and stack.  */
558   info->reg_words = MIN (num_words, max_regs);
559   info->stack_words = num_words - info->reg_words;
560
561   /* The alignment applied to registers is also applied to stack arguments.  */
562   if (info->stack_words)
563     {
564       info->stack_offset = cum->stack_words;
565       if (even_reg_p)
566         info->stack_offset += info->stack_offset & 1;
567     }
568 }
569
570 /* Set up the stack and frame (if desired) for the function.  */
571 static void
572 score_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
573 {
574   const char *fnname;
575   struct score_frame_info *f = score_cached_frame ();
576   HOST_WIDE_INT tsize = f->total_size;
577
578   fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
579   if (!flag_inhibit_size_directive)
580     {
581       fputs ("\t.ent\t", file);
582       assemble_name (file, fnname);
583       fputs ("\n", file);
584     }
585   assemble_name (file, fnname);
586   fputs (":\n", file);
587
588   if (!flag_inhibit_size_directive)
589     {
590       fprintf (file,
591                "\t.frame\t%s," HOST_WIDE_INT_PRINT_DEC ",%s, %d\t\t"
592                "# vars= " HOST_WIDE_INT_PRINT_DEC ", regs= %d"
593                ", args= " HOST_WIDE_INT_PRINT_DEC
594                ", gp= " HOST_WIDE_INT_PRINT_DEC "\n",
595                (reg_names[(frame_pointer_needed)
596                 ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM]),
597                tsize,
598                reg_names[RA_REGNUM],
599                crtl->is_leaf ? 1 : 0,
600                f->var_size,
601                f->num_gp,
602                f->args_size,
603                f->cprestore_size);
604
605       fprintf(file, "\t.mask\t0x%08x," HOST_WIDE_INT_PRINT_DEC "\n",
606               f->mask,
607               (f->gp_sp_offset - f->total_size));
608     }
609 }
610
611 /* Do any necessary cleanup after a function to restore stack, frame,
612    and regs.  */
613 static void
614 score_function_epilogue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
615 {
616   if (!flag_inhibit_size_directive)
617     {
618       const char *fnname;
619       fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
620       fputs ("\t.end\t", file);
621       assemble_name (file, fnname);
622       fputs ("\n", file);
623     }
624 }
625
626 /* Returns true if X contains a SYMBOL_REF.  */
627 static bool
628 score_symbolic_expression_p (rtx x)
629 {
630   if (GET_CODE (x) == SYMBOL_REF)
631     return true;
632
633   if (GET_CODE (x) == CONST)
634     return score_symbolic_expression_p (XEXP (x, 0));
635
636   if (UNARY_P (x))
637     return score_symbolic_expression_p (XEXP (x, 0));
638
639   if (ARITHMETIC_P (x))
640     return (score_symbolic_expression_p (XEXP (x, 0))
641             || score_symbolic_expression_p (XEXP (x, 1)));
642
643   return false;
644 }
645
646 /* Choose the section to use for the constant rtx expression X that has
647    mode MODE.  */
648 static section *
649 score_select_rtx_section (enum machine_mode mode, rtx x, unsigned HOST_WIDE_INT align)
650 {
651   if (GET_MODE_SIZE (mode) <= SCORE_SDATA_MAX)
652     return get_named_section (0, ".sdata", 0);
653   else if (flag_pic && score_symbolic_expression_p (x))
654     return get_named_section (0, ".data.rel.ro", 3);
655   else
656     return mergeable_constant_section (mode, align, 0);
657 }
658
659 /* Implement TARGET_IN_SMALL_DATA_P.  */
660 static bool
661 score_in_small_data_p (const_tree decl)
662 {
663   HOST_WIDE_INT size;
664
665   if (TREE_CODE (decl) == STRING_CST
666       || TREE_CODE (decl) == FUNCTION_DECL)
667     return false;
668
669   if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl) != 0)
670     {
671       const char *name;
672       name = DECL_SECTION_NAME (decl);
673       if (strcmp (name, ".sdata") != 0
674           && strcmp (name, ".sbss") != 0)
675         return true;
676       if (!DECL_EXTERNAL (decl))
677         return false;
678     }
679   size = int_size_in_bytes (TREE_TYPE (decl));
680   return (size > 0 && size <= SCORE_SDATA_MAX);
681 }
682
683 /* Implement TARGET_ASM_FILE_START.  */
684 static void
685 score_asm_file_start (void)
686 {
687   default_file_start ();
688   fprintf (asm_out_file, ASM_COMMENT_START
689            "GCC for S+core %s \n", SCORE_GCC_VERSION);
690
691   if (flag_pic)
692     fprintf (asm_out_file, "\t.set pic\n");
693 }
694
695 /* Implement TARGET_ASM_FILE_END.  When using assembler macros, emit
696    .externs for any small-data variables that turned out to be external.  */
697 static void
698 score_asm_file_end (void)
699 {
700   tree name_tree;
701   struct extern_list *p;
702   if (extern_head)
703     {
704       fputs ("\n", asm_out_file);
705       for (p = extern_head; p != 0; p = p->next)
706         {
707           name_tree = get_identifier (p->name);
708           if (!TREE_ASM_WRITTEN (name_tree)
709               && TREE_SYMBOL_REFERENCED (name_tree))
710             {
711               TREE_ASM_WRITTEN (name_tree) = 1;
712               fputs ("\t.extern\t", asm_out_file);
713               assemble_name (asm_out_file, p->name);
714               fprintf (asm_out_file, ", %d\n", p->size);
715             }
716         }
717     }
718 }
719
720 /* Implement TARGET_OPTION_OVERRIDE hook.  */
721 static void
722 score_option_override (void)
723 {
724   flag_pic = false;
725   score_sdata_max = SCORE_DEFAULT_SDATA_MAX;
726
727 }
728
729 /* Implement REGNO_REG_CLASS macro.  */
730 int
731 score_reg_class (int regno)
732 {
733   int c;
734   gcc_assert (regno >= 0 && regno < FIRST_PSEUDO_REGISTER);
735
736   if (regno == FRAME_POINTER_REGNUM
737       || regno == ARG_POINTER_REGNUM)
738     return ALL_REGS;
739
740   for (c = 0; c < N_REG_CLASSES; c++)
741     if (TEST_HARD_REG_BIT (reg_class_contents[c], regno))
742       return c;
743
744   return NO_REGS;
745 }
746
747 /* Implement PREFERRED_RELOAD_CLASS macro.  */
748 enum reg_class
749 score_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, enum reg_class rclass)
750 {
751   if (reg_class_subset_p (G16_REGS, rclass))
752     return G16_REGS;
753   if (reg_class_subset_p (G32_REGS, rclass))
754     return G32_REGS;
755   return rclass;
756 }
757
758 /* Implement SECONDARY_INPUT_RELOAD_CLASS
759    and SECONDARY_OUTPUT_RELOAD_CLASS macro.  */
760 enum reg_class
761 score_secondary_reload_class (enum reg_class rclass,
762                               enum machine_mode mode ATTRIBUTE_UNUSED,
763                               rtx x)
764 {
765   int regno = -1;
766   if (GET_CODE (x) == REG || GET_CODE(x) == SUBREG)
767     regno = true_regnum (x);
768
769   if (!GR_REG_CLASS_P (rclass))
770     return GP_REG_P (regno) ? NO_REGS : G32_REGS;
771   return NO_REGS;
772 }
773
774
775 /* Return truth value on whether or not a given hard register
776    can support a given mode.  */
777 int
778 score_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
779 {
780   int size = GET_MODE_SIZE (mode);
781   enum mode_class mclass = GET_MODE_CLASS (mode);
782
783   if (mclass == MODE_CC)
784     return regno == CC_REGNUM;
785   else if (regno == FRAME_POINTER_REGNUM
786            || regno == ARG_POINTER_REGNUM)
787     return mclass == MODE_INT;
788   else if (GP_REG_P (regno))
789     /* ((regno <= (GP_REG_LAST- HARD_REGNO_NREGS (dummy, mode)) + 1)  */
790     return !(regno & 1) || (size <= UNITS_PER_WORD);
791   else if (CE_REG_P (regno))
792     return (mclass == MODE_INT
793             && ((size <= UNITS_PER_WORD)
794                 || (regno == CE_REG_FIRST && size == 2 * UNITS_PER_WORD)));
795   else
796     return (mclass == MODE_INT) && (size <= UNITS_PER_WORD);
797 }
798
799 /* Implement INITIAL_ELIMINATION_OFFSET.  FROM is either the frame
800    pointer or argument pointer.  TO is either the stack pointer or
801    hard frame pointer.  */
802 HOST_WIDE_INT
803 score_initial_elimination_offset (int from,
804                                   int to ATTRIBUTE_UNUSED)
805 {
806   struct score_frame_info *f = score_compute_frame_size (get_frame_size ());
807   switch (from)
808     {
809     case ARG_POINTER_REGNUM:
810       return f->total_size;
811     case FRAME_POINTER_REGNUM:
812       return 0;
813     default:
814       gcc_unreachable ();
815     }
816 }
817
818 /* Implement TARGET_FUNCTION_ARG_ADVANCE hook.  */
819 static void
820 score_function_arg_advance (cumulative_args_t cum_args, enum machine_mode mode,
821                             const_tree type, bool named)
822 {
823   struct score_arg_info info;
824   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_args);
825   score_classify_arg (cum, mode, type, named, &info);
826   cum->num_gprs = info.reg_offset + info.reg_words;
827   if (info.stack_words > 0)
828     cum->stack_words = info.stack_offset + info.stack_words;
829   cum->arg_number++;
830 }
831
832 /* Implement TARGET_ARG_PARTIAL_BYTES macro.  */
833 int
834 score_arg_partial_bytes (cumulative_args_t cum_args,
835                          enum machine_mode mode, tree type, bool named)
836 {
837   struct score_arg_info info;
838   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_args);
839   score_classify_arg (cum, mode, type, named, &info);
840   return info.stack_words > 0 ? info.reg_words * UNITS_PER_WORD : 0;
841 }
842
843 /* Implement TARGET_FUNCTION_ARG hook.  */
844 static rtx
845 score_function_arg (cumulative_args_t cum_args, enum machine_mode mode,
846                     const_tree type, bool named)
847 {
848   struct score_arg_info info;
849   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_args);
850
851   if (mode == VOIDmode || !named)
852     return 0;
853
854   score_classify_arg (cum, mode, type, named, &info);
855
856   if (info.reg_offset == ARG_REG_NUM)
857     return 0;
858
859   if (!info.stack_words)
860     return gen_rtx_REG (mode, ARG_REG_FIRST + info.reg_offset);
861   else
862     {
863       rtx ret = gen_rtx_PARALLEL (mode, rtvec_alloc (info.reg_words));
864       unsigned int i, part_offset = 0;
865       for (i = 0; i < info.reg_words; i++)
866         {
867           rtx reg;
868           reg = gen_rtx_REG (SImode, ARG_REG_FIRST + info.reg_offset + i);
869           XVECEXP (ret, 0, i) = gen_rtx_EXPR_LIST (SImode, reg,
870                                                    GEN_INT (part_offset));
871           part_offset += UNITS_PER_WORD;
872         }
873       return ret;
874     }
875 }
876
877 /* Implement FUNCTION_VALUE and LIBCALL_VALUE.  For normal calls,
878    VALTYPE is the return type and MODE is VOIDmode.  For libcalls,
879    VALTYPE is null and MODE is the mode of the return value.  */
880 rtx
881 score_function_value (const_tree valtype, const_tree func, enum machine_mode mode)
882 {
883   if (valtype)
884     {
885       int unsignedp;
886       mode = TYPE_MODE (valtype);
887       unsignedp = TYPE_UNSIGNED (valtype);
888       mode = promote_function_mode (valtype, mode, &unsignedp, func, 1);
889     }
890   return gen_rtx_REG (mode, RT_REGNUM);
891 }
892
893 /* Implement TARGET_ASM_TRAMPOLINE_TEMPLATE.  */
894
895 static void
896 score_asm_trampoline_template (FILE *f)
897 {
898   fprintf (f, "\t.set r1\n");
899   fprintf (f, "\tmv r31, r3\n");
900   fprintf (f, "\tbl nextinsn\n");
901   fprintf (f, "nextinsn:\n");
902   fprintf (f, "\tlw r1, [r3, 6*4-8]\n");
903   fprintf (f, "\tlw r23, [r3, 6*4-4]\n");
904   fprintf (f, "\tmv r3, r31\n");
905   fprintf (f, "\tbr! r1\n");
906   fprintf (f, "\tnop!\n");
907   fprintf (f, "\t.set nor1\n");
908 }
909
910 /* Implement TARGET_TRAMPOLINE_INIT.  */
911 static void
912 score_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
913 {
914 #define CODE_SIZE        (TRAMPOLINE_INSNS * UNITS_PER_WORD)
915
916   rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
917   rtx mem;
918
919   emit_block_move (m_tramp, assemble_trampoline_template (),
920                    GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
921
922   mem = adjust_address (m_tramp, SImode, CODE_SIZE);
923   emit_move_insn (mem, fnaddr);
924   mem = adjust_address (m_tramp, SImode, CODE_SIZE + GET_MODE_SIZE (SImode));
925   emit_move_insn (mem, chain_value);
926
927 #undef CODE_SIZE
928 }
929
930 /* This function is used to implement REG_MODE_OK_FOR_BASE_P macro.  */
931 int
932 score_regno_mode_ok_for_base_p (int regno, int strict)
933 {
934   if (regno >= FIRST_PSEUDO_REGISTER)
935     {
936       if (!strict)
937         return 1;
938       regno = reg_renumber[regno];
939     }
940   if (regno == ARG_POINTER_REGNUM
941       || regno == FRAME_POINTER_REGNUM)
942     return 1;
943   return GP_REG_P (regno);
944 }
945
946 /* Implement TARGET_LEGITIMATE_ADDRESS_P macro.  */
947 static bool
948 score_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
949 {
950   struct score_address_info addr;
951
952   return score_classify_address (&addr, mode, x, strict);
953 }
954
955 /* Implement TARGET_REGISTER_MOVE_COST.
956
957    Return a number assessing the cost of moving a register in class
958    FROM to class TO. */
959 static int
960 score_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
961                           reg_class_t from, reg_class_t to)
962 {
963   if (GR_REG_CLASS_P (from))
964     {
965       if (GR_REG_CLASS_P (to))
966         return 2;
967       else if (SP_REG_CLASS_P (to))
968         return 4;
969       else if (CP_REG_CLASS_P (to))
970         return 5;
971       else if (CE_REG_CLASS_P (to))
972         return 6;
973     }
974   if (GR_REG_CLASS_P (to))
975     {
976       if (GR_REG_CLASS_P (from))
977         return 2;
978       else if (SP_REG_CLASS_P (from))
979         return 4;
980       else if (CP_REG_CLASS_P (from))
981         return 5;
982       else if (CE_REG_CLASS_P (from))
983         return 6;
984     }
985   return 12;
986 }
987
988 /* Return the number of instructions needed to load a symbol of the
989    given type into a register.  */
990 static int
991 score_symbol_insns (enum score_symbol_type type)
992 {
993   switch (type)
994     {
995     case SYMBOL_GENERAL:
996       return 2;
997
998     case SYMBOL_SMALL_DATA:
999       return 1;
1000     }
1001
1002   gcc_unreachable ();
1003 }
1004
1005 /* Return the number of instructions needed to load or store a value
1006    of mode MODE at X.  Return 0 if X isn't valid for MODE.  */
1007 static int
1008 score_address_insns (rtx x, enum machine_mode mode)
1009 {
1010   struct score_address_info addr;
1011   int factor;
1012
1013   if (mode == BLKmode)
1014     factor = 1;
1015   else
1016     factor = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1017
1018   if (score_classify_address (&addr, mode, x, false))
1019     switch (addr.type)
1020       {
1021       case SCORE_ADD_REG:
1022       case SCORE_ADD_CONST_INT:
1023         return factor;
1024
1025       case SCORE_ADD_SYMBOLIC:
1026         return factor * score_symbol_insns (addr.symbol_type);
1027       }
1028   return 0;
1029 }
1030
1031 /* Implement TARGET_RTX_COSTS macro.  */
1032 bool
1033 score_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
1034                  int *total, bool speed ATTRIBUTE_UNUSED)
1035 {
1036   enum machine_mode mode = GET_MODE (x);
1037
1038   switch (code)
1039     {
1040     case CONST_INT:
1041       if (outer_code == SET)
1042         {
1043           if (((INTVAL (x) & 0xffff) == 0) 
1044               || (INTVAL (x) >= -32768 && INTVAL (x) <= 32767))
1045             *total = COSTS_N_INSNS (1);
1046           else
1047             *total = COSTS_N_INSNS (2);
1048         }
1049       else if (outer_code == PLUS || outer_code == MINUS)
1050         {
1051           if (INTVAL (x) >= -8192 && INTVAL (x) <= 8191)
1052             *total = 0;
1053           else if (((INTVAL (x) & 0xffff) == 0)
1054                    || (INTVAL (x) >= -32768 && INTVAL (x) <= 32767))
1055             *total = 1;
1056           else
1057             *total = COSTS_N_INSNS (2);
1058         }
1059       else if (outer_code == AND || outer_code == IOR)
1060         {
1061           if (INTVAL (x) >= 0 && INTVAL (x) <= 16383)
1062             *total = 0;
1063           else if (((INTVAL (x) & 0xffff) == 0)
1064                    || (INTVAL (x) >= 0 && INTVAL (x) <= 65535))
1065             *total = 1;
1066           else
1067             *total = COSTS_N_INSNS (2);
1068         }
1069       else
1070         {
1071           *total = 0;
1072         }
1073       return true;
1074
1075     case CONST:
1076     case SYMBOL_REF:
1077     case LABEL_REF:
1078     case CONST_DOUBLE:
1079       *total = COSTS_N_INSNS (2);
1080       return true;
1081
1082     case MEM:
1083       {
1084         /* If the address is legitimate, return the number of
1085            instructions it needs, otherwise use the default handling.  */
1086         int n = score_address_insns (XEXP (x, 0), GET_MODE (x));
1087         if (n > 0)
1088           {
1089             *total = COSTS_N_INSNS (n + 1);
1090             return true;
1091           }
1092         return false;
1093       }
1094
1095     case FFS:
1096       *total = COSTS_N_INSNS (6);
1097       return true;
1098
1099     case NOT:
1100       *total = COSTS_N_INSNS (1);
1101       return true;
1102
1103     case AND:
1104     case IOR:
1105     case XOR:
1106       if (mode == DImode)
1107         {
1108           *total = COSTS_N_INSNS (2);
1109           return true;
1110         }
1111       return false;
1112
1113     case ASHIFT:
1114     case ASHIFTRT:
1115     case LSHIFTRT:
1116       if (mode == DImode)
1117         {
1118           *total = COSTS_N_INSNS ((GET_CODE (XEXP (x, 1)) == CONST_INT)
1119                                   ? 4 : 12);
1120           return true;
1121         }
1122       return false;
1123
1124     case ABS:
1125       *total = COSTS_N_INSNS (4);
1126       return true;
1127
1128     case PLUS:
1129     case MINUS:
1130       if (mode == DImode)
1131         {
1132           *total = COSTS_N_INSNS (4);
1133           return true;
1134         }
1135       *total = COSTS_N_INSNS (1);
1136       return true;
1137
1138     case NEG:
1139       if (mode == DImode)
1140         {
1141           *total = COSTS_N_INSNS (4);
1142           return true;
1143         }
1144       return false;
1145
1146     case MULT:
1147       *total = optimize_size ? COSTS_N_INSNS (2) : COSTS_N_INSNS (12);
1148       return true;
1149
1150     case DIV:
1151     case MOD:
1152     case UDIV:
1153     case UMOD:
1154       *total = optimize_size ? COSTS_N_INSNS (2) : COSTS_N_INSNS (33);
1155       return true;
1156
1157     case SIGN_EXTEND:
1158     case ZERO_EXTEND:
1159       switch (GET_MODE (XEXP (x, 0)))
1160         {
1161         case QImode:
1162         case HImode:
1163           if (GET_CODE (XEXP (x, 0)) == MEM)
1164             {
1165               *total = COSTS_N_INSNS (2);
1166
1167               if (!TARGET_LITTLE_ENDIAN &&
1168                   side_effects_p (XEXP (XEXP (x, 0), 0)))
1169                 *total = 100;
1170             }
1171           else
1172             *total = COSTS_N_INSNS (1);
1173           break;
1174
1175         default:
1176           *total = COSTS_N_INSNS (1);
1177           break;
1178         }
1179       return true;
1180
1181     default:
1182       return false;
1183     }
1184 }
1185
1186 /* Implement TARGET_ADDRESS_COST macro.  */
1187 int
1188 score_address_cost (rtx addr, enum machine_mode mode ATTRIBUTE_UNUSED,
1189                     addr_space_t as ATTRIBUTE_UNUSED,
1190                     bool speed ATTRIBUTE_UNUSED)
1191 {
1192   return score_address_insns (addr, SImode);
1193 }
1194
1195 /* Implement ASM_OUTPUT_EXTERNAL macro.  */
1196 int
1197 score_output_external (FILE *file ATTRIBUTE_UNUSED,
1198                        tree decl, const char *name)
1199 {
1200   register struct extern_list *p;
1201
1202   if (score_in_small_data_p (decl))
1203     {
1204       p = ggc_alloc<extern_list> ();
1205       p->next = extern_head;
1206       p->name = name;
1207       p->size = int_size_in_bytes (TREE_TYPE (decl));
1208       extern_head = p;
1209     }
1210   return 0;
1211 }
1212
1213 /* Implement RETURN_ADDR_RTX.  Note, we do not support moving
1214    back to a previous frame.  */
1215 rtx
1216 score_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
1217 {
1218   if (count != 0)
1219     return const0_rtx;
1220   return get_hard_reg_initial_val (Pmode, RA_REGNUM);
1221 }
1222
1223 /* Implement PRINT_OPERAND macro.  */
1224 /* Score-specific operand codes:
1225    '['        print .set nor1 directive
1226    ']'        print .set r1 directive
1227    'U'        print hi part of a CONST_INT rtx
1228    'E'        print log2(v)
1229    'F'        print log2(~v)
1230    'D'        print SFmode const double
1231    'S'        selectively print "!" if operand is 15bit instruction accessible
1232    'V'        print "v!" if operand is 15bit instruction accessible, or "lfh!"
1233    'L'        low  part of DImode reg operand
1234    'H'        high part of DImode reg operand
1235    'C'        print part of opcode for a branch condition.  */
1236 void
1237 score_print_operand (FILE *file, rtx op, int c)
1238 {
1239   enum rtx_code code = UNKNOWN;
1240   if (!PRINT_OPERAND_PUNCT_VALID_P (c))
1241     code = GET_CODE (op);
1242
1243   if (c == '[')
1244     {
1245       fprintf (file, ".set r1\n");
1246     }
1247   else if (c == ']')
1248     {
1249       fprintf (file, "\n\t.set nor1");
1250     }
1251   else if (c == 'U')
1252     {
1253       gcc_assert (code == CONST_INT);
1254       fprintf (file, HOST_WIDE_INT_PRINT_HEX,
1255                (INTVAL (op) >> 16) & 0xffff);
1256     }
1257   else if (c == 'D')
1258     {
1259       if (GET_CODE (op) == CONST_DOUBLE)
1260         {
1261           rtx temp = gen_lowpart (SImode, op);
1262           gcc_assert (GET_MODE (op) == SFmode);
1263           fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (temp) & 0xffffffff);
1264         }
1265       else
1266         output_addr_const (file, op);
1267     }
1268   else if (c == 'S')
1269     {
1270       gcc_assert (code == REG);
1271       if (G16_REG_P (REGNO (op)))
1272         fprintf (file, "!");
1273     }
1274   else if (c == 'V')
1275     {
1276       gcc_assert (code == REG);
1277       fprintf (file, G16_REG_P (REGNO (op)) ? "v!" : "lfh!");
1278     }
1279   else if (c == 'C')
1280     {
1281       enum machine_mode mode = GET_MODE (XEXP (op, 0));
1282
1283       switch (code)
1284         {
1285         case EQ: fputs ("eq", file); break;
1286         case NE: fputs ("ne", file); break;
1287         case GT: fputs ("gt", file); break;
1288         case GE: fputs (mode != CCmode ? "pl" : "ge", file); break;
1289         case LT: fputs (mode != CCmode ? "mi" : "lt", file); break;
1290         case LE: fputs ("le", file); break;
1291         case GTU: fputs ("gtu", file); break;
1292         case GEU: fputs ("cs", file); break;
1293         case LTU: fputs ("cc", file); break;
1294         case LEU: fputs ("leu", file); break;
1295         default:
1296           output_operand_lossage ("invalid operand for code: '%c'", code);
1297         }
1298     }
1299   else if (c == 'E')
1300     {
1301       unsigned HOST_WIDE_INT i;
1302       unsigned HOST_WIDE_INT pow2mask = 1;
1303       unsigned HOST_WIDE_INT val;
1304
1305       val = INTVAL (op);
1306       for (i = 0; i < 32; i++)
1307         {
1308           if (val == pow2mask)
1309             break;
1310           pow2mask <<= 1;
1311         }
1312       gcc_assert (i < 32);
1313       fprintf (file, HOST_WIDE_INT_PRINT_HEX, i);
1314     }
1315   else if (c == 'F')
1316     {
1317       unsigned HOST_WIDE_INT i;
1318       unsigned HOST_WIDE_INT pow2mask = 1;
1319       unsigned HOST_WIDE_INT val;
1320
1321       val = ~INTVAL (op);
1322       for (i = 0; i < 32; i++)
1323         {
1324           if (val == pow2mask)
1325             break;
1326           pow2mask <<= 1;
1327         }
1328       gcc_assert (i < 32);
1329       fprintf (file, HOST_WIDE_INT_PRINT_HEX, i);
1330     }
1331   else if (code == REG)
1332     {
1333       int regnum = REGNO (op);
1334       if ((c == 'H' && !WORDS_BIG_ENDIAN)
1335           || (c == 'L' && WORDS_BIG_ENDIAN))
1336         regnum ++;
1337       fprintf (file, "%s", reg_names[regnum]);
1338     }
1339   else
1340     {
1341       switch (code)
1342         {
1343         case MEM:
1344           score_print_operand_address (file, op);
1345           break;
1346         default:
1347           output_addr_const (file, op);
1348         }
1349     }
1350 }
1351
1352 /* Implement PRINT_OPERAND_ADDRESS macro.  */
1353 void
1354 score_print_operand_address (FILE *file, rtx x)
1355 {
1356   struct score_address_info addr;
1357   enum rtx_code code = GET_CODE (x);
1358   enum machine_mode mode = GET_MODE (x);
1359
1360   if (code == MEM)
1361     x = XEXP (x, 0);
1362
1363   if (score_classify_address (&addr, mode, x, true))
1364     {
1365       switch (addr.type)
1366         {
1367         case SCORE_ADD_REG:
1368           {
1369             switch (addr.code)
1370               {
1371               case PRE_DEC:
1372                 fprintf (file, "[%s,-%ld]+", reg_names[REGNO (addr.reg)],
1373                          INTVAL (addr.offset));
1374                 break;
1375               case POST_DEC:
1376                 fprintf (file, "[%s]+,-%ld", reg_names[REGNO (addr.reg)],
1377                          INTVAL (addr.offset));
1378                 break;
1379               case PRE_INC:
1380                 fprintf (file, "[%s, %ld]+", reg_names[REGNO (addr.reg)],
1381                          INTVAL (addr.offset));
1382                 break;
1383               case POST_INC:
1384                 fprintf (file, "[%s]+, %ld", reg_names[REGNO (addr.reg)],
1385                          INTVAL (addr.offset));
1386                 break;
1387               default:
1388                 if (INTVAL(addr.offset) == 0)
1389                   fprintf(file, "[%s]", reg_names[REGNO (addr.reg)]);
1390                 else
1391                   fprintf(file, "[%s, %ld]", reg_names[REGNO (addr.reg)],
1392                           INTVAL(addr.offset));
1393                 break;
1394               }
1395           }
1396           return;
1397         case SCORE_ADD_CONST_INT:
1398         case SCORE_ADD_SYMBOLIC:
1399           output_addr_const (file, x);
1400           return;
1401         }
1402     }
1403   print_rtl (stderr, x);
1404   gcc_unreachable ();
1405 }
1406
1407 /* Implement SELECT_CC_MODE macro.  */
1408 enum machine_mode
1409 score_select_cc_mode (enum rtx_code op, rtx x, rtx y)
1410 {
1411   if ((op == EQ || op == NE || op == LT || op == GE)
1412       && y == const0_rtx
1413       && GET_MODE (x) == SImode)
1414     {
1415       switch (GET_CODE (x))
1416         {
1417         case PLUS:
1418         case MINUS:
1419         case NEG:
1420         case AND:
1421         case IOR:
1422         case XOR:
1423         case NOT:
1424         case ASHIFT:
1425         case LSHIFTRT:
1426         case ASHIFTRT:
1427           return CC_NZmode;
1428
1429         case SIGN_EXTEND:
1430         case ZERO_EXTEND:
1431         case ROTATE:
1432         case ROTATERT:
1433           return (op == LT || op == GE) ? CC_Nmode : CCmode;
1434
1435         default:
1436           return CCmode;
1437         }
1438     }
1439
1440   if ((op == EQ || op == NE)
1441       && (GET_CODE (y) == NEG)
1442       && register_operand (XEXP (y, 0), SImode)
1443       && register_operand (x, SImode))
1444     {
1445       return CC_NZmode;
1446     }
1447
1448   return CCmode;
1449 }
1450
1451 /* Generate the prologue instructions for entry into a S+core function.  */
1452 void
1453 score_prologue (void)
1454 {
1455 #define EMIT_PL(_rtx)        RTX_FRAME_RELATED_P (_rtx) = 1
1456
1457   struct score_frame_info *f = score_compute_frame_size (get_frame_size ());
1458   HOST_WIDE_INT size;
1459   int regno;
1460
1461   size = f->total_size - f->gp_reg_size;
1462
1463   if (flag_pic)
1464     emit_insn (gen_cpload_score7 ());
1465
1466   for (regno = (int) GP_REG_LAST; regno >= (int) GP_REG_FIRST; regno--)
1467     {
1468       if (BITSET_P (f->mask, regno - GP_REG_FIRST))
1469         {
1470           rtx mem = gen_rtx_MEM (SImode,
1471                                  gen_rtx_PRE_DEC (SImode, stack_pointer_rtx));
1472           rtx reg = gen_rtx_REG (SImode, regno);
1473           if (!crtl->calls_eh_return)
1474             MEM_READONLY_P (mem) = 1;
1475           EMIT_PL (emit_insn (gen_pushsi_score7 (mem, reg)));
1476         }
1477     }
1478
1479   if (size > 0)
1480     {
1481       rtx_insn *insn;
1482
1483       if (size >= -32768 && size <= 32767)
1484         EMIT_PL (emit_insn (gen_add3_insn (stack_pointer_rtx,
1485                                            stack_pointer_rtx,
1486                                            GEN_INT (-size))));
1487       else
1488         {
1489           EMIT_PL (emit_move_insn (gen_rtx_REG (Pmode, SCORE_PROLOGUE_TEMP_REGNUM),
1490                                    GEN_INT (size)));
1491           EMIT_PL (emit_insn
1492                    (gen_sub3_insn (stack_pointer_rtx,
1493                                    stack_pointer_rtx,
1494                                    gen_rtx_REG (Pmode,
1495                                                 SCORE_PROLOGUE_TEMP_REGNUM))));
1496         }
1497       insn = get_last_insn ();
1498       REG_NOTES (insn) =
1499         alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR,
1500                          gen_rtx_SET (VOIDmode, stack_pointer_rtx,
1501                                       plus_constant (Pmode, stack_pointer_rtx,
1502                                                      -size)),
1503                                       REG_NOTES (insn));
1504     }
1505
1506   if (frame_pointer_needed)
1507     EMIT_PL (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx));
1508
1509   if (flag_pic && f->cprestore_size)
1510     {
1511       if (frame_pointer_needed)
1512         emit_insn (gen_cprestore_use_fp_score7 (GEN_INT (size - f->cprestore_size)));
1513       else
1514         emit_insn (gen_cprestore_use_sp_score7 (GEN_INT (size - f->cprestore_size)));
1515     }
1516
1517 #undef EMIT_PL
1518 }
1519
1520 /* Generate the epilogue instructions in a S+core function.  */
1521 void
1522 score_epilogue (int sibcall_p)
1523 {
1524   struct score_frame_info *f = score_compute_frame_size (get_frame_size ());
1525   HOST_WIDE_INT size;
1526   int regno;
1527   rtx base;
1528
1529   size = f->total_size - f->gp_reg_size;
1530
1531   if (!frame_pointer_needed)
1532     base = stack_pointer_rtx;
1533   else
1534     base = hard_frame_pointer_rtx;
1535
1536   if (size)
1537     {
1538       if (size >= -32768 && size <= 32767)
1539         emit_insn (gen_add3_insn (base, base, GEN_INT (size)));
1540       else
1541         {
1542           emit_move_insn (gen_rtx_REG (Pmode, SCORE_EPILOGUE_TEMP_REGNUM),
1543                           GEN_INT (size));
1544           emit_insn (gen_add3_insn (base, base,
1545                                     gen_rtx_REG (Pmode,
1546                                                  SCORE_EPILOGUE_TEMP_REGNUM)));
1547         }
1548     }
1549
1550   if (base != stack_pointer_rtx)
1551     emit_move_insn (stack_pointer_rtx, base);
1552
1553   if (crtl->calls_eh_return)
1554     emit_insn (gen_add3_insn (stack_pointer_rtx,
1555                               stack_pointer_rtx,
1556                               EH_RETURN_STACKADJ_RTX));
1557
1558   for (regno = (int) GP_REG_FIRST; regno <= (int) GP_REG_LAST; regno++)
1559     {
1560       if (BITSET_P (f->mask, regno - GP_REG_FIRST))
1561         {
1562           rtx mem = gen_rtx_MEM (SImode,
1563                                  gen_rtx_POST_INC (SImode, stack_pointer_rtx));
1564           rtx reg = gen_rtx_REG (SImode, regno);
1565
1566           if (!crtl->calls_eh_return)
1567             MEM_READONLY_P (mem) = 1;
1568
1569           emit_insn (gen_popsi_score7 (reg, mem));
1570         }
1571     }
1572
1573   if (!sibcall_p)
1574     emit_jump_insn (gen_return_internal_score7 (gen_rtx_REG (Pmode, RA_REGNUM)));
1575 }
1576
1577 /* Return true if X is a symbolic constant that can be calculated in
1578    the same way as a bare symbol.  If it is, store the type of the
1579    symbol in *SYMBOL_TYPE.  */
1580 int
1581 score_symbolic_constant_p (rtx x, enum score_symbol_type *symbol_type)
1582 {
1583   HOST_WIDE_INT offset;
1584
1585   score_split_const (x, &x, &offset);
1586   if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
1587     *symbol_type = score_classify_symbol (x);
1588   else
1589     return 0;
1590
1591   if (offset == 0)
1592     return 1;
1593
1594   /* if offset > 15bit, must reload  */
1595   if (!IMM_IN_RANGE (offset, 15, 1))
1596     return 0;
1597
1598   switch (*symbol_type)
1599     {
1600     case SYMBOL_GENERAL:
1601       return 1;
1602     case SYMBOL_SMALL_DATA:
1603       return score_offset_within_object_p (x, offset);
1604     }
1605   gcc_unreachable ();
1606 }
1607
1608 void
1609 score_movsicc (rtx *ops)
1610 {
1611   enum machine_mode mode;
1612
1613   mode = score_select_cc_mode (GET_CODE (ops[1]), ops[2], ops[3]);
1614   emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (mode, CC_REGNUM),
1615                           gen_rtx_COMPARE (mode, XEXP (ops[1], 0),
1616                                            XEXP (ops[1], 1))));
1617 }
1618
1619 /* Call and sibcall pattern all need call this function.  */
1620 void
1621 score_call (rtx *ops, bool sib)
1622 {
1623   rtx addr = XEXP (ops[0], 0);
1624   if (!call_insn_operand (addr, VOIDmode))
1625     {
1626       rtx oaddr = addr;
1627       addr = gen_reg_rtx (Pmode);
1628       gen_move_insn (addr, oaddr);
1629     }
1630
1631   if (sib)
1632     emit_call_insn (gen_sibcall_internal_score7 (addr, ops[1]));
1633   else
1634     emit_call_insn (gen_call_internal_score7 (addr, ops[1]));
1635 }
1636
1637 /* Call value and sibcall value pattern all need call this function.  */
1638 void
1639 score_call_value (rtx *ops, bool sib)
1640 {
1641   rtx result = ops[0];
1642   rtx addr = XEXP (ops[1], 0);
1643   rtx arg = ops[2];
1644
1645   if (!call_insn_operand (addr, VOIDmode))
1646     {
1647       rtx oaddr = addr;
1648       addr = gen_reg_rtx (Pmode);
1649       gen_move_insn (addr, oaddr);
1650     }
1651
1652   if (sib)
1653     emit_call_insn (gen_sibcall_value_internal_score7 (result, addr, arg));
1654   else
1655     emit_call_insn (gen_call_value_internal_score7 (result, addr, arg));
1656 }
1657
1658 /* Machine Split  */
1659 void
1660 score_movdi (rtx *ops)
1661 {
1662   rtx dst = ops[0];
1663   rtx src = ops[1];
1664   rtx dst0 = score_subw (dst, 0);
1665   rtx dst1 = score_subw (dst, 1);
1666   rtx src0 = score_subw (src, 0);
1667   rtx src1 = score_subw (src, 1);
1668
1669   if (GET_CODE (dst0) == REG && reg_overlap_mentioned_p (dst0, src))
1670     {
1671       emit_move_insn (dst1, src1);
1672       emit_move_insn (dst0, src0);
1673     }
1674   else
1675     {
1676       emit_move_insn (dst0, src0);
1677       emit_move_insn (dst1, src1);
1678     }
1679 }
1680
1681 void
1682 score_zero_extract_andi (rtx *ops)
1683 {
1684   if (INTVAL (ops[1]) == 1 && const_uimm5 (ops[2], SImode))
1685     emit_insn (gen_zero_extract_bittst_score7 (ops[0], ops[2]));
1686   else
1687     {
1688       unsigned HOST_WIDE_INT mask;
1689       mask = (0xffffffffU & ((1U << INTVAL (ops[1])) - 1U));
1690       mask = mask << INTVAL (ops[2]);
1691       emit_insn (gen_andsi3_cmp_score7 (ops[3], ops[0],
1692                                  gen_int_mode (mask, SImode)));
1693     }
1694 }
1695
1696 /* Check addr could be present as PRE/POST mode.  */
1697 static bool
1698 score_pindex_mem (rtx addr)
1699 {
1700   if (GET_CODE (addr) == MEM)
1701     {
1702       switch (GET_CODE (XEXP (addr, 0)))
1703         {
1704         case PRE_DEC:
1705         case POST_DEC:
1706         case PRE_INC:
1707         case POST_INC:
1708           return true;
1709         default:
1710           break;
1711         }
1712     }
1713   return false;
1714 }
1715
1716 /* Output asm code for ld/sw insn.  */
1717 static int
1718 score_pr_addr_post (rtx *ops, int idata, int iaddr, char *ip, enum score_mem_unit unit)
1719 {
1720   struct score_address_info ai;
1721
1722   gcc_assert (GET_CODE (ops[idata]) == REG);
1723   gcc_assert (score_classify_address (&ai, SImode, XEXP (ops[iaddr], 0), true));
1724
1725   if (!score_pindex_mem (ops[iaddr])
1726       && ai.type == SCORE_ADD_REG
1727       && GET_CODE (ai.offset) == CONST_INT
1728       && G16_REG_P (REGNO (ops[idata]))
1729       && G16_REG_P (REGNO (ai.reg)))
1730     {
1731       if (INTVAL (ai.offset) == 0)
1732         {
1733           ops[iaddr] = ai.reg;
1734           return snprintf (ip, INS_BUF_SZ,
1735                            "!\t%%%d, [%%%d]", idata, iaddr);
1736         }
1737       if (REGNO (ai.reg) == HARD_FRAME_POINTER_REGNUM)
1738         {
1739           HOST_WIDE_INT offset = INTVAL (ai.offset);
1740           if (SCORE_ALIGN_UNIT (offset, unit)
1741               && (((offset >> unit) >= 0) && ((offset >> unit) <= 31)))
1742             {
1743               ops[iaddr] = ai.offset;
1744               return snprintf (ip, INS_BUF_SZ,
1745                                "p!\t%%%d, %%c%d", idata, iaddr);
1746             }
1747         }
1748     }
1749   return snprintf (ip, INS_BUF_SZ, "\t%%%d, %%a%d", idata, iaddr);
1750 }
1751
1752 /* Output asm insn for load.  */
1753 const char *
1754 score_linsn (rtx *ops, enum score_mem_unit unit, bool sign)
1755 {
1756   const char *pre_ins[] =
1757     {"lbu", "lhu", "lw", "??", "lb", "lh", "lw", "??"};
1758   char *ip;
1759
1760   strcpy (score_ins, pre_ins[(sign ? 4 : 0) + unit]);
1761   ip = score_ins + strlen (score_ins);
1762
1763   if ((!sign && unit != SCORE_HWORD)
1764       || (sign && unit != SCORE_BYTE))
1765     score_pr_addr_post (ops, 0, 1, ip, unit);
1766   else
1767     snprintf (ip, INS_BUF_SZ, "\t%%0, %%a1");
1768
1769   return score_ins;
1770 }
1771
1772 /* Output asm insn for store.  */
1773 const char *
1774 score_sinsn (rtx *ops, enum score_mem_unit unit)
1775 {
1776   const char *pre_ins[] = {"sb", "sh", "sw"};
1777   char *ip;
1778
1779   strcpy (score_ins, pre_ins[unit]);
1780   ip = score_ins + strlen (score_ins);
1781   score_pr_addr_post (ops, 1, 0, ip, unit);
1782   return score_ins;
1783 }
1784
1785 /* Output asm insn for load immediate.  */
1786 const char *
1787 score_limm (rtx *ops)
1788 {
1789   HOST_WIDE_INT v;
1790
1791   gcc_assert (GET_CODE (ops[0]) == REG);
1792   gcc_assert (GET_CODE (ops[1]) == CONST_INT);
1793
1794   v = INTVAL (ops[1]);
1795   if (G16_REG_P (REGNO (ops[0])) && IMM_IN_RANGE (v, 8, 0))
1796     return "ldiu!\t%0, %c1";
1797   else if (IMM_IN_RANGE (v, 16, 1))
1798     return "ldi\t%0, %c1";
1799   else if ((v & 0xffff) == 0)
1800     return "ldis\t%0, %U1";
1801   else
1802     return "li\t%0, %c1";
1803 }
1804
1805 /* Output asm insn for move.  */
1806 const char *
1807 score_move (rtx *ops)
1808 {
1809   gcc_assert (GET_CODE (ops[0]) == REG);
1810   gcc_assert (GET_CODE (ops[1]) == REG);
1811
1812   if (G16_REG_P (REGNO (ops[0])))
1813     {
1814       if (G16_REG_P (REGNO (ops[1])))
1815         return "mv!\t%0, %1";
1816       else
1817         return "mlfh!\t%0, %1";
1818     }
1819   else if (G16_REG_P (REGNO (ops[1])))
1820     return "mhfl!\t%0, %1";
1821   else
1822     return "mv\t%0, %1";
1823 }
1824
1825 /* Generate add insn.  */
1826 const char *
1827 score_select_add_imm (rtx *ops, bool set_cc)
1828 {
1829   HOST_WIDE_INT v = INTVAL (ops[2]);
1830
1831   gcc_assert (GET_CODE (ops[2]) == CONST_INT);
1832   gcc_assert (REGNO (ops[0]) == REGNO (ops[1]));
1833
1834   if (set_cc && G16_REG_P (REGNO (ops[0])))
1835     {
1836       if (v > 0 && IMM_IS_POW_OF_2 ((unsigned HOST_WIDE_INT) v, 0, 15))
1837         {
1838           ops[2] = GEN_INT (ffs (v) - 1);
1839           return "addei!\t%0, %c2";
1840         }
1841
1842       if (v < 0 && IMM_IS_POW_OF_2 ((unsigned HOST_WIDE_INT) (-v), 0, 15))
1843         {
1844           ops[2] = GEN_INT (ffs (-v) - 1);
1845           return "subei!\t%0, %c2";
1846         }
1847     }
1848
1849   if (set_cc)
1850     return "addi.c\t%0, %c2";
1851   else
1852     return "addi\t%0, %c2";
1853 }
1854
1855 /* Output arith insn.  */
1856 const char *
1857 score_select (rtx *ops, const char *inst_pre,
1858               bool commu, const char *letter, bool set_cc)
1859 {
1860   gcc_assert (GET_CODE (ops[0]) == REG);
1861   gcc_assert (GET_CODE (ops[1]) == REG);
1862
1863   if (set_cc && G16_REG_P (REGNO (ops[0]))
1864       && (GET_CODE (ops[2]) == REG ? G16_REG_P (REGNO (ops[2])) : 1)
1865       && REGNO (ops[0]) == REGNO (ops[1]))
1866     {
1867       snprintf (score_ins, INS_BUF_SZ, "%s!\t%%0, %%%s2", inst_pre, letter);
1868       return score_ins;
1869     }
1870
1871   if (commu && set_cc && G16_REG_P (REGNO (ops[0]))
1872       && G16_REG_P (REGNO (ops[1]))
1873       && REGNO (ops[0]) == REGNO (ops[2]))
1874     {
1875       gcc_assert (GET_CODE (ops[2]) == REG);
1876       snprintf (score_ins, INS_BUF_SZ, "%s!\t%%0, %%%s1", inst_pre, letter);
1877       return score_ins;
1878     }
1879
1880   if (set_cc)
1881     snprintf (score_ins, INS_BUF_SZ, "%s.c\t%%0, %%1, %%%s2", inst_pre, letter);
1882   else
1883     snprintf (score_ins, INS_BUF_SZ, "%s\t%%0, %%1, %%%s2", inst_pre, letter);
1884   return score_ins;
1885 }
1886
1887 /* Return nonzero when an argument must be passed by reference.  */
1888 static bool
1889 score_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
1890                          enum machine_mode mode, const_tree type,
1891                          bool named ATTRIBUTE_UNUSED)
1892 {
1893   /* If we have a variable-sized parameter, we have no choice.  */
1894   return targetm.calls.must_pass_in_stack (mode, type);
1895 }
1896
1897 /* Implement TARGET_FUNCTION_OK_FOR_SIBCALL.  */
1898 static bool
1899 score_function_ok_for_sibcall (ATTRIBUTE_UNUSED tree decl,
1900                                ATTRIBUTE_UNUSED tree exp)
1901 {
1902   return true;
1903 }
1904
1905 /* Implement TARGET_SCHED_ISSUE_RATE.  */
1906 static int
1907 score_issue_rate (void)
1908 {
1909   return 1;
1910 }
1911
1912 /* We can always eliminate to the hard frame pointer.  We can eliminate
1913    to the stack pointer unless a frame pointer is needed.  */
1914
1915 static bool
1916 score_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
1917 {
1918   return (to == HARD_FRAME_POINTER_REGNUM
1919           || (to  == STACK_POINTER_REGNUM && !frame_pointer_needed));
1920 }
1921
1922 /* Argument support functions.  */
1923
1924 /* Initialize CUMULATIVE_ARGS for a function.  */
1925 void
1926 score_init_cumulative_args (CUMULATIVE_ARGS *cum,
1927                             tree fntype ATTRIBUTE_UNUSED,
1928                             rtx libname ATTRIBUTE_UNUSED)
1929 {
1930   memset (cum, 0, sizeof (CUMULATIVE_ARGS));
1931 }
1932
1933 static void
1934 score_conditional_register_usage (void)
1935 {
1936    if (!flag_pic)
1937      fixed_regs[PIC_OFFSET_TABLE_REGNUM] =
1938      call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 0;
1939 }
1940
1941 struct gcc_target targetm = TARGET_INITIALIZER;