OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [config/] [score/] [score.c] - Blame information for rev 282

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 282 jeremybenn
/* Output routines for Sunplus S+CORE processor
2
   Copyright (C) 2005, 2007, 2008, 2009 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 "real.h"
29
#include "insn-config.h"
30
#include "conditions.h"
31
#include "insn-attr.h"
32
#include "recog.h"
33
#include "toplev.h"
34
#include "output.h"
35
#include "tree.h"
36
#include "function.h"
37
#include "expr.h"
38
#include "optabs.h"
39
#include "flags.h"
40
#include "reload.h"
41
#include "tm_p.h"
42
#include "ggc.h"
43
#include "gstab.h"
44
#include "hashtab.h"
45
#include "debug.h"
46
#include "target.h"
47
#include "target-def.h"
48
#include "integrate.h"
49
#include "langhooks.h"
50
#include "score7.h"
51
#include "score3.h"
52
#include "df.h"
53
 
54
#undef  TARGET_ASM_FILE_START
55
#define TARGET_ASM_FILE_START           score_asm_file_start
56
 
57
#undef  TARGET_ASM_FILE_END
58
#define TARGET_ASM_FILE_END             score_asm_file_end
59
 
60
#undef  TARGET_ASM_FUNCTION_PROLOGUE
61
#define TARGET_ASM_FUNCTION_PROLOGUE    score_function_prologue
62
 
63
#undef  TARGET_ASM_FUNCTION_EPILOGUE
64
#define TARGET_ASM_FUNCTION_EPILOGUE    score_function_epilogue
65
 
66
#undef TARGET_DEFAULT_TARGET_FLAGS
67
#define TARGET_DEFAULT_TARGET_FLAGS     TARGET_DEFAULT
68
#undef TARGET_HANDLE_OPTION
69
#define TARGET_HANDLE_OPTION            score_handle_option
70
 
71
#undef TARGET_LEGITIMIZE_ADDRESS
72
#define TARGET_LEGITIMIZE_ADDRESS       score_legitimize_address
73
 
74
#undef  TARGET_SCHED_ISSUE_RATE
75
#define TARGET_SCHED_ISSUE_RATE         score_issue_rate
76
 
77
#undef TARGET_ASM_SELECT_RTX_SECTION
78
#define TARGET_ASM_SELECT_RTX_SECTION   score_select_rtx_section
79
 
80
#undef  TARGET_IN_SMALL_DATA_P
81
#define TARGET_IN_SMALL_DATA_P          score_in_small_data_p
82
 
83
#undef  TARGET_FUNCTION_OK_FOR_SIBCALL
84
#define TARGET_FUNCTION_OK_FOR_SIBCALL  score_function_ok_for_sibcall
85
 
86
#undef TARGET_STRICT_ARGUMENT_NAMING
87
#define TARGET_STRICT_ARGUMENT_NAMING   hook_bool_CUMULATIVE_ARGS_true
88
 
89
#undef TARGET_ASM_OUTPUT_MI_THUNK
90
#define TARGET_ASM_OUTPUT_MI_THUNK      score_output_mi_thunk
91
 
92
#undef TARGET_PROMOTE_FUNCTION_MODE
93
#define TARGET_PROMOTE_FUNCTION_MODE    default_promote_function_mode_always_promote
94
 
95
#undef TARGET_PROMOTE_PROTOTYPES
96
#define TARGET_PROMOTE_PROTOTYPES       hook_bool_tree_true
97
 
98
#undef TARGET_MUST_PASS_IN_STACK
99
#define TARGET_MUST_PASS_IN_STACK       must_pass_in_stack_var_size
100
 
101
#undef TARGET_ARG_PARTIAL_BYTES
102
#define TARGET_ARG_PARTIAL_BYTES        score_arg_partial_bytes
103
 
104
#undef TARGET_PASS_BY_REFERENCE
105
#define TARGET_PASS_BY_REFERENCE        score_pass_by_reference
106
 
107
#undef TARGET_RETURN_IN_MEMORY
108
#define TARGET_RETURN_IN_MEMORY         score_return_in_memory
109
 
110
#undef TARGET_RTX_COSTS
111
#define TARGET_RTX_COSTS                score_rtx_costs
112
 
113
#undef TARGET_ADDRESS_COST
114
#define TARGET_ADDRESS_COST             score_address_cost
115
 
116
#undef TARGET_LEGITIMATE_ADDRESS_P
117
#define TARGET_LEGITIMATE_ADDRESS_P     score_legitimate_address_p
118
 
119
#undef TARGET_CAN_ELIMINATE
120
#define TARGET_CAN_ELIMINATE            score_can_eliminate
121
 
122
#undef TARGET_ASM_TRAMPOLINE_TEMPLATE
123
#define TARGET_ASM_TRAMPOLINE_TEMPLATE  score_asm_trampoline_template
124
#undef TARGET_TRAMPOLINE_INIT
125
#define TARGET_TRAMPOLINE_INIT          score_trampoline_init
126
 
127
struct extern_list *extern_head = 0;
128
 
129
/* default 0 = NO_REGS  */
130
enum reg_class score_char_to_class[256];
131
 
132
/* Implement TARGET_RETURN_IN_MEMORY.  In S+core,
133
   small structures are returned in a register.
134
   Objects with varying size must still be returned in memory.  */
135
static bool
136
score_return_in_memory (tree type, tree fndecl ATTRIBUTE_UNUSED)
137
{
138
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
139
    return score7_return_in_memory (type, fndecl);
140
  else if (TARGET_SCORE3)
141
    return score3_return_in_memory (type, fndecl);
142
 
143
  gcc_unreachable ();
144
}
145
 
146
/* Return nonzero when an argument must be passed by reference.  */
147
static bool
148
score_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
149
                         enum machine_mode mode, tree type,
150
                         bool named ATTRIBUTE_UNUSED)
151
{
152
  /* If we have a variable-sized parameter, we have no choice.  */
153
  return targetm.calls.must_pass_in_stack (mode, type);
154
}
155
 
156
/* Implement TARGET_ASM_OUTPUT_MI_THUNK.  Generate rtl rather than asm text
157
   in order to avoid duplicating too much logic from elsewhere.  */
158
static void
159
score_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
160
                       HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
161
                       tree function)
162
{
163
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
164
    return score7_output_mi_thunk (file, thunk_fndecl, delta,
165
                                   vcall_offset, function);
166
  else if (TARGET_SCORE3)
167
    return score3_output_mi_thunk (file, thunk_fndecl, delta,
168
                                   vcall_offset, function);
169
  gcc_unreachable ();
170
}
171
 
172
/* Implement TARGET_FUNCTION_OK_FOR_SIBCALL.  */
173
static bool
174
score_function_ok_for_sibcall (ATTRIBUTE_UNUSED tree decl,
175
                               ATTRIBUTE_UNUSED tree exp)
176
{
177
  return true;
178
}
179
 
180
/* Set up the stack and frame (if desired) for the function.  */
181
static void
182
score_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
183
{
184
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
185
    return score7_function_prologue (file, size);
186
  else if (TARGET_SCORE3)
187
    return score3_function_prologue (file, size);
188
 
189
  gcc_unreachable ();
190
}
191
 
192
/* Do any necessary cleanup after a function to restore stack, frame,
193
   and regs.  */
194
static void
195
score_function_epilogue (FILE *file,
196
                         HOST_WIDE_INT size ATTRIBUTE_UNUSED)
197
{
198
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
199
    return score7_function_epilogue (file, size);
200
  else if (TARGET_SCORE3)
201
    return score3_function_epilogue (file, size);
202
 
203
  gcc_unreachable ();
204
}
205
 
206
/* Implement TARGET_SCHED_ISSUE_RATE.  */
207
static int
208
score_issue_rate (void)
209
{
210
  return 1;
211
}
212
 
213
/* Choose the section to use for the constant rtx expression X that has
214
   mode MODE.  */
215
static section *
216
score_select_rtx_section (enum machine_mode mode, rtx x,
217
                          unsigned HOST_WIDE_INT align)
218
{
219
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
220
    return score7_select_rtx_section (mode, x, align);
221
  else if (TARGET_SCORE3)
222
    return score3_select_rtx_section (mode, x, align);
223
 
224
  gcc_unreachable ();
225
}
226
 
227
/* Implement TARGET_IN_SMALL_DATA_P.  */
228
static bool
229
score_in_small_data_p (tree decl)
230
{
231
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
232
    return score7_in_small_data_p (decl);
233
  else if (TARGET_SCORE3)
234
    return score3_in_small_data_p (decl);
235
 
236
  gcc_unreachable ();
237
}
238
 
239
/* Implement TARGET_ASM_FILE_START.  */
240
static void
241
score_asm_file_start (void)
242
{
243
  if (TARGET_SCORE5)
244
    fprintf (asm_out_file, "# Sunplus S+core5 %s rev=%s\n",
245
             TARGET_LITTLE_ENDIAN ? "el" : "eb", SCORE_GCC_VERSION);
246
  else if (TARGET_SCORE5U)
247
    fprintf (asm_out_file, "# Sunplus S+core5u %s rev=%s\n",
248
             TARGET_LITTLE_ENDIAN ? "el" : "eb", SCORE_GCC_VERSION);
249
  else if (TARGET_SCORE7D)
250
    fprintf (asm_out_file, "# Sunplus S+core7d %s rev=%s\n",
251
             TARGET_LITTLE_ENDIAN ? "el" : "eb", SCORE_GCC_VERSION);
252
  else if (TARGET_SCORE7)
253
    fprintf (asm_out_file, "# Sunplus S+core7 %s rev=%s\n",
254
             TARGET_LITTLE_ENDIAN ? "el" : "eb", SCORE_GCC_VERSION);
255
  else if (TARGET_SCORE3D)
256
    fprintf (asm_out_file, "# Sunplus S+core3d %s rev=%s\n",
257
             TARGET_LITTLE_ENDIAN ? "el" : "eb", SCORE_GCC_VERSION);
258
  else if (TARGET_SCORE3)
259
    fprintf (asm_out_file, "# Sunplus S+core3 %s rev=%s\n",
260
             TARGET_LITTLE_ENDIAN ? "el" : "eb", SCORE_GCC_VERSION);
261
  else
262
    fprintf (asm_out_file, "# Sunplus S+core unknown %s rev=%s\n",
263
             TARGET_LITTLE_ENDIAN ? "el" : "eb", SCORE_GCC_VERSION);
264
 
265
  default_file_start ();
266
 
267
  if (flag_pic)
268
    fprintf (asm_out_file, "\t.set pic\n");
269
}
270
 
271
/* Implement TARGET_ASM_FILE_END.  When using assembler macros, emit
272
   .externs for any small-data variables that turned out to be external.  */
273
static void
274
score_asm_file_end (void)
275
{
276
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
277
    return score7_asm_file_end ();
278
  else if (TARGET_SCORE3)
279
    return score3_asm_file_end ();
280
 
281
  gcc_unreachable ();
282
}
283
 
284
#define MASK_ALL_CPU_BITS \
285
  (MASK_SCORE5 | MASK_SCORE5U | MASK_SCORE7 | MASK_SCORE7D \
286
   | MASK_SCORE3 | MASK_SCORE3D)
287
 
288
/* Implement TARGET_HANDLE_OPTION.  */
289
static bool
290
score_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
291
{
292
  switch (code)
293
    {
294
    case OPT_mscore7d:
295
      target_flags &= ~(MASK_ALL_CPU_BITS);
296
      target_flags |= MASK_SCORE7 | MASK_SCORE7D;
297
      return true;
298
 
299
    case OPT_mscore3d:
300
      target_flags &= ~(MASK_ALL_CPU_BITS);
301
      target_flags |= MASK_SCORE3 | MASK_SCORE3D;
302
      return true;
303
 
304
    case OPT_march_:
305
      if (strcmp (arg, "score5") == 0)
306
        {
307
          target_flags &= ~(MASK_ALL_CPU_BITS);
308
          target_flags |= MASK_SCORE5;
309
          return true;
310
        }
311
      else if (strcmp (arg, "score5u") == 0)
312
        {
313
          target_flags &= ~(MASK_ALL_CPU_BITS);
314
          target_flags |= MASK_SCORE5U;
315
          return true;
316
        }
317
      else if (strcmp (arg, "score7") == 0)
318
        {
319
          target_flags &= ~(MASK_ALL_CPU_BITS);
320
          target_flags |= MASK_SCORE7;
321
          return true;
322
        }
323
      else if (strcmp (arg, "score7d") == 0)
324
        {
325
          target_flags &= ~(MASK_ALL_CPU_BITS);
326
          target_flags |= MASK_SCORE7 | MASK_SCORE7D;
327
          return true;
328
        }
329
      else if (strcmp (arg, "score3") == 0)
330
        {
331
          target_flags &= ~(MASK_ALL_CPU_BITS);
332
          target_flags |= MASK_SCORE3;
333
          return true;
334
        }
335
      else if (strcmp (arg, "score3d") == 0)
336
        {
337
          target_flags &= ~(MASK_ALL_CPU_BITS);
338
          target_flags |= MASK_SCORE3 | MASK_SCORE3D;
339
          return true;
340
        }
341
      else
342
        return false;
343
 
344
    default:
345
      return true;
346
    }
347
}
348
 
349
/* Implement OVERRIDE_OPTIONS macro.  */
350
void
351
score_override_options (void)
352
{
353
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
354
    return score7_override_options ();
355
  else if (TARGET_SCORE3)
356
    return score3_override_options ();
357
 
358
  return score7_override_options ();
359
}
360
 
361
/* Implement REGNO_REG_CLASS macro.  */
362
int
363
score_reg_class (int regno)
364
{
365
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
366
    return score7_reg_class (regno);
367
  else if (TARGET_SCORE3)
368
    return score3_reg_class (regno);
369
 
370
  gcc_unreachable ();
371
}
372
 
373
/* Implement PREFERRED_RELOAD_CLASS macro.  */
374
enum reg_class
375
score_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, enum reg_class rclass)
376
{
377
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
378
    return score7_preferred_reload_class (x, rclass);
379
  else if (TARGET_SCORE3)
380
    return score3_preferred_reload_class (x, rclass);
381
 
382
  gcc_unreachable ();
383
}
384
 
385
/* Implement SECONDARY_INPUT_RELOAD_CLASS
386
   and SECONDARY_OUTPUT_RELOAD_CLASS macro.  */
387
enum reg_class
388
score_secondary_reload_class (enum reg_class rclass,
389
                              enum machine_mode mode ATTRIBUTE_UNUSED,
390
                              rtx x)
391
{
392
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
393
    return score7_secondary_reload_class (rclass, mode, x);
394
  else if (TARGET_SCORE3)
395
    return score3_secondary_reload_class (rclass, mode, x);
396
 
397
  gcc_unreachable ();
398
}
399
 
400
/* Implement CONST_OK_FOR_LETTER_P macro.  */
401
int
402
score_const_ok_for_letter_p (HOST_WIDE_INT value, char c)
403
{
404
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
405
    return score7_const_ok_for_letter_p (value, c);
406
  else if (TARGET_SCORE3)
407
    return score3_const_ok_for_letter_p (value, c);
408
 
409
  gcc_unreachable ();
410
}
411
 
412
/* Implement EXTRA_CONSTRAINT macro.  */
413
int
414
score_extra_constraint (rtx op, char c)
415
{
416
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
417
    return score7_extra_constraint (op, c);
418
  else if (TARGET_SCORE3)
419
    return score3_extra_constraint (op, c);
420
 
421
  gcc_unreachable ();
422
}
423
 
424
/* Return truth value on whether or not a given hard register
425
   can support a given mode.  */
426
int
427
score_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
428
{
429
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
430
    return score7_hard_regno_mode_ok (regno, mode);
431
  else if (TARGET_SCORE3)
432
    return score3_hard_regno_mode_ok (regno, mode);
433
 
434
  gcc_unreachable ();
435
}
436
 
437
/* We can always eliminate to the hard frame pointer.  We can eliminate
438
   to the stack pointer unless a frame pointer is needed.  */
439
 
440
static bool
441
score_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
442
{
443
  return (to == HARD_FRAME_POINTER_REGNUM
444
          || (to  == STACK_POINTER_REGNUM && !frame_pointer_needed));
445
}
446
 
447
/* Implement INITIAL_ELIMINATION_OFFSET.  FROM is either the frame
448
   pointer or argument pointer.  TO is either the stack pointer or
449
   hard frame pointer.  */
450
HOST_WIDE_INT
451
score_initial_elimination_offset (int from,
452
                                  int to ATTRIBUTE_UNUSED)
453
{
454
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
455
    return score7_initial_elimination_offset (from, to);
456
  else if (TARGET_SCORE3)
457
    return score3_initial_elimination_offset (from, to);
458
 
459
  gcc_unreachable ();
460
}
461
 
462
/* Argument support functions.  */
463
 
464
/* Initialize CUMULATIVE_ARGS for a function.  */
465
void
466
score_init_cumulative_args (CUMULATIVE_ARGS *cum,
467
                            tree fntype ATTRIBUTE_UNUSED,
468
                            rtx libname ATTRIBUTE_UNUSED)
469
{
470
  memset (cum, 0, sizeof (CUMULATIVE_ARGS));
471
}
472
 
473
/* Implement FUNCTION_ARG_ADVANCE macro.  */
474
void
475
score_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
476
                            tree type, int named)
477
{
478
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
479
    return score7_function_arg_advance (cum, mode, type, named);
480
  else if (TARGET_SCORE3)
481
    return score3_function_arg_advance (cum, mode, type, named);
482
 
483
  gcc_unreachable ();
484
}
485
 
486
/* Implement TARGET_ARG_PARTIAL_BYTES macro.  */
487
int
488
score_arg_partial_bytes (CUMULATIVE_ARGS *cum,
489
                         enum machine_mode mode, tree type, bool named)
490
{
491
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
492
    return score7_arg_partial_bytes (cum, mode, type, named);
493
  else if (TARGET_SCORE3)
494
    return score3_arg_partial_bytes (cum, mode, type, named);
495
 
496
  gcc_unreachable ();
497
}
498
 
499
/* Implement FUNCTION_ARG macro.  */
500
rtx
501
score_function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
502
                    tree type, int named)
503
{
504
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
505
    return score7_function_arg (cum, mode, type, named);
506
  else if (TARGET_SCORE3)
507
    return score3_function_arg (cum, mode, type, named);
508
 
509
  gcc_unreachable ();
510
}
511
 
512
/* Implement FUNCTION_VALUE and LIBCALL_VALUE.  For normal calls,
513
   VALTYPE is the return type and MODE is VOIDmode.  For libcalls,
514
   VALTYPE is null and MODE is the mode of the return value.  */
515
rtx
516
score_function_value (tree valtype, tree func ATTRIBUTE_UNUSED,
517
                      enum machine_mode mode)
518
{
519
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
520
    return score7_function_value (valtype, func, mode);
521
  else if (TARGET_SCORE3)
522
    return score3_function_value (valtype, func, mode);
523
 
524
  gcc_unreachable ();
525
}
526
 
527
/* Implement TARGET_ASM_TRAMPOLINE_TEMPLATE.  */
528
static void
529
score_asm_trampoline_template (FILE *f)
530
{
531
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
532
    return score7_asm_trampoline_template (f);
533
  else if (TARGET_SCORE3)
534
    return score3_asm_trampoline_template (f);
535
 
536
  gcc_unreachable ();
537
}
538
 
539
/* Implement TARGET_TRAMPOLINE_INIT.  */
540
static void
541
score_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
542
{
543
  /* ??? These two routines are identical.  */
544
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
545
    return score7_trampoline_init (m_tramp, fndecl, chain_value);
546
  else if (TARGET_SCORE3)
547
    return score3_trampoline_init (m_tramp, fndecl, chain_value);
548
 
549
  gcc_unreachable ();
550
}
551
 
552
/* This function is used to implement REG_MODE_OK_FOR_BASE_P macro.  */
553
int
554
score_regno_mode_ok_for_base_p (int regno, int strict)
555
{
556
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
557
    return score7_regno_mode_ok_for_base_p (regno, strict);
558
  else if (TARGET_SCORE3)
559
    return score3_regno_mode_ok_for_base_p (regno, strict);
560
 
561
  gcc_unreachable ();
562
}
563
 
564
/* Implement TARGET_LEGITIMIZE_ADDRESS_P.  */
565
bool
566
score_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
567
{
568
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
569
    return score7_legitimate_address_p (mode, x, strict);
570
  else if (TARGET_SCORE3)
571
    return score3_legitimate_address_p (mode, x, strict);
572
 
573
  gcc_unreachable ();
574
}
575
 
576
/* This function is used to implement LEGITIMIZE_ADDRESS.  If X can
577
   be legitimized in a way that the generic machinery might not expect,
578
   return the new address, else return X.  */
579
static rtx
580
score_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
581
                          enum machine_mode mode ATTRIBUTE_UNUSED)
582
{
583
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
584
    return score7_legitimize_address (x);
585
  else if (TARGET_SCORE3)
586
    return score3_legitimize_address (x);
587
 
588
  gcc_unreachable ();
589
}
590
 
591
/* Return a number assessing the cost of moving a register in class
592
   FROM to class TO. */
593
int
594
score_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
595
                          enum reg_class from, enum reg_class to)
596
{
597
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
598
    return score7_register_move_cost (mode, from, to);
599
  else if (TARGET_SCORE3)
600
    return score3_register_move_cost (mode, from, to);
601
 
602
  gcc_unreachable ();
603
}
604
 
605
/* Implement TARGET_RTX_COSTS macro.  */
606
bool
607
score_rtx_costs (rtx x, int code, int outer_code, int *total,
608
                 bool speed ATTRIBUTE_UNUSED)
609
{
610
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
611
    return score7_rtx_costs (x, code, outer_code, total, speed);
612
  else if (TARGET_SCORE3)
613
    return score3_rtx_costs (x, code, outer_code, total, speed);
614
 
615
  gcc_unreachable ();
616
}
617
 
618
/* Implement TARGET_ADDRESS_COST macro.  */
619
int
620
score_address_cost (rtx addr,
621
                    bool speed ATTRIBUTE_UNUSED)
622
{
623
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
624
    return score7_address_cost (addr);
625
  else if (TARGET_SCORE3)
626
    return score3_address_cost (addr);
627
 
628
  gcc_unreachable ();
629
}
630
 
631
/* Implement ASM_OUTPUT_EXTERNAL macro.  */
632
int
633
score_output_external (FILE *file ATTRIBUTE_UNUSED,
634
                       tree decl, const char *name)
635
{
636
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
637
    return score7_output_external (file, decl, name);
638
  else if (TARGET_SCORE3)
639
    return score3_output_external (file, decl, name);
640
 
641
  gcc_unreachable ();
642
}
643
 
644
/* Implement RETURN_ADDR_RTX.  Note, we do not support moving
645
   back to a previous frame.  */
646
rtx
647
score_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
648
{
649
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
650
    return score7_return_addr (count, frame);
651
  else if (TARGET_SCORE3)
652
    return score3_return_addr (count, frame);
653
 
654
  gcc_unreachable ();
655
}
656
 
657
/* Implement PRINT_OPERAND macro.  */
658
void
659
score_print_operand (FILE *file, rtx op, int c)
660
{
661
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
662
    return score7_print_operand (file, op, c);
663
  else if (TARGET_SCORE3)
664
    return score3_print_operand (file, op, c);
665
 
666
  gcc_unreachable ();
667
}
668
 
669
/* Implement PRINT_OPERAND_ADDRESS macro.  */
670
void
671
score_print_operand_address (FILE *file, rtx x)
672
{
673
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
674
    return score7_print_operand_address (file, x);
675
  else if (TARGET_SCORE3)
676
    return score3_print_operand_address (file, x);
677
 
678
  gcc_unreachable ();
679
}
680
 
681
/* Implement SELECT_CC_MODE macro.  */
682
enum machine_mode
683
score_select_cc_mode (enum rtx_code op, rtx x, rtx y)
684
{
685
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
686
    return score7_select_cc_mode (op, x, y);
687
  else if (TARGET_SCORE3)
688
    return score3_select_cc_mode (op, x, y);
689
 
690
  gcc_unreachable ();
691
}
692
 
693
/* Return true if X is a symbolic constant that can be calculated in
694
   the same way as a bare symbol.  If it is, store the type of the
695
   symbol in *SYMBOL_TYPE.  */
696
int
697
score_symbolic_constant_p (rtx x, enum score_symbol_type *symbol_type)
698
{
699
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
700
    return score7_symbolic_constant_p (x, symbol_type);
701
  else if (TARGET_SCORE3)
702
    return score3_symbolic_constant_p (x, symbol_type);
703
 
704
  gcc_unreachable ();
705
}
706
 
707
/* Generate the prologue instructions for entry into a S+core function.  */
708
void
709
score_prologue (void)
710
{
711
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
712
    return score7_prologue ();
713
  else if (TARGET_SCORE3)
714
    return score3_prologue ();
715
 
716
  gcc_unreachable ();
717
}
718
 
719
/* Generate the epilogue instructions in a S+core function.  */
720
void
721
score_epilogue (int sibcall_p)
722
{
723
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
724
    return score7_epilogue (sibcall_p);
725
  else if (TARGET_SCORE3)
726
    return score3_epilogue (sibcall_p);
727
 
728
  gcc_unreachable ();
729
}
730
 
731
/* Call and sibcall pattern all need call this function.  */
732
void
733
score_call (rtx *ops, bool sib)
734
{
735
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
736
    return score7_call (ops, sib);
737
  else if (TARGET_SCORE3)
738
    return score3_call (ops, sib);
739
 
740
  gcc_unreachable ();
741
}
742
 
743
/* Call value and sibcall value pattern all need call this function.  */
744
void
745
score_call_value (rtx *ops, bool sib)
746
{
747
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
748
    return score7_call_value (ops, sib);
749
  else if (TARGET_SCORE3)
750
    return score3_call_value (ops, sib);
751
 
752
  gcc_unreachable ();
753
}
754
 
755
void
756
score_movsicc (rtx *ops)
757
{
758
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
759
    return score7_movsicc (ops);
760
  else if (TARGET_SCORE3)
761
    return score3_movsicc (ops);
762
 
763
  gcc_unreachable ();
764
}
765
 
766
/* Machine Split  */
767
void
768
score_movdi (rtx *ops)
769
{
770
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
771
    return score7_movdi (ops);
772
  else if (TARGET_SCORE3)
773
    return score3_movdi (ops);
774
 
775
  gcc_unreachable ();
776
}
777
 
778
void
779
score_zero_extract_andi (rtx *ops)
780
{
781
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
782
    return score7_zero_extract_andi (ops);
783
  else if (TARGET_SCORE3)
784
    return score3_zero_extract_andi (ops);
785
 
786
  gcc_unreachable ();
787
}
788
 
789
/* Output asm insn for move.  */
790
const char *
791
score_move (rtx *ops)
792
{
793
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
794
    return score7_move (ops);
795
  else if (TARGET_SCORE3)
796
    return score3_move (ops);
797
 
798
  gcc_unreachable ();
799
}
800
 
801
/* Output asm insn for load.  */
802
const char *
803
score_linsn (rtx *ops, enum score_mem_unit unit, bool sign)
804
{
805
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
806
    return score7_linsn (ops, unit, sign);
807
  else if (TARGET_SCORE3)
808
    return score3_linsn (ops, unit, sign);
809
 
810
  gcc_unreachable ();
811
}
812
 
813
/* Output asm insn for store.  */
814
const char *
815
score_sinsn (rtx *ops, enum score_mem_unit unit)
816
{
817
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
818
    return score7_sinsn (ops, unit);
819
  else if (TARGET_SCORE3)
820
    return score3_sinsn (ops, unit);
821
 
822
  gcc_unreachable ();
823
}
824
 
825
/* Output asm insn for load immediate.  */
826
const char *
827
score_limm (rtx *ops)
828
{
829
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
830
    return score7_limm (ops);
831
  else if (TARGET_SCORE3)
832
    return score3_limm (ops);
833
 
834
  gcc_unreachable ();
835
}
836
 
837
 
838
/* Generate add insn.  */
839
const char *
840
score_select_add_imm (rtx *ops, bool set_cc)
841
{
842
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
843
    return score7_select_add_imm (ops, set_cc);
844
  else if (TARGET_SCORE3)
845
    return score3_select_add_imm (ops, set_cc);
846
 
847
  gcc_unreachable ();
848
}
849
 
850
/* Output arith insn.  */
851
const char *
852
score_select (rtx *ops, const char *inst_pre,
853
            bool commu, const char *letter, bool set_cc)
854
{
855
  if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
856
    return score7_select (ops, inst_pre, commu, letter, set_cc);
857
  else if (TARGET_SCORE3)
858
    return score3_select (ops, inst_pre, commu, letter, set_cc);
859
 
860
  gcc_unreachable ();
861
}
862
 
863
/* Output switch case insn, only supported in score3.  */
864
const char *
865
score_output_casesi (rtx *operands)
866
{
867
  if (TARGET_SCORE3)
868
    return score3_output_casesi (operands);
869
 
870
  gcc_unreachable ();
871
}
872
 
873
/* Output rpush insn, only supported in score3.  */
874
const char *
875
score_rpush (rtx *operands)
876
{
877
  if (TARGET_SCORE3)
878
    return score3_rpush (operands);
879
 
880
  gcc_unreachable ();
881
}
882
 
883
/* Output rpop insn, only supported in score3.  */
884
const char *
885
score_rpop (rtx *operands)
886
{
887
  if (TARGET_SCORE3)
888
    return score3_rpop (operands);
889
 
890
  gcc_unreachable ();
891
}
892
 
893
/* Emit lcb/lce insns.  */
894
bool
895
score_unaligned_load (rtx *ops)
896
{
897
  rtx dst = ops[0];
898
  rtx src = ops[1];
899
  rtx len = ops[2];
900
  rtx off = ops[3];
901
  rtx addr_reg;
902
 
903
  if (INTVAL (len) != BITS_PER_WORD
904
      || (INTVAL (off) % BITS_PER_UNIT) != 0)
905
    return false;
906
 
907
  gcc_assert (GET_MODE_SIZE (GET_MODE (dst)) == GET_MODE_SIZE (SImode));
908
 
909
  addr_reg = copy_addr_to_reg (XEXP (src, 0));
910
  emit_insn (gen_move_lcb (addr_reg, addr_reg));
911
  emit_insn (gen_move_lce (addr_reg, addr_reg, dst));
912
 
913
  return true;
914
}
915
 
916
/* Emit scb/sce insns.  */
917
bool
918
score_unaligned_store (rtx *ops)
919
{
920
  rtx dst = ops[0];
921
  rtx len = ops[1];
922
  rtx off = ops[2];
923
  rtx src = ops[3];
924
  rtx addr_reg;
925
 
926
  if (INTVAL(len) != BITS_PER_WORD
927
      || (INTVAL(off) % BITS_PER_UNIT) != 0)
928
    return false;
929
 
930
  gcc_assert (GET_MODE_SIZE (GET_MODE (src)) == GET_MODE_SIZE (SImode));
931
 
932
  addr_reg = copy_addr_to_reg (XEXP (dst, 0));
933
  emit_insn (gen_move_scb (addr_reg, addr_reg, src));
934
  emit_insn (gen_move_sce (addr_reg, addr_reg));
935
 
936
  return true;
937
}
938
 
939
/* If length is short, generate move insns straight.  */
940
static void
941
score_block_move_straight (rtx dst, rtx src, HOST_WIDE_INT length)
942
{
943
  HOST_WIDE_INT leftover;
944
  int i, reg_count;
945
  rtx *regs;
946
 
947
  leftover = length % UNITS_PER_WORD;
948
  length -= leftover;
949
  reg_count = length / UNITS_PER_WORD;
950
 
951
  regs = XALLOCAVEC (rtx, reg_count);
952
  for (i = 0; i < reg_count; i++)
953
    regs[i] = gen_reg_rtx (SImode);
954
 
955
  /* Load from src to regs.  */
956
  if (MEM_ALIGN (src) >= BITS_PER_WORD)
957
    {
958
      HOST_WIDE_INT offset = 0;
959
      for (i = 0; i < reg_count; offset += UNITS_PER_WORD, i++)
960
        emit_move_insn (regs[i], adjust_address (src, SImode, offset));
961
    }
962
  else if (reg_count >= 1)
963
    {
964
      rtx src_reg = copy_addr_to_reg (XEXP (src, 0));
965
 
966
      emit_insn (gen_move_lcb (src_reg, src_reg));
967
      for (i = 0; i < (reg_count - 1); i++)
968
        emit_insn (gen_move_lcw (src_reg, src_reg, regs[i]));
969
      emit_insn (gen_move_lce (src_reg, src_reg, regs[i]));
970
    }
971
 
972
  /* Store regs to dest.  */
973
  if (MEM_ALIGN (dst) >= BITS_PER_WORD)
974
    {
975
      HOST_WIDE_INT offset = 0;
976
      for (i = 0; i < reg_count; offset += UNITS_PER_WORD, i++)
977
        emit_move_insn (adjust_address (dst, SImode, offset), regs[i]);
978
    }
979
  else if (reg_count >= 1)
980
    {
981
      rtx dst_reg = copy_addr_to_reg (XEXP (dst, 0));
982
 
983
      emit_insn (gen_move_scb (dst_reg, dst_reg, regs[0]));
984
      for (i = 1; i < reg_count; i++)
985
        emit_insn (gen_move_scw (dst_reg, dst_reg, regs[i]));
986
      emit_insn (gen_move_sce (dst_reg, dst_reg));
987
    }
988
 
989
  /* Mop up any left-over bytes.  */
990
  if (leftover > 0)
991
    {
992
      src = adjust_address (src, BLKmode, length);
993
      dst = adjust_address (dst, BLKmode, length);
994
      move_by_pieces (dst, src, leftover,
995
                      MIN (MEM_ALIGN (src), MEM_ALIGN (dst)), 0);
996
    }
997
}
998
 
999
/* Generate loop head when dst or src is unaligned.  */
1000
static void
1001
score_block_move_loop_head (rtx dst_reg, HOST_WIDE_INT dst_align,
1002
                            rtx src_reg, HOST_WIDE_INT src_align,
1003
                            HOST_WIDE_INT length)
1004
{
1005
  bool src_unaligned = (src_align < BITS_PER_WORD);
1006
  bool dst_unaligned = (dst_align < BITS_PER_WORD);
1007
 
1008
  rtx temp = gen_reg_rtx (SImode);
1009
 
1010
  gcc_assert (length == UNITS_PER_WORD);
1011
 
1012
  if (src_unaligned)
1013
    {
1014
      emit_insn (gen_move_lcb (src_reg, src_reg));
1015
      emit_insn (gen_move_lcw (src_reg, src_reg, temp));
1016
    }
1017
  else
1018
    emit_insn (gen_move_lw_a (src_reg,
1019
                              src_reg, gen_int_mode (4, SImode), temp));
1020
 
1021
  if (dst_unaligned)
1022
    emit_insn (gen_move_scb (dst_reg, dst_reg, temp));
1023
  else
1024
    emit_insn (gen_move_sw_a (dst_reg,
1025
                              dst_reg, gen_int_mode (4, SImode), temp));
1026
}
1027
 
1028
/* Generate loop body, copy length bytes per iteration.  */
1029
static void
1030
score_block_move_loop_body (rtx dst_reg, HOST_WIDE_INT dst_align,
1031
                            rtx src_reg, HOST_WIDE_INT src_align,
1032
                            HOST_WIDE_INT length)
1033
{
1034
  int reg_count = length / UNITS_PER_WORD;
1035
  rtx *regs = XALLOCAVEC (rtx, reg_count);
1036
  int i;
1037
  bool src_unaligned = (src_align < BITS_PER_WORD);
1038
  bool dst_unaligned = (dst_align < BITS_PER_WORD);
1039
 
1040
  for (i = 0; i < reg_count; i++)
1041
    regs[i] = gen_reg_rtx (SImode);
1042
 
1043
  if (src_unaligned)
1044
    {
1045
      for (i = 0; i < reg_count; i++)
1046
        emit_insn (gen_move_lcw (src_reg, src_reg, regs[i]));
1047
    }
1048
  else
1049
    {
1050
      for (i = 0; i < reg_count; i++)
1051
        emit_insn (gen_move_lw_a (src_reg,
1052
                                  src_reg, gen_int_mode (4, SImode), regs[i]));
1053
    }
1054
 
1055
  if (dst_unaligned)
1056
    {
1057
      for (i = 0; i < reg_count; i++)
1058
        emit_insn (gen_move_scw (dst_reg, dst_reg, regs[i]));
1059
    }
1060
  else
1061
    {
1062
      for (i = 0; i < reg_count; i++)
1063
        emit_insn (gen_move_sw_a (dst_reg,
1064
                                  dst_reg, gen_int_mode (4, SImode), regs[i]));
1065
    }
1066
}
1067
 
1068
/* Generate loop foot, copy the leftover bytes.  */
1069
static void
1070
score_block_move_loop_foot (rtx dst_reg, HOST_WIDE_INT dst_align,
1071
                            rtx src_reg, HOST_WIDE_INT src_align,
1072
                            HOST_WIDE_INT length)
1073
{
1074
  bool src_unaligned = (src_align < BITS_PER_WORD);
1075
  bool dst_unaligned = (dst_align < BITS_PER_WORD);
1076
 
1077
  HOST_WIDE_INT leftover;
1078
 
1079
  leftover = length % UNITS_PER_WORD;
1080
  length -= leftover;
1081
 
1082
  if (length > 0)
1083
    score_block_move_loop_body (dst_reg, dst_align,
1084
                              src_reg, src_align, length);
1085
 
1086
  if (dst_unaligned)
1087
    emit_insn (gen_move_sce (dst_reg, dst_reg));
1088
 
1089
  if (leftover > 0)
1090
    {
1091
      HOST_WIDE_INT src_adj = src_unaligned ? -4 : 0;
1092
      HOST_WIDE_INT dst_adj = dst_unaligned ? -4 : 0;
1093
      rtx temp;
1094
 
1095
      gcc_assert (leftover < UNITS_PER_WORD);
1096
 
1097
      if (leftover >= UNITS_PER_WORD / 2
1098
          && src_align >= BITS_PER_WORD / 2
1099
          && dst_align >= BITS_PER_WORD / 2)
1100
        {
1101
          temp = gen_reg_rtx (HImode);
1102
          emit_insn (gen_move_lhu_b (src_reg, src_reg,
1103
                                     gen_int_mode (src_adj, SImode), temp));
1104
          emit_insn (gen_move_sh_b (dst_reg, dst_reg,
1105
                                    gen_int_mode (dst_adj, SImode), temp));
1106
          leftover -= UNITS_PER_WORD / 2;
1107
          src_adj = UNITS_PER_WORD / 2;
1108
          dst_adj = UNITS_PER_WORD / 2;
1109
        }
1110
 
1111
      while (leftover > 0)
1112
        {
1113
          temp = gen_reg_rtx (QImode);
1114
          emit_insn (gen_move_lbu_b (src_reg, src_reg,
1115
                                     gen_int_mode (src_adj, SImode), temp));
1116
          emit_insn (gen_move_sb_b (dst_reg, dst_reg,
1117
                                    gen_int_mode (dst_adj, SImode), temp));
1118
          leftover--;
1119
          src_adj = 1;
1120
          dst_adj = 1;
1121
        }
1122
    }
1123
}
1124
 
1125
#define MIN_MOVE_REGS 3
1126
#define MIN_MOVE_BYTES (MIN_MOVE_REGS * UNITS_PER_WORD)
1127
#define MAX_MOVE_REGS 4
1128
#define MAX_MOVE_BYTES (MAX_MOVE_REGS * UNITS_PER_WORD)
1129
 
1130
/* The length is large, generate a loop if necessary.
1131
   The loop is consisted by loop head/body/foot.  */
1132
static void
1133
score_block_move_loop (rtx dst, rtx src, HOST_WIDE_INT length)
1134
{
1135
  HOST_WIDE_INT src_align = MEM_ALIGN (src);
1136
  HOST_WIDE_INT dst_align = MEM_ALIGN (dst);
1137
  HOST_WIDE_INT loop_mov_bytes;
1138
  HOST_WIDE_INT iteration = 0;
1139
  HOST_WIDE_INT head_length = 0, leftover;
1140
  rtx label, src_reg, dst_reg, final_dst, test;
1141
 
1142
  bool gen_loop_head = (src_align < BITS_PER_WORD
1143
                        || dst_align < BITS_PER_WORD);
1144
 
1145
  if (gen_loop_head)
1146
    head_length += UNITS_PER_WORD;
1147
 
1148
  for (loop_mov_bytes = MAX_MOVE_BYTES;
1149
       loop_mov_bytes >= MIN_MOVE_BYTES;
1150
       loop_mov_bytes -= UNITS_PER_WORD)
1151
    {
1152
      iteration = (length - head_length) / loop_mov_bytes;
1153
      if (iteration > 1)
1154
        break;
1155
    }
1156
  if (iteration <= 1)
1157
    {
1158
      score_block_move_straight (dst, src, length);
1159
      return;
1160
    }
1161
 
1162
  leftover = (length - head_length) % loop_mov_bytes;
1163
  length -= leftover;
1164
 
1165
  src_reg = copy_addr_to_reg (XEXP (src, 0));
1166
  dst_reg = copy_addr_to_reg (XEXP (dst, 0));
1167
  final_dst = expand_simple_binop (Pmode, PLUS, dst_reg, GEN_INT (length),
1168
                                   0, 0, OPTAB_WIDEN);
1169
 
1170
  if (gen_loop_head)
1171
    score_block_move_loop_head (dst_reg, dst_align,
1172
                              src_reg, src_align, head_length);
1173
 
1174
  label = gen_label_rtx ();
1175
  emit_label (label);
1176
 
1177
  score_block_move_loop_body (dst_reg, dst_align,
1178
                            src_reg, src_align, loop_mov_bytes);
1179
 
1180
  test = gen_rtx_NE (VOIDmode, dst_reg, final_dst);
1181
  emit_jump_insn (gen_cbranchsi4 (test, dst_reg, final_dst, label));
1182
 
1183
  score_block_move_loop_foot (dst_reg, dst_align,
1184
                            src_reg, src_align, leftover);
1185
}
1186
 
1187
/* Generate block move, for misc.md: "movmemsi".  */
1188
bool
1189
score_block_move (rtx *ops)
1190
{
1191
  rtx dst = ops[0];
1192
  rtx src = ops[1];
1193
  rtx length = ops[2];
1194
 
1195
  if (TARGET_LITTLE_ENDIAN
1196
      && (MEM_ALIGN (src) < BITS_PER_WORD || MEM_ALIGN (dst) < BITS_PER_WORD)
1197
      && INTVAL (length) >= UNITS_PER_WORD)
1198
    return false;
1199
 
1200
  if (GET_CODE (length) == CONST_INT)
1201
    {
1202
      if (INTVAL (length) <= 2 * MAX_MOVE_BYTES)
1203
        {
1204
          score_block_move_straight (dst, src, INTVAL (length));
1205
          return true;
1206
        }
1207
      else if (optimize &&
1208
               !(flag_unroll_loops || flag_unroll_all_loops))
1209
        {
1210
          score_block_move_loop (dst, src, INTVAL (length));
1211
          return true;
1212
        }
1213
    }
1214
  return false;
1215
}
1216
 
1217
struct gcc_target targetm = TARGET_INITIALIZER;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.