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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [config/] [mep/] [mep.c] - Blame information for rev 709

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 709 jeremybenn
/* Definitions for Toshiba Media Processor
2
   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
3
   2011
4
   Free Software Foundation, Inc.
5
   Contributed by Red Hat, Inc.
6
 
7
This file is part of GCC.
8
 
9
GCC is free software; you can redistribute it and/or modify it under
10
the terms of the GNU General Public License as published by the Free
11
Software Foundation; either version 3, or (at your option) any later
12
version.
13
 
14
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15
WARRANTY; without even the implied warranty of MERCHANTABILITY or
16
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17
for more details.
18
 
19
You should have received a copy of the GNU General Public License
20
along with GCC; see the file COPYING3.  If not see
21
<http://www.gnu.org/licenses/>.  */
22
 
23
#include "config.h"
24
#include "system.h"
25
#include "coretypes.h"
26
#include "tm.h"
27
#include "rtl.h"
28
#include "tree.h"
29
#include "regs.h"
30
#include "hard-reg-set.h"
31
#include "insn-config.h"
32
#include "conditions.h"
33
#include "insn-flags.h"
34
#include "output.h"
35
#include "insn-attr.h"
36
#include "flags.h"
37
#include "recog.h"
38
#include "obstack.h"
39
#include "tree.h"
40
#include "expr.h"
41
#include "except.h"
42
#include "function.h"
43
#include "optabs.h"
44
#include "reload.h"
45
#include "tm_p.h"
46
#include "ggc.h"
47
#include "diagnostic-core.h"
48
#include "integrate.h"
49
#include "target.h"
50
#include "target-def.h"
51
#include "langhooks.h"
52
#include "df.h"
53
#include "gimple.h"
54
#include "opts.h"
55
 
56
/* Structure of this file:
57
 
58
 + Command Line Option Support
59
 + Pattern support - constraints, predicates, expanders
60
 + Reload Support
61
 + Costs
62
 + Functions to save and restore machine-specific function data.
63
 + Frame/Epilog/Prolog Related
64
 + Operand Printing
65
 + Function args in registers
66
 + Handle pipeline hazards
67
 + Handle attributes
68
 + Trampolines
69
 + Machine-dependent Reorg
70
 + Builtins.  */
71
 
72
/* Symbol encodings:
73
 
74
   Symbols are encoded as @ <char> . <name> where <char> is one of these:
75
 
76
   b - based
77
   t - tiny
78
   n - near
79
   f - far
80
   i - io, near
81
   I - io, far
82
   c - cb (control bus)  */
83
 
84
struct GTY(()) machine_function
85
{
86
  int mep_frame_pointer_needed;
87
 
88
  /* For varargs. */
89
  int arg_regs_to_save;
90
  int regsave_filler;
91
  int frame_filler;
92
  int frame_locked;
93
 
94
  /* Records __builtin_return address.  */
95
  rtx eh_stack_adjust;
96
 
97
  int reg_save_size;
98
  int reg_save_slot[FIRST_PSEUDO_REGISTER];
99
  unsigned char reg_saved[FIRST_PSEUDO_REGISTER];
100
 
101
  /* 2 if the current function has an interrupt attribute, 1 if not, 0
102
     if unknown.  This is here because resource.c uses EPILOGUE_USES
103
     which needs it.  */
104
  int interrupt_handler;
105
 
106
  /* Likewise, for disinterrupt attribute.  */
107
  int disable_interrupts;
108
 
109
  /* Number of doloop tags used so far.  */
110
  int doloop_tags;
111
 
112
  /* True if the last tag was allocated to a doloop_end.  */
113
  bool doloop_tag_from_end;
114
 
115
  /* True if reload changes $TP.  */
116
  bool reload_changes_tp;
117
 
118
  /* 2 if there are asm()s without operands, 1 if not, 0 if unknown.
119
     We only set this if the function is an interrupt handler.  */
120
  int asms_without_operands;
121
};
122
 
123
#define MEP_CONTROL_REG(x) \
124
  (GET_CODE (x) == REG && ANY_CONTROL_REGNO_P (REGNO (x)))
125
 
126
static GTY(()) section * based_section;
127
static GTY(()) section * tinybss_section;
128
static GTY(()) section * far_section;
129
static GTY(()) section * farbss_section;
130
static GTY(()) section * frodata_section;
131
static GTY(()) section * srodata_section;
132
 
133
static GTY(()) section * vtext_section;
134
static GTY(()) section * vftext_section;
135
static GTY(()) section * ftext_section;
136
 
137
static void mep_set_leaf_registers (int);
138
static bool symbol_p (rtx);
139
static bool symbolref_p (rtx);
140
static void encode_pattern_1 (rtx);
141
static void encode_pattern (rtx);
142
static bool const_in_range (rtx, int, int);
143
static void mep_rewrite_mult (rtx, rtx);
144
static void mep_rewrite_mulsi3 (rtx, rtx, rtx, rtx);
145
static void mep_rewrite_maddsi3 (rtx, rtx, rtx, rtx, rtx);
146
static bool mep_reuse_lo_p_1 (rtx, rtx, rtx, bool);
147
static bool move_needs_splitting (rtx, rtx, enum machine_mode);
148
static bool mep_expand_setcc_1 (enum rtx_code, rtx, rtx, rtx);
149
static bool mep_nongeneral_reg (rtx);
150
static bool mep_general_copro_reg (rtx);
151
static bool mep_nonregister (rtx);
152
static struct machine_function* mep_init_machine_status (void);
153
static rtx mep_tp_rtx (void);
154
static rtx mep_gp_rtx (void);
155
static bool mep_interrupt_p (void);
156
static bool mep_disinterrupt_p (void);
157
static bool mep_reg_set_p (rtx, rtx);
158
static bool mep_reg_set_in_function (int);
159
static bool mep_interrupt_saved_reg (int);
160
static bool mep_call_saves_register (int);
161
static rtx F (rtx);
162
static void add_constant (int, int, int, int);
163
static rtx maybe_dead_move (rtx, rtx, bool);
164
static void mep_reload_pointer (int, const char *);
165
static void mep_start_function (FILE *, HOST_WIDE_INT);
166
static bool mep_function_ok_for_sibcall (tree, tree);
167
static int unique_bit_in (HOST_WIDE_INT);
168
static int bit_size_for_clip (HOST_WIDE_INT);
169
static int bytesize (const_tree, enum machine_mode);
170
static tree mep_validate_based_tiny (tree *, tree, tree, int, bool *);
171
static tree mep_validate_near_far (tree *, tree, tree, int, bool *);
172
static tree mep_validate_disinterrupt (tree *, tree, tree, int, bool *);
173
static tree mep_validate_interrupt (tree *, tree, tree, int, bool *);
174
static tree mep_validate_io_cb (tree *, tree, tree, int, bool *);
175
static tree mep_validate_vliw (tree *, tree, tree, int, bool *);
176
static bool mep_function_attribute_inlinable_p (const_tree);
177
static bool mep_can_inline_p (tree, tree);
178
static bool mep_lookup_pragma_disinterrupt (const char *);
179
static int mep_multiple_address_regions (tree, bool);
180
static int mep_attrlist_to_encoding (tree, tree);
181
static void mep_insert_attributes (tree, tree *);
182
static void mep_encode_section_info (tree, rtx, int);
183
static section * mep_select_section (tree, int, unsigned HOST_WIDE_INT);
184
static void mep_unique_section (tree, int);
185
static unsigned int mep_section_type_flags (tree, const char *, int);
186
static void mep_asm_named_section (const char *, unsigned int, tree);
187
static bool mep_mentioned_p (rtx, rtx, int);
188
static void mep_reorg_regmove (rtx);
189
static rtx mep_insert_repeat_label_last (rtx, rtx, bool, bool);
190
static void mep_reorg_repeat (rtx);
191
static bool mep_invertable_branch_p (rtx);
192
static void mep_invert_branch (rtx, rtx);
193
static void mep_reorg_erepeat (rtx);
194
static void mep_jmp_return_reorg (rtx);
195
static void mep_reorg_addcombine (rtx);
196
static void mep_reorg (void);
197
static void mep_init_intrinsics (void);
198
static void mep_init_builtins (void);
199
static void mep_intrinsic_unavailable (int);
200
static bool mep_get_intrinsic_insn (int, const struct cgen_insn **);
201
static bool mep_get_move_insn (int, const struct cgen_insn **);
202
static rtx mep_convert_arg (enum machine_mode, rtx);
203
static rtx mep_convert_regnum (const struct cgen_regnum_operand *, rtx);
204
static rtx mep_legitimize_arg (const struct insn_operand_data *, rtx, int);
205
static void mep_incompatible_arg (const struct insn_operand_data *, rtx, int, tree);
206
static rtx mep_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
207
static int mep_adjust_cost (rtx, rtx, rtx, int);
208
static int mep_issue_rate (void);
209
static rtx mep_find_ready_insn (rtx *, int, enum attr_slot, int);
210
static void mep_move_ready_insn (rtx *, int, rtx);
211
static int mep_sched_reorder (FILE *, int, rtx *, int *, int);
212
static rtx mep_make_bundle (rtx, rtx);
213
static void mep_bundle_insns (rtx);
214
static bool mep_rtx_cost (rtx, int, int, int, int *, bool);
215
static int mep_address_cost (rtx, bool);
216
static void mep_setup_incoming_varargs (cumulative_args_t, enum machine_mode,
217
                                        tree, int *, int);
218
static bool mep_pass_by_reference (cumulative_args_t cum, enum machine_mode,
219
                                   const_tree, bool);
220
static rtx mep_function_arg (cumulative_args_t, enum machine_mode,
221
                             const_tree, bool);
222
static void mep_function_arg_advance (cumulative_args_t, enum machine_mode,
223
                                      const_tree, bool);
224
static bool mep_vector_mode_supported_p (enum machine_mode);
225
static rtx  mep_allocate_initial_value (rtx);
226
static void mep_asm_init_sections (void);
227
static int mep_comp_type_attributes (const_tree, const_tree);
228
static bool mep_narrow_volatile_bitfield (void);
229
static rtx mep_expand_builtin_saveregs (void);
230
static tree mep_build_builtin_va_list (void);
231
static void mep_expand_va_start (tree, rtx);
232
static tree mep_gimplify_va_arg_expr (tree, tree, gimple_seq *, gimple_seq *);
233
static bool mep_can_eliminate (const int, const int);
234
static void mep_conditional_register_usage (void);
235
static void mep_trampoline_init (rtx, tree, rtx);
236
 
237
#define WANT_GCC_DEFINITIONS
238
#include "mep-intrin.h"
239
#undef WANT_GCC_DEFINITIONS
240
 
241
 
242
/* Command Line Option Support.  */
243
 
244
char mep_leaf_registers [FIRST_PSEUDO_REGISTER];
245
 
246
/* True if we can use cmov instructions to move values back and forth
247
   between core and coprocessor registers.  */
248
bool mep_have_core_copro_moves_p;
249
 
250
/* True if we can use cmov instructions (or a work-alike) to move
251
   values between coprocessor registers.  */
252
bool mep_have_copro_copro_moves_p;
253
 
254
/* A table of all coprocessor instructions that can act like
255
   a coprocessor-to-coprocessor cmov.  */
256
static const int mep_cmov_insns[] = {
257
  mep_cmov,
258
  mep_cpmov,
259
  mep_fmovs,
260
  mep_caddi3,
261
  mep_csubi3,
262
  mep_candi3,
263
  mep_cori3,
264
  mep_cxori3,
265
  mep_cand3,
266
  mep_cor3
267
};
268
 
269
 
270
static void
271
mep_set_leaf_registers (int enable)
272
{
273
  int i;
274
 
275
  if (mep_leaf_registers[0] != enable)
276
    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
277
      mep_leaf_registers[i] = enable;
278
}
279
 
280
static void
281
mep_conditional_register_usage (void)
282
{
283
  int i;
284
 
285
  if (!TARGET_OPT_MULT && !TARGET_OPT_DIV)
286
    {
287
      fixed_regs[HI_REGNO] = 1;
288
      fixed_regs[LO_REGNO] = 1;
289
      call_used_regs[HI_REGNO] = 1;
290
      call_used_regs[LO_REGNO] = 1;
291
    }
292
 
293
  for (i = FIRST_SHADOW_REGISTER; i <= LAST_SHADOW_REGISTER; i++)
294
    global_regs[i] = 1;
295
}
296
 
297
static void
298
mep_option_override (void)
299
{
300
  unsigned int i;
301
  int j;
302
  cl_deferred_option *opt;
303
  VEC(cl_deferred_option,heap) *vec
304
    = (VEC(cl_deferred_option,heap) *) mep_deferred_options;
305
 
306
  FOR_EACH_VEC_ELT (cl_deferred_option, vec, i, opt)
307
    {
308
      switch (opt->opt_index)
309
        {
310
        case OPT_mivc2:
311
          for (j = 0; j < 32; j++)
312
            fixed_regs[j + 48] = 0;
313
          for (j = 0; j < 32; j++)
314
            call_used_regs[j + 48] = 1;
315
          for (j = 6; j < 8; j++)
316
            call_used_regs[j + 48] = 0;
317
 
318
#define RN(n,s) reg_names[FIRST_CCR_REGNO + n] = s
319
          RN (0, "$csar0");
320
          RN (1, "$cc");
321
          RN (4, "$cofr0");
322
          RN (5, "$cofr1");
323
          RN (6, "$cofa0");
324
          RN (7, "$cofa1");
325
          RN (15, "$csar1");
326
 
327
          RN (16, "$acc0_0");
328
          RN (17, "$acc0_1");
329
          RN (18, "$acc0_2");
330
          RN (19, "$acc0_3");
331
          RN (20, "$acc0_4");
332
          RN (21, "$acc0_5");
333
          RN (22, "$acc0_6");
334
          RN (23, "$acc0_7");
335
 
336
          RN (24, "$acc1_0");
337
          RN (25, "$acc1_1");
338
          RN (26, "$acc1_2");
339
          RN (27, "$acc1_3");
340
          RN (28, "$acc1_4");
341
          RN (29, "$acc1_5");
342
          RN (30, "$acc1_6");
343
          RN (31, "$acc1_7");
344
#undef RN
345
          break;
346
 
347
        default:
348
          gcc_unreachable ();
349
        }
350
    }
351
 
352
  if (flag_pic == 1)
353
    warning (OPT_fpic, "-fpic is not supported");
354
  if (flag_pic == 2)
355
    warning (OPT_fPIC, "-fPIC is not supported");
356
  if (TARGET_S && TARGET_M)
357
    error ("only one of -ms and -mm may be given");
358
  if (TARGET_S && TARGET_L)
359
    error ("only one of -ms and -ml may be given");
360
  if (TARGET_M && TARGET_L)
361
    error ("only one of -mm and -ml may be given");
362
  if (TARGET_S && global_options_set.x_mep_tiny_cutoff)
363
    error ("only one of -ms and -mtiny= may be given");
364
  if (TARGET_M && global_options_set.x_mep_tiny_cutoff)
365
    error ("only one of -mm and -mtiny= may be given");
366
  if (TARGET_OPT_CLIP && ! TARGET_OPT_MINMAX)
367
    warning (0, "-mclip currently has no effect without -mminmax");
368
 
369
  if (mep_const_section)
370
    {
371
      if (strcmp (mep_const_section, "tiny") != 0
372
          && strcmp (mep_const_section, "near") != 0
373
          && strcmp (mep_const_section, "far") != 0)
374
        error ("-mc= must be -mc=tiny, -mc=near, or -mc=far");
375
    }
376
 
377
  if (TARGET_S)
378
    mep_tiny_cutoff = 65536;
379
  if (TARGET_M)
380
    mep_tiny_cutoff = 0;
381
  if (TARGET_L && ! global_options_set.x_mep_tiny_cutoff)
382
    mep_tiny_cutoff = 0;
383
 
384
  if (TARGET_64BIT_CR_REGS)
385
    flag_split_wide_types = 0;
386
 
387
  init_machine_status = mep_init_machine_status;
388
  mep_init_intrinsics ();
389
}
390
 
391
/* Pattern Support - constraints, predicates, expanders.  */
392
 
393
/* MEP has very few instructions that can refer to the span of
394
   addresses used by symbols, so it's common to check for them.  */
395
 
396
static bool
397
symbol_p (rtx x)
398
{
399
  int c = GET_CODE (x);
400
 
401
  return (c == CONST_INT
402
          || c == CONST
403
          || c == SYMBOL_REF);
404
}
405
 
406
static bool
407
symbolref_p (rtx x)
408
{
409
  int c;
410
 
411
  if (GET_CODE (x) != MEM)
412
    return false;
413
 
414
  c = GET_CODE (XEXP (x, 0));
415
  return (c == CONST_INT
416
          || c == CONST
417
          || c == SYMBOL_REF);
418
}
419
 
420
/* static const char *reg_class_names[] = REG_CLASS_NAMES; */
421
 
422
#define GEN_REG(R, STRICT)                              \
423
  (GR_REGNO_P (R)                                       \
424
   || (!STRICT                                          \
425
       && ((R) == ARG_POINTER_REGNUM                    \
426
           || (R) >= FIRST_PSEUDO_REGISTER)))
427
 
428
static char pattern[12], *patternp;
429
static GTY(()) rtx patternr[12];
430
#define RTX_IS(x) (strcmp (pattern, x) == 0)
431
 
432
static void
433
encode_pattern_1 (rtx x)
434
{
435
  int i;
436
 
437
  if (patternp == pattern + sizeof (pattern) - 2)
438
    {
439
      patternp[-1] = '?';
440
      return;
441
    }
442
 
443
  patternr[patternp-pattern] = x;
444
 
445
  switch (GET_CODE (x))
446
    {
447
    case REG:
448
      *patternp++ = 'r';
449
      break;
450
    case MEM:
451
      *patternp++ = 'm';
452
    case CONST:
453
      encode_pattern_1 (XEXP(x, 0));
454
      break;
455
    case PLUS:
456
      *patternp++ = '+';
457
      encode_pattern_1 (XEXP(x, 0));
458
      encode_pattern_1 (XEXP(x, 1));
459
      break;
460
    case LO_SUM:
461
      *patternp++ = 'L';
462
      encode_pattern_1 (XEXP(x, 0));
463
      encode_pattern_1 (XEXP(x, 1));
464
      break;
465
    case HIGH:
466
      *patternp++ = 'H';
467
      encode_pattern_1 (XEXP(x, 0));
468
      break;
469
    case SYMBOL_REF:
470
      *patternp++ = 's';
471
      break;
472
    case LABEL_REF:
473
      *patternp++ = 'l';
474
      break;
475
    case CONST_INT:
476
    case CONST_DOUBLE:
477
      *patternp++ = 'i';
478
      break;
479
    case UNSPEC:
480
      *patternp++ = 'u';
481
      *patternp++ = '0' + XCINT(x, 1, UNSPEC);
482
      for (i=0; i<XVECLEN (x, 0); i++)
483
        encode_pattern_1 (XVECEXP (x, 0, i));
484
      break;
485
    case USE:
486
      *patternp++ = 'U';
487
      break;
488
    default:
489
      *patternp++ = '?';
490
#if 0
491
      fprintf (stderr, "can't encode pattern %s\n", GET_RTX_NAME(GET_CODE(x)));
492
      debug_rtx (x);
493
      gcc_unreachable ();
494
#endif
495
      break;
496
    }
497
}
498
 
499
static void
500
encode_pattern (rtx x)
501
{
502
  patternp = pattern;
503
  encode_pattern_1 (x);
504
  *patternp = 0;
505
}
506
 
507
int
508
mep_section_tag (rtx x)
509
{
510
  const char *name;
511
 
512
  while (1)
513
    {
514
      switch (GET_CODE (x))
515
        {
516
        case MEM:
517
        case CONST:
518
          x = XEXP (x, 0);
519
          break;
520
        case UNSPEC:
521
          x = XVECEXP (x, 0, 0);
522
          break;
523
        case PLUS:
524
          if (GET_CODE (XEXP (x, 1)) != CONST_INT)
525
            return 0;
526
          x = XEXP (x, 0);
527
          break;
528
        default:
529
          goto done;
530
        }
531
    }
532
 done:
533
  if (GET_CODE (x) != SYMBOL_REF)
534
    return 0;
535
  name = XSTR (x, 0);
536
  if (name[0] == '@' && name[2] == '.')
537
    {
538
      if (name[1] == 'i' || name[1] == 'I')
539
        {
540
          if (name[1] == 'I')
541
            return 'f'; /* near */
542
          return 'n'; /* far */
543
        }
544
      return name[1];
545
    }
546
  return 0;
547
}
548
 
549
int
550
mep_regno_reg_class (int regno)
551
{
552
  switch (regno)
553
    {
554
    case SP_REGNO:              return SP_REGS;
555
    case TP_REGNO:              return TP_REGS;
556
    case GP_REGNO:              return GP_REGS;
557
    case 0:                      return R0_REGS;
558
    case HI_REGNO:              return HI_REGS;
559
    case LO_REGNO:              return LO_REGS;
560
    case ARG_POINTER_REGNUM:    return GENERAL_REGS;
561
    }
562
 
563
  if (GR_REGNO_P (regno))
564
    return regno < FIRST_GR_REGNO + 8 ? TPREL_REGS : GENERAL_REGS;
565
  if (CONTROL_REGNO_P (regno))
566
    return CONTROL_REGS;
567
 
568
  if (CR_REGNO_P (regno))
569
    {
570
      int i, j;
571
 
572
      /* Search for the register amongst user-defined subclasses of
573
         the coprocessor registers.  */
574
      for (i = USER0_REGS; i <= USER3_REGS; ++i)
575
        {
576
          if (! TEST_HARD_REG_BIT (reg_class_contents[i], regno))
577
            continue;
578
          for (j = 0; j < N_REG_CLASSES; ++j)
579
            {
580
              enum reg_class sub = reg_class_subclasses[i][j];
581
 
582
              if (sub == LIM_REG_CLASSES)
583
                return i;
584
              if (TEST_HARD_REG_BIT (reg_class_contents[sub], regno))
585
                break;
586
            }
587
        }
588
 
589
      return LOADABLE_CR_REGNO_P (regno) ? LOADABLE_CR_REGS : CR_REGS;
590
    }
591
 
592
  if (CCR_REGNO_P (regno))
593
    return CCR_REGS;
594
 
595
  gcc_assert (regno >= FIRST_SHADOW_REGISTER && regno <= LAST_SHADOW_REGISTER);
596
  return NO_REGS;
597
}
598
 
599
#if 0
600
int
601
mep_reg_class_from_constraint (int c, const char *str)
602
{
603
  switch (c)
604
    {
605
    case 'a':
606
      return SP_REGS;
607
    case 'b':
608
      return TP_REGS;
609
    case 'c':
610
      return CONTROL_REGS;
611
    case 'd':
612
      return HILO_REGS;
613
    case 'e':
614
      {
615
        switch (str[1])
616
          {
617
          case 'm':
618
            return LOADABLE_CR_REGS;
619
          case 'x':
620
            return mep_have_copro_copro_moves_p ? CR_REGS : NO_REGS;
621
          case 'r':
622
            return mep_have_core_copro_moves_p ? CR_REGS : NO_REGS;
623
          default:
624
            return NO_REGS;
625
          }
626
      }
627
    case 'h':
628
      return HI_REGS;
629
    case 'j':
630
      return RPC_REGS;
631
    case 'l':
632
      return LO_REGS;
633
    case 't':
634
      return TPREL_REGS;
635
    case 'v':
636
      return GP_REGS;
637
    case 'x':
638
      return CR_REGS;
639
    case 'y':
640
      return CCR_REGS;
641
    case 'z':
642
      return R0_REGS;
643
 
644
    case 'A':
645
    case 'B':
646
    case 'C':
647
    case 'D':
648
      {
649
        enum reg_class which = c - 'A' + USER0_REGS;
650
        return (reg_class_size[which] > 0 ? which : NO_REGS);
651
      }
652
 
653
    default:
654
      return NO_REGS;
655
    }
656
}
657
 
658
bool
659
mep_const_ok_for_letter_p (HOST_WIDE_INT value, int c)
660
{
661
  switch (c)
662
    {
663
      case 'I': return value >= -32768 && value <      32768;
664
      case 'J': return value >=      0 && value <      65536;
665
      case 'K': return value >=      0 && value < 0x01000000;
666
      case 'L': return value >=    -32 && value <         32;
667
      case 'M': return value >=      0 && value <         32;
668
      case 'N': return value >=      0 && value <         16;
669
      case 'O':
670
        if (value & 0xffff)
671
          return false;
672
        return value >= -2147483647-1 && value <= 2147483647;
673
    default:
674
      gcc_unreachable ();
675
    }
676
}
677
 
678
bool
679
mep_extra_constraint (rtx value, int c)
680
{
681
  encode_pattern (value);
682
 
683
  switch (c)
684
    {
685
    case 'R':
686
      /* For near symbols, like what call uses.  */
687
      if (GET_CODE (value) == REG)
688
        return 0;
689
      return mep_call_address_operand (value, GET_MODE (value));
690
 
691
    case 'S':
692
      /* For signed 8-bit immediates.  */
693
      return (GET_CODE (value) == CONST_INT
694
              && INTVAL (value) >= -128
695
              && INTVAL (value) <= 127);
696
 
697
    case 'T':
698
      /* For tp/gp relative symbol values.  */
699
      return (RTX_IS ("u3s") || RTX_IS ("u2s")
700
              || RTX_IS ("+u3si") || RTX_IS ("+u2si"));
701
 
702
    case 'U':
703
      /* Non-absolute memories.  */
704
      return GET_CODE (value) == MEM && ! CONSTANT_P (XEXP (value, 0));
705
 
706
    case 'W':
707
      /* %hi(sym) */
708
      return RTX_IS ("Hs");
709
 
710
    case 'Y':
711
      /* Register indirect.  */
712
      return RTX_IS ("mr");
713
 
714
    case 'Z':
715
      return mep_section_tag (value) == 'c' && RTX_IS ("ms");
716
    }
717
 
718
  return false;
719
}
720
#endif
721
 
722
#undef PASS
723
#undef FAIL
724
 
725
static bool
726
const_in_range (rtx x, int minv, int maxv)
727
{
728
  return (GET_CODE (x) == CONST_INT
729
          && INTVAL (x) >= minv
730
          && INTVAL (x) <= maxv);
731
}
732
 
733
/* Given three integer registers DEST, SRC1 and SRC2, return an rtx X
734
   such that "mulr DEST,X" will calculate DEST = SRC1 * SRC2.  If a move
735
   is needed, emit it before INSN if INSN is nonnull, otherwise emit it
736
   at the end of the insn stream.  */
737
 
738
rtx
739
mep_mulr_source (rtx insn, rtx dest, rtx src1, rtx src2)
740
{
741
  if (rtx_equal_p (dest, src1))
742
    return src2;
743
  else if (rtx_equal_p (dest, src2))
744
    return src1;
745
  else
746
    {
747
      if (insn == 0)
748
        emit_insn (gen_movsi (copy_rtx (dest), src1));
749
      else
750
        emit_insn_before (gen_movsi (copy_rtx (dest), src1), insn);
751
      return src2;
752
    }
753
}
754
 
755
/* Replace INSN's pattern with PATTERN, a multiplication PARALLEL.
756
   Change the last element of PATTERN from (clobber (scratch:SI))
757
   to (clobber (reg:SI HI_REGNO)).  */
758
 
759
static void
760
mep_rewrite_mult (rtx insn, rtx pattern)
761
{
762
  rtx hi_clobber;
763
 
764
  hi_clobber = XVECEXP (pattern, 0, XVECLEN (pattern, 0) - 1);
765
  XEXP (hi_clobber, 0) = gen_rtx_REG (SImode, HI_REGNO);
766
  PATTERN (insn) = pattern;
767
  INSN_CODE (insn) = -1;
768
}
769
 
770
/* Subroutine of mep_reuse_lo_p.  Rewrite instruction INSN so that it
771
   calculates SRC1 * SRC2 and stores the result in $lo.  Also make it
772
   store the result in DEST if nonnull.  */
773
 
774
static void
775
mep_rewrite_mulsi3 (rtx insn, rtx dest, rtx src1, rtx src2)
776
{
777
  rtx lo, pattern;
778
 
779
  lo = gen_rtx_REG (SImode, LO_REGNO);
780
  if (dest)
781
    pattern = gen_mulsi3r (lo, dest, copy_rtx (dest),
782
                           mep_mulr_source (insn, dest, src1, src2));
783
  else
784
    pattern = gen_mulsi3_lo (lo, src1, src2);
785
  mep_rewrite_mult (insn, pattern);
786
}
787
 
788
/* Like mep_rewrite_mulsi3, but calculate SRC1 * SRC2 + SRC3.  First copy
789
   SRC3 into $lo, then use either madd or maddr.  The move into $lo will
790
   be deleted by a peephole2 if SRC3 is already in $lo.  */
791
 
792
static void
793
mep_rewrite_maddsi3 (rtx insn, rtx dest, rtx src1, rtx src2, rtx src3)
794
{
795
  rtx lo, pattern;
796
 
797
  lo = gen_rtx_REG (SImode, LO_REGNO);
798
  emit_insn_before (gen_movsi (copy_rtx (lo), src3), insn);
799
  if (dest)
800
    pattern = gen_maddsi3r (lo, dest, copy_rtx (dest),
801
                            mep_mulr_source (insn, dest, src1, src2),
802
                            copy_rtx (lo));
803
  else
804
    pattern = gen_maddsi3_lo (lo, src1, src2, copy_rtx (lo));
805
  mep_rewrite_mult (insn, pattern);
806
}
807
 
808
/* Return true if $lo has the same value as integer register GPR when
809
   instruction INSN is reached.  If necessary, rewrite the instruction
810
   that sets $lo so that it uses a proper SET, not a CLOBBER.  LO is an
811
   rtx for (reg:SI LO_REGNO).
812
 
813
   This function is intended to be used by the peephole2 pass.  Since
814
   that pass goes from the end of a basic block to the beginning, and
815
   propagates liveness information on the way, there is no need to
816
   update register notes here.
817
 
818
   If GPR_DEAD_P is true on entry, and this function returns true,
819
   then the caller will replace _every_ use of GPR in and after INSN
820
   with LO.  This means that if the instruction that sets $lo is a
821
   mulr- or maddr-type instruction, we can rewrite it to use mul or
822
   madd instead.  In combination with the copy progagation pass,
823
   this allows us to replace sequences like:
824
 
825
        mov GPR,R1
826
        mulr GPR,R2
827
 
828
   with:
829
 
830
        mul R1,R2
831
 
832
   if GPR is no longer used.  */
833
 
834
static bool
835
mep_reuse_lo_p_1 (rtx lo, rtx gpr, rtx insn, bool gpr_dead_p)
836
{
837
  do
838
    {
839
      insn = PREV_INSN (insn);
840
      if (INSN_P (insn))
841
        switch (recog_memoized (insn))
842
          {
843
          case CODE_FOR_mulsi3_1:
844
            extract_insn (insn);
845
            if (rtx_equal_p (recog_data.operand[0], gpr))
846
              {
847
                mep_rewrite_mulsi3 (insn,
848
                                    gpr_dead_p ? NULL : recog_data.operand[0],
849
                                    recog_data.operand[1],
850
                                    recog_data.operand[2]);
851
                return true;
852
              }
853
            return false;
854
 
855
          case CODE_FOR_maddsi3:
856
            extract_insn (insn);
857
            if (rtx_equal_p (recog_data.operand[0], gpr))
858
              {
859
                mep_rewrite_maddsi3 (insn,
860
                                     gpr_dead_p ? NULL : recog_data.operand[0],
861
                                     recog_data.operand[1],
862
                                     recog_data.operand[2],
863
                                     recog_data.operand[3]);
864
                return true;
865
              }
866
            return false;
867
 
868
          case CODE_FOR_mulsi3r:
869
          case CODE_FOR_maddsi3r:
870
            extract_insn (insn);
871
            return rtx_equal_p (recog_data.operand[1], gpr);
872
 
873
          default:
874
            if (reg_set_p (lo, insn)
875
                || reg_set_p (gpr, insn)
876
                || volatile_insn_p (PATTERN (insn)))
877
              return false;
878
 
879
            if (gpr_dead_p && reg_referenced_p (gpr, PATTERN (insn)))
880
              gpr_dead_p = false;
881
            break;
882
          }
883
    }
884
  while (!NOTE_INSN_BASIC_BLOCK_P (insn));
885
  return false;
886
}
887
 
888
/* A wrapper around mep_reuse_lo_p_1 that preserves recog_data.  */
889
 
890
bool
891
mep_reuse_lo_p (rtx lo, rtx gpr, rtx insn, bool gpr_dead_p)
892
{
893
  bool result = mep_reuse_lo_p_1 (lo, gpr, insn, gpr_dead_p);
894
  extract_insn (insn);
895
  return result;
896
}
897
 
898
/* Return true if SET can be turned into a post-modify load or store
899
   that adds OFFSET to GPR.  In other words, return true if SET can be
900
   changed into:
901
 
902
       (parallel [SET (set GPR (plus:SI GPR OFFSET))]).
903
 
904
   It's OK to change SET to an equivalent operation in order to
905
   make it match.  */
906
 
907
static bool
908
mep_use_post_modify_for_set_p (rtx set, rtx gpr, rtx offset)
909
{
910
  rtx *reg, *mem;
911
  unsigned int reg_bytes, mem_bytes;
912
  enum machine_mode reg_mode, mem_mode;
913
 
914
  /* Only simple SETs can be converted.  */
915
  if (GET_CODE (set) != SET)
916
    return false;
917
 
918
  /* Point REG to what we hope will be the register side of the set and
919
     MEM to what we hope will be the memory side.  */
920
  if (GET_CODE (SET_DEST (set)) == MEM)
921
    {
922
      mem = &SET_DEST (set);
923
      reg = &SET_SRC (set);
924
    }
925
  else
926
    {
927
      reg = &SET_DEST (set);
928
      mem = &SET_SRC (set);
929
      if (GET_CODE (*mem) == SIGN_EXTEND)
930
        mem = &XEXP (*mem, 0);
931
    }
932
 
933
  /* Check that *REG is a suitable coprocessor register.  */
934
  if (GET_CODE (*reg) != REG || !LOADABLE_CR_REGNO_P (REGNO (*reg)))
935
    return false;
936
 
937
  /* Check that *MEM is a suitable memory reference.  */
938
  if (GET_CODE (*mem) != MEM || !rtx_equal_p (XEXP (*mem, 0), gpr))
939
    return false;
940
 
941
  /* Get the number of bytes in each operand.  */
942
  mem_bytes = GET_MODE_SIZE (GET_MODE (*mem));
943
  reg_bytes = GET_MODE_SIZE (GET_MODE (*reg));
944
 
945
  /* Check that OFFSET is suitably aligned.  */
946
  if (INTVAL (offset) & (mem_bytes - 1))
947
    return false;
948
 
949
  /* Convert *MEM to a normal integer mode.  */
950
  mem_mode = mode_for_size (mem_bytes * BITS_PER_UNIT, MODE_INT, 0);
951
  *mem = change_address (*mem, mem_mode, NULL);
952
 
953
  /* Adjust *REG as well.  */
954
  *reg = shallow_copy_rtx (*reg);
955
  if (reg == &SET_DEST (set) && reg_bytes < UNITS_PER_WORD)
956
    {
957
      /* SET is a subword load.  Convert it to an explicit extension.  */
958
      PUT_MODE (*reg, SImode);
959
      *mem = gen_rtx_SIGN_EXTEND (SImode, *mem);
960
    }
961
  else
962
    {
963
      reg_mode = mode_for_size (reg_bytes * BITS_PER_UNIT, MODE_INT, 0);
964
      PUT_MODE (*reg, reg_mode);
965
    }
966
  return true;
967
}
968
 
969
/* Return the effect of frame-related instruction INSN.  */
970
 
971
static rtx
972
mep_frame_expr (rtx insn)
973
{
974
  rtx note, expr;
975
 
976
  note = find_reg_note (insn, REG_FRAME_RELATED_EXPR, 0);
977
  expr = (note != 0 ? XEXP (note, 0) : copy_rtx (PATTERN (insn)));
978
  RTX_FRAME_RELATED_P (expr) = 1;
979
  return expr;
980
}
981
 
982
/* Merge instructions INSN1 and INSN2 using a PARALLEL.  Store the
983
   new pattern in INSN1; INSN2 will be deleted by the caller.  */
984
 
985
static void
986
mep_make_parallel (rtx insn1, rtx insn2)
987
{
988
  rtx expr;
989
 
990
  if (RTX_FRAME_RELATED_P (insn2))
991
    {
992
      expr = mep_frame_expr (insn2);
993
      if (RTX_FRAME_RELATED_P (insn1))
994
        expr = gen_rtx_SEQUENCE (VOIDmode,
995
                                 gen_rtvec (2, mep_frame_expr (insn1), expr));
996
      set_unique_reg_note (insn1, REG_FRAME_RELATED_EXPR, expr);
997
      RTX_FRAME_RELATED_P (insn1) = 1;
998
    }
999
 
1000
  PATTERN (insn1) = gen_rtx_PARALLEL (VOIDmode,
1001
                                      gen_rtvec (2, PATTERN (insn1),
1002
                                                 PATTERN (insn2)));
1003
  INSN_CODE (insn1) = -1;
1004
}
1005
 
1006
/* SET_INSN is an instruction that adds OFFSET to REG.  Go back through
1007
   the basic block to see if any previous load or store instruction can
1008
   be persuaded to do SET_INSN as a side-effect.  Return true if so.  */
1009
 
1010
static bool
1011
mep_use_post_modify_p_1 (rtx set_insn, rtx reg, rtx offset)
1012
{
1013
  rtx insn;
1014
 
1015
  insn = set_insn;
1016
  do
1017
    {
1018
      insn = PREV_INSN (insn);
1019
      if (INSN_P (insn))
1020
        {
1021
          if (mep_use_post_modify_for_set_p (PATTERN (insn), reg, offset))
1022
            {
1023
              mep_make_parallel (insn, set_insn);
1024
              return true;
1025
            }
1026
 
1027
          if (reg_set_p (reg, insn)
1028
              || reg_referenced_p (reg, PATTERN (insn))
1029
              || volatile_insn_p (PATTERN (insn)))
1030
            return false;
1031
        }
1032
    }
1033
  while (!NOTE_INSN_BASIC_BLOCK_P (insn));
1034
  return false;
1035
}
1036
 
1037
/* A wrapper around mep_use_post_modify_p_1 that preserves recog_data.  */
1038
 
1039
bool
1040
mep_use_post_modify_p (rtx insn, rtx reg, rtx offset)
1041
{
1042
  bool result = mep_use_post_modify_p_1 (insn, reg, offset);
1043
  extract_insn (insn);
1044
  return result;
1045
}
1046
 
1047
bool
1048
mep_allow_clip (rtx ux, rtx lx, int s)
1049
{
1050
  HOST_WIDE_INT u = INTVAL (ux);
1051
  HOST_WIDE_INT l = INTVAL (lx);
1052
  int i;
1053
 
1054
  if (!TARGET_OPT_CLIP)
1055
    return false;
1056
 
1057
  if (s)
1058
    {
1059
      for (i = 0; i < 30; i ++)
1060
        if ((u == ((HOST_WIDE_INT) 1 << i) - 1)
1061
            && (l == - ((HOST_WIDE_INT) 1 << i)))
1062
          return true;
1063
    }
1064
  else
1065
    {
1066
      if (l != 0)
1067
        return false;
1068
 
1069
      for (i = 0; i < 30; i ++)
1070
        if ((u == ((HOST_WIDE_INT) 1 << i) - 1))
1071
          return true;
1072
    }
1073
  return false;
1074
}
1075
 
1076
bool
1077
mep_bit_position_p (rtx x, bool looking_for)
1078
{
1079
  if (GET_CODE (x) != CONST_INT)
1080
    return false;
1081
  switch ((int) INTVAL(x) & 0xff)
1082
    {
1083
    case 0x01: case 0x02: case 0x04: case 0x08:
1084
    case 0x10: case 0x20: case 0x40: case 0x80:
1085
      return looking_for;
1086
    case 0xfe: case 0xfd: case 0xfb: case 0xf7:
1087
    case 0xef: case 0xdf: case 0xbf: case 0x7f:
1088
      return !looking_for;
1089
    }
1090
  return false;
1091
}
1092
 
1093
static bool
1094
move_needs_splitting (rtx dest, rtx src,
1095
                      enum machine_mode mode ATTRIBUTE_UNUSED)
1096
{
1097
  int s = mep_section_tag (src);
1098
 
1099
  while (1)
1100
    {
1101
      if (GET_CODE (src) == CONST
1102
          || GET_CODE (src) == MEM)
1103
        src = XEXP (src, 0);
1104
      else if (GET_CODE (src) == SYMBOL_REF
1105
               || GET_CODE (src) == LABEL_REF
1106
               || GET_CODE (src) == PLUS)
1107
        break;
1108
      else
1109
        return false;
1110
    }
1111
  if (s == 'f'
1112
      || (GET_CODE (src) == PLUS
1113
          && GET_CODE (XEXP (src, 1)) == CONST_INT
1114
          && (INTVAL (XEXP (src, 1)) < -65536
1115
              || INTVAL (XEXP (src, 1)) > 0xffffff))
1116
      || (GET_CODE (dest) == REG
1117
          && REGNO (dest) > 7 && REGNO (dest) < FIRST_PSEUDO_REGISTER))
1118
    return true;
1119
  return false;
1120
}
1121
 
1122
bool
1123
mep_split_mov (rtx *operands, int symbolic)
1124
{
1125
  if (symbolic)
1126
    {
1127
      if (move_needs_splitting (operands[0], operands[1], SImode))
1128
        return true;
1129
      return false;
1130
    }
1131
 
1132
  if (GET_CODE (operands[1]) != CONST_INT)
1133
    return false;
1134
 
1135
  if (constraint_satisfied_p (operands[1], CONSTRAINT_I)
1136
      || constraint_satisfied_p (operands[1], CONSTRAINT_J)
1137
      || constraint_satisfied_p (operands[1], CONSTRAINT_O))
1138
    return false;
1139
 
1140
  if (((!reload_completed && !reload_in_progress)
1141
       || (REG_P (operands[0]) && REGNO (operands[0]) < 8))
1142
      && constraint_satisfied_p (operands[1], CONSTRAINT_K))
1143
    return false;
1144
 
1145
  return true;
1146
}
1147
 
1148
/* Irritatingly, the "jsrv" insn *toggles* PSW.OM rather than set
1149
   it to one specific value.  So the insn chosen depends on whether
1150
   the source and destination modes match.  */
1151
 
1152
bool
1153
mep_vliw_mode_match (rtx tgt)
1154
{
1155
  bool src_vliw = mep_vliw_function_p (cfun->decl);
1156
  bool tgt_vliw = INTVAL (tgt);
1157
 
1158
  return src_vliw == tgt_vliw;
1159
}
1160
 
1161
/* Like the above, but also test for near/far mismatches.  */
1162
 
1163
bool
1164
mep_vliw_jmp_match (rtx tgt)
1165
{
1166
  bool src_vliw = mep_vliw_function_p (cfun->decl);
1167
  bool tgt_vliw = INTVAL (tgt);
1168
 
1169
  if (mep_section_tag (DECL_RTL (cfun->decl)) == 'f')
1170
    return false;
1171
 
1172
  return src_vliw == tgt_vliw;
1173
}
1174
 
1175
bool
1176
mep_multi_slot (rtx x)
1177
{
1178
  return get_attr_slot (x) == SLOT_MULTI;
1179
}
1180
 
1181
/* Implement TARGET_LEGITIMATE_CONSTANT_P.  */
1182
 
1183
static bool
1184
mep_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
1185
{
1186
  /* We can't convert symbol values to gp- or tp-rel values after
1187
     reload, as reload might have used $gp or $tp for other
1188
     purposes.  */
1189
  if (GET_CODE (x) == SYMBOL_REF && (reload_in_progress || reload_completed))
1190
    {
1191
      char e = mep_section_tag (x);
1192
      return (e != 't' && e != 'b');
1193
    }
1194
  return 1;
1195
}
1196
 
1197
/* Be careful not to use macros that need to be compiled one way for
1198
   strict, and another way for not-strict, like REG_OK_FOR_BASE_P.  */
1199
 
1200
bool
1201
mep_legitimate_address (enum machine_mode mode, rtx x, int strict)
1202
{
1203
  int the_tag;
1204
 
1205
#define DEBUG_LEGIT 0
1206
#if DEBUG_LEGIT
1207
  fprintf (stderr, "legit: mode %s strict %d ", mode_name[mode], strict);
1208
  debug_rtx (x);
1209
#endif
1210
 
1211
  if (GET_CODE (x) == LO_SUM
1212
      && GET_CODE (XEXP (x, 0)) == REG
1213
      && GEN_REG (REGNO (XEXP (x, 0)), strict)
1214
      && CONSTANT_P (XEXP (x, 1)))
1215
    {
1216
      if (GET_MODE_SIZE (mode) > 4)
1217
        {
1218
          /* We will end up splitting this, and lo_sums are not
1219
             offsettable for us.  */
1220
#if DEBUG_LEGIT
1221
          fprintf(stderr, " - nope, %%lo(sym)[reg] not splittable\n");
1222
#endif
1223
          return false;
1224
        }
1225
#if DEBUG_LEGIT
1226
      fprintf (stderr, " - yup, %%lo(sym)[reg]\n");
1227
#endif
1228
      return true;
1229
    }
1230
 
1231
  if (GET_CODE (x) == REG
1232
      && GEN_REG (REGNO (x), strict))
1233
    {
1234
#if DEBUG_LEGIT
1235
      fprintf (stderr, " - yup, [reg]\n");
1236
#endif
1237
      return true;
1238
    }
1239
 
1240
  if (GET_CODE (x) == PLUS
1241
      && GET_CODE (XEXP (x, 0)) == REG
1242
      && GEN_REG (REGNO (XEXP (x, 0)), strict)
1243
      && const_in_range (XEXP (x, 1), -32768, 32767))
1244
    {
1245
#if DEBUG_LEGIT
1246
      fprintf (stderr, " - yup, [reg+const]\n");
1247
#endif
1248
      return true;
1249
    }
1250
 
1251
  if (GET_CODE (x) == PLUS
1252
      && GET_CODE (XEXP (x, 0)) == REG
1253
      && GEN_REG (REGNO (XEXP (x, 0)), strict)
1254
      && GET_CODE (XEXP (x, 1)) == CONST
1255
      && (GET_CODE (XEXP (XEXP (x, 1), 0)) == UNSPEC
1256
          || (GET_CODE (XEXP (XEXP (x, 1), 0)) == PLUS
1257
              && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 0)) == UNSPEC
1258
              && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 1)) == CONST_INT)))
1259
    {
1260
#if DEBUG_LEGIT
1261
      fprintf (stderr, " - yup, [reg+unspec]\n");
1262
#endif
1263
      return true;
1264
    }
1265
 
1266
  the_tag = mep_section_tag (x);
1267
 
1268
  if (the_tag == 'f')
1269
    {
1270
#if DEBUG_LEGIT
1271
      fprintf (stderr, " - nope, [far]\n");
1272
#endif
1273
      return false;
1274
    }
1275
 
1276
  if (mode == VOIDmode
1277
      && GET_CODE (x) == SYMBOL_REF)
1278
    {
1279
#if DEBUG_LEGIT
1280
      fprintf (stderr, " - yup, call [symbol]\n");
1281
#endif
1282
      return true;
1283
    }
1284
 
1285
  if ((mode == SImode || mode == SFmode)
1286
      && CONSTANT_P (x)
1287
      && mep_legitimate_constant_p (mode, x)
1288
      && the_tag != 't' && the_tag != 'b')
1289
    {
1290
      if (GET_CODE (x) != CONST_INT
1291
          || (INTVAL (x) <= 0xfffff
1292
              && INTVAL (x) >= 0
1293
              && (INTVAL (x) % 4) == 0))
1294
        {
1295
#if DEBUG_LEGIT
1296
          fprintf (stderr, " - yup, [const]\n");
1297
#endif
1298
          return true;
1299
        }
1300
    }
1301
 
1302
#if DEBUG_LEGIT
1303
  fprintf (stderr, " - nope.\n");
1304
#endif
1305
  return false;
1306
}
1307
 
1308
int
1309
mep_legitimize_reload_address (rtx *x, enum machine_mode mode, int opnum,
1310
                               int type_i,
1311
                               int ind_levels ATTRIBUTE_UNUSED)
1312
{
1313
  enum reload_type type = (enum reload_type) type_i;
1314
 
1315
  if (GET_CODE (*x) == PLUS
1316
      && GET_CODE (XEXP (*x, 0)) == MEM
1317
      && GET_CODE (XEXP (*x, 1)) == REG)
1318
    {
1319
      /* GCC will by default copy the MEM into a REG, which results in
1320
         an invalid address.  For us, the best thing to do is move the
1321
         whole expression to a REG.  */
1322
      push_reload (*x, NULL_RTX, x, NULL,
1323
                   GENERAL_REGS, mode, VOIDmode,
1324
                   0, 0, opnum, type);
1325
      return 1;
1326
    }
1327
 
1328
  if (GET_CODE (*x) == PLUS
1329
      && GET_CODE (XEXP (*x, 0)) == SYMBOL_REF
1330
      && GET_CODE (XEXP (*x, 1)) == CONST_INT)
1331
    {
1332
      char e = mep_section_tag (XEXP (*x, 0));
1333
 
1334
      if (e != 't' && e != 'b')
1335
        {
1336
          /* GCC thinks that (sym+const) is a valid address.  Well,
1337
             sometimes it is, this time it isn't.  The best thing to
1338
             do is reload the symbol to a register, since reg+int
1339
             tends to work, and we can't just add the symbol and
1340
             constant anyway.  */
1341
          push_reload (XEXP (*x, 0), NULL_RTX, &(XEXP(*x, 0)), NULL,
1342
                       GENERAL_REGS, mode, VOIDmode,
1343
                       0, 0, opnum, type);
1344
          return 1;
1345
        }
1346
    }
1347
  return 0;
1348
}
1349
 
1350
int
1351
mep_core_address_length (rtx insn, int opn)
1352
{
1353
  rtx set = single_set (insn);
1354
  rtx mem = XEXP (set, opn);
1355
  rtx other = XEXP (set, 1-opn);
1356
  rtx addr = XEXP (mem, 0);
1357
 
1358
  if (register_operand (addr, Pmode))
1359
    return 2;
1360
  if (GET_CODE (addr) == PLUS)
1361
    {
1362
      rtx addend = XEXP (addr, 1);
1363
 
1364
      gcc_assert (REG_P (XEXP (addr, 0)));
1365
 
1366
      switch (REGNO (XEXP (addr, 0)))
1367
        {
1368
        case STACK_POINTER_REGNUM:
1369
          if (GET_MODE_SIZE (GET_MODE (mem)) == 4
1370
              && mep_imm7a4_operand (addend, VOIDmode))
1371
            return 2;
1372
          break;
1373
 
1374
        case 13: /* TP */
1375
          gcc_assert (REG_P (other));
1376
 
1377
          if (REGNO (other) >= 8)
1378
            break;
1379
 
1380
          if (GET_CODE (addend) == CONST
1381
              && GET_CODE (XEXP (addend, 0)) == UNSPEC
1382
              && XINT (XEXP (addend, 0), 1) == UNS_TPREL)
1383
            return 2;
1384
 
1385
          if (GET_CODE (addend) == CONST_INT
1386
              && INTVAL (addend) >= 0
1387
              && INTVAL (addend) <= 127
1388
              && INTVAL (addend) % GET_MODE_SIZE (GET_MODE (mem)) == 0)
1389
            return 2;
1390
          break;
1391
        }
1392
    }
1393
 
1394
  return 4;
1395
}
1396
 
1397
int
1398
mep_cop_address_length (rtx insn, int opn)
1399
{
1400
  rtx set = single_set (insn);
1401
  rtx mem = XEXP (set, opn);
1402
  rtx addr = XEXP (mem, 0);
1403
 
1404
  if (GET_CODE (mem) != MEM)
1405
    return 2;
1406
  if (register_operand (addr, Pmode))
1407
    return 2;
1408
  if (GET_CODE (addr) == POST_INC)
1409
    return 2;
1410
 
1411
  return 4;
1412
}
1413
 
1414
#define DEBUG_EXPAND_MOV 0
1415
bool
1416
mep_expand_mov (rtx *operands, enum machine_mode mode)
1417
{
1418
  int i, t;
1419
  int tag[2];
1420
  rtx tpsym, tpoffs;
1421
  int post_reload = 0;
1422
 
1423
  tag[0] = mep_section_tag (operands[0]);
1424
  tag[1] = mep_section_tag (operands[1]);
1425
 
1426
  if (!reload_in_progress
1427
      && !reload_completed
1428
      && GET_CODE (operands[0]) != REG
1429
      && GET_CODE (operands[0]) != SUBREG
1430
      && GET_CODE (operands[1]) != REG
1431
      && GET_CODE (operands[1]) != SUBREG)
1432
    operands[1] = copy_to_mode_reg (mode, operands[1]);
1433
 
1434
#if DEBUG_EXPAND_MOV
1435
  fprintf(stderr, "expand move %s %d\n", mode_name[mode],
1436
          reload_in_progress || reload_completed);
1437
  debug_rtx (operands[0]);
1438
  debug_rtx (operands[1]);
1439
#endif
1440
 
1441
  if (mode == DImode || mode == DFmode)
1442
    return false;
1443
 
1444
  if (reload_in_progress || reload_completed)
1445
    {
1446
      rtx r;
1447
 
1448
      if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == TP_REGNO)
1449
        cfun->machine->reload_changes_tp = true;
1450
 
1451
      if (tag[0] == 't' || tag[1] == 't')
1452
        {
1453
          r = has_hard_reg_initial_val (Pmode, GP_REGNO);
1454
          if (!r || GET_CODE (r) != REG || REGNO (r) != GP_REGNO)
1455
            post_reload = 1;
1456
        }
1457
      if (tag[0] == 'b' || tag[1] == 'b')
1458
        {
1459
          r = has_hard_reg_initial_val (Pmode, TP_REGNO);
1460
          if (!r || GET_CODE (r) != REG || REGNO (r) != TP_REGNO)
1461
            post_reload = 1;
1462
        }
1463
      if (cfun->machine->reload_changes_tp == true)
1464
        post_reload = 1;
1465
    }
1466
 
1467
  if (!post_reload)
1468
    {
1469
      rtx n;
1470
      if (symbol_p (operands[1]))
1471
        {
1472
          t = mep_section_tag (operands[1]);
1473
          if (t == 'b' || t == 't')
1474
            {
1475
 
1476
              if (GET_CODE (operands[1]) == SYMBOL_REF)
1477
                {
1478
                  tpsym = operands[1];
1479
                  n = gen_rtx_UNSPEC (mode,
1480
                                      gen_rtvec (1, operands[1]),
1481
                                      t == 'b' ? UNS_TPREL : UNS_GPREL);
1482
                  n = gen_rtx_CONST (mode, n);
1483
                }
1484
              else if (GET_CODE (operands[1]) == CONST
1485
                       && GET_CODE (XEXP (operands[1], 0)) == PLUS
1486
                       && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF
1487
                       && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT)
1488
                {
1489
                  tpsym = XEXP (XEXP (operands[1], 0), 0);
1490
                  tpoffs = XEXP (XEXP (operands[1], 0), 1);
1491
                  n = gen_rtx_UNSPEC (mode,
1492
                                      gen_rtvec (1, tpsym),
1493
                                      t == 'b' ? UNS_TPREL : UNS_GPREL);
1494
                  n = gen_rtx_PLUS (mode, n, tpoffs);
1495
                  n = gen_rtx_CONST (mode, n);
1496
                }
1497
              else if (GET_CODE (operands[1]) == CONST
1498
                       && GET_CODE (XEXP (operands[1], 0)) == UNSPEC)
1499
                return false;
1500
              else
1501
                {
1502
                  error ("unusual TP-relative address");
1503
                  return false;
1504
                }
1505
 
1506
              n = gen_rtx_PLUS (mode, (t == 'b' ? mep_tp_rtx ()
1507
                                       : mep_gp_rtx ()), n);
1508
              n = emit_insn (gen_rtx_SET (mode, operands[0], n));
1509
#if DEBUG_EXPAND_MOV
1510
              fprintf(stderr, "mep_expand_mov emitting ");
1511
              debug_rtx(n);
1512
#endif
1513
              return true;
1514
            }
1515
        }
1516
 
1517
      for (i=0; i < 2; i++)
1518
        {
1519
          t = mep_section_tag (operands[i]);
1520
          if (GET_CODE (operands[i]) == MEM && (t == 'b' || t == 't'))
1521
            {
1522
              rtx sym, n, r;
1523
              int u;
1524
 
1525
              sym = XEXP (operands[i], 0);
1526
              if (GET_CODE (sym) == CONST
1527
                  && GET_CODE (XEXP (sym, 0)) == UNSPEC)
1528
                sym = XVECEXP (XEXP (sym, 0), 0, 0);
1529
 
1530
              if (t == 'b')
1531
                {
1532
                  r = mep_tp_rtx ();
1533
                  u = UNS_TPREL;
1534
                }
1535
              else
1536
                {
1537
                  r = mep_gp_rtx ();
1538
                  u = UNS_GPREL;
1539
                }
1540
 
1541
              n = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym), u);
1542
              n = gen_rtx_CONST (Pmode, n);
1543
              n = gen_rtx_PLUS (Pmode, r, n);
1544
              operands[i] = replace_equiv_address (operands[i], n);
1545
            }
1546
        }
1547
    }
1548
 
1549
  if ((GET_CODE (operands[1]) != REG
1550
       && MEP_CONTROL_REG (operands[0]))
1551
      || (GET_CODE (operands[0]) != REG
1552
          && MEP_CONTROL_REG (operands[1])))
1553
    {
1554
      rtx temp;
1555
#if DEBUG_EXPAND_MOV
1556
      fprintf (stderr, "cr-mem, forcing op1 to reg\n");
1557
#endif
1558
      temp = gen_reg_rtx (mode);
1559
      emit_move_insn (temp, operands[1]);
1560
      operands[1] = temp;
1561
    }
1562
 
1563
  if (symbolref_p (operands[0])
1564
      && (mep_section_tag (XEXP (operands[0], 0)) == 'f'
1565
          || (GET_MODE_SIZE (mode) != 4)))
1566
    {
1567
      rtx temp;
1568
 
1569
      gcc_assert (!reload_in_progress && !reload_completed);
1570
 
1571
      temp = force_reg (Pmode, XEXP (operands[0], 0));
1572
      operands[0] = replace_equiv_address (operands[0], temp);
1573
      emit_move_insn (operands[0], operands[1]);
1574
      return true;
1575
    }
1576
 
1577
  if (!post_reload && (tag[1] == 't' || tag[1] == 'b'))
1578
    tag[1] = 0;
1579
 
1580
  if (symbol_p (operands[1])
1581
      && (tag[1] == 'f' || tag[1] == 't' || tag[1] == 'b'))
1582
    {
1583
      emit_insn (gen_movsi_topsym_s (operands[0], operands[1]));
1584
      emit_insn (gen_movsi_botsym_s (operands[0], operands[0], operands[1]));
1585
      return true;
1586
    }
1587
 
1588
  if (symbolref_p (operands[1])
1589
      && (tag[1] == 'f' || tag[1] == 't' || tag[1] == 'b'))
1590
    {
1591
      rtx temp;
1592
 
1593
      if (reload_in_progress || reload_completed)
1594
        temp = operands[0];
1595
      else
1596
        temp = gen_reg_rtx (Pmode);
1597
 
1598
      emit_insn (gen_movsi_topsym_s (temp, operands[1]));
1599
      emit_insn (gen_movsi_botsym_s (temp, temp, operands[1]));
1600
      emit_move_insn (operands[0], replace_equiv_address (operands[1], temp));
1601
      return true;
1602
    }
1603
 
1604
  return false;
1605
}
1606
 
1607
/* Cases where the pattern can't be made to use at all.  */
1608
 
1609
bool
1610
mep_mov_ok (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
1611
{
1612
  int i;
1613
 
1614
#define DEBUG_MOV_OK 0
1615
#if DEBUG_MOV_OK
1616
  fprintf (stderr, "mep_mov_ok %s %c=%c\n", mode_name[mode], mep_section_tag (operands[0]),
1617
           mep_section_tag (operands[1]));
1618
  debug_rtx (operands[0]);
1619
  debug_rtx (operands[1]);
1620
#endif
1621
 
1622
  /* We want the movh patterns to get these.  */
1623
  if (GET_CODE (operands[1]) == HIGH)
1624
    return false;
1625
 
1626
  /* We can't store a register to a far variable without using a
1627
     scratch register to hold the address.  Using far variables should
1628
     be split by mep_emit_mov anyway.  */
1629
  if (mep_section_tag (operands[0]) == 'f'
1630
      || mep_section_tag (operands[1]) == 'f')
1631
    {
1632
#if DEBUG_MOV_OK
1633
      fprintf (stderr, " - no, f\n");
1634
#endif
1635
      return false;
1636
    }
1637
  i = mep_section_tag (operands[1]);
1638
  if ((i == 'b' || i == 't') && !reload_completed && !reload_in_progress)
1639
    /* These are supposed to be generated with adds of the appropriate
1640
       register.  During and after reload, however, we allow them to
1641
       be accessed as normal symbols because adding a dependency on
1642
       the base register now might cause problems.  */
1643
    {
1644
#if DEBUG_MOV_OK
1645
      fprintf (stderr, " - no, bt\n");
1646
#endif
1647
      return false;
1648
    }
1649
 
1650
  /* The only moves we can allow involve at least one general
1651
     register, so require it.  */
1652
  for (i = 0; i < 2; i ++)
1653
    {
1654
      /* Allow subregs too, before reload.  */
1655
      rtx x = operands[i];
1656
 
1657
      if (GET_CODE (x) == SUBREG)
1658
        x = XEXP (x, 0);
1659
      if (GET_CODE (x) == REG
1660
          && ! MEP_CONTROL_REG (x))
1661
        {
1662
#if DEBUG_MOV_OK
1663
          fprintf (stderr, " - ok\n");
1664
#endif
1665
          return true;
1666
        }
1667
    }
1668
#if DEBUG_MOV_OK
1669
  fprintf (stderr, " - no, no gen reg\n");
1670
#endif
1671
  return false;
1672
}
1673
 
1674
#define DEBUG_SPLIT_WIDE_MOVE 0
1675
void
1676
mep_split_wide_move (rtx *operands, enum machine_mode mode)
1677
{
1678
  int i;
1679
 
1680
#if DEBUG_SPLIT_WIDE_MOVE
1681
  fprintf (stderr, "\n\033[34mmep_split_wide_move\033[0m mode %s\n", mode_name[mode]);
1682
  debug_rtx (operands[0]);
1683
  debug_rtx (operands[1]);
1684
#endif
1685
 
1686
  for (i = 0; i <= 1; i++)
1687
    {
1688
      rtx op = operands[i], hi, lo;
1689
 
1690
      switch (GET_CODE (op))
1691
        {
1692
        case REG:
1693
          {
1694
            unsigned int regno = REGNO (op);
1695
 
1696
            if (TARGET_64BIT_CR_REGS && CR_REGNO_P (regno))
1697
              {
1698
                rtx i32;
1699
 
1700
                lo = gen_rtx_REG (SImode, regno);
1701
                i32 = GEN_INT (32);
1702
                hi = gen_rtx_ZERO_EXTRACT (SImode,
1703
                                           gen_rtx_REG (DImode, regno),
1704
                                           i32, i32);
1705
              }
1706
            else
1707
              {
1708
                hi = gen_rtx_REG (SImode, regno + TARGET_LITTLE_ENDIAN);
1709
                lo = gen_rtx_REG (SImode, regno + TARGET_BIG_ENDIAN);
1710
              }
1711
          }
1712
          break;
1713
 
1714
        case CONST_INT:
1715
        case CONST_DOUBLE:
1716
        case MEM:
1717
          hi = operand_subword (op, TARGET_LITTLE_ENDIAN, 0, mode);
1718
          lo = operand_subword (op, TARGET_BIG_ENDIAN, 0, mode);
1719
          break;
1720
 
1721
        default:
1722
          gcc_unreachable ();
1723
        }
1724
 
1725
      /* The high part of CR <- GPR moves must be done after the low part.  */
1726
      operands [i + 4] = lo;
1727
      operands [i + 2] = hi;
1728
    }
1729
 
1730
  if (reg_mentioned_p (operands[2], operands[5])
1731
      || GET_CODE (operands[2]) == ZERO_EXTRACT
1732
      || GET_CODE (operands[4]) == ZERO_EXTRACT)
1733
    {
1734
      rtx tmp;
1735
 
1736
      /* Overlapping register pairs -- make sure we don't
1737
         early-clobber ourselves.  */
1738
      tmp = operands[2];
1739
      operands[2] = operands[4];
1740
      operands[4] = tmp;
1741
      tmp = operands[3];
1742
      operands[3] = operands[5];
1743
      operands[5] = tmp;
1744
    }
1745
 
1746
#if DEBUG_SPLIT_WIDE_MOVE
1747
  fprintf(stderr, "\033[34m");
1748
  debug_rtx (operands[2]);
1749
  debug_rtx (operands[3]);
1750
  debug_rtx (operands[4]);
1751
  debug_rtx (operands[5]);
1752
  fprintf(stderr, "\033[0m");
1753
#endif
1754
}
1755
 
1756
/* Emit a setcc instruction in its entirity.  */
1757
 
1758
static bool
1759
mep_expand_setcc_1 (enum rtx_code code, rtx dest, rtx op1, rtx op2)
1760
{
1761
  rtx tmp;
1762
 
1763
  switch (code)
1764
    {
1765
    case GT:
1766
    case GTU:
1767
      tmp = op1, op1 = op2, op2 = tmp;
1768
      code = swap_condition (code);
1769
      /* FALLTHRU */
1770
 
1771
    case LT:
1772
    case LTU:
1773
      op1 = force_reg (SImode, op1);
1774
      emit_insn (gen_rtx_SET (VOIDmode, dest,
1775
                              gen_rtx_fmt_ee (code, SImode, op1, op2)));
1776
      return true;
1777
 
1778
    case EQ:
1779
      if (op2 != const0_rtx)
1780
        op1 = expand_binop (SImode, sub_optab, op1, op2, NULL, 1, OPTAB_WIDEN);
1781
      mep_expand_setcc_1 (LTU, dest, op1, const1_rtx);
1782
      return true;
1783
 
1784
    case NE:
1785
      /* Branchful sequence:
1786
                mov dest, 0             16-bit
1787
                beq op1, op2, Lover     16-bit (op2 < 16), 32-bit otherwise
1788
                mov dest, 1             16-bit
1789
 
1790
         Branchless sequence:
1791
                add3 tmp, op1, -op2     32-bit (or mov + sub)
1792
                sltu3 tmp, tmp, 1       16-bit
1793
                xor3 dest, tmp, 1       32-bit
1794
        */
1795
      if (optimize_size && op2 != const0_rtx)
1796
        return false;
1797
 
1798
      if (op2 != const0_rtx)
1799
        op1 = expand_binop (SImode, sub_optab, op1, op2, NULL, 1, OPTAB_WIDEN);
1800
 
1801
      op2 = gen_reg_rtx (SImode);
1802
      mep_expand_setcc_1 (LTU, op2, op1, const1_rtx);
1803
 
1804
      emit_insn (gen_rtx_SET (VOIDmode, dest,
1805
                              gen_rtx_XOR (SImode, op2, const1_rtx)));
1806
      return true;
1807
 
1808
    case LE:
1809
      if (GET_CODE (op2) != CONST_INT
1810
          || INTVAL (op2) == 0x7ffffff)
1811
        return false;
1812
      op2 = GEN_INT (INTVAL (op2) + 1);
1813
      return mep_expand_setcc_1 (LT, dest, op1, op2);
1814
 
1815
    case LEU:
1816
      if (GET_CODE (op2) != CONST_INT
1817
          || INTVAL (op2) == -1)
1818
        return false;
1819
      op2 = GEN_INT (trunc_int_for_mode (INTVAL (op2) + 1, SImode));
1820
      return mep_expand_setcc_1 (LTU, dest, op1, op2);
1821
 
1822
    case GE:
1823
      if (GET_CODE (op2) != CONST_INT
1824
          || INTVAL (op2) == trunc_int_for_mode (0x80000000, SImode))
1825
        return false;
1826
      op2 = GEN_INT (INTVAL (op2) - 1);
1827
      return mep_expand_setcc_1 (GT, dest, op1, op2);
1828
 
1829
    case GEU:
1830
      if (GET_CODE (op2) != CONST_INT
1831
          || op2 == const0_rtx)
1832
        return false;
1833
      op2 = GEN_INT (trunc_int_for_mode (INTVAL (op2) - 1, SImode));
1834
      return mep_expand_setcc_1 (GTU, dest, op1, op2);
1835
 
1836
    default:
1837
      gcc_unreachable ();
1838
    }
1839
}
1840
 
1841
bool
1842
mep_expand_setcc (rtx *operands)
1843
{
1844
  rtx dest = operands[0];
1845
  enum rtx_code code = GET_CODE (operands[1]);
1846
  rtx op0 = operands[2];
1847
  rtx op1 = operands[3];
1848
 
1849
  return mep_expand_setcc_1 (code, dest, op0, op1);
1850
}
1851
 
1852
rtx
1853
mep_expand_cbranch (rtx *operands)
1854
{
1855
  enum rtx_code code = GET_CODE (operands[0]);
1856
  rtx op0 = operands[1];
1857
  rtx op1 = operands[2];
1858
  rtx tmp;
1859
 
1860
 restart:
1861
  switch (code)
1862
    {
1863
    case LT:
1864
      if (mep_imm4_operand (op1, SImode))
1865
        break;
1866
 
1867
      tmp = gen_reg_rtx (SImode);
1868
      gcc_assert (mep_expand_setcc_1 (LT, tmp, op0, op1));
1869
      code = NE;
1870
      op0 = tmp;
1871
      op1 = const0_rtx;
1872
      break;
1873
 
1874
    case GE:
1875
      if (mep_imm4_operand (op1, SImode))
1876
        break;
1877
 
1878
      tmp = gen_reg_rtx (SImode);
1879
      gcc_assert (mep_expand_setcc_1 (LT, tmp, op0, op1));
1880
 
1881
      code = EQ;
1882
      op0 = tmp;
1883
      op1 = const0_rtx;
1884
      break;
1885
 
1886
    case EQ:
1887
    case NE:
1888
      if (! mep_reg_or_imm4_operand (op1, SImode))
1889
        op1 = force_reg (SImode, op1);
1890
      break;
1891
 
1892
    case LE:
1893
    case GT:
1894
      if (GET_CODE (op1) == CONST_INT
1895
          && INTVAL (op1) != 0x7fffffff)
1896
        {
1897
          op1 = GEN_INT (INTVAL (op1) + 1);
1898
          code = (code == LE ? LT : GE);
1899
          goto restart;
1900
        }
1901
 
1902
      tmp = gen_reg_rtx (SImode);
1903
      gcc_assert (mep_expand_setcc_1 (LT, tmp, op1, op0));
1904
 
1905
      code = (code == LE ? EQ : NE);
1906
      op0 = tmp;
1907
      op1 = const0_rtx;
1908
      break;
1909
 
1910
    case LTU:
1911
      if (op1 == const1_rtx)
1912
        {
1913
          code = EQ;
1914
          op1 = const0_rtx;
1915
          break;
1916
        }
1917
 
1918
      tmp = gen_reg_rtx (SImode);
1919
      gcc_assert (mep_expand_setcc_1 (LTU, tmp, op0, op1));
1920
      code = NE;
1921
      op0 = tmp;
1922
      op1 = const0_rtx;
1923
      break;
1924
 
1925
    case LEU:
1926
      tmp = gen_reg_rtx (SImode);
1927
      if (mep_expand_setcc_1 (LEU, tmp, op0, op1))
1928
        code = NE;
1929
      else if (mep_expand_setcc_1 (LTU, tmp, op1, op0))
1930
        code = EQ;
1931
      else
1932
        gcc_unreachable ();
1933
      op0 = tmp;
1934
      op1 = const0_rtx;
1935
      break;
1936
 
1937
    case GTU:
1938
      tmp = gen_reg_rtx (SImode);
1939
      gcc_assert (mep_expand_setcc_1 (GTU, tmp, op0, op1)
1940
                  || mep_expand_setcc_1 (LTU, tmp, op1, op0));
1941
      code = NE;
1942
      op0 = tmp;
1943
      op1 = const0_rtx;
1944
      break;
1945
 
1946
    case GEU:
1947
      tmp = gen_reg_rtx (SImode);
1948
      if (mep_expand_setcc_1 (GEU, tmp, op0, op1))
1949
        code = NE;
1950
      else if (mep_expand_setcc_1 (LTU, tmp, op0, op1))
1951
        code = EQ;
1952
      else
1953
        gcc_unreachable ();
1954
      op0 = tmp;
1955
      op1 = const0_rtx;
1956
      break;
1957
 
1958
    default:
1959
      gcc_unreachable ();
1960
    }
1961
 
1962
  return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
1963
}
1964
 
1965
const char *
1966
mep_emit_cbranch (rtx *operands, int ne)
1967
{
1968
  if (GET_CODE (operands[1]) == REG)
1969
    return ne ? "bne\t%0, %1, %l2" : "beq\t%0, %1, %l2";
1970
  else if (INTVAL (operands[1]) == 0 && !mep_vliw_function_p(cfun->decl))
1971
    return ne ? "bnez\t%0, %l2" : "beqz\t%0, %l2";
1972
  else
1973
    return ne ? "bnei\t%0, %1, %l2" : "beqi\t%0, %1, %l2";
1974
}
1975
 
1976
void
1977
mep_expand_call (rtx *operands, int returns_value)
1978
{
1979
  rtx addr = operands[returns_value];
1980
  rtx tp = mep_tp_rtx ();
1981
  rtx gp = mep_gp_rtx ();
1982
 
1983
  gcc_assert (GET_CODE (addr) == MEM);
1984
 
1985
  addr = XEXP (addr, 0);
1986
 
1987
  if (! mep_call_address_operand (addr, VOIDmode))
1988
    addr = force_reg (SImode, addr);
1989
 
1990
  if (! operands[returns_value+2])
1991
    operands[returns_value+2] = const0_rtx;
1992
 
1993
  if (returns_value)
1994
    emit_call_insn (gen_call_value_internal (operands[0], addr, operands[2],
1995
                                             operands[3], tp, gp));
1996
  else
1997
    emit_call_insn (gen_call_internal (addr, operands[1],
1998
                                       operands[2], tp, gp));
1999
}
2000
 
2001
/* Aliasing Support.  */
2002
 
2003
/* If X is a machine specific address (i.e. a symbol or label being
2004
   referenced as a displacement from the GOT implemented using an
2005
   UNSPEC), then return the base term.  Otherwise return X.  */
2006
 
2007
rtx
2008
mep_find_base_term (rtx x)
2009
{
2010
  rtx base, term;
2011
  int unspec;
2012
 
2013
  if (GET_CODE (x) != PLUS)
2014
    return x;
2015
  base = XEXP (x, 0);
2016
  term = XEXP (x, 1);
2017
 
2018
  if (has_hard_reg_initial_val(Pmode, TP_REGNO)
2019
      && base == mep_tp_rtx ())
2020
    unspec = UNS_TPREL;
2021
  else if (has_hard_reg_initial_val(Pmode, GP_REGNO)
2022
           && base == mep_gp_rtx ())
2023
    unspec = UNS_GPREL;
2024
  else
2025
    return x;
2026
 
2027
  if (GET_CODE (term) != CONST)
2028
    return x;
2029
  term = XEXP (term, 0);
2030
 
2031
  if (GET_CODE (term) != UNSPEC
2032
      || XINT (term, 1) != unspec)
2033
    return x;
2034
 
2035
  return XVECEXP (term, 0, 0);
2036
}
2037
 
2038
/* Reload Support.  */
2039
 
2040
/* Return true if the registers in CLASS cannot represent the change from
2041
   modes FROM to TO.  */
2042
 
2043
bool
2044
mep_cannot_change_mode_class (enum machine_mode from, enum machine_mode to,
2045
                               enum reg_class regclass)
2046
{
2047
  if (from == to)
2048
    return false;
2049
 
2050
  /* 64-bit COP regs must remain 64-bit COP regs.  */
2051
  if (TARGET_64BIT_CR_REGS
2052
      && (regclass == CR_REGS
2053
          || regclass == LOADABLE_CR_REGS)
2054
      && (GET_MODE_SIZE (to) < 8
2055
          || GET_MODE_SIZE (from) < 8))
2056
    return true;
2057
 
2058
  return false;
2059
}
2060
 
2061
#define MEP_NONGENERAL_CLASS(C) (!reg_class_subset_p (C, GENERAL_REGS))
2062
 
2063
static bool
2064
mep_general_reg (rtx x)
2065
{
2066
  while (GET_CODE (x) == SUBREG)
2067
    x = XEXP (x, 0);
2068
  return GET_CODE (x) == REG && GR_REGNO_P (REGNO (x));
2069
}
2070
 
2071
static bool
2072
mep_nongeneral_reg (rtx x)
2073
{
2074
  while (GET_CODE (x) == SUBREG)
2075
    x = XEXP (x, 0);
2076
  return (GET_CODE (x) == REG
2077
          && !GR_REGNO_P (REGNO (x)) && REGNO (x) < FIRST_PSEUDO_REGISTER);
2078
}
2079
 
2080
static bool
2081
mep_general_copro_reg (rtx x)
2082
{
2083
  while (GET_CODE (x) == SUBREG)
2084
    x = XEXP (x, 0);
2085
  return (GET_CODE (x) == REG && CR_REGNO_P (REGNO (x)));
2086
}
2087
 
2088
static bool
2089
mep_nonregister (rtx x)
2090
{
2091
  while (GET_CODE (x) == SUBREG)
2092
    x = XEXP (x, 0);
2093
  return (GET_CODE (x) != REG || REGNO (x) >= FIRST_PSEUDO_REGISTER);
2094
}
2095
 
2096
#define DEBUG_RELOAD 0
2097
 
2098
/* Return the secondary reload class needed for moving value X to or
2099
   from a register in coprocessor register class CLASS.  */
2100
 
2101
static enum reg_class
2102
mep_secondary_copro_reload_class (enum reg_class rclass, rtx x)
2103
{
2104
  if (mep_general_reg (x))
2105
    /* We can do the move directly if mep_have_core_copro_moves_p,
2106
       otherwise we need to go through memory.  Either way, no secondary
2107
       register is needed.  */
2108
    return NO_REGS;
2109
 
2110
  if (mep_general_copro_reg (x))
2111
    {
2112
      /* We can do the move directly if mep_have_copro_copro_moves_p.  */
2113
      if (mep_have_copro_copro_moves_p)
2114
        return NO_REGS;
2115
 
2116
      /* Otherwise we can use a temporary if mep_have_core_copro_moves_p.  */
2117
      if (mep_have_core_copro_moves_p)
2118
        return GENERAL_REGS;
2119
 
2120
      /* Otherwise we need to do it through memory.  No secondary
2121
         register is needed.  */
2122
      return NO_REGS;
2123
    }
2124
 
2125
  if (reg_class_subset_p (rclass, LOADABLE_CR_REGS)
2126
      && constraint_satisfied_p (x, CONSTRAINT_U))
2127
    /* X is a memory value that we can access directly.  */
2128
    return NO_REGS;
2129
 
2130
  /* We have to move X into a GPR first and then copy it to
2131
     the coprocessor register.  The move from the GPR to the
2132
     coprocessor might be done directly or through memory,
2133
     depending on mep_have_core_copro_moves_p. */
2134
  return GENERAL_REGS;
2135
}
2136
 
2137
/* Copying X to register in RCLASS.  */
2138
 
2139
enum reg_class
2140
mep_secondary_input_reload_class (enum reg_class rclass,
2141
                                  enum machine_mode mode ATTRIBUTE_UNUSED,
2142
                                  rtx x)
2143
{
2144
  int rv = NO_REGS;
2145
 
2146
#if DEBUG_RELOAD
2147
  fprintf (stderr, "secondary input reload copy to %s %s from ", reg_class_names[rclass], mode_name[mode]);
2148
  debug_rtx (x);
2149
#endif
2150
 
2151
  if (reg_class_subset_p (rclass, CR_REGS))
2152
    rv = mep_secondary_copro_reload_class (rclass, x);
2153
  else if (MEP_NONGENERAL_CLASS (rclass)
2154
           && (mep_nonregister (x) || mep_nongeneral_reg (x)))
2155
    rv = GENERAL_REGS;
2156
 
2157
#if DEBUG_RELOAD
2158
  fprintf (stderr, " - requires %s\n", reg_class_names[rv]);
2159
#endif
2160
  return (enum reg_class) rv;
2161
}
2162
 
2163
/* Copying register in RCLASS to X.  */
2164
 
2165
enum reg_class
2166
mep_secondary_output_reload_class (enum reg_class rclass,
2167
                                   enum machine_mode mode ATTRIBUTE_UNUSED,
2168
                                   rtx x)
2169
{
2170
  int rv = NO_REGS;
2171
 
2172
#if DEBUG_RELOAD
2173
  fprintf (stderr, "secondary output reload copy from %s %s to ", reg_class_names[rclass], mode_name[mode]);
2174
  debug_rtx (x);
2175
#endif
2176
 
2177
  if (reg_class_subset_p (rclass, CR_REGS))
2178
    rv = mep_secondary_copro_reload_class (rclass, x);
2179
  else if (MEP_NONGENERAL_CLASS (rclass)
2180
           && (mep_nonregister (x) || mep_nongeneral_reg (x)))
2181
    rv = GENERAL_REGS;
2182
 
2183
#if DEBUG_RELOAD
2184
  fprintf (stderr, " - requires %s\n", reg_class_names[rv]);
2185
#endif
2186
 
2187
  return (enum reg_class) rv;
2188
}
2189
 
2190
/* Implement SECONDARY_MEMORY_NEEDED.  */
2191
 
2192
bool
2193
mep_secondary_memory_needed (enum reg_class rclass1, enum reg_class rclass2,
2194
                             enum machine_mode mode ATTRIBUTE_UNUSED)
2195
{
2196
  if (!mep_have_core_copro_moves_p)
2197
    {
2198
      if (reg_classes_intersect_p (rclass1, CR_REGS)
2199
          && reg_classes_intersect_p (rclass2, GENERAL_REGS))
2200
        return true;
2201
      if (reg_classes_intersect_p (rclass2, CR_REGS)
2202
          && reg_classes_intersect_p (rclass1, GENERAL_REGS))
2203
        return true;
2204
      if (!mep_have_copro_copro_moves_p
2205
          && reg_classes_intersect_p (rclass1, CR_REGS)
2206
          && reg_classes_intersect_p (rclass2, CR_REGS))
2207
        return true;
2208
    }
2209
  return false;
2210
}
2211
 
2212
void
2213
mep_expand_reload (rtx *operands, enum machine_mode mode)
2214
{
2215
  /* There are three cases for each direction:
2216
     register, farsym
2217
     control, farsym
2218
     control, nearsym */
2219
 
2220
  int s0 = mep_section_tag (operands[0]) == 'f';
2221
  int s1 = mep_section_tag (operands[1]) == 'f';
2222
  int c0 = mep_nongeneral_reg (operands[0]);
2223
  int c1 = mep_nongeneral_reg (operands[1]);
2224
  int which = (s0 ? 20:0) + (c0 ? 10:0) + (s1 ? 2:0) + (c1 ? 1:0);
2225
 
2226
#if DEBUG_RELOAD
2227
  fprintf (stderr, "expand_reload %s\n", mode_name[mode]);
2228
  debug_rtx (operands[0]);
2229
  debug_rtx (operands[1]);
2230
#endif
2231
 
2232
  switch (which)
2233
    {
2234
    case 00: /* Don't know why this gets here.  */
2235
    case 02: /* general = far */
2236
      emit_move_insn (operands[0], operands[1]);
2237
      return;
2238
 
2239
    case 10: /* cr = mem */
2240
    case 11: /* cr = cr */
2241
    case 01: /* mem = cr */
2242
    case 12: /* cr = far */
2243
      emit_move_insn (operands[2], operands[1]);
2244
      emit_move_insn (operands[0], operands[2]);
2245
      return;
2246
 
2247
    case 20: /* far = general */
2248
      emit_move_insn (operands[2], XEXP (operands[1], 0));
2249
      emit_move_insn (operands[0], gen_rtx_MEM (mode, operands[2]));
2250
      return;
2251
 
2252
    case 21: /* far = cr */
2253
    case 22: /* far = far */
2254
    default:
2255
      fprintf (stderr, "unsupported expand reload case %02d for mode %s\n",
2256
               which, mode_name[mode]);
2257
      debug_rtx (operands[0]);
2258
      debug_rtx (operands[1]);
2259
      gcc_unreachable ();
2260
    }
2261
}
2262
 
2263
/* Implement PREFERRED_RELOAD_CLASS.  See whether X is a constant that
2264
   can be moved directly into registers 0 to 7, but not into the rest.
2265
   If so, and if the required class includes registers 0 to 7, restrict
2266
   it to those registers.  */
2267
 
2268
enum reg_class
2269
mep_preferred_reload_class (rtx x, enum reg_class rclass)
2270
{
2271
  switch (GET_CODE (x))
2272
    {
2273
    case CONST_INT:
2274
      if (INTVAL (x) >= 0x10000
2275
          && INTVAL (x) < 0x01000000
2276
          && (INTVAL (x) & 0xffff) != 0
2277
          && reg_class_subset_p (TPREL_REGS, rclass))
2278
        rclass = TPREL_REGS;
2279
      break;
2280
 
2281
    case CONST:
2282
    case SYMBOL_REF:
2283
    case LABEL_REF:
2284
      if (mep_section_tag (x) != 'f'
2285
          && reg_class_subset_p (TPREL_REGS, rclass))
2286
        rclass = TPREL_REGS;
2287
      break;
2288
 
2289
    default:
2290
      break;
2291
    }
2292
  return rclass;
2293
}
2294
 
2295
/* Implement REGISTER_MOVE_COST.  Return 2 for direct single-register
2296
   moves, 4 for direct double-register moves, and 1000 for anything
2297
   that requires a temporary register or temporary stack slot.  */
2298
 
2299
int
2300
mep_register_move_cost (enum machine_mode mode, enum reg_class from, enum reg_class to)
2301
{
2302
  if (mep_have_copro_copro_moves_p
2303
      && reg_class_subset_p (from, CR_REGS)
2304
      && reg_class_subset_p (to, CR_REGS))
2305
    {
2306
      if (TARGET_32BIT_CR_REGS && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
2307
        return 4;
2308
      return 2;
2309
    }
2310
  if (reg_class_subset_p (from, CR_REGS)
2311
      && reg_class_subset_p (to, CR_REGS))
2312
    {
2313
      if (TARGET_32BIT_CR_REGS && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
2314
        return 8;
2315
      return 4;
2316
    }
2317
  if (reg_class_subset_p (from, CR_REGS)
2318
      || reg_class_subset_p (to, CR_REGS))
2319
    {
2320
      if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
2321
        return 4;
2322
      return 2;
2323
    }
2324
  if (mep_secondary_memory_needed (from, to, mode))
2325
    return 1000;
2326
  if (MEP_NONGENERAL_CLASS (from) && MEP_NONGENERAL_CLASS (to))
2327
    return 1000;
2328
 
2329
  if (GET_MODE_SIZE (mode) > 4)
2330
    return 4;
2331
 
2332
  return 2;
2333
}
2334
 
2335
 
2336
/* Functions to save and restore machine-specific function data.  */
2337
 
2338
static struct machine_function *
2339
mep_init_machine_status (void)
2340
{
2341
  return ggc_alloc_cleared_machine_function ();
2342
}
2343
 
2344
static rtx
2345
mep_allocate_initial_value (rtx reg)
2346
{
2347
  int rss;
2348
 
2349
  if (GET_CODE (reg) != REG)
2350
    return NULL_RTX;
2351
 
2352
  if (REGNO (reg) >= FIRST_PSEUDO_REGISTER)
2353
    return NULL_RTX;
2354
 
2355
  /* In interrupt functions, the "initial" values of $gp and $tp are
2356
     provided by the prologue.  They are not necessarily the same as
2357
     the values that the caller was using.  */
2358
  if (REGNO (reg) == TP_REGNO || REGNO (reg) == GP_REGNO)
2359
    if (mep_interrupt_p ())
2360
      return NULL_RTX;
2361
 
2362
  if (! cfun->machine->reg_save_slot[REGNO(reg)])
2363
    {
2364
      cfun->machine->reg_save_size += 4;
2365
      cfun->machine->reg_save_slot[REGNO(reg)] = cfun->machine->reg_save_size;
2366
    }
2367
 
2368
  rss = cfun->machine->reg_save_slot[REGNO(reg)];
2369
  return gen_rtx_MEM (SImode, plus_constant (arg_pointer_rtx, -rss));
2370
}
2371
 
2372
rtx
2373
mep_return_addr_rtx (int count)
2374
{
2375
  if (count != 0)
2376
    return const0_rtx;
2377
 
2378
  return get_hard_reg_initial_val (Pmode, LP_REGNO);
2379
}
2380
 
2381
static rtx
2382
mep_tp_rtx (void)
2383
{
2384
  return get_hard_reg_initial_val (Pmode, TP_REGNO);
2385
}
2386
 
2387
static rtx
2388
mep_gp_rtx (void)
2389
{
2390
  return get_hard_reg_initial_val (Pmode, GP_REGNO);
2391
}
2392
 
2393
static bool
2394
mep_interrupt_p (void)
2395
{
2396
  if (cfun->machine->interrupt_handler == 0)
2397
    {
2398
      int interrupt_handler
2399
        = (lookup_attribute ("interrupt",
2400
                             DECL_ATTRIBUTES (current_function_decl))
2401
           != NULL_TREE);
2402
      cfun->machine->interrupt_handler = interrupt_handler ? 2 : 1;
2403
    }
2404
  return cfun->machine->interrupt_handler == 2;
2405
}
2406
 
2407
static bool
2408
mep_disinterrupt_p (void)
2409
{
2410
  if (cfun->machine->disable_interrupts == 0)
2411
    {
2412
      int disable_interrupts
2413
        = (lookup_attribute ("disinterrupt",
2414
                             DECL_ATTRIBUTES (current_function_decl))
2415
           != NULL_TREE);
2416
      cfun->machine->disable_interrupts = disable_interrupts ? 2 : 1;
2417
    }
2418
  return cfun->machine->disable_interrupts == 2;
2419
}
2420
 
2421
 
2422
/* Frame/Epilog/Prolog Related.  */
2423
 
2424
static bool
2425
mep_reg_set_p (rtx reg, rtx insn)
2426
{
2427
  /* Similar to reg_set_p in rtlanal.c, but we ignore calls */
2428
  if (INSN_P (insn))
2429
    {
2430
      if (FIND_REG_INC_NOTE (insn, reg))
2431
        return true;
2432
      insn = PATTERN (insn);
2433
    }
2434
 
2435
  if (GET_CODE (insn) == SET
2436
      && GET_CODE (XEXP (insn, 0)) == REG
2437
      && GET_CODE (XEXP (insn, 1)) == REG
2438
      && REGNO (XEXP (insn, 0)) == REGNO (XEXP (insn, 1)))
2439
    return false;
2440
 
2441
  return set_of (reg, insn) != NULL_RTX;
2442
}
2443
 
2444
 
2445
#define MEP_SAVES_UNKNOWN 0
2446
#define MEP_SAVES_YES 1
2447
#define MEP_SAVES_MAYBE 2
2448
#define MEP_SAVES_NO 3
2449
 
2450
static bool
2451
mep_reg_set_in_function (int regno)
2452
{
2453
  rtx reg, insn;
2454
 
2455
  if (mep_interrupt_p () && df_regs_ever_live_p(regno))
2456
    return true;
2457
 
2458
  if (regno == LP_REGNO && (profile_arc_flag > 0 || profile_flag > 0))
2459
    return true;
2460
 
2461
  push_topmost_sequence ();
2462
  insn = get_insns ();
2463
  pop_topmost_sequence ();
2464
 
2465
  if (!insn)
2466
    return false;
2467
 
2468
  reg = gen_rtx_REG (SImode, regno);
2469
 
2470
  for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn))
2471
    if (INSN_P (insn) && mep_reg_set_p (reg, insn))
2472
      return true;
2473
  return false;
2474
}
2475
 
2476
static bool
2477
mep_asm_without_operands_p (void)
2478
{
2479
  if (cfun->machine->asms_without_operands == 0)
2480
    {
2481
      rtx insn;
2482
 
2483
      push_topmost_sequence ();
2484
      insn = get_insns ();
2485
      pop_topmost_sequence ();
2486
 
2487
      cfun->machine->asms_without_operands = 1;
2488
      while (insn)
2489
        {
2490
          if (INSN_P (insn)
2491
              && GET_CODE (PATTERN (insn)) == ASM_INPUT)
2492
            {
2493
              cfun->machine->asms_without_operands = 2;
2494
              break;
2495
            }
2496
          insn = NEXT_INSN (insn);
2497
        }
2498
 
2499
    }
2500
  return cfun->machine->asms_without_operands == 2;
2501
}
2502
 
2503
/* Interrupt functions save/restore every call-preserved register, and
2504
   any call-used register it uses (or all if it calls any function,
2505
   since they may get clobbered there too).  Here we check to see
2506
   which call-used registers need saving.  */
2507
 
2508
#define IVC2_ISAVED_REG(r) (TARGET_IVC2 \
2509
                           && (r == FIRST_CCR_REGNO + 1 \
2510
                               || (r >= FIRST_CCR_REGNO + 8 && r <= FIRST_CCR_REGNO + 11) \
2511
                               || (r >= FIRST_CCR_REGNO + 16 && r <= FIRST_CCR_REGNO + 31)))
2512
 
2513
static bool
2514
mep_interrupt_saved_reg (int r)
2515
{
2516
  if (!mep_interrupt_p ())
2517
    return false;
2518
  if (r == REGSAVE_CONTROL_TEMP
2519
      || (TARGET_64BIT_CR_REGS && TARGET_COP && r == REGSAVE_CONTROL_TEMP+1))
2520
    return true;
2521
  if (mep_asm_without_operands_p ()
2522
      && (!fixed_regs[r]
2523
          || (r == RPB_REGNO || r == RPE_REGNO || r == RPC_REGNO || r == LP_REGNO)
2524
          || IVC2_ISAVED_REG (r)))
2525
    return true;
2526
  if (!current_function_is_leaf)
2527
    /* Function calls mean we need to save $lp.  */
2528
    if (r == LP_REGNO || IVC2_ISAVED_REG (r))
2529
      return true;
2530
  if (!current_function_is_leaf || cfun->machine->doloop_tags > 0)
2531
    /* The interrupt handler might use these registers for repeat blocks,
2532
       or it might call a function that does so.  */
2533
    if (r == RPB_REGNO || r == RPE_REGNO || r == RPC_REGNO)
2534
      return true;
2535
  if (current_function_is_leaf && call_used_regs[r] && !df_regs_ever_live_p(r))
2536
    return false;
2537
  /* Functions we call might clobber these.  */
2538
  if (call_used_regs[r] && !fixed_regs[r])
2539
    return true;
2540
  /* Additional registers that need to be saved for IVC2.  */
2541
  if (IVC2_ISAVED_REG (r))
2542
    return true;
2543
 
2544
  return false;
2545
}
2546
 
2547
static bool
2548
mep_call_saves_register (int r)
2549
{
2550
  if (! cfun->machine->frame_locked)
2551
    {
2552
      int rv = MEP_SAVES_NO;
2553
 
2554
      if (cfun->machine->reg_save_slot[r])
2555
        rv = MEP_SAVES_YES;
2556
      else if (r == LP_REGNO && (profile_arc_flag > 0 || profile_flag > 0))
2557
        rv = MEP_SAVES_YES;
2558
      else if (r == FRAME_POINTER_REGNUM && frame_pointer_needed)
2559
        rv = MEP_SAVES_YES;
2560
      else if ((!call_used_regs[r] || r == LP_REGNO) && df_regs_ever_live_p(r))
2561
        rv = MEP_SAVES_YES;
2562
      else if (crtl->calls_eh_return && (r == 10 || r == 11))
2563
        /* We need these to have stack slots so that they can be set during
2564
           unwinding.  */
2565
        rv = MEP_SAVES_YES;
2566
      else if (mep_interrupt_saved_reg (r))
2567
        rv = MEP_SAVES_YES;
2568
      cfun->machine->reg_saved[r] = rv;
2569
    }
2570
  return cfun->machine->reg_saved[r] == MEP_SAVES_YES;
2571
}
2572
 
2573
/* Return true if epilogue uses register REGNO.  */
2574
 
2575
bool
2576
mep_epilogue_uses (int regno)
2577
{
2578
  /* Since $lp is a call-saved register, the generic code will normally
2579
     mark it used in the epilogue if it needs to be saved and restored.
2580
     However, when profiling is enabled, the profiling code will implicitly
2581
     clobber $11.  This case has to be handled specially both here and in
2582
     mep_call_saves_register.  */
2583
  if (regno == LP_REGNO && (profile_arc_flag > 0 || profile_flag > 0))
2584
    return true;
2585
  /* Interrupt functions save/restore pretty much everything.  */
2586
  return (reload_completed && mep_interrupt_saved_reg (regno));
2587
}
2588
 
2589
static int
2590
mep_reg_size (int regno)
2591
{
2592
  if (CR_REGNO_P (regno) && TARGET_64BIT_CR_REGS)
2593
    return 8;
2594
  return 4;
2595
}
2596
 
2597
/* Worker function for TARGET_CAN_ELIMINATE.  */
2598
 
2599
bool
2600
mep_can_eliminate (const int from, const int to)
2601
{
2602
  return  (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM
2603
           ? ! frame_pointer_needed
2604
           : true);
2605
}
2606
 
2607
int
2608
mep_elimination_offset (int from, int to)
2609
{
2610
  int reg_save_size;
2611
  int i;
2612
  int frame_size = get_frame_size () + crtl->outgoing_args_size;
2613
  int total_size;
2614
 
2615
  if (!cfun->machine->frame_locked)
2616
    memset (cfun->machine->reg_saved, 0, sizeof (cfun->machine->reg_saved));
2617
 
2618
  /* We don't count arg_regs_to_save in the arg pointer offset, because
2619
     gcc thinks the arg pointer has moved along with the saved regs.
2620
     However, we do count it when we adjust $sp in the prologue.  */
2621
  reg_save_size = 0;
2622
  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2623
    if (mep_call_saves_register (i))
2624
      reg_save_size += mep_reg_size (i);
2625
 
2626
  if (reg_save_size % 8)
2627
    cfun->machine->regsave_filler = 8 - (reg_save_size % 8);
2628
  else
2629
    cfun->machine->regsave_filler = 0;
2630
 
2631
  /* This is what our total stack adjustment looks like.  */
2632
  total_size = (reg_save_size + frame_size + cfun->machine->regsave_filler);
2633
 
2634
  if (total_size % 8)
2635
    cfun->machine->frame_filler = 8 - (total_size % 8);
2636
  else
2637
    cfun->machine->frame_filler = 0;
2638
 
2639
 
2640
  if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
2641
    return reg_save_size + cfun->machine->regsave_filler;
2642
 
2643
  if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
2644
    return cfun->machine->frame_filler + frame_size;
2645
 
2646
  if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
2647
    return reg_save_size + cfun->machine->regsave_filler + cfun->machine->frame_filler + frame_size;
2648
 
2649
  gcc_unreachable ();
2650
}
2651
 
2652
static rtx
2653
F (rtx x)
2654
{
2655
  RTX_FRAME_RELATED_P (x) = 1;
2656
  return x;
2657
}
2658
 
2659
/* Since the prologue/epilogue code is generated after optimization,
2660
   we can't rely on gcc to split constants for us.  So, this code
2661
   captures all the ways to add a constant to a register in one logic
2662
   chunk, including optimizing away insns we just don't need.  This
2663
   makes the prolog/epilog code easier to follow.  */
2664
static void
2665
add_constant (int dest, int src, int value, int mark_frame)
2666
{
2667
  rtx insn;
2668
  int hi, lo;
2669
 
2670
  if (src == dest && value == 0)
2671
    return;
2672
 
2673
  if (value == 0)
2674
    {
2675
      insn = emit_move_insn (gen_rtx_REG (SImode, dest),
2676
                             gen_rtx_REG (SImode, src));
2677
      if (mark_frame)
2678
        RTX_FRAME_RELATED_P(insn) = 1;
2679
      return;
2680
    }
2681
 
2682
  if (value >= -32768 && value <= 32767)
2683
    {
2684
      insn = emit_insn (gen_addsi3 (gen_rtx_REG (SImode, dest),
2685
                                    gen_rtx_REG (SImode, src),
2686
                                    GEN_INT (value)));
2687
      if (mark_frame)
2688
        RTX_FRAME_RELATED_P(insn) = 1;
2689
      return;
2690
    }
2691
 
2692
  /* Big constant, need to use a temp register.  We use
2693
     REGSAVE_CONTROL_TEMP because it's call clobberable (the reg save
2694
     area is always small enough to directly add to).  */
2695
 
2696
  hi = trunc_int_for_mode (value & 0xffff0000, SImode);
2697
  lo = value & 0xffff;
2698
 
2699
  insn = emit_move_insn (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2700
                         GEN_INT (hi));
2701
 
2702
  if (lo)
2703
    {
2704
      insn = emit_insn (gen_iorsi3 (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2705
                                    gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2706
                                    GEN_INT (lo)));
2707
    }
2708
 
2709
  insn = emit_insn (gen_addsi3 (gen_rtx_REG (SImode, dest),
2710
                                gen_rtx_REG (SImode, src),
2711
                                gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP)));
2712
  if (mark_frame)
2713
    {
2714
      RTX_FRAME_RELATED_P(insn) = 1;
2715
      add_reg_note (insn, REG_FRAME_RELATED_EXPR,
2716
                    gen_rtx_SET (SImode,
2717
                                 gen_rtx_REG (SImode, dest),
2718
                                 gen_rtx_PLUS (SImode,
2719
                                               gen_rtx_REG (SImode, dest),
2720
                                               GEN_INT (value))));
2721
    }
2722
}
2723
 
2724
/* Move SRC to DEST.  Mark the move as being potentially dead if
2725
   MAYBE_DEAD_P.  */
2726
 
2727
static rtx
2728
maybe_dead_move (rtx dest, rtx src, bool ATTRIBUTE_UNUSED maybe_dead_p)
2729
{
2730
  rtx insn = emit_move_insn (dest, src);
2731
#if 0
2732
  if (maybe_dead_p)
2733
    REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL);
2734
#endif
2735
  return insn;
2736
}
2737
 
2738
/* Used for interrupt functions, which can't assume that $tp and $gp
2739
   contain the correct pointers.  */
2740
 
2741
static void
2742
mep_reload_pointer (int regno, const char *symbol)
2743
{
2744
  rtx reg, sym;
2745
 
2746
  if (!df_regs_ever_live_p(regno) && current_function_is_leaf)
2747
    return;
2748
 
2749
  reg = gen_rtx_REG (SImode, regno);
2750
  sym = gen_rtx_SYMBOL_REF (SImode, symbol);
2751
  emit_insn (gen_movsi_topsym_s (reg, sym));
2752
  emit_insn (gen_movsi_botsym_s (reg, reg, sym));
2753
}
2754
 
2755
/* Assign save slots for any register not already saved.  DImode
2756
   registers go at the end of the reg save area; the rest go at the
2757
   beginning.  This is for alignment purposes.  Returns true if a frame
2758
   is really needed.  */
2759
static bool
2760
mep_assign_save_slots (int reg_save_size)
2761
{
2762
  bool really_need_stack_frame = false;
2763
  int di_ofs = 0;
2764
  int i;
2765
 
2766
  for (i=0; i<FIRST_PSEUDO_REGISTER; i++)
2767
    if (mep_call_saves_register(i))
2768
      {
2769
        int regsize = mep_reg_size (i);
2770
 
2771
        if ((i != TP_REGNO && i != GP_REGNO && i != LP_REGNO)
2772
            || mep_reg_set_in_function (i))
2773
          really_need_stack_frame = true;
2774
 
2775
        if (cfun->machine->reg_save_slot[i])
2776
          continue;
2777
 
2778
        if (regsize < 8)
2779
          {
2780
            cfun->machine->reg_save_size += regsize;
2781
            cfun->machine->reg_save_slot[i] = cfun->machine->reg_save_size;
2782
          }
2783
        else
2784
          {
2785
            cfun->machine->reg_save_slot[i] = reg_save_size - di_ofs;
2786
            di_ofs += 8;
2787
          }
2788
      }
2789
  cfun->machine->frame_locked = 1;
2790
  return really_need_stack_frame;
2791
}
2792
 
2793
void
2794
mep_expand_prologue (void)
2795
{
2796
  int i, rss, sp_offset = 0;
2797
  int reg_save_size;
2798
  int frame_size;
2799
  int really_need_stack_frame;
2800
 
2801
  /* We must not allow register renaming in interrupt functions,
2802
     because that invalidates the correctness of the set of call-used
2803
     registers we're going to save/restore.  */
2804
  mep_set_leaf_registers (mep_interrupt_p () ? 0 : 1);
2805
 
2806
  if (mep_disinterrupt_p ())
2807
    emit_insn (gen_mep_disable_int ());
2808
 
2809
  cfun->machine->mep_frame_pointer_needed = frame_pointer_needed;
2810
 
2811
  reg_save_size = mep_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM);
2812
  frame_size = mep_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM);
2813
  really_need_stack_frame = frame_size;
2814
 
2815
  really_need_stack_frame |= mep_assign_save_slots (reg_save_size);
2816
 
2817
  sp_offset = reg_save_size;
2818
  if (sp_offset + frame_size < 128)
2819
    sp_offset += frame_size ;
2820
 
2821
  add_constant (SP_REGNO, SP_REGNO, -sp_offset, 1);
2822
 
2823
  for (i=0; i<FIRST_PSEUDO_REGISTER; i++)
2824
    if (mep_call_saves_register(i))
2825
      {
2826
        rtx mem;
2827
        bool maybe_dead_p;
2828
        enum machine_mode rmode;
2829
 
2830
        rss = cfun->machine->reg_save_slot[i];
2831
 
2832
        if ((i == TP_REGNO || i == GP_REGNO || i == LP_REGNO)
2833
            && (!mep_reg_set_in_function (i)
2834
                && !mep_interrupt_p ()))
2835
          continue;
2836
 
2837
        if (mep_reg_size (i) == 8)
2838
          rmode = DImode;
2839
        else
2840
          rmode = SImode;
2841
 
2842
        /* If there is a pseudo associated with this register's initial value,
2843
           reload might have already spilt it to the stack slot suggested by
2844
           ALLOCATE_INITIAL_VALUE.  The moves emitted here can then be safely
2845
           deleted as dead.  */
2846
        mem = gen_rtx_MEM (rmode,
2847
                           plus_constant (stack_pointer_rtx, sp_offset - rss));
2848
        maybe_dead_p = rtx_equal_p (mem, has_hard_reg_initial_val (rmode, i));
2849
 
2850
        if (GR_REGNO_P (i) || LOADABLE_CR_REGNO_P (i))
2851
          F(maybe_dead_move (mem, gen_rtx_REG (rmode, i), maybe_dead_p));
2852
        else if (rmode == DImode)
2853
          {
2854
            rtx insn;
2855
            int be = TARGET_BIG_ENDIAN ? 4 : 0;
2856
 
2857
            mem = gen_rtx_MEM (SImode,
2858
                               plus_constant (stack_pointer_rtx, sp_offset - rss + be));
2859
 
2860
            maybe_dead_move (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2861
                             gen_rtx_REG (SImode, i),
2862
                             maybe_dead_p);
2863
            maybe_dead_move (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP+1),
2864
                             gen_rtx_ZERO_EXTRACT (SImode,
2865
                                                   gen_rtx_REG (DImode, i),
2866
                                                   GEN_INT (32),
2867
                                                   GEN_INT (32)),
2868
                             maybe_dead_p);
2869
            insn = maybe_dead_move (mem,
2870
                                    gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2871
                                    maybe_dead_p);
2872
            RTX_FRAME_RELATED_P (insn) = 1;
2873
 
2874
            add_reg_note (insn, REG_FRAME_RELATED_EXPR,
2875
                          gen_rtx_SET (VOIDmode,
2876
                                       copy_rtx (mem),
2877
                                       gen_rtx_REG (rmode, i)));
2878
            mem = gen_rtx_MEM (SImode,
2879
                               plus_constant (stack_pointer_rtx, sp_offset - rss + (4-be)));
2880
            insn = maybe_dead_move (mem,
2881
                                    gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP+1),
2882
                                    maybe_dead_p);
2883
          }
2884
        else
2885
          {
2886
            rtx insn;
2887
            maybe_dead_move (gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP),
2888
                             gen_rtx_REG (rmode, i),
2889
                             maybe_dead_p);
2890
            insn = maybe_dead_move (mem,
2891
                                    gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP),
2892
                                    maybe_dead_p);
2893
            RTX_FRAME_RELATED_P (insn) = 1;
2894
 
2895
            add_reg_note (insn, REG_FRAME_RELATED_EXPR,
2896
                          gen_rtx_SET (VOIDmode,
2897
                                       copy_rtx (mem),
2898
                                       gen_rtx_REG (rmode, i)));
2899
          }
2900
      }
2901
 
2902
  if (frame_pointer_needed)
2903
    {
2904
      /* We've already adjusted down by sp_offset.  Total $sp change
2905
         is reg_save_size + frame_size.  We want a net change here of
2906
         just reg_save_size.  */
2907
      add_constant (FP_REGNO, SP_REGNO, sp_offset - reg_save_size, 1);
2908
    }
2909
 
2910
  add_constant (SP_REGNO, SP_REGNO, sp_offset-(reg_save_size+frame_size), 1);
2911
 
2912
  if (mep_interrupt_p ())
2913
    {
2914
      mep_reload_pointer(GP_REGNO, "__sdabase");
2915
      mep_reload_pointer(TP_REGNO, "__tpbase");
2916
    }
2917
}
2918
 
2919
static void
2920
mep_start_function (FILE *file, HOST_WIDE_INT hwi_local)
2921
{
2922
  int local = hwi_local;
2923
  int frame_size = local + crtl->outgoing_args_size;
2924
  int reg_save_size;
2925
  int ffill;
2926
  int i, sp, skip;
2927
  int sp_offset;
2928
  int slot_map[FIRST_PSEUDO_REGISTER], si, sj;
2929
 
2930
  reg_save_size = mep_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM);
2931
  frame_size = mep_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM);
2932
  sp_offset = reg_save_size + frame_size;
2933
 
2934
  ffill = cfun->machine->frame_filler;
2935
 
2936
  if (cfun->machine->mep_frame_pointer_needed)
2937
    reg_names[FP_REGNO] = "$fp";
2938
  else
2939
    reg_names[FP_REGNO] = "$8";
2940
 
2941
  if (sp_offset == 0)
2942
    return;
2943
 
2944
  if (debug_info_level == DINFO_LEVEL_NONE)
2945
    {
2946
      fprintf (file, "\t# frame: %d", sp_offset);
2947
      if (reg_save_size)
2948
        fprintf (file, "   %d regs", reg_save_size);
2949
      if (local)
2950
        fprintf (file, "   %d locals", local);
2951
      if (crtl->outgoing_args_size)
2952
        fprintf (file, "   %d args", crtl->outgoing_args_size);
2953
      fprintf (file, "\n");
2954
      return;
2955
    }
2956
 
2957
  fprintf (file, "\t#\n");
2958
  fprintf (file, "\t# Initial Frame Information:\n");
2959
  if (sp_offset || !frame_pointer_needed)
2960
    fprintf (file, "\t# Entry   ---------- 0\n");
2961
 
2962
  /* Sort registers by save slots, so they're printed in the order
2963
     they appear in memory, not the order they're saved in.  */
2964
  for (si=0; si<FIRST_PSEUDO_REGISTER; si++)
2965
    slot_map[si] = si;
2966
  for (si=0; si<FIRST_PSEUDO_REGISTER-1; si++)
2967
    for (sj=si+1; sj<FIRST_PSEUDO_REGISTER; sj++)
2968
      if (cfun->machine->reg_save_slot[slot_map[si]]
2969
          > cfun->machine->reg_save_slot[slot_map[sj]])
2970
        {
2971
          int t = slot_map[si];
2972
          slot_map[si] = slot_map[sj];
2973
          slot_map[sj] = t;
2974
        }
2975
 
2976
  sp = 0;
2977
  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2978
    {
2979
      int rsize;
2980
      int r = slot_map[i];
2981
      int rss = cfun->machine->reg_save_slot[r];
2982
 
2983
      if (!mep_call_saves_register (r))
2984
        continue;
2985
 
2986
      if ((r == TP_REGNO || r == GP_REGNO || r == LP_REGNO)
2987
          && (!mep_reg_set_in_function (r)
2988
              && !mep_interrupt_p ()))
2989
        continue;
2990
 
2991
      rsize = mep_reg_size(r);
2992
      skip = rss - (sp+rsize);
2993
      if (skip)
2994
        fprintf (file, "\t#         %3d bytes for alignment\n", skip);
2995
      fprintf (file, "\t#         %3d bytes for saved %-3s   %3d($sp)\n",
2996
               rsize, reg_names[r], sp_offset - rss);
2997
      sp = rss;
2998
    }
2999
 
3000
  skip = reg_save_size - sp;
3001
  if (skip)
3002
    fprintf (file, "\t#         %3d bytes for alignment\n", skip);
3003
 
3004
  if (frame_pointer_needed)
3005
    fprintf (file, "\t# FP ---> ---------- %d (sp-%d)\n", reg_save_size, sp_offset-reg_save_size);
3006
  if (local)
3007
    fprintf (file, "\t#         %3d bytes for local vars\n", local);
3008
  if (ffill)
3009
    fprintf (file, "\t#         %3d bytes for alignment\n", ffill);
3010
  if (crtl->outgoing_args_size)
3011
    fprintf (file, "\t#         %3d bytes for outgoing args\n",
3012
             crtl->outgoing_args_size);
3013
  fprintf (file, "\t# SP ---> ---------- %d\n", sp_offset);
3014
  fprintf (file, "\t#\n");
3015
}
3016
 
3017
 
3018
static int mep_prevent_lp_restore = 0;
3019
static int mep_sibcall_epilogue = 0;
3020
 
3021
void
3022
mep_expand_epilogue (void)
3023
{
3024
  int i, sp_offset = 0;
3025
  int reg_save_size = 0;
3026
  int frame_size;
3027
  int lp_temp = LP_REGNO, lp_slot = -1;
3028
  int really_need_stack_frame = get_frame_size() + crtl->outgoing_args_size;
3029
  int interrupt_handler = mep_interrupt_p ();
3030
 
3031
  if (profile_arc_flag == 2)
3032
    emit_insn (gen_mep_bb_trace_ret ());
3033
 
3034
  reg_save_size = mep_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM);
3035
  frame_size = mep_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM);
3036
 
3037
  really_need_stack_frame |= mep_assign_save_slots (reg_save_size);
3038
 
3039
  if (frame_pointer_needed)
3040
    {
3041
      /* If we have a frame pointer, we won't have a reliable stack
3042
         pointer (alloca, you know), so rebase SP from FP */
3043
      emit_move_insn (gen_rtx_REG (SImode, SP_REGNO),
3044
                      gen_rtx_REG (SImode, FP_REGNO));
3045
      sp_offset = reg_save_size;
3046
    }
3047
  else
3048
    {
3049
      /* SP is right under our local variable space.  Adjust it if
3050
         needed.  */
3051
      sp_offset = reg_save_size + frame_size;
3052
      if (sp_offset >= 128)
3053
        {
3054
          add_constant (SP_REGNO, SP_REGNO, frame_size, 0);
3055
          sp_offset -= frame_size;
3056
        }
3057
    }
3058
 
3059
  /* This is backwards so that we restore the control and coprocessor
3060
     registers before the temporary registers we use to restore
3061
     them.  */
3062
  for (i=FIRST_PSEUDO_REGISTER-1; i>=1; i--)
3063
    if (mep_call_saves_register (i))
3064
      {
3065
        enum machine_mode rmode;
3066
        int rss = cfun->machine->reg_save_slot[i];
3067
 
3068
        if (mep_reg_size (i) == 8)
3069
          rmode = DImode;
3070
        else
3071
          rmode = SImode;
3072
 
3073
        if ((i == TP_REGNO || i == GP_REGNO || i == LP_REGNO)
3074
            && !(mep_reg_set_in_function (i) || interrupt_handler))
3075
          continue;
3076
        if (mep_prevent_lp_restore && i == LP_REGNO)
3077
          continue;
3078
        if (!mep_prevent_lp_restore
3079
            && !interrupt_handler
3080
            && (i == 10 || i == 11))
3081
          continue;
3082
 
3083
        if (GR_REGNO_P (i) || LOADABLE_CR_REGNO_P (i))
3084
          emit_move_insn (gen_rtx_REG (rmode, i),
3085
                          gen_rtx_MEM (rmode,
3086
                                       plus_constant (stack_pointer_rtx,
3087
                                                      sp_offset-rss)));
3088
        else
3089
          {
3090
            if (i == LP_REGNO && !mep_sibcall_epilogue && !interrupt_handler)
3091
              /* Defer this one so we can jump indirect rather than
3092
                 copying the RA to $lp and "ret".  EH epilogues
3093
                 automatically skip this anyway.  */
3094
              lp_slot = sp_offset-rss;
3095
            else
3096
              {
3097
                emit_move_insn (gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP),
3098
                                gen_rtx_MEM (rmode,
3099
                                             plus_constant (stack_pointer_rtx,
3100
                                                            sp_offset-rss)));
3101
                emit_move_insn (gen_rtx_REG (rmode, i),
3102
                                gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP));
3103
              }
3104
          }
3105
      }
3106
  if (lp_slot != -1)
3107
    {
3108
      /* Restore this one last so we know it will be in the temp
3109
         register when we return by jumping indirectly via the temp.  */
3110
      emit_move_insn (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
3111
                      gen_rtx_MEM (SImode,
3112
                                   plus_constant (stack_pointer_rtx,
3113
                                                  lp_slot)));
3114
      lp_temp = REGSAVE_CONTROL_TEMP;
3115
    }
3116
 
3117
 
3118
  add_constant (SP_REGNO, SP_REGNO, sp_offset, 0);
3119
 
3120
  if (crtl->calls_eh_return && mep_prevent_lp_restore)
3121
    emit_insn (gen_addsi3 (gen_rtx_REG (SImode, SP_REGNO),
3122
                           gen_rtx_REG (SImode, SP_REGNO),
3123
                           cfun->machine->eh_stack_adjust));
3124
 
3125
  if (mep_sibcall_epilogue)
3126
    return;
3127
 
3128
  if (mep_disinterrupt_p ())
3129
    emit_insn (gen_mep_enable_int ());
3130
 
3131
  if (mep_prevent_lp_restore)
3132
    {
3133
      emit_jump_insn (gen_eh_return_internal ());
3134
      emit_barrier ();
3135
    }
3136
  else if (interrupt_handler)
3137
    emit_jump_insn (gen_mep_reti ());
3138
  else
3139
    emit_jump_insn (gen_return_internal (gen_rtx_REG (SImode, lp_temp)));
3140
}
3141
 
3142
void
3143
mep_expand_eh_return (rtx *operands)
3144
{
3145
  if (GET_CODE (operands[0]) != REG || REGNO (operands[0]) != LP_REGNO)
3146
    {
3147
      rtx ra = gen_rtx_REG (Pmode, LP_REGNO);
3148
      emit_move_insn (ra, operands[0]);
3149
      operands[0] = ra;
3150
    }
3151
 
3152
  emit_insn (gen_eh_epilogue (operands[0]));
3153
}
3154
 
3155
void
3156
mep_emit_eh_epilogue (rtx *operands ATTRIBUTE_UNUSED)
3157
{
3158
  cfun->machine->eh_stack_adjust = gen_rtx_REG (Pmode, 0);
3159
  mep_prevent_lp_restore = 1;
3160
  mep_expand_epilogue ();
3161
  mep_prevent_lp_restore = 0;
3162
}
3163
 
3164
void
3165
mep_expand_sibcall_epilogue (void)
3166
{
3167
  mep_sibcall_epilogue = 1;
3168
  mep_expand_epilogue ();
3169
  mep_sibcall_epilogue = 0;
3170
}
3171
 
3172
static bool
3173
mep_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
3174
{
3175
  if (decl == NULL)
3176
    return false;
3177
 
3178
  if (mep_section_tag (DECL_RTL (decl)) == 'f')
3179
    return false;
3180
 
3181
  /* Can't call to a sibcall from an interrupt or disinterrupt function.  */
3182
  if (mep_interrupt_p () || mep_disinterrupt_p ())
3183
    return false;
3184
 
3185
  return true;
3186
}
3187
 
3188
rtx
3189
mep_return_stackadj_rtx (void)
3190
{
3191
  return gen_rtx_REG (SImode, 10);
3192
}
3193
 
3194
rtx
3195
mep_return_handler_rtx (void)
3196
{
3197
  return gen_rtx_REG (SImode, LP_REGNO);
3198
}
3199
 
3200
void
3201
mep_function_profiler (FILE *file)
3202
{
3203
  /* Always right at the beginning of the function.  */
3204
  fprintf (file, "\t# mep function profiler\n");
3205
  fprintf (file, "\tadd\t$sp, -8\n");
3206
  fprintf (file, "\tsw\t$0, ($sp)\n");
3207
  fprintf (file, "\tldc\t$0, $lp\n");
3208
  fprintf (file, "\tsw\t$0, 4($sp)\n");
3209
  fprintf (file, "\tbsr\t__mep_mcount\n");
3210
  fprintf (file, "\tlw\t$0, 4($sp)\n");
3211
  fprintf (file, "\tstc\t$0, $lp\n");
3212
  fprintf (file, "\tlw\t$0, ($sp)\n");
3213
  fprintf (file, "\tadd\t$sp, 8\n\n");
3214
}
3215
 
3216
const char *
3217
mep_emit_bb_trace_ret (void)
3218
{
3219
  fprintf (asm_out_file, "\t# end of block profiling\n");
3220
  fprintf (asm_out_file, "\tadd\t$sp, -8\n");
3221
  fprintf (asm_out_file, "\tsw\t$0, ($sp)\n");
3222
  fprintf (asm_out_file, "\tldc\t$0, $lp\n");
3223
  fprintf (asm_out_file, "\tsw\t$0, 4($sp)\n");
3224
  fprintf (asm_out_file, "\tbsr\t__bb_trace_ret\n");
3225
  fprintf (asm_out_file, "\tlw\t$0, 4($sp)\n");
3226
  fprintf (asm_out_file, "\tstc\t$0, $lp\n");
3227
  fprintf (asm_out_file, "\tlw\t$0, ($sp)\n");
3228
  fprintf (asm_out_file, "\tadd\t$sp, 8\n\n");
3229
  return "";
3230
}
3231
 
3232
#undef SAVE
3233
#undef RESTORE
3234
 
3235
/* Operand Printing.  */
3236
 
3237
void
3238
mep_print_operand_address (FILE *stream, rtx address)
3239
{
3240
  if (GET_CODE (address) == MEM)
3241
    address = XEXP (address, 0);
3242
  else
3243
    /* cf: gcc.dg/asm-4.c.  */
3244
    gcc_assert (GET_CODE (address) == REG);
3245
 
3246
  mep_print_operand (stream, address, 0);
3247
}
3248
 
3249
static struct
3250
{
3251
  char code;
3252
  const char *pattern;
3253
  const char *format;
3254
}
3255
const conversions[] =
3256
{
3257
  { 0, "r", "0" },
3258
  { 0, "m+ri", "3(2)" },
3259
  { 0, "mr", "(1)" },
3260
  { 0, "ms", "(1)" },
3261
  { 0, "ml", "(1)" },
3262
  { 0, "mLrs", "%lo(3)(2)" },
3263
  { 0, "mLr+si", "%lo(4+5)(2)" },
3264
  { 0, "m+ru2s", "%tpoff(5)(2)" },
3265
  { 0, "m+ru3s", "%sdaoff(5)(2)" },
3266
  { 0, "m+r+u2si", "%tpoff(6+7)(2)" },
3267
  { 0, "m+ru2+si", "%tpoff(6+7)(2)" },
3268
  { 0, "m+r+u3si", "%sdaoff(6+7)(2)" },
3269
  { 0, "m+ru3+si", "%sdaoff(6+7)(2)" },
3270
  { 0, "mi", "(1)" },
3271
  { 0, "m+si", "(2+3)" },
3272
  { 0, "m+li", "(2+3)" },
3273
  { 0, "i", "0" },
3274
  { 0, "s", "0" },
3275
  { 0, "+si", "1+2" },
3276
  { 0, "+u2si", "%tpoff(3+4)" },
3277
  { 0, "+u3si", "%sdaoff(3+4)" },
3278
  { 0, "l", "0" },
3279
  { 'b', "i", "0" },
3280
  { 'B', "i", "0" },
3281
  { 'U', "i", "0" },
3282
  { 'h', "i", "0" },
3283
  { 'h', "Hs", "%hi(1)" },
3284
  { 'I', "i", "0" },
3285
  { 'I', "u2s", "%tpoff(2)" },
3286
  { 'I', "u3s", "%sdaoff(2)" },
3287
  { 'I', "+u2si", "%tpoff(3+4)" },
3288
  { 'I', "+u3si", "%sdaoff(3+4)" },
3289
  { 'J', "i", "0" },
3290
  { 'P', "mr", "(1\\+),\\0" },
3291
  { 'x', "i", "0" },
3292
  { 0, 0, 0 }
3293
};
3294
 
3295
static int
3296
unique_bit_in (HOST_WIDE_INT i)
3297
{
3298
  switch (i & 0xff)
3299
    {
3300
    case 0x01: case 0xfe: return 0;
3301
    case 0x02: case 0xfd: return 1;
3302
    case 0x04: case 0xfb: return 2;
3303
    case 0x08: case 0xf7: return 3;
3304
    case 0x10: case 0x7f: return 4;
3305
    case 0x20: case 0xbf: return 5;
3306
    case 0x40: case 0xdf: return 6;
3307
    case 0x80: case 0xef: return 7;
3308
    default:
3309
      gcc_unreachable ();
3310
    }
3311
}
3312
 
3313
static int
3314
bit_size_for_clip (HOST_WIDE_INT i)
3315
{
3316
  int rv;
3317
 
3318
  for (rv = 0; rv < 31; rv ++)
3319
    if (((HOST_WIDE_INT) 1 << rv) > i)
3320
      return rv + 1;
3321
  gcc_unreachable ();
3322
}
3323
 
3324
/* Print an operand to a assembler instruction.  */
3325
 
3326
void
3327
mep_print_operand (FILE *file, rtx x, int code)
3328
{
3329
  int i, j;
3330
  const char *real_name;
3331
 
3332
  if (code == '<')
3333
    {
3334
      /* Print a mnemonic to do CR <- CR moves.  Find out which intrinsic
3335
         we're using, then skip over the "mep_" part of its name.  */
3336
      const struct cgen_insn *insn;
3337
 
3338
      if (mep_get_move_insn (mep_cmov, &insn))
3339
        fputs (cgen_intrinsics[insn->intrinsic] + 4, file);
3340
      else
3341
        mep_intrinsic_unavailable (mep_cmov);
3342
      return;
3343
    }
3344
  if (code == 'L')
3345
    {
3346
      switch (GET_CODE (x))
3347
        {
3348
        case AND:
3349
          fputs ("clr", file);
3350
          return;
3351
        case IOR:
3352
          fputs ("set", file);
3353
          return;
3354
        case XOR:
3355
          fputs ("not", file);
3356
          return;
3357
        default:
3358
          output_operand_lossage ("invalid %%L code");
3359
        }
3360
    }
3361
  if (code == 'M')
3362
    {
3363
      /* Print the second operand of a CR <- CR move.  If we're using
3364
         a two-operand instruction (i.e., a real cmov), then just print
3365
         the operand normally.  If we're using a "reg, reg, immediate"
3366
         instruction such as caddi3, print the operand followed by a
3367
         zero field.  If we're using a three-register instruction,
3368
         print the operand twice.  */
3369
      const struct cgen_insn *insn;
3370
 
3371
      mep_print_operand (file, x, 0);
3372
      if (mep_get_move_insn (mep_cmov, &insn)
3373
          && insn_data[insn->icode].n_operands == 3)
3374
        {
3375
          fputs (", ", file);
3376
          if (insn_data[insn->icode].operand[2].predicate (x, VOIDmode))
3377
            mep_print_operand (file, x, 0);
3378
          else
3379
            mep_print_operand (file, const0_rtx, 0);
3380
        }
3381
      return;
3382
    }
3383
 
3384
  encode_pattern (x);
3385
  for (i = 0; conversions[i].pattern; i++)
3386
    if (conversions[i].code == code
3387
        && strcmp(conversions[i].pattern, pattern) == 0)
3388
      {
3389
        for (j = 0; conversions[i].format[j]; j++)
3390
          if (conversions[i].format[j] == '\\')
3391
            {
3392
              fputc (conversions[i].format[j+1], file);
3393
              j++;
3394
            }
3395
          else if (ISDIGIT(conversions[i].format[j]))
3396
            {
3397
              rtx r = patternr[conversions[i].format[j] - '0'];
3398
              switch (GET_CODE (r))
3399
                {
3400
                case REG:
3401
                  fprintf (file, "%s", reg_names [REGNO (r)]);
3402
                  break;
3403
                case CONST_INT:
3404
                  switch (code)
3405
                    {
3406
                    case 'b':
3407
                      fprintf (file, "%d", unique_bit_in (INTVAL (r)));
3408
                      break;
3409
                    case 'B':
3410
                      fprintf (file, "%d", bit_size_for_clip (INTVAL (r)));
3411
                      break;
3412
                    case 'h':
3413
                      fprintf (file, "0x%x", ((int) INTVAL (r) >> 16) & 0xffff);
3414
                      break;
3415
                    case 'U':
3416
                      fprintf (file, "%d", bit_size_for_clip (INTVAL (r)) - 1);
3417
                      break;
3418
                    case 'J':
3419
                      fprintf (file, "0x%x", (int) INTVAL (r) & 0xffff);
3420
                      break;
3421
                    case 'x':
3422
                      if (INTVAL (r) & ~(HOST_WIDE_INT)0xff
3423
                          && !(INTVAL (r) & 0xff))
3424
                        fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL(r));
3425
                      else
3426
                        fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL(r));
3427
                      break;
3428
                    case 'I':
3429
                      if (INTVAL (r) & ~(HOST_WIDE_INT)0xff
3430
                          && conversions[i].format[j+1] == 0)
3431
                        {
3432
                          fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (r));
3433
                          fprintf (file, " # 0x%x", (int) INTVAL(r) & 0xffff);
3434
                        }
3435
                      else
3436
                        fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL(r));
3437
                      break;
3438
                    default:
3439
                      fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL(r));
3440
                      break;
3441
                    }
3442
                  break;
3443
                case CONST_DOUBLE:
3444
                  fprintf(file, "[const_double 0x%lx]",
3445
                          (unsigned long) CONST_DOUBLE_HIGH(r));
3446
                  break;
3447
                case SYMBOL_REF:
3448
                  real_name = targetm.strip_name_encoding (XSTR (r, 0));
3449
                  assemble_name (file, real_name);
3450
                  break;
3451
                case LABEL_REF:
3452
                  output_asm_label (r);
3453
                  break;
3454
                default:
3455
                  fprintf (stderr, "don't know how to print this operand:");
3456
                  debug_rtx (r);
3457
                  gcc_unreachable ();
3458
                }
3459
            }
3460
          else
3461
            {
3462
              if (conversions[i].format[j] == '+'
3463
                  && (!code || code == 'I')
3464
                  && ISDIGIT (conversions[i].format[j+1])
3465
                  && GET_CODE (patternr[conversions[i].format[j+1] - '0']) == CONST_INT
3466
                  && INTVAL (patternr[conversions[i].format[j+1] - '0']) < 0)
3467
                continue;
3468
              fputc(conversions[i].format[j], file);
3469
            }
3470
        break;
3471
      }
3472
  if (!conversions[i].pattern)
3473
    {
3474
      error ("unconvertible operand %c %qs", code?code:'-', pattern);
3475
      debug_rtx(x);
3476
    }
3477
 
3478
  return;
3479
}
3480
 
3481
void
3482
mep_final_prescan_insn (rtx insn, rtx *operands ATTRIBUTE_UNUSED,
3483
                        int noperands ATTRIBUTE_UNUSED)
3484
{
3485
  /* Despite the fact that MeP is perfectly capable of branching and
3486
     doing something else in the same bundle, gcc does jump
3487
     optimization *after* scheduling, so we cannot trust the bundling
3488
     flags on jump instructions.  */
3489
  if (GET_MODE (insn) == BImode
3490
      && get_attr_slots (insn) != SLOTS_CORE)
3491
    fputc ('+', asm_out_file);
3492
}
3493
 
3494
/* Function args in registers.  */
3495
 
3496
static void
3497
mep_setup_incoming_varargs (cumulative_args_t cum,
3498
                            enum machine_mode mode ATTRIBUTE_UNUSED,
3499
                            tree type ATTRIBUTE_UNUSED, int *pretend_size,
3500
                            int second_time ATTRIBUTE_UNUSED)
3501
{
3502
  int nsave = 4 - (get_cumulative_args (cum)->nregs + 1);
3503
 
3504
  if (nsave > 0)
3505
    cfun->machine->arg_regs_to_save = nsave;
3506
  *pretend_size = nsave * 4;
3507
}
3508
 
3509
static int
3510
bytesize (const_tree type, enum machine_mode mode)
3511
{
3512
  if (mode == BLKmode)
3513
    return int_size_in_bytes (type);
3514
  return GET_MODE_SIZE (mode);
3515
}
3516
 
3517
static rtx
3518
mep_expand_builtin_saveregs (void)
3519
{
3520
  int bufsize, i, ns;
3521
  rtx regbuf;
3522
 
3523
  ns = cfun->machine->arg_regs_to_save;
3524
  if (TARGET_IVC2)
3525
    {
3526
      bufsize = 8 * ((ns + 1) / 2) + 8 * ns;
3527
      regbuf = assign_stack_local (SImode, bufsize, 64);
3528
    }
3529
  else
3530
    {
3531
      bufsize = ns * 4;
3532
      regbuf = assign_stack_local (SImode, bufsize, 32);
3533
    }
3534
 
3535
  move_block_from_reg (5-ns, regbuf, ns);
3536
 
3537
  if (TARGET_IVC2)
3538
    {
3539
      rtx tmp = gen_rtx_MEM (DImode, XEXP (regbuf, 0));
3540
      int ofs = 8 * ((ns+1)/2);
3541
 
3542
      for (i=0; i<ns; i++)
3543
        {
3544
          int rn = (4-ns) + i + 49;
3545
          rtx ptr;
3546
 
3547
          ptr = offset_address (tmp, GEN_INT (ofs), 2);
3548
          emit_move_insn (ptr, gen_rtx_REG (DImode, rn));
3549
          ofs += 8;
3550
        }
3551
    }
3552
  return XEXP (regbuf, 0);
3553
}
3554
 
3555
#define VECTOR_TYPE_P(t) (TREE_CODE(t) == VECTOR_TYPE)
3556
 
3557
static tree
3558
mep_build_builtin_va_list (void)
3559
{
3560
  tree f_next_gp, f_next_gp_limit, f_next_cop, f_next_stack;
3561
  tree record;
3562
 
3563
 
3564
  record = (*lang_hooks.types.make_type) (RECORD_TYPE);
3565
 
3566
  f_next_gp = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3567
                          get_identifier ("__va_next_gp"), ptr_type_node);
3568
  f_next_gp_limit = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3569
                                get_identifier ("__va_next_gp_limit"),
3570
                                ptr_type_node);
3571
  f_next_cop = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("__va_next_cop"),
3572
                           ptr_type_node);
3573
  f_next_stack = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("__va_next_stack"),
3574
                             ptr_type_node);
3575
 
3576
  DECL_FIELD_CONTEXT (f_next_gp) = record;
3577
  DECL_FIELD_CONTEXT (f_next_gp_limit) = record;
3578
  DECL_FIELD_CONTEXT (f_next_cop) = record;
3579
  DECL_FIELD_CONTEXT (f_next_stack) = record;
3580
 
3581
  TYPE_FIELDS (record) = f_next_gp;
3582
  DECL_CHAIN (f_next_gp) = f_next_gp_limit;
3583
  DECL_CHAIN (f_next_gp_limit) = f_next_cop;
3584
  DECL_CHAIN (f_next_cop) = f_next_stack;
3585
 
3586
  layout_type (record);
3587
 
3588
  return record;
3589
}
3590
 
3591
static void
3592
mep_expand_va_start (tree valist, rtx nextarg)
3593
{
3594
  tree f_next_gp, f_next_gp_limit, f_next_cop, f_next_stack;
3595
  tree next_gp, next_gp_limit, next_cop, next_stack;
3596
  tree t, u;
3597
  int ns;
3598
 
3599
  ns = cfun->machine->arg_regs_to_save;
3600
 
3601
  f_next_gp = TYPE_FIELDS (va_list_type_node);
3602
  f_next_gp_limit = DECL_CHAIN (f_next_gp);
3603
  f_next_cop = DECL_CHAIN (f_next_gp_limit);
3604
  f_next_stack = DECL_CHAIN (f_next_cop);
3605
 
3606
  next_gp = build3 (COMPONENT_REF, TREE_TYPE (f_next_gp), valist, f_next_gp,
3607
                    NULL_TREE);
3608
  next_gp_limit = build3 (COMPONENT_REF, TREE_TYPE (f_next_gp_limit),
3609
                          valist, f_next_gp_limit, NULL_TREE);
3610
  next_cop = build3 (COMPONENT_REF, TREE_TYPE (f_next_cop), valist, f_next_cop,
3611
                     NULL_TREE);
3612
  next_stack = build3 (COMPONENT_REF, TREE_TYPE (f_next_stack),
3613
                       valist, f_next_stack, NULL_TREE);
3614
 
3615
  /* va_list.next_gp = expand_builtin_saveregs (); */
3616
  u = make_tree (sizetype, expand_builtin_saveregs ());
3617
  u = fold_convert (ptr_type_node, u);
3618
  t = build2 (MODIFY_EXPR, ptr_type_node, next_gp, u);
3619
  TREE_SIDE_EFFECTS (t) = 1;
3620
  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3621
 
3622
  /* va_list.next_gp_limit = va_list.next_gp + 4 * ns; */
3623
  u = fold_build_pointer_plus_hwi (u, 4 * ns);
3624
  t = build2 (MODIFY_EXPR, ptr_type_node, next_gp_limit, u);
3625
  TREE_SIDE_EFFECTS (t) = 1;
3626
  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3627
 
3628
  u = fold_build_pointer_plus_hwi (u, 8 * ((ns+1)/2));
3629
  /* va_list.next_cop = ROUND_UP(va_list.next_gp_limit,8); */
3630
  t = build2 (MODIFY_EXPR, ptr_type_node, next_cop, u);
3631
  TREE_SIDE_EFFECTS (t) = 1;
3632
  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3633
 
3634
  /* va_list.next_stack = nextarg; */
3635
  u = make_tree (ptr_type_node, nextarg);
3636
  t = build2 (MODIFY_EXPR, ptr_type_node, next_stack, u);
3637
  TREE_SIDE_EFFECTS (t) = 1;
3638
  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3639
}
3640
 
3641
static tree
3642
mep_gimplify_va_arg_expr (tree valist, tree type,
3643
                          gimple_seq *pre_p,
3644
                          gimple_seq *post_p ATTRIBUTE_UNUSED)
3645
{
3646
  HOST_WIDE_INT size, rsize;
3647
  bool by_reference, ivc2_vec;
3648
  tree f_next_gp, f_next_gp_limit, f_next_cop, f_next_stack;
3649
  tree next_gp, next_gp_limit, next_cop, next_stack;
3650
  tree label_sover, label_selse;
3651
  tree tmp, res_addr;
3652
 
3653
  ivc2_vec = TARGET_IVC2 && VECTOR_TYPE_P (type);
3654
 
3655
  size = int_size_in_bytes (type);
3656
  by_reference = (size > (ivc2_vec ? 8 : 4)) || (size <= 0);
3657
 
3658
  if (by_reference)
3659
    {
3660
      type = build_pointer_type (type);
3661
      size = 4;
3662
    }
3663
  rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
3664
 
3665
  f_next_gp = TYPE_FIELDS (va_list_type_node);
3666
  f_next_gp_limit = DECL_CHAIN (f_next_gp);
3667
  f_next_cop = DECL_CHAIN (f_next_gp_limit);
3668
  f_next_stack = DECL_CHAIN (f_next_cop);
3669
 
3670
  next_gp = build3 (COMPONENT_REF, TREE_TYPE (f_next_gp), valist, f_next_gp,
3671
                    NULL_TREE);
3672
  next_gp_limit = build3 (COMPONENT_REF, TREE_TYPE (f_next_gp_limit),
3673
                          valist, f_next_gp_limit, NULL_TREE);
3674
  next_cop = build3 (COMPONENT_REF, TREE_TYPE (f_next_cop), valist, f_next_cop,
3675
                     NULL_TREE);
3676
  next_stack = build3 (COMPONENT_REF, TREE_TYPE (f_next_stack),
3677
                       valist, f_next_stack, NULL_TREE);
3678
 
3679
  /* if f_next_gp < f_next_gp_limit
3680
       IF (VECTOR_P && IVC2)
3681
         val = *f_next_cop;
3682
       ELSE
3683
         val = *f_next_gp;
3684
       f_next_gp += 4;
3685
       f_next_cop += 8;
3686
     else
3687
       label_selse:
3688
       val = *f_next_stack;
3689
       f_next_stack += rsize;
3690
     label_sover:
3691
  */
3692
 
3693
  label_sover = create_artificial_label (UNKNOWN_LOCATION);
3694
  label_selse = create_artificial_label (UNKNOWN_LOCATION);
3695
  res_addr = create_tmp_var (ptr_type_node, NULL);
3696
 
3697
  tmp = build2 (GE_EXPR, boolean_type_node, next_gp,
3698
                unshare_expr (next_gp_limit));
3699
  tmp = build3 (COND_EXPR, void_type_node, tmp,
3700
                build1 (GOTO_EXPR, void_type_node,
3701
                        unshare_expr (label_selse)),
3702
                NULL_TREE);
3703
  gimplify_and_add (tmp, pre_p);
3704
 
3705
  if (ivc2_vec)
3706
    {
3707
      tmp = build2 (MODIFY_EXPR, void_type_node, res_addr, next_cop);
3708
      gimplify_and_add (tmp, pre_p);
3709
    }
3710
  else
3711
    {
3712
      tmp = build2 (MODIFY_EXPR, void_type_node, res_addr, next_gp);
3713
      gimplify_and_add (tmp, pre_p);
3714
    }
3715
 
3716
  tmp = fold_build_pointer_plus_hwi (unshare_expr (next_gp), 4);
3717
  gimplify_assign (unshare_expr (next_gp), tmp, pre_p);
3718
 
3719
  tmp = fold_build_pointer_plus_hwi (unshare_expr (next_cop), 8);
3720
  gimplify_assign (unshare_expr (next_cop), tmp, pre_p);
3721
 
3722
  tmp = build1 (GOTO_EXPR, void_type_node, unshare_expr (label_sover));
3723
  gimplify_and_add (tmp, pre_p);
3724
 
3725
  /* - - */
3726
 
3727
  tmp = build1 (LABEL_EXPR, void_type_node, unshare_expr (label_selse));
3728
  gimplify_and_add (tmp, pre_p);
3729
 
3730
  tmp = build2 (MODIFY_EXPR, void_type_node, res_addr, unshare_expr (next_stack));
3731
  gimplify_and_add (tmp, pre_p);
3732
 
3733
  tmp = fold_build_pointer_plus_hwi (unshare_expr (next_stack), rsize);
3734
  gimplify_assign (unshare_expr (next_stack), tmp, pre_p);
3735
 
3736
  /* - - */
3737
 
3738
  tmp = build1 (LABEL_EXPR, void_type_node, unshare_expr (label_sover));
3739
  gimplify_and_add (tmp, pre_p);
3740
 
3741
  res_addr = fold_convert (build_pointer_type (type), res_addr);
3742
 
3743
  if (by_reference)
3744
    res_addr = build_va_arg_indirect_ref (res_addr);
3745
 
3746
  return build_va_arg_indirect_ref (res_addr);
3747
}
3748
 
3749
void
3750
mep_init_cumulative_args (CUMULATIVE_ARGS *pcum, tree fntype,
3751
                          rtx libname ATTRIBUTE_UNUSED,
3752
                          tree fndecl ATTRIBUTE_UNUSED)
3753
{
3754
  pcum->nregs = 0;
3755
 
3756
  if (fntype && lookup_attribute ("vliw", TYPE_ATTRIBUTES (fntype)))
3757
    pcum->vliw = 1;
3758
  else
3759
    pcum->vliw = 0;
3760
}
3761
 
3762
/* The ABI is thus: Arguments are in $1, $2, $3, $4, stack.  Arguments
3763
   larger than 4 bytes are passed indirectly.  Return value in 0,
3764
   unless bigger than 4 bytes, then the caller passes a pointer as the
3765
   first arg.  For varargs, we copy $1..$4 to the stack.  */
3766
 
3767
static rtx
3768
mep_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
3769
                  const_tree type ATTRIBUTE_UNUSED,
3770
                  bool named ATTRIBUTE_UNUSED)
3771
{
3772
  CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
3773
 
3774
  /* VOIDmode is a signal for the backend to pass data to the call
3775
     expander via the second operand to the call pattern.  We use
3776
     this to determine whether to use "jsr" or "jsrv".  */
3777
  if (mode == VOIDmode)
3778
    return GEN_INT (cum->vliw);
3779
 
3780
  /* If we havn't run out of argument registers, return the next.  */
3781
  if (cum->nregs < 4)
3782
    {
3783
      if (type && TARGET_IVC2 && VECTOR_TYPE_P (type))
3784
        return gen_rtx_REG (mode, cum->nregs + 49);
3785
      else
3786
        return gen_rtx_REG (mode, cum->nregs + 1);
3787
    }
3788
 
3789
  /* Otherwise the argument goes on the stack.  */
3790
  return NULL_RTX;
3791
}
3792
 
3793
static bool
3794
mep_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
3795
                       enum machine_mode mode,
3796
                       const_tree        type,
3797
                       bool              named ATTRIBUTE_UNUSED)
3798
{
3799
  int size = bytesize (type, mode);
3800
 
3801
  /* This is non-obvious, but yes, large values passed after we've run
3802
     out of registers are *still* passed by reference - we put the
3803
     address of the parameter on the stack, as well as putting the
3804
     parameter itself elsewhere on the stack.  */
3805
 
3806
  if (size <= 0 || size > 8)
3807
    return true;
3808
  if (size <= 4)
3809
    return false;
3810
  if (TARGET_IVC2 && get_cumulative_args (cum)->nregs < 4
3811
      && type != NULL_TREE && VECTOR_TYPE_P (type))
3812
    return false;
3813
  return true;
3814
}
3815
 
3816
static void
3817
mep_function_arg_advance (cumulative_args_t pcum,
3818
                          enum machine_mode mode ATTRIBUTE_UNUSED,
3819
                          const_tree type ATTRIBUTE_UNUSED,
3820
                          bool named ATTRIBUTE_UNUSED)
3821
{
3822
  get_cumulative_args (pcum)->nregs += 1;
3823
}
3824
 
3825
bool
3826
mep_return_in_memory (const_tree type, const_tree decl ATTRIBUTE_UNUSED)
3827
{
3828
  int size = bytesize (type, BLKmode);
3829
  if (TARGET_IVC2 && VECTOR_TYPE_P (type))
3830
    return size > 0 && size <= 8 ? 0 : 1;
3831
  return size > 0 && size <= 4 ? 0 : 1;
3832
}
3833
 
3834
static bool
3835
mep_narrow_volatile_bitfield (void)
3836
{
3837
  return true;
3838
  return false;
3839
}
3840
 
3841
/* Implement FUNCTION_VALUE.  All values are returned in $0.  */
3842
 
3843
rtx
3844
mep_function_value (const_tree type, const_tree func ATTRIBUTE_UNUSED)
3845
{
3846
  if (TARGET_IVC2 && VECTOR_TYPE_P (type))
3847
    return gen_rtx_REG (TYPE_MODE (type), 48);
3848
  return gen_rtx_REG (TYPE_MODE (type), RETURN_VALUE_REGNUM);
3849
}
3850
 
3851
/* Implement LIBCALL_VALUE, using the same rules as mep_function_value.  */
3852
 
3853
rtx
3854
mep_libcall_value (enum machine_mode mode)
3855
{
3856
  return gen_rtx_REG (mode, RETURN_VALUE_REGNUM);
3857
}
3858
 
3859
/* Handle pipeline hazards.  */
3860
 
3861
typedef enum { op_none, op_stc, op_fsft, op_ret } op_num;
3862
static const char *opnames[] = { "", "stc", "fsft", "ret" };
3863
 
3864
static int prev_opcode = 0;
3865
 
3866
/* This isn't as optimal as it could be, because we don't know what
3867
   control register the STC opcode is storing in.  We only need to add
3868
   the nop if it's the relevent register, but we add it for irrelevent
3869
   registers also.  */
3870
 
3871
void
3872
mep_asm_output_opcode (FILE *file, const char *ptr)
3873
{
3874
  int this_opcode = op_none;
3875
  const char *hazard = 0;
3876
 
3877
  switch (*ptr)
3878
    {
3879
    case 'f':
3880
      if (strncmp (ptr, "fsft", 4) == 0 && !ISGRAPH (ptr[4]))
3881
        this_opcode = op_fsft;
3882
      break;
3883
    case 'r':
3884
      if (strncmp (ptr, "ret", 3) == 0 && !ISGRAPH (ptr[3]))
3885
        this_opcode = op_ret;
3886
      break;
3887
    case 's':
3888
      if (strncmp (ptr, "stc", 3) == 0 && !ISGRAPH (ptr[3]))
3889
        this_opcode = op_stc;
3890
      break;
3891
    }
3892
 
3893
  if (prev_opcode == op_stc && this_opcode == op_fsft)
3894
    hazard = "nop";
3895
  if (prev_opcode == op_stc && this_opcode == op_ret)
3896
    hazard = "nop";
3897
 
3898
  if (hazard)
3899
    fprintf(file, "%s\t# %s-%s hazard\n\t",
3900
            hazard, opnames[prev_opcode], opnames[this_opcode]);
3901
 
3902
  prev_opcode = this_opcode;
3903
}
3904
 
3905
/* Handle attributes.  */
3906
 
3907
static tree
3908
mep_validate_based_tiny (tree *node, tree name, tree args,
3909
                         int flags ATTRIBUTE_UNUSED, bool *no_add)
3910
{
3911
  if (TREE_CODE (*node) != VAR_DECL
3912
      && TREE_CODE (*node) != POINTER_TYPE
3913
      && TREE_CODE (*node) != TYPE_DECL)
3914
    {
3915
      warning (0, "%qE attribute only applies to variables", name);
3916
      *no_add = true;
3917
    }
3918
  else if (args == NULL_TREE && TREE_CODE (*node) == VAR_DECL)
3919
    {
3920
      if (! (TREE_PUBLIC (*node) || TREE_STATIC (*node)))
3921
        {
3922
          warning (0, "address region attributes not allowed with auto storage class");
3923
          *no_add = true;
3924
        }
3925
      /* Ignore storage attribute of pointed to variable: char __far * x;  */
3926
      if (TREE_TYPE (*node) && TREE_CODE (TREE_TYPE (*node)) == POINTER_TYPE)
3927
        {
3928
          warning (0, "address region attributes on pointed-to types ignored");
3929
          *no_add = true;
3930
        }
3931
    }
3932
 
3933
  return NULL_TREE;
3934
}
3935
 
3936
static int
3937
mep_multiple_address_regions (tree list, bool check_section_attr)
3938
{
3939
  tree a;
3940
  int count_sections = 0;
3941
  int section_attr_count = 0;
3942
 
3943
  for (a = list; a; a = TREE_CHAIN (a))
3944
    {
3945
      if (is_attribute_p ("based", TREE_PURPOSE (a))
3946
          || is_attribute_p ("tiny", TREE_PURPOSE (a))
3947
          || is_attribute_p ("near", TREE_PURPOSE (a))
3948
          || is_attribute_p ("far", TREE_PURPOSE (a))
3949
          || is_attribute_p ("io", TREE_PURPOSE (a)))
3950
        count_sections ++;
3951
      if (check_section_attr)
3952
        section_attr_count += is_attribute_p ("section", TREE_PURPOSE (a));
3953
    }
3954
 
3955
  if (check_section_attr)
3956
    return section_attr_count;
3957
  else
3958
    return count_sections;
3959
}
3960
 
3961
#define MEP_ATTRIBUTES(decl) \
3962
  (TYPE_P (decl)) ? TYPE_ATTRIBUTES (decl) \
3963
                : DECL_ATTRIBUTES (decl) \
3964
                  ? (DECL_ATTRIBUTES (decl)) \
3965
                  : TYPE_ATTRIBUTES (TREE_TYPE (decl))
3966
 
3967
static tree
3968
mep_validate_near_far (tree *node, tree name, tree args,
3969
                       int flags ATTRIBUTE_UNUSED, bool *no_add)
3970
{
3971
  if (TREE_CODE (*node) != VAR_DECL
3972
      && TREE_CODE (*node) != FUNCTION_DECL
3973
      && TREE_CODE (*node) != METHOD_TYPE
3974
      && TREE_CODE (*node) != POINTER_TYPE
3975
      && TREE_CODE (*node) != TYPE_DECL)
3976
    {
3977
      warning (0, "%qE attribute only applies to variables and functions",
3978
               name);
3979
      *no_add = true;
3980
    }
3981
  else if (args == NULL_TREE && TREE_CODE (*node) == VAR_DECL)
3982
    {
3983
      if (! (TREE_PUBLIC (*node) || TREE_STATIC (*node)))
3984
        {
3985
          warning (0, "address region attributes not allowed with auto storage class");
3986
          *no_add = true;
3987
        }
3988
      /* Ignore storage attribute of pointed to variable: char __far * x;  */
3989
      if (TREE_TYPE (*node) && TREE_CODE (TREE_TYPE (*node)) == POINTER_TYPE)
3990
        {
3991
          warning (0, "address region attributes on pointed-to types ignored");
3992
          *no_add = true;
3993
        }
3994
    }
3995
  else if (mep_multiple_address_regions (MEP_ATTRIBUTES (*node), false) > 0)
3996
    {
3997
      warning (0, "duplicate address region attribute %qE in declaration of %qE on line %d",
3998
               name, DECL_NAME (*node), DECL_SOURCE_LINE (*node));
3999
      DECL_ATTRIBUTES (*node) = NULL_TREE;
4000
    }
4001
  return NULL_TREE;
4002
}
4003
 
4004
static tree
4005
mep_validate_disinterrupt (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
4006
                           int flags ATTRIBUTE_UNUSED, bool *no_add)
4007
{
4008
  if (TREE_CODE (*node) != FUNCTION_DECL
4009
      && TREE_CODE (*node) != METHOD_TYPE)
4010
    {
4011
      warning (0, "%qE attribute only applies to functions", name);
4012
      *no_add = true;
4013
    }
4014
  return NULL_TREE;
4015
}
4016
 
4017
static tree
4018
mep_validate_interrupt (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
4019
                        int flags ATTRIBUTE_UNUSED, bool *no_add)
4020
{
4021
  tree function_type;
4022
 
4023
  if (TREE_CODE (*node) != FUNCTION_DECL)
4024
    {
4025
      warning (0, "%qE attribute only applies to functions", name);
4026
      *no_add = true;
4027
      return NULL_TREE;
4028
    }
4029
 
4030
  if (DECL_DECLARED_INLINE_P (*node))
4031
    error ("cannot inline interrupt function %qE", DECL_NAME (*node));
4032
  DECL_UNINLINABLE (*node) = 1;
4033
 
4034
  function_type = TREE_TYPE (*node);
4035
 
4036
  if (TREE_TYPE (function_type) != void_type_node)
4037
    error ("interrupt function must have return type of void");
4038
 
4039
  if (prototype_p (function_type)
4040
      && (TREE_VALUE (TYPE_ARG_TYPES (function_type)) != void_type_node
4041
          || TREE_CHAIN (TYPE_ARG_TYPES (function_type)) != NULL_TREE))
4042
    error ("interrupt function must have no arguments");
4043
 
4044
  return NULL_TREE;
4045
}
4046
 
4047
static tree
4048
mep_validate_io_cb (tree *node, tree name, tree args,
4049
                    int flags ATTRIBUTE_UNUSED, bool *no_add)
4050
{
4051
  if (TREE_CODE (*node) != VAR_DECL)
4052
    {
4053
      warning (0, "%qE attribute only applies to variables", name);
4054
      *no_add = true;
4055
    }
4056
 
4057
  if (args != NULL_TREE)
4058
    {
4059
      if (TREE_CODE (TREE_VALUE (args)) == NON_LVALUE_EXPR)
4060
        TREE_VALUE (args) = TREE_OPERAND (TREE_VALUE (args), 0);
4061
      if (TREE_CODE (TREE_VALUE (args)) != INTEGER_CST)
4062
        {
4063
          warning (0, "%qE attribute allows only an integer constant argument",
4064
                   name);
4065
          *no_add = true;
4066
        }
4067
    }
4068
 
4069
  if (*no_add == false && !TARGET_IO_NO_VOLATILE)
4070
    TREE_THIS_VOLATILE (*node) = 1;
4071
 
4072
  return NULL_TREE;
4073
}
4074
 
4075
static tree
4076
mep_validate_vliw (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
4077
                   int flags ATTRIBUTE_UNUSED, bool *no_add)
4078
{
4079
  if (TREE_CODE (*node) != FUNCTION_TYPE
4080
      && TREE_CODE (*node) != FUNCTION_DECL
4081
      && TREE_CODE (*node) != METHOD_TYPE
4082
      && TREE_CODE (*node) != FIELD_DECL
4083
      && TREE_CODE (*node) != TYPE_DECL)
4084
    {
4085
      static int gave_pointer_note = 0;
4086
      static int gave_array_note = 0;
4087
      static const char * given_type = NULL;
4088
 
4089
      given_type = tree_code_name[TREE_CODE (*node)];
4090
      if (TREE_CODE (*node) == POINTER_TYPE)
4091
        given_type = "pointers";
4092
      if (TREE_CODE (*node) == ARRAY_TYPE)
4093
        given_type = "arrays";
4094
 
4095
      if (given_type)
4096
        warning (0, "%qE attribute only applies to functions, not %s",
4097
                 name, given_type);
4098
      else
4099
        warning (0, "%qE attribute only applies to functions",
4100
                 name);
4101
      *no_add = true;
4102
 
4103
      if (TREE_CODE (*node) == POINTER_TYPE
4104
          && !gave_pointer_note)
4105
        {
4106
          inform (input_location,
4107
                  "to describe a pointer to a VLIW function, use syntax like this:\n%s",
4108
                  "   typedef int (__vliw *vfuncptr) ();");
4109
          gave_pointer_note = 1;
4110
        }
4111
 
4112
      if (TREE_CODE (*node) == ARRAY_TYPE
4113
          && !gave_array_note)
4114
        {
4115
          inform (input_location,
4116
                  "to describe an array of VLIW function pointers, use syntax like this:\n%s",
4117
                  "   typedef int (__vliw *vfuncptr[]) ();");
4118
          gave_array_note = 1;
4119
        }
4120
    }
4121
  if (!TARGET_VLIW)
4122
    error ("VLIW functions are not allowed without a VLIW configuration");
4123
  return NULL_TREE;
4124
}
4125
 
4126
static const struct attribute_spec mep_attribute_table[11] =
4127
{
4128
  /* name         min max decl   type   func   handler
4129
     affects_type_identity */
4130
  { "based",        0, 0, false, false, false, mep_validate_based_tiny, false },
4131
  { "tiny",         0, 0, false, false, false, mep_validate_based_tiny, false },
4132
  { "near",         0, 0, false, false, false, mep_validate_near_far, false },
4133
  { "far",          0, 0, false, false, false, mep_validate_near_far, false },
4134
  { "disinterrupt", 0, 0, false, false, false, mep_validate_disinterrupt,
4135
    false },
4136
  { "interrupt",    0, 0, false, false, false, mep_validate_interrupt, false },
4137
  { "io",           0, 1, false, false, false, mep_validate_io_cb, false },
4138
  { "cb",           0, 1, false, false, false, mep_validate_io_cb, false },
4139
  { "vliw",         0, 0, false, true,  false, mep_validate_vliw, false },
4140
  { NULL,           0, 0, false, false, false, NULL, false }
4141
};
4142
 
4143
static bool
4144
mep_function_attribute_inlinable_p (const_tree callee)
4145
{
4146
  tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (callee));
4147
  if (!attrs) attrs = DECL_ATTRIBUTES (callee);
4148
  return (lookup_attribute ("disinterrupt", attrs) == 0
4149
          && lookup_attribute ("interrupt", attrs) == 0);
4150
}
4151
 
4152
static bool
4153
mep_can_inline_p (tree caller, tree callee)
4154
{
4155
  if (TREE_CODE (callee) == ADDR_EXPR)
4156
    callee = TREE_OPERAND (callee, 0);
4157
 
4158
  if (!mep_vliw_function_p (caller)
4159
      && mep_vliw_function_p (callee))
4160
    {
4161
      return false;
4162
    }
4163
  return true;
4164
}
4165
 
4166
#define FUNC_CALL               1
4167
#define FUNC_DISINTERRUPT       2
4168
 
4169
 
4170
struct GTY(()) pragma_entry {
4171
  int used;
4172
  int flag;
4173
  const char *funcname;
4174
};
4175
typedef struct pragma_entry pragma_entry;
4176
 
4177
/* Hash table of farcall-tagged sections.  */
4178
static GTY((param_is (pragma_entry))) htab_t pragma_htab;
4179
 
4180
static int
4181
pragma_entry_eq (const void *p1, const void *p2)
4182
{
4183
  const pragma_entry *old = (const pragma_entry *) p1;
4184
  const char *new_name = (const char *) p2;
4185
 
4186
  return strcmp (old->funcname, new_name) == 0;
4187
}
4188
 
4189
static hashval_t
4190
pragma_entry_hash (const void *p)
4191
{
4192
  const pragma_entry *old = (const pragma_entry *) p;
4193
  return htab_hash_string (old->funcname);
4194
}
4195
 
4196
static void
4197
mep_note_pragma_flag (const char *funcname, int flag)
4198
{
4199
  pragma_entry **slot;
4200
 
4201
  if (!pragma_htab)
4202
    pragma_htab = htab_create_ggc (31, pragma_entry_hash,
4203
                                    pragma_entry_eq, NULL);
4204
 
4205
  slot = (pragma_entry **)
4206
    htab_find_slot_with_hash (pragma_htab, funcname,
4207
                              htab_hash_string (funcname), INSERT);
4208
 
4209
  if (!*slot)
4210
    {
4211
      *slot = ggc_alloc_pragma_entry ();
4212
      (*slot)->flag = 0;
4213
      (*slot)->used = 0;
4214
      (*slot)->funcname = ggc_strdup (funcname);
4215
    }
4216
  (*slot)->flag |= flag;
4217
}
4218
 
4219
static bool
4220
mep_lookup_pragma_flag (const char *funcname, int flag)
4221
{
4222
  pragma_entry **slot;
4223
 
4224
  if (!pragma_htab)
4225
    return false;
4226
 
4227
  if (funcname[0] == '@' && funcname[2] == '.')
4228
    funcname += 3;
4229
 
4230
  slot = (pragma_entry **)
4231
    htab_find_slot_with_hash (pragma_htab, funcname,
4232
                              htab_hash_string (funcname), NO_INSERT);
4233
  if (slot && *slot && ((*slot)->flag & flag))
4234
    {
4235
      (*slot)->used |= flag;
4236
      return true;
4237
    }
4238
  return false;
4239
}
4240
 
4241
bool
4242
mep_lookup_pragma_call (const char *funcname)
4243
{
4244
  return mep_lookup_pragma_flag (funcname, FUNC_CALL);
4245
}
4246
 
4247
void
4248
mep_note_pragma_call (const char *funcname)
4249
{
4250
  mep_note_pragma_flag (funcname, FUNC_CALL);
4251
}
4252
 
4253
bool
4254
mep_lookup_pragma_disinterrupt (const char *funcname)
4255
{
4256
  return mep_lookup_pragma_flag (funcname, FUNC_DISINTERRUPT);
4257
}
4258
 
4259
void
4260
mep_note_pragma_disinterrupt (const char *funcname)
4261
{
4262
  mep_note_pragma_flag (funcname, FUNC_DISINTERRUPT);
4263
}
4264
 
4265
static int
4266
note_unused_pragma_disinterrupt (void **slot, void *data ATTRIBUTE_UNUSED)
4267
{
4268
  const pragma_entry *d = (const pragma_entry *)(*slot);
4269
 
4270
  if ((d->flag & FUNC_DISINTERRUPT)
4271
      && !(d->used & FUNC_DISINTERRUPT))
4272
    warning (0, "\"#pragma disinterrupt %s\" not used", d->funcname);
4273
  return 1;
4274
}
4275
 
4276
void
4277
mep_file_cleanups (void)
4278
{
4279
  if (pragma_htab)
4280
    htab_traverse (pragma_htab, note_unused_pragma_disinterrupt, NULL);
4281
}
4282
 
4283
/* These three functions provide a bridge between the pramgas that
4284
   affect register classes, and the functions that maintain them.  We
4285
   can't call those functions directly as pragma handling is part of
4286
   the front end and doesn't have direct access to them.  */
4287
 
4288
void
4289
mep_save_register_info (void)
4290
{
4291
  save_register_info ();
4292
}
4293
 
4294
void
4295
mep_reinit_regs (void)
4296
{
4297
  reinit_regs ();
4298
}
4299
 
4300
void
4301
mep_init_regs (void)
4302
{
4303
  init_regs ();
4304
}
4305
 
4306
 
4307
 
4308
static int
4309
mep_attrlist_to_encoding (tree list, tree decl)
4310
{
4311
  if (mep_multiple_address_regions (list, false) > 1)
4312
    {
4313
      warning (0, "duplicate address region attribute %qE in declaration of %qE on line %d",
4314
               TREE_PURPOSE (TREE_CHAIN (list)),
4315
               DECL_NAME (decl),
4316
               DECL_SOURCE_LINE (decl));
4317
      TREE_CHAIN (list) = NULL_TREE;
4318
    }
4319
 
4320
  while (list)
4321
    {
4322
      if (is_attribute_p ("based", TREE_PURPOSE (list)))
4323
        return 'b';
4324
      if (is_attribute_p ("tiny", TREE_PURPOSE (list)))
4325
        return 't';
4326
      if (is_attribute_p ("near", TREE_PURPOSE (list)))
4327
        return 'n';
4328
      if (is_attribute_p ("far", TREE_PURPOSE (list)))
4329
        return 'f';
4330
      if (is_attribute_p ("io", TREE_PURPOSE (list)))
4331
        {
4332
          if (TREE_VALUE (list)
4333
              && TREE_VALUE (TREE_VALUE (list))
4334
              && TREE_CODE (TREE_VALUE (TREE_VALUE (list))) == INTEGER_CST)
4335
            {
4336
              int location = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE(list)));
4337
              if (location >= 0
4338
                  && location <= 0x1000000)
4339
                return 'i';
4340
            }
4341
          return 'I';
4342
        }
4343
      if (is_attribute_p ("cb", TREE_PURPOSE (list)))
4344
        return 'c';
4345
      list = TREE_CHAIN (list);
4346
    }
4347
  if (TARGET_TF
4348
      && TREE_CODE (decl) == FUNCTION_DECL
4349
      && DECL_SECTION_NAME (decl) == 0)
4350
    return 'f';
4351
  return 0;
4352
}
4353
 
4354
static int
4355
mep_comp_type_attributes (const_tree t1, const_tree t2)
4356
{
4357
  int vliw1, vliw2;
4358
 
4359
  vliw1 = (lookup_attribute ("vliw", TYPE_ATTRIBUTES (t1)) != 0);
4360
  vliw2 = (lookup_attribute ("vliw", TYPE_ATTRIBUTES (t2)) != 0);
4361
 
4362
  if (vliw1 != vliw2)
4363
    return 0;
4364
 
4365
  return 1;
4366
}
4367
 
4368
static void
4369
mep_insert_attributes (tree decl, tree *attributes)
4370
{
4371
  int size;
4372
  const char *secname = 0;
4373
  tree attrib, attrlist;
4374
  char encoding;
4375
 
4376
  if (TREE_CODE (decl) == FUNCTION_DECL)
4377
    {
4378
      const char *funcname = IDENTIFIER_POINTER (DECL_NAME (decl));
4379
 
4380
      if (mep_lookup_pragma_disinterrupt (funcname))
4381
        {
4382
          attrib = build_tree_list (get_identifier ("disinterrupt"), NULL_TREE);
4383
          *attributes = chainon (*attributes, attrib);
4384
        }
4385
    }
4386
 
4387
  if (TREE_CODE (decl) != VAR_DECL
4388
      || ! (TREE_PUBLIC (decl) || TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
4389
    return;
4390
 
4391
  if (TREE_READONLY (decl) && TARGET_DC)
4392
    /* -mdc means that const variables default to the near section,
4393
       regardless of the size cutoff.  */
4394
    return;
4395
 
4396
  /* User specified an attribute, so override the default.
4397
     Ignore storage attribute of pointed to variable. char __far * x;  */
4398
  if (! (TREE_TYPE (decl) && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE))
4399
    {
4400
      if (TYPE_P (decl) && TYPE_ATTRIBUTES (decl) && *attributes)
4401
        TYPE_ATTRIBUTES (decl) = NULL_TREE;
4402
      else if (DECL_ATTRIBUTES (decl) && *attributes)
4403
        DECL_ATTRIBUTES (decl) = NULL_TREE;
4404
    }
4405
 
4406
  attrlist = *attributes ? *attributes : DECL_ATTRIBUTES (decl);
4407
  encoding = mep_attrlist_to_encoding (attrlist, decl);
4408
  if (!encoding && TYPE_P (TREE_TYPE (decl)))
4409
    {
4410
      attrlist = TYPE_ATTRIBUTES (TREE_TYPE (decl));
4411
      encoding = mep_attrlist_to_encoding (attrlist, decl);
4412
    }
4413
  if (encoding)
4414
    {
4415
      /* This means that the declaration has a specific section
4416
         attribute, so we should not apply the default rules.  */
4417
 
4418
      if (encoding == 'i' || encoding == 'I')
4419
        {
4420
          tree attr = lookup_attribute ("io", attrlist);
4421
          if (attr
4422
              && TREE_VALUE (attr)
4423
              && TREE_VALUE (TREE_VALUE(attr)))
4424
            {
4425
              int location = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE(attr)));
4426
              static tree previous_value = 0;
4427
              static int previous_location = 0;
4428
              static tree previous_name = 0;
4429
 
4430
              /* We take advantage of the fact that gcc will reuse the
4431
                 same tree pointer when applying an attribute to a
4432
                 list of decls, but produce a new tree for attributes
4433
                 on separate source lines, even when they're textually
4434
                 identical.  This is the behavior we want.  */
4435
              if (TREE_VALUE (attr) == previous_value
4436
                  && location == previous_location)
4437
                {
4438
                  warning(0, "__io address 0x%x is the same for %qE and %qE",
4439
                          location, previous_name, DECL_NAME (decl));
4440
                }
4441
              previous_name = DECL_NAME (decl);
4442
              previous_location = location;
4443
              previous_value = TREE_VALUE (attr);
4444
            }
4445
        }
4446
      return;
4447
    }
4448
 
4449
 
4450
  /* Declarations of arrays can change size.  Don't trust them.  */
4451
  if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
4452
    size = 0;
4453
  else
4454
    size = int_size_in_bytes (TREE_TYPE (decl));
4455
 
4456
  if (TARGET_RAND_TPGP && size <= 4 && size > 0)
4457
    {
4458
      if (TREE_PUBLIC (decl)
4459
          || DECL_EXTERNAL (decl)
4460
          || TREE_STATIC (decl))
4461
        {
4462
          const char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
4463
          int key = 0;
4464
 
4465
          while (*name)
4466
            key += *name++;
4467
 
4468
          switch (key & 3)
4469
            {
4470
            case 0:
4471
              secname = "based";
4472
              break;
4473
            case 1:
4474
              secname = "tiny";
4475
              break;
4476
            case 2:
4477
              secname = "far";
4478
              break;
4479
            default:
4480
              ;
4481
            }
4482
        }
4483
    }
4484
  else
4485
    {
4486
      if (size <= mep_based_cutoff && size > 0)
4487
        secname = "based";
4488
      else if (size <= mep_tiny_cutoff && size > 0)
4489
        secname = "tiny";
4490
      else if (TARGET_L)
4491
        secname = "far";
4492
    }
4493
 
4494
  if (mep_const_section && TREE_READONLY (decl))
4495
    {
4496
      if (strcmp (mep_const_section, "tiny") == 0)
4497
        secname = "tiny";
4498
      else if (strcmp (mep_const_section, "near") == 0)
4499
        return;
4500
      else if (strcmp (mep_const_section, "far") == 0)
4501
        secname = "far";
4502
    }
4503
 
4504
  if (!secname)
4505
    return;
4506
 
4507
  if (!mep_multiple_address_regions (*attributes, true)
4508
      && !mep_multiple_address_regions (DECL_ATTRIBUTES (decl), false))
4509
    {
4510
      attrib = build_tree_list (get_identifier (secname), NULL_TREE);
4511
 
4512
      /* Chain the attribute directly onto the variable's DECL_ATTRIBUTES
4513
         in order to avoid the POINTER_TYPE bypasses in mep_validate_near_far
4514
         and mep_validate_based_tiny.  */
4515
      DECL_ATTRIBUTES (decl) = chainon (DECL_ATTRIBUTES (decl), attrib);
4516
    }
4517
}
4518
 
4519
static void
4520
mep_encode_section_info (tree decl, rtx rtl, int first)
4521
{
4522
  rtx rtlname;
4523
  const char *oldname;
4524
  const char *secname;
4525
  char encoding;
4526
  char *newname;
4527
  tree idp;
4528
  int maxsize;
4529
  tree type;
4530
  tree mep_attributes;
4531
 
4532
  if (! first)
4533
    return;
4534
 
4535
  if (TREE_CODE (decl) != VAR_DECL
4536
      && TREE_CODE (decl) != FUNCTION_DECL)
4537
    return;
4538
 
4539
  rtlname = XEXP (rtl, 0);
4540
  if (GET_CODE (rtlname) == SYMBOL_REF)
4541
    oldname = XSTR (rtlname, 0);
4542
  else if (GET_CODE (rtlname) == MEM
4543
           && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
4544
    oldname = XSTR (XEXP (rtlname, 0), 0);
4545
  else
4546
    gcc_unreachable ();
4547
 
4548
  type = TREE_TYPE (decl);
4549
  if (type == error_mark_node)
4550
    return;
4551
  mep_attributes = MEP_ATTRIBUTES (decl);
4552
 
4553
  encoding = mep_attrlist_to_encoding (mep_attributes, decl);
4554
 
4555
  if (encoding)
4556
    {
4557
      newname = (char *) alloca (strlen (oldname) + 4);
4558
      sprintf (newname, "@%c.%s", encoding, oldname);
4559
      idp = get_identifier (newname);
4560
      XEXP (rtl, 0) =
4561
        gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
4562
      SYMBOL_REF_WEAK (XEXP (rtl, 0)) = DECL_WEAK (decl);
4563
      SET_SYMBOL_REF_DECL (XEXP (rtl, 0), decl);
4564
 
4565
      switch (encoding)
4566
        {
4567
        case 'b':
4568
          maxsize = 128;
4569
          secname = "based";
4570
          break;
4571
        case 't':
4572
          maxsize = 65536;
4573
          secname = "tiny";
4574
          break;
4575
        case 'n':
4576
          maxsize = 0x1000000;
4577
          secname = "near";
4578
          break;
4579
        default:
4580
          maxsize = 0;
4581
          secname = 0;
4582
          break;
4583
        }
4584
      if (maxsize && int_size_in_bytes (TREE_TYPE (decl)) > maxsize)
4585
        {
4586
          warning (0, "variable %s (%ld bytes) is too large for the %s section (%d bytes)",
4587
                   oldname,
4588
                   (long) int_size_in_bytes (TREE_TYPE (decl)),
4589
                   secname,
4590
                   maxsize);
4591
        }
4592
    }
4593
}
4594
 
4595
const char *
4596
mep_strip_name_encoding (const char *sym)
4597
{
4598
  while (1)
4599
    {
4600
      if (*sym == '*')
4601
        sym++;
4602
      else if (*sym == '@' && sym[2] == '.')
4603
        sym += 3;
4604
      else
4605
        return sym;
4606
    }
4607
}
4608
 
4609
static section *
4610
mep_select_section (tree decl, int reloc ATTRIBUTE_UNUSED,
4611
                    unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
4612
{
4613
  int readonly = 1;
4614
  int encoding;
4615
 
4616
  switch (TREE_CODE (decl))
4617
    {
4618
    case VAR_DECL:
4619
      if (!TREE_READONLY (decl)
4620
          || TREE_SIDE_EFFECTS (decl)
4621
          || !DECL_INITIAL (decl)
4622
          || (DECL_INITIAL (decl) != error_mark_node
4623
              && !TREE_CONSTANT (DECL_INITIAL (decl))))
4624
        readonly = 0;
4625
      break;
4626
    case CONSTRUCTOR:
4627
      if (! TREE_CONSTANT (decl))
4628
        readonly = 0;
4629
      break;
4630
 
4631
    default:
4632
      break;
4633
    }
4634
 
4635
  if (TREE_CODE (decl) == FUNCTION_DECL)
4636
    {
4637
      const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
4638
 
4639
      if (name[0] == '@' && name[2] == '.')
4640
        encoding = name[1];
4641
      else
4642
        encoding = 0;
4643
 
4644
      if (flag_function_sections || DECL_ONE_ONLY (decl))
4645
        mep_unique_section (decl, 0);
4646
      else if (lookup_attribute ("vliw", TYPE_ATTRIBUTES (TREE_TYPE (decl))))
4647
        {
4648
          if (encoding == 'f')
4649
            return vftext_section;
4650
          else
4651
            return vtext_section;
4652
        }
4653
      else if (encoding == 'f')
4654
        return ftext_section;
4655
      else
4656
        return text_section;
4657
    }
4658
 
4659
  if (TREE_CODE (decl) == VAR_DECL)
4660
    {
4661
      const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
4662
 
4663
      if (name[0] == '@' && name[2] == '.')
4664
        switch (name[1])
4665
          {
4666
          case 'b':
4667
            return based_section;
4668
 
4669
          case 't':
4670
            if (readonly)
4671
              return srodata_section;
4672
            if (DECL_INITIAL (decl))
4673
              return sdata_section;
4674
            return tinybss_section;
4675
 
4676
          case 'f':
4677
            if (readonly)
4678
              return frodata_section;
4679
            return far_section;
4680
 
4681
          case 'i':
4682
          case 'I':
4683
            error_at (DECL_SOURCE_LOCATION (decl),
4684
                      "variable %D of type %<io%> must be uninitialized", decl);
4685
            return data_section;
4686
 
4687
          case 'c':
4688
            error_at (DECL_SOURCE_LOCATION (decl),
4689
                      "variable %D of type %<cb%> must be uninitialized", decl);
4690
            return data_section;
4691
          }
4692
    }
4693
 
4694
  if (readonly)
4695
    return readonly_data_section;
4696
 
4697
  return data_section;
4698
}
4699
 
4700
static void
4701
mep_unique_section (tree decl, int reloc)
4702
{
4703
  static const char *prefixes[][2] =
4704
  {
4705
    { ".text.",   ".gnu.linkonce.t." },
4706
    { ".rodata.", ".gnu.linkonce.r." },
4707
    { ".data.",   ".gnu.linkonce.d." },
4708
    { ".based.",   ".gnu.linkonce.based." },
4709
    { ".sdata.",   ".gnu.linkonce.s." },
4710
    { ".far.",     ".gnu.linkonce.far." },
4711
    { ".ftext.",   ".gnu.linkonce.ft." },
4712
    { ".frodata.", ".gnu.linkonce.frd." },
4713
    { ".srodata.", ".gnu.linkonce.srd." },
4714
    { ".vtext.",   ".gnu.linkonce.v." },
4715
    { ".vftext.",   ".gnu.linkonce.vf." }
4716
  };
4717
  int sec = 2; /* .data */
4718
  int len;
4719
  const char *name, *prefix;
4720
  char *string;
4721
 
4722
  name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
4723
  if (DECL_RTL (decl))
4724
    name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
4725
 
4726
  if (TREE_CODE (decl) == FUNCTION_DECL)
4727
    {
4728
      if (lookup_attribute ("vliw", TYPE_ATTRIBUTES (TREE_TYPE (decl))))
4729
        sec = 9; /* .vtext */
4730
      else
4731
        sec = 0; /* .text */
4732
    }
4733
  else if (decl_readonly_section (decl, reloc))
4734
    sec = 1; /* .rodata */
4735
 
4736
  if (name[0] == '@' && name[2] == '.')
4737
    {
4738
      switch (name[1])
4739
        {
4740
        case 'b':
4741
          sec = 3; /* .based */
4742
          break;
4743
        case 't':
4744
          if (sec == 1)
4745
            sec = 8; /* .srodata */
4746
          else
4747
            sec = 4; /* .sdata */
4748
          break;
4749
        case 'f':
4750
          if (sec == 0)
4751
            sec = 6; /* .ftext */
4752
          else if (sec == 9)
4753
            sec = 10; /* .vftext */
4754
          else if (sec == 1)
4755
            sec = 7; /* .frodata */
4756
          else
4757
            sec = 5; /* .far. */
4758
          break;
4759
        }
4760
      name += 3;
4761
    }
4762
 
4763
  prefix = prefixes[sec][DECL_ONE_ONLY(decl)];
4764
  len    = strlen (name) + strlen (prefix);
4765
  string = (char *) alloca (len + 1);
4766
 
4767
  sprintf (string, "%s%s", prefix, name);
4768
 
4769
  DECL_SECTION_NAME (decl) = build_string (len, string);
4770
}
4771
 
4772
/* Given a decl, a section name, and whether the decl initializer
4773
   has relocs, choose attributes for the section.  */
4774
 
4775
#define SECTION_MEP_VLIW        SECTION_MACH_DEP
4776
 
4777
static unsigned int
4778
mep_section_type_flags (tree decl, const char *name, int reloc)
4779
{
4780
  unsigned int flags = default_section_type_flags (decl, name, reloc);
4781
 
4782
  if (decl && TREE_CODE (decl) == FUNCTION_DECL
4783
      && lookup_attribute ("vliw", TYPE_ATTRIBUTES (TREE_TYPE (decl))))
4784
    flags |= SECTION_MEP_VLIW;
4785
 
4786
  return flags;
4787
}
4788
 
4789
/* Switch to an arbitrary section NAME with attributes as specified
4790
   by FLAGS.  ALIGN specifies any known alignment requirements for
4791
   the section; 0 if the default should be used.
4792
 
4793
   Differs from the standard ELF version only in support of VLIW mode.  */
4794
 
4795
static void
4796
mep_asm_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_UNUSED)
4797
{
4798
  char flagchars[8], *f = flagchars;
4799
  const char *type;
4800
 
4801
  if (!(flags & SECTION_DEBUG))
4802
    *f++ = 'a';
4803
  if (flags & SECTION_WRITE)
4804
    *f++ = 'w';
4805
  if (flags & SECTION_CODE)
4806
    *f++ = 'x';
4807
  if (flags & SECTION_SMALL)
4808
    *f++ = 's';
4809
  if (flags & SECTION_MEP_VLIW)
4810
    *f++ = 'v';
4811
  *f = '\0';
4812
 
4813
  if (flags & SECTION_BSS)
4814
    type = "nobits";
4815
  else
4816
    type = "progbits";
4817
 
4818
  fprintf (asm_out_file, "\t.section\t%s,\"%s\",@%s\n",
4819
           name, flagchars, type);
4820
 
4821
  if (flags & SECTION_CODE)
4822
    fputs ((flags & SECTION_MEP_VLIW ? "\t.vliw\n" : "\t.core\n"),
4823
           asm_out_file);
4824
}
4825
 
4826
void
4827
mep_output_aligned_common (FILE *stream, tree decl, const char *name,
4828
                           int size, int align, int global)
4829
{
4830
  /* We intentionally don't use mep_section_tag() here.  */
4831
  if (name[0] == '@'
4832
      && (name[1] == 'i' || name[1] == 'I' || name[1] == 'c')
4833
      && name[2] == '.')
4834
    {
4835
      int location = -1;
4836
      tree attr = lookup_attribute ((name[1] == 'c' ? "cb" : "io"),
4837
                                    DECL_ATTRIBUTES (decl));
4838
      if (attr
4839
          && TREE_VALUE (attr)
4840
          && TREE_VALUE (TREE_VALUE(attr)))
4841
        location = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE(attr)));
4842
      if (location == -1)
4843
        return;
4844
      if (global)
4845
        {
4846
          fprintf (stream, "\t.globl\t");
4847
          assemble_name (stream, name);
4848
          fprintf (stream, "\n");
4849
        }
4850
      assemble_name (stream, name);
4851
      fprintf (stream, " = %d\n", location);
4852
      return;
4853
    }
4854
  if (name[0] == '@' && name[2] == '.')
4855
    {
4856
      const char *sec = 0;
4857
      switch (name[1])
4858
        {
4859
        case 'b':
4860
          switch_to_section (based_section);
4861
          sec = ".based";
4862
          break;
4863
        case 't':
4864
          switch_to_section (tinybss_section);
4865
          sec = ".sbss";
4866
          break;
4867
        case 'f':
4868
          switch_to_section (farbss_section);
4869
          sec = ".farbss";
4870
          break;
4871
        }
4872
      if (sec)
4873
        {
4874
          const char *name2;
4875
          int p2align = 0;
4876
 
4877
          while (align > BITS_PER_UNIT)
4878
            {
4879
              align /= 2;
4880
              p2align ++;
4881
            }
4882
          name2 = targetm.strip_name_encoding (name);
4883
          if (global)
4884
            fprintf (stream, "\t.globl\t%s\n", name2);
4885
          fprintf (stream, "\t.p2align %d\n", p2align);
4886
          fprintf (stream, "\t.type\t%s,@object\n", name2);
4887
          fprintf (stream, "\t.size\t%s,%d\n", name2, size);
4888
          fprintf (stream, "%s:\n\t.zero\t%d\n", name2, size);
4889
          return;
4890
        }
4891
    }
4892
 
4893
  if (!global)
4894
    {
4895
      fprintf (stream, "\t.local\t");
4896
      assemble_name (stream, name);
4897
      fprintf (stream, "\n");
4898
    }
4899
  fprintf (stream, "\t.comm\t");
4900
  assemble_name (stream, name);
4901
  fprintf (stream, ",%u,%u\n", size, align / BITS_PER_UNIT);
4902
}
4903
 
4904
/* Trampolines.  */
4905
 
4906
static void
4907
mep_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
4908
{
4909
  rtx addr = XEXP (m_tramp, 0);
4910
  rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
4911
 
4912
  emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__mep_trampoline_helper"),
4913
                     LCT_NORMAL, VOIDmode, 3,
4914
                     addr, Pmode,
4915
                     fnaddr, Pmode,
4916
                     static_chain, Pmode);
4917
}
4918
 
4919
/* Experimental Reorg.  */
4920
 
4921
static bool
4922
mep_mentioned_p (rtx in,
4923
                 rtx reg, /* NULL for mem */
4924
                 int modes_too) /* if nonzero, modes must match also.  */
4925
{
4926
  const char *fmt;
4927
  int i;
4928
  enum rtx_code code;
4929
 
4930
  if (in == 0)
4931
    return false;
4932
  if (reg && GET_CODE (reg) != REG)
4933
    return false;
4934
 
4935
  if (GET_CODE (in) == LABEL_REF)
4936
    return (reg == 0);
4937
 
4938
  code = GET_CODE (in);
4939
 
4940
  switch (code)
4941
    {
4942
    case MEM:
4943
      if (reg)
4944
        return mep_mentioned_p (XEXP (in, 0), reg, modes_too);
4945
      return true;
4946
 
4947
    case REG:
4948
      if (!reg)
4949
        return false;
4950
      if (modes_too && (GET_MODE (in) != GET_MODE (reg)))
4951
        return false;
4952
      return (REGNO (in) == REGNO (reg));
4953
 
4954
    case SCRATCH:
4955
    case CC0:
4956
    case PC:
4957
    case CONST_INT:
4958
    case CONST_DOUBLE:
4959
      return false;
4960
 
4961
    default:
4962
      break;
4963
    }
4964
 
4965
  /* Set's source should be read-only.  */
4966
  if (code == SET && !reg)
4967
    return mep_mentioned_p (SET_DEST (in), reg, modes_too);
4968
 
4969
  fmt = GET_RTX_FORMAT (code);
4970
 
4971
  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
4972
    {
4973
      if (fmt[i] == 'E')
4974
        {
4975
          register int j;
4976
          for (j = XVECLEN (in, i) - 1; j >= 0; j--)
4977
            if (mep_mentioned_p (XVECEXP (in, i, j), reg, modes_too))
4978
              return true;
4979
        }
4980
      else if (fmt[i] == 'e'
4981
               && mep_mentioned_p (XEXP (in, i), reg, modes_too))
4982
        return true;
4983
    }
4984
  return false;
4985
}
4986
 
4987
#define EXPERIMENTAL_REGMOVE_REORG 1
4988
 
4989
#if EXPERIMENTAL_REGMOVE_REORG
4990
 
4991
static int
4992
mep_compatible_reg_class (int r1, int r2)
4993
{
4994
  if (GR_REGNO_P (r1) && GR_REGNO_P (r2))
4995
    return 1;
4996
  if (CR_REGNO_P (r1) && CR_REGNO_P (r2))
4997
    return 1;
4998
  return 0;
4999
}
5000
 
5001
static void
5002
mep_reorg_regmove (rtx insns)
5003
{
5004
  rtx insn, next, pat, follow, *where;
5005
  int count = 0, done = 0, replace, before = 0;
5006
 
5007
  if (dump_file)
5008
    for (insn = insns; insn; insn = NEXT_INSN (insn))
5009
      if (GET_CODE (insn) == INSN)
5010
        before++;
5011
 
5012
  /* We're looking for (set r2 r1) moves where r1 dies, followed by a
5013
     set that uses the r2 and r2 dies there.  We replace r2 with r1
5014
     and see if it's still a valid insn.  If so, delete the first set.
5015
     Copied from reorg.c.  */
5016
 
5017
  while (!done)
5018
    {
5019
      done = 1;
5020
      for (insn = insns; insn; insn = next)
5021
        {
5022
          next = NEXT_INSN (insn);
5023
          if (GET_CODE (insn) != INSN)
5024
            continue;
5025
          pat = PATTERN (insn);
5026
 
5027
          replace = 0;
5028
 
5029
          if (GET_CODE (pat) == SET
5030
              && GET_CODE (SET_SRC (pat)) == REG
5031
              && GET_CODE (SET_DEST (pat)) == REG
5032
              && find_regno_note (insn, REG_DEAD, REGNO (SET_SRC (pat)))
5033
              && mep_compatible_reg_class (REGNO (SET_SRC (pat)), REGNO (SET_DEST (pat))))
5034
            {
5035
              follow = next_nonnote_insn (insn);
5036
              if (dump_file)
5037
                fprintf (dump_file, "superfluous moves: considering %d\n", INSN_UID (insn));
5038
 
5039
              while (follow && GET_CODE (follow) == INSN
5040
                     && GET_CODE (PATTERN (follow)) == SET
5041
                     && !dead_or_set_p (follow, SET_SRC (pat))
5042
                     && !mep_mentioned_p (PATTERN (follow), SET_SRC (pat), 0)
5043
                     && !mep_mentioned_p (PATTERN (follow), SET_DEST (pat), 0))
5044
                {
5045
                  if (dump_file)
5046
                    fprintf (dump_file, "\tskipping %d\n", INSN_UID (follow));
5047
                  follow = next_nonnote_insn (follow);
5048
                }
5049
 
5050
              if (dump_file)
5051
                fprintf (dump_file, "\tfollow is %d\n", INSN_UID (follow));
5052
              if (follow && GET_CODE (follow) == INSN
5053
                  && GET_CODE (PATTERN (follow)) == SET
5054
                  && find_regno_note (follow, REG_DEAD, REGNO (SET_DEST (pat))))
5055
                {
5056
                  if (GET_CODE (SET_DEST (PATTERN (follow))) == REG)
5057
                    {
5058
                      if (mep_mentioned_p (SET_SRC (PATTERN (follow)), SET_DEST (pat), 1))
5059
                        {
5060
                          replace = 1;
5061
                          where = & SET_SRC (PATTERN (follow));
5062
                        }
5063
                    }
5064
                  else if (GET_CODE (SET_DEST (PATTERN (follow))) == MEM)
5065
                    {
5066
                      if (mep_mentioned_p (PATTERN (follow), SET_DEST (pat), 1))
5067
                        {
5068
                          replace = 1;
5069
                          where = & PATTERN (follow);
5070
                        }
5071
                    }
5072
                }
5073
            }
5074
 
5075
          /* If so, follow is the corresponding insn */
5076
          if (replace)
5077
            {
5078
              if (dump_file)
5079
                {
5080
                  rtx x;
5081
 
5082
                  fprintf (dump_file, "----- Candidate for superfluous move deletion:\n\n");
5083
                  for (x = insn; x ;x = NEXT_INSN (x))
5084
                    {
5085
                      print_rtl_single (dump_file, x);
5086
                      if (x == follow)
5087
                        break;
5088
                      fprintf (dump_file, "\n");
5089
                    }
5090
                }
5091
 
5092
              if (validate_replace_rtx_subexp (SET_DEST (pat), SET_SRC (pat),
5093
                                               follow, where))
5094
                {
5095
                  count ++;
5096
                  next = delete_insn (insn);
5097
                  if (dump_file)
5098
                    {
5099
                      fprintf (dump_file, "\n----- Success!  new insn:\n\n");
5100
                      print_rtl_single (dump_file, follow);
5101
                    }
5102
                  done = 0;
5103
                }
5104
            }
5105
        }
5106
    }
5107
 
5108
  if (dump_file)
5109
    {
5110
      fprintf (dump_file, "\n%d insn%s deleted out of %d.\n\n", count, count == 1 ? "" : "s", before);
5111
      fprintf (dump_file, "=====\n");
5112
    }
5113
}
5114
#endif
5115
 
5116
 
5117
/* Figure out where to put LABEL, which is the label for a repeat loop.
5118
   If INCLUDING, LAST_INSN is the last instruction in the loop, otherwise
5119
   the loop ends just before LAST_INSN.  If SHARED, insns other than the
5120
   "repeat" might use LABEL to jump to the loop's continuation point.
5121
 
5122
   Return the last instruction in the adjusted loop.  */
5123
 
5124
static rtx
5125
mep_insert_repeat_label_last (rtx last_insn, rtx label, bool including,
5126
                              bool shared)
5127
{
5128
  rtx next, prev;
5129
  int count = 0, code, icode;
5130
 
5131
  if (dump_file)
5132
    fprintf (dump_file, "considering end of repeat loop at insn %d\n",
5133
             INSN_UID (last_insn));
5134
 
5135
  /* Set PREV to the last insn in the loop.  */
5136
  prev = last_insn;
5137
  if (!including)
5138
    prev = PREV_INSN (prev);
5139
 
5140
  /* Set NEXT to the next insn after the repeat label.  */
5141
  next = last_insn;
5142
  if (!shared)
5143
    while (prev != 0)
5144
      {
5145
        code = GET_CODE (prev);
5146
        if (code == CALL_INSN || code == CODE_LABEL || code == BARRIER)
5147
          break;
5148
 
5149
        if (INSN_P (prev))
5150
          {
5151
            if (GET_CODE (PATTERN (prev)) == SEQUENCE)
5152
              prev = XVECEXP (PATTERN (prev), 0, 1);
5153
 
5154
            /* Other insns that should not be in the last two opcodes.  */
5155
            icode = recog_memoized (prev);
5156
            if (icode < 0
5157
                || icode == CODE_FOR_repeat
5158
                || icode == CODE_FOR_erepeat
5159
                || get_attr_may_trap (prev) == MAY_TRAP_YES)
5160
              break;
5161
 
5162
            /* That leaves JUMP_INSN and INSN.  It will have BImode if it
5163
               is the second instruction in a VLIW bundle.  In that case,
5164
               loop again: if the first instruction also satisfies the
5165
               conditions above then we will reach here again and put
5166
               both of them into the repeat epilogue.  Otherwise both
5167
               should remain outside.  */
5168
            if (GET_MODE (prev) != BImode)
5169
              {
5170
                count++;
5171
                next = prev;
5172
                if (dump_file)
5173
                  print_rtl_single (dump_file, next);
5174
                if (count == 2)
5175
                  break;
5176
              }
5177
          }
5178
        prev = PREV_INSN (prev);
5179
      }
5180
 
5181
  /* See if we're adding the label immediately after the repeat insn.
5182
     If so, we need to separate them with a nop.  */
5183
  prev = prev_real_insn (next);
5184
  if (prev)
5185
    switch (recog_memoized (prev))
5186
      {
5187
      case CODE_FOR_repeat:
5188
      case CODE_FOR_erepeat:
5189
        if (dump_file)
5190
          fprintf (dump_file, "Adding nop inside loop\n");
5191
        emit_insn_before (gen_nop (), next);
5192
        break;
5193
 
5194
      default:
5195
        break;
5196
      }
5197
 
5198
  /* Insert the label.  */
5199
  emit_label_before (label, next);
5200
 
5201
  /* Insert the nops.  */
5202
  if (dump_file && count < 2)
5203
    fprintf (dump_file, "Adding %d nop%s\n\n",
5204
             2 - count, count == 1 ? "" : "s");
5205
 
5206
  for (; count < 2; count++)
5207
    if (including)
5208
      last_insn = emit_insn_after (gen_nop (), last_insn);
5209
    else
5210
      emit_insn_before (gen_nop (), last_insn);
5211
 
5212
  return last_insn;
5213
}
5214
 
5215
 
5216
void
5217
mep_emit_doloop (rtx *operands, int is_end)
5218
{
5219
  rtx tag;
5220
 
5221
  if (cfun->machine->doloop_tags == 0
5222
      || cfun->machine->doloop_tag_from_end == is_end)
5223
    {
5224
      cfun->machine->doloop_tags++;
5225
      cfun->machine->doloop_tag_from_end = is_end;
5226
    }
5227
 
5228
  tag = GEN_INT (cfun->machine->doloop_tags - 1);
5229
  if (is_end)
5230
    emit_jump_insn (gen_doloop_end_internal (operands[0], operands[4], tag));
5231
  else
5232
    emit_insn (gen_doloop_begin_internal (operands[0], operands[0], tag));
5233
}
5234
 
5235
 
5236
/* Code for converting doloop_begins and doloop_ends into valid
5237
   MeP instructions.  A doloop_begin is just a placeholder:
5238
 
5239
        $count = unspec ($count)
5240
 
5241
   where $count is initially the number of iterations - 1.
5242
   doloop_end has the form:
5243
 
5244
        if ($count-- == 0) goto label
5245
 
5246
   The counter variable is private to the doloop insns, nothing else
5247
   relies on its value.
5248
 
5249
   There are three cases, in decreasing order of preference:
5250
 
5251
      1. A loop has exactly one doloop_begin and one doloop_end.
5252
         The doloop_end branches to the first instruction after
5253
         the doloop_begin.
5254
 
5255
         In this case we can replace the doloop_begin with a repeat
5256
         instruction and remove the doloop_end.  I.e.:
5257
 
5258
                $count1 = unspec ($count1)
5259
            label:
5260
                ...
5261
                insn1
5262
                insn2
5263
                if ($count2-- == 0) goto label
5264
 
5265
          becomes:
5266
 
5267
                repeat $count1,repeat_label
5268
            label:
5269
                ...
5270
            repeat_label:
5271
                insn1
5272
                insn2
5273
                # end repeat
5274
 
5275
      2. As for (1), except there are several doloop_ends.  One of them
5276
         (call it X) falls through to a label L.  All the others fall
5277
         through to branches to L.
5278
 
5279
         In this case, we remove X and replace the other doloop_ends
5280
         with branches to the repeat label.  For example:
5281
 
5282
                $count1 = unspec ($count1)
5283
            start:
5284
                ...
5285
                if ($count2-- == 0) goto label
5286
            end:
5287
                ...
5288
                if ($count3-- == 0) goto label
5289
                goto end
5290
 
5291
         becomes:
5292
 
5293
                repeat $count1,repeat_label
5294
            start:
5295
                ...
5296
            repeat_label:
5297
                nop
5298
                nop
5299
                # end repeat
5300
            end:
5301
                ...
5302
                goto repeat_label
5303
 
5304
      3. The fallback case.  Replace doloop_begins with:
5305
 
5306
                $count = $count + 1
5307
 
5308
         Replace doloop_ends with the equivalent of:
5309
 
5310
                $count = $count - 1
5311
                if ($count == 0) goto label
5312
 
5313
         Note that this might need a scratch register if $count
5314
         is stored in memory.  */
5315
 
5316
/* A structure describing one doloop_begin.  */
5317
struct mep_doloop_begin {
5318
  /* The next doloop_begin with the same tag.  */
5319
  struct mep_doloop_begin *next;
5320
 
5321
  /* The instruction itself.  */
5322
  rtx insn;
5323
 
5324
  /* The initial counter value.  This is known to be a general register.  */
5325
  rtx counter;
5326
};
5327
 
5328
/* A structure describing a doloop_end.  */
5329
struct mep_doloop_end {
5330
  /* The next doloop_end with the same loop tag.  */
5331
  struct mep_doloop_end *next;
5332
 
5333
  /* The instruction itself.  */
5334
  rtx insn;
5335
 
5336
  /* The first instruction after INSN when the branch isn't taken.  */
5337
  rtx fallthrough;
5338
 
5339
  /* The location of the counter value.  Since doloop_end_internal is a
5340
     jump instruction, it has to allow the counter to be stored anywhere
5341
     (any non-fixed register or memory location).  */
5342
  rtx counter;
5343
 
5344
  /* The target label (the place where the insn branches when the counter
5345
     isn't zero).  */
5346
  rtx label;
5347
 
5348
  /* A scratch register.  Only available when COUNTER isn't stored
5349
     in a general register.  */
5350
  rtx scratch;
5351
};
5352
 
5353
 
5354
/* One do-while loop.  */
5355
struct mep_doloop {
5356
  /* All the doloop_begins for this loop (in no particular order).  */
5357
  struct mep_doloop_begin *begin;
5358
 
5359
  /* All the doloop_ends.  When there is more than one, arrange things
5360
     so that the first one is the most likely to be X in case (2) above.  */
5361
  struct mep_doloop_end *end;
5362
};
5363
 
5364
 
5365
/* Return true if LOOP can be converted into repeat/repeat_end form
5366
   (that is, if it matches cases (1) or (2) above).  */
5367
 
5368
static bool
5369
mep_repeat_loop_p (struct mep_doloop *loop)
5370
{
5371
  struct mep_doloop_end *end;
5372
  rtx fallthrough;
5373
 
5374
  /* There must be exactly one doloop_begin and at least one doloop_end.  */
5375
  if (loop->begin == 0 || loop->end == 0 || loop->begin->next != 0)
5376
    return false;
5377
 
5378
  /* The first doloop_end (X) must branch back to the insn after
5379
     the doloop_begin.  */
5380
  if (prev_real_insn (loop->end->label) != loop->begin->insn)
5381
    return false;
5382
 
5383
  /* All the other doloop_ends must branch to the same place as X.
5384
     When the branch isn't taken, they must jump to the instruction
5385
     after X.  */
5386
  fallthrough = loop->end->fallthrough;
5387
  for (end = loop->end->next; end != 0; end = end->next)
5388
    if (end->label != loop->end->label
5389
        || !simplejump_p (end->fallthrough)
5390
        || next_real_insn (JUMP_LABEL (end->fallthrough)) != fallthrough)
5391
      return false;
5392
 
5393
  return true;
5394
}
5395
 
5396
 
5397
/* The main repeat reorg function.  See comment above for details.  */
5398
 
5399
static void
5400
mep_reorg_repeat (rtx insns)
5401
{
5402
  rtx insn;
5403
  struct mep_doloop *loops, *loop;
5404
  struct mep_doloop_begin *begin;
5405
  struct mep_doloop_end *end;
5406
 
5407
  /* Quick exit if we haven't created any loops.  */
5408
  if (cfun->machine->doloop_tags == 0)
5409
    return;
5410
 
5411
  /* Create an array of mep_doloop structures.  */
5412
  loops = (struct mep_doloop *) alloca (sizeof (loops[0]) * cfun->machine->doloop_tags);
5413
  memset (loops, 0, sizeof (loops[0]) * cfun->machine->doloop_tags);
5414
 
5415
  /* Search the function for do-while insns and group them by loop tag.  */
5416
  for (insn = insns; insn; insn = NEXT_INSN (insn))
5417
    if (INSN_P (insn))
5418
      switch (recog_memoized (insn))
5419
        {
5420
        case CODE_FOR_doloop_begin_internal:
5421
          insn_extract (insn);
5422
          loop = &loops[INTVAL (recog_data.operand[2])];
5423
 
5424
          begin = (struct mep_doloop_begin *) alloca (sizeof (struct mep_doloop_begin));
5425
          begin->next = loop->begin;
5426
          begin->insn = insn;
5427
          begin->counter = recog_data.operand[0];
5428
 
5429
          loop->begin = begin;
5430
          break;
5431
 
5432
        case CODE_FOR_doloop_end_internal:
5433
          insn_extract (insn);
5434
          loop = &loops[INTVAL (recog_data.operand[2])];
5435
 
5436
          end = (struct mep_doloop_end *) alloca (sizeof (struct mep_doloop_end));
5437
          end->insn = insn;
5438
          end->fallthrough = next_real_insn (insn);
5439
          end->counter = recog_data.operand[0];
5440
          end->label = recog_data.operand[1];
5441
          end->scratch = recog_data.operand[3];
5442
 
5443
          /* If this insn falls through to an unconditional jump,
5444
             give it a lower priority than the others.  */
5445
          if (loop->end != 0 && simplejump_p (end->fallthrough))
5446
            {
5447
              end->next = loop->end->next;
5448
              loop->end->next = end;
5449
            }
5450
          else
5451
            {
5452
              end->next = loop->end;
5453
              loop->end = end;
5454
            }
5455
          break;
5456
        }
5457
 
5458
  /* Convert the insns for each loop in turn.  */
5459
  for (loop = loops; loop < loops + cfun->machine->doloop_tags; loop++)
5460
    if (mep_repeat_loop_p (loop))
5461
      {
5462
        /* Case (1) or (2).  */
5463
        rtx repeat_label, label_ref;
5464
 
5465
        /* Create a new label for the repeat insn.  */
5466
        repeat_label = gen_label_rtx ();
5467
 
5468
        /* Replace the doloop_begin with a repeat.  */
5469
        label_ref = gen_rtx_LABEL_REF (VOIDmode, repeat_label);
5470
        emit_insn_before (gen_repeat (loop->begin->counter, label_ref),
5471
                          loop->begin->insn);
5472
        delete_insn (loop->begin->insn);
5473
 
5474
        /* Insert the repeat label before the first doloop_end.
5475
           Fill the gap with nops if there are other doloop_ends.  */
5476
        mep_insert_repeat_label_last (loop->end->insn, repeat_label,
5477
                                      false, loop->end->next != 0);
5478
 
5479
        /* Emit a repeat_end (to improve the readability of the output).  */
5480
        emit_insn_before (gen_repeat_end (), loop->end->insn);
5481
 
5482
        /* Delete the first doloop_end.  */
5483
        delete_insn (loop->end->insn);
5484
 
5485
        /* Replace the others with branches to REPEAT_LABEL.  */
5486
        for (end = loop->end->next; end != 0; end = end->next)
5487
          {
5488
            emit_jump_insn_before (gen_jump (repeat_label), end->insn);
5489
            delete_insn (end->insn);
5490
            delete_insn (end->fallthrough);
5491
          }
5492
      }
5493
    else
5494
      {
5495
        /* Case (3).  First replace all the doloop_begins with increment
5496
           instructions.  */
5497
        for (begin = loop->begin; begin != 0; begin = begin->next)
5498
          {
5499
            emit_insn_before (gen_add3_insn (copy_rtx (begin->counter),
5500
                                             begin->counter, const1_rtx),
5501
                              begin->insn);
5502
            delete_insn (begin->insn);
5503
          }
5504
 
5505
        /* Replace all the doloop_ends with decrement-and-branch sequences.  */
5506
        for (end = loop->end; end != 0; end = end->next)
5507
          {
5508
            rtx reg;
5509
 
5510
            start_sequence ();
5511
 
5512
            /* Load the counter value into a general register.  */
5513
            reg = end->counter;
5514
            if (!REG_P (reg) || REGNO (reg) > 15)
5515
              {
5516
                reg = end->scratch;
5517
                emit_move_insn (copy_rtx (reg), copy_rtx (end->counter));
5518
              }
5519
 
5520
            /* Decrement the counter.  */
5521
            emit_insn (gen_add3_insn (copy_rtx (reg), copy_rtx (reg),
5522
                                      constm1_rtx));
5523
 
5524
            /* Copy it back to its original location.  */
5525
            if (reg != end->counter)
5526
              emit_move_insn (copy_rtx (end->counter), copy_rtx (reg));
5527
 
5528
            /* Jump back to the start label.  */
5529
            insn = emit_jump_insn (gen_mep_bne_true (reg, const0_rtx,
5530
                                                     end->label));
5531
            JUMP_LABEL (insn) = end->label;
5532
            LABEL_NUSES (end->label)++;
5533
 
5534
            /* Emit the whole sequence before the doloop_end.  */
5535
            insn = get_insns ();
5536
            end_sequence ();
5537
            emit_insn_before (insn, end->insn);
5538
 
5539
            /* Delete the doloop_end.  */
5540
            delete_insn (end->insn);
5541
          }
5542
      }
5543
}
5544
 
5545
 
5546
static bool
5547
mep_invertable_branch_p (rtx insn)
5548
{
5549
  rtx cond, set;
5550
  enum rtx_code old_code;
5551
  int i;
5552
 
5553
  set = PATTERN (insn);
5554
  if (GET_CODE (set) != SET)
5555
    return false;
5556
  if (GET_CODE (XEXP (set, 1)) != IF_THEN_ELSE)
5557
    return false;
5558
  cond = XEXP (XEXP (set, 1), 0);
5559
  old_code = GET_CODE (cond);
5560
  switch (old_code)
5561
    {
5562
    case EQ:
5563
      PUT_CODE (cond, NE);
5564
      break;
5565
    case NE:
5566
      PUT_CODE (cond, EQ);
5567
      break;
5568
    case LT:
5569
      PUT_CODE (cond, GE);
5570
      break;
5571
    case GE:
5572
      PUT_CODE (cond, LT);
5573
      break;
5574
    default:
5575
      return false;
5576
    }
5577
  INSN_CODE (insn) = -1;
5578
  i = recog_memoized (insn);
5579
  PUT_CODE (cond, old_code);
5580
  INSN_CODE (insn) = -1;
5581
  return i >= 0;
5582
}
5583
 
5584
static void
5585
mep_invert_branch (rtx insn, rtx after)
5586
{
5587
  rtx cond, set, label;
5588
  int i;
5589
 
5590
  set = PATTERN (insn);
5591
 
5592
  gcc_assert (GET_CODE (set) == SET);
5593
  gcc_assert (GET_CODE (XEXP (set, 1)) == IF_THEN_ELSE);
5594
 
5595
  cond = XEXP (XEXP (set, 1), 0);
5596
  switch (GET_CODE (cond))
5597
    {
5598
    case EQ:
5599
      PUT_CODE (cond, NE);
5600
      break;
5601
    case NE:
5602
      PUT_CODE (cond, EQ);
5603
      break;
5604
    case LT:
5605
      PUT_CODE (cond, GE);
5606
      break;
5607
    case GE:
5608
      PUT_CODE (cond, LT);
5609
      break;
5610
    default:
5611
      gcc_unreachable ();
5612
    }
5613
  label = gen_label_rtx ();
5614
  emit_label_after (label, after);
5615
  for (i=1; i<=2; i++)
5616
    if (GET_CODE (XEXP (XEXP (set, 1), i)) == LABEL_REF)
5617
      {
5618
        rtx ref = XEXP (XEXP (set, 1), i);
5619
        if (LABEL_NUSES (XEXP (ref, 0)) == 1)
5620
          delete_insn (XEXP (ref, 0));
5621
        XEXP (ref, 0) = label;
5622
        LABEL_NUSES (label) ++;
5623
        JUMP_LABEL (insn) = label;
5624
      }
5625
  INSN_CODE (insn) = -1;
5626
  i = recog_memoized (insn);
5627
  gcc_assert (i >= 0);
5628
}
5629
 
5630
static void
5631
mep_reorg_erepeat (rtx insns)
5632
{
5633
  rtx insn, prev, l, x;
5634
  int count;
5635
 
5636
  for (insn = insns; insn; insn = NEXT_INSN (insn))
5637
    if (JUMP_P (insn)
5638
        && ! JUMP_TABLE_DATA_P (insn)
5639
        && mep_invertable_branch_p (insn))
5640
      {
5641
        if (dump_file)
5642
          {
5643
            fprintf (dump_file, "\n------------------------------\n");
5644
            fprintf (dump_file, "erepeat: considering this jump:\n");
5645
            print_rtl_single (dump_file, insn);
5646
          }
5647
        count = simplejump_p (insn) ? 0 : 1;
5648
        for (prev = PREV_INSN (insn); prev; prev = PREV_INSN (prev))
5649
          {
5650
            if (GET_CODE (prev) == CALL_INSN
5651
                || BARRIER_P (prev))
5652
              break;
5653
 
5654
            if (prev == JUMP_LABEL (insn))
5655
              {
5656
                rtx newlast;
5657
                if (dump_file)
5658
                  fprintf (dump_file, "found loop top, %d insns\n", count);
5659
 
5660
                if (LABEL_NUSES (prev) == 1)
5661
                  /* We're the only user, always safe */ ;
5662
                else if (LABEL_NUSES (prev) == 2)
5663
                  {
5664
                    /* See if there's a barrier before this label.  If
5665
                       so, we know nobody inside the loop uses it.
5666
                       But we must be careful to put the erepeat
5667
                       *after* the label.  */
5668
                    rtx barrier;
5669
                    for (barrier = PREV_INSN (prev);
5670
                         barrier && GET_CODE (barrier) == NOTE;
5671
                         barrier = PREV_INSN (barrier))
5672
                      ;
5673
                    if (barrier && GET_CODE (barrier) != BARRIER)
5674
                      break;
5675
                  }
5676
                else
5677
                  {
5678
                    /* We don't know who else, within or without our loop, uses this */
5679
                    if (dump_file)
5680
                      fprintf (dump_file, "... but there are multiple users, too risky.\n");
5681
                    break;
5682
                  }
5683
 
5684
                /* Generate a label to be used by the erepat insn.  */
5685
                l = gen_label_rtx ();
5686
 
5687
                /* Insert the erepeat after INSN's target label.  */
5688
                x = gen_erepeat (gen_rtx_LABEL_REF (VOIDmode, l));
5689
                LABEL_NUSES (l)++;
5690
                emit_insn_after (x, prev);
5691
 
5692
                /* Insert the erepeat label.  */
5693
                newlast = (mep_insert_repeat_label_last
5694
                           (insn, l, !simplejump_p (insn), false));
5695
                if (simplejump_p (insn))
5696
                  {
5697
                    emit_insn_before (gen_erepeat_end (), insn);
5698
                    delete_insn (insn);
5699
                  }
5700
                else
5701
                  {
5702
                    mep_invert_branch (insn, newlast);
5703
                    emit_insn_after (gen_erepeat_end (), newlast);
5704
                  }
5705
                break;
5706
              }
5707
 
5708
            if (LABEL_P (prev))
5709
              {
5710
                /* A label is OK if there is exactly one user, and we
5711
                   can find that user before the next label.  */
5712
                rtx user = 0;
5713
                int safe = 0;
5714
                if (LABEL_NUSES (prev) == 1)
5715
                  {
5716
                    for (user = PREV_INSN (prev);
5717
                         user && (INSN_P (user) || GET_CODE (user) == NOTE);
5718
                         user = PREV_INSN (user))
5719
                      if (GET_CODE (user) == JUMP_INSN
5720
                          && JUMP_LABEL (user) == prev)
5721
                        {
5722
                          safe = INSN_UID (user);
5723
                          break;
5724
                        }
5725
                  }
5726
                if (!safe)
5727
                  break;
5728
                if (dump_file)
5729
                  fprintf (dump_file, "... ignoring jump from insn %d to %d\n",
5730
                           safe, INSN_UID (prev));
5731
              }
5732
 
5733
            if (INSN_P (prev))
5734
              {
5735
                count ++;
5736
              }
5737
          }
5738
      }
5739
  if (dump_file)
5740
    fprintf (dump_file, "\n==============================\n");
5741
}
5742
 
5743
/* Replace a jump to a return, with a copy of the return.  GCC doesn't
5744
   always do this on its own.  */
5745
 
5746
static void
5747
mep_jmp_return_reorg (rtx insns)
5748
{
5749
  rtx insn, label, ret;
5750
  int ret_code;
5751
 
5752
  for (insn = insns; insn; insn = NEXT_INSN (insn))
5753
    if (simplejump_p (insn))
5754
    {
5755
      /* Find the fist real insn the jump jumps to.  */
5756
      label = ret = JUMP_LABEL (insn);
5757
      while (ret
5758
             && (GET_CODE (ret) == NOTE
5759
                 || GET_CODE (ret) == CODE_LABEL
5760
                 || GET_CODE (PATTERN (ret)) == USE))
5761
        ret = NEXT_INSN (ret);
5762
 
5763
      if (ret)
5764
        {
5765
          /* Is it a return?  */
5766
          ret_code = recog_memoized (ret);
5767
          if (ret_code == CODE_FOR_return_internal
5768
              || ret_code == CODE_FOR_eh_return_internal)
5769
            {
5770
              /* It is.  Replace the jump with a return.  */
5771
              LABEL_NUSES (label) --;
5772
              if (LABEL_NUSES (label) == 0)
5773
                delete_insn (label);
5774
              PATTERN (insn) = copy_rtx (PATTERN (ret));
5775
              INSN_CODE (insn) = -1;
5776
            }
5777
        }
5778
    }
5779
}
5780
 
5781
 
5782
static void
5783
mep_reorg_addcombine (rtx insns)
5784
{
5785
  rtx i, n;
5786
 
5787
  for (i = insns; i; i = NEXT_INSN (i))
5788
    if (INSN_P (i)
5789
        && INSN_CODE (i) == CODE_FOR_addsi3
5790
        && GET_CODE (SET_DEST (PATTERN (i))) == REG
5791
        && GET_CODE (XEXP (SET_SRC (PATTERN (i)), 0)) == REG
5792
        && REGNO (SET_DEST (PATTERN (i))) == REGNO (XEXP (SET_SRC (PATTERN (i)), 0))
5793
        && GET_CODE (XEXP (SET_SRC (PATTERN (i)), 1)) == CONST_INT)
5794
      {
5795
        n = NEXT_INSN (i);
5796
        if (INSN_P (n)
5797
            && INSN_CODE (n) == CODE_FOR_addsi3
5798
            && GET_CODE (SET_DEST (PATTERN (n))) == REG
5799
            && GET_CODE (XEXP (SET_SRC (PATTERN (n)), 0)) == REG
5800
            && REGNO (SET_DEST (PATTERN (n))) == REGNO (XEXP (SET_SRC (PATTERN (n)), 0))
5801
            && GET_CODE (XEXP (SET_SRC (PATTERN (n)), 1)) == CONST_INT)
5802
          {
5803
            int ic = INTVAL (XEXP (SET_SRC (PATTERN (i)), 1));
5804
            int nc = INTVAL (XEXP (SET_SRC (PATTERN (n)), 1));
5805
            if (REGNO (SET_DEST (PATTERN (i))) == REGNO (SET_DEST (PATTERN (n)))
5806
                && ic + nc < 32767
5807
                && ic + nc > -32768)
5808
              {
5809
                XEXP (SET_SRC (PATTERN (i)), 1) = GEN_INT (ic + nc);
5810
                NEXT_INSN (i) = NEXT_INSN (n);
5811
                if (NEXT_INSN (i))
5812
                  PREV_INSN (NEXT_INSN (i)) = i;
5813
              }
5814
          }
5815
      }
5816
}
5817
 
5818
/* If this insn adjusts the stack, return the adjustment, else return
5819
   zero.  */
5820
static int
5821
add_sp_insn_p (rtx insn)
5822
{
5823
  rtx pat;
5824
 
5825
  if (! single_set (insn))
5826
    return 0;
5827
  pat = PATTERN (insn);
5828
  if (GET_CODE (SET_DEST (pat)) != REG)
5829
    return 0;
5830
  if (REGNO (SET_DEST (pat)) != SP_REGNO)
5831
    return 0;
5832
  if (GET_CODE (SET_SRC (pat)) != PLUS)
5833
    return 0;
5834
  if (GET_CODE (XEXP (SET_SRC (pat), 0)) != REG)
5835
    return 0;
5836
  if (REGNO (XEXP (SET_SRC (pat), 0)) != SP_REGNO)
5837
    return 0;
5838
  if (GET_CODE (XEXP (SET_SRC (pat), 1)) != CONST_INT)
5839
    return 0;
5840
  return INTVAL (XEXP (SET_SRC (pat), 1));
5841
}
5842
 
5843
/* Check for trivial functions that set up an unneeded stack
5844
   frame.  */
5845
static void
5846
mep_reorg_noframe (rtx insns)
5847
{
5848
  rtx start_frame_insn;
5849
  rtx end_frame_insn = 0;
5850
  int sp_adjust, sp2;
5851
  rtx sp;
5852
 
5853
  /* The first insn should be $sp = $sp + N */
5854
  while (insns && ! INSN_P (insns))
5855
    insns = NEXT_INSN (insns);
5856
  if (!insns)
5857
    return;
5858
 
5859
  sp_adjust = add_sp_insn_p (insns);
5860
  if (sp_adjust == 0)
5861
    return;
5862
 
5863
  start_frame_insn = insns;
5864
  sp = SET_DEST (PATTERN (start_frame_insn));
5865
 
5866
  insns = next_real_insn (insns);
5867
 
5868
  while (insns)
5869
    {
5870
      rtx next = next_real_insn (insns);
5871
      if (!next)
5872
        break;
5873
 
5874
      sp2 = add_sp_insn_p (insns);
5875
      if (sp2)
5876
        {
5877
          if (end_frame_insn)
5878
            return;
5879
          end_frame_insn = insns;
5880
          if (sp2 != -sp_adjust)
5881
            return;
5882
        }
5883
      else if (mep_mentioned_p (insns, sp, 0))
5884
        return;
5885
      else if (CALL_P (insns))
5886
        return;
5887
 
5888
      insns = next;
5889
    }
5890
 
5891
  if (end_frame_insn)
5892
    {
5893
      delete_insn (start_frame_insn);
5894
      delete_insn (end_frame_insn);
5895
    }
5896
}
5897
 
5898
static void
5899
mep_reorg (void)
5900
{
5901
  rtx insns = get_insns ();
5902
 
5903
  /* We require accurate REG_DEAD notes.  */
5904
  compute_bb_for_insn ();
5905
  df_note_add_problem ();
5906
  df_analyze ();
5907
 
5908
  mep_reorg_addcombine (insns);
5909
#if EXPERIMENTAL_REGMOVE_REORG
5910
  /* VLIW packing has been done already, so we can't just delete things.  */
5911
  if (!mep_vliw_function_p (cfun->decl))
5912
    mep_reorg_regmove (insns);
5913
#endif
5914
  mep_jmp_return_reorg (insns);
5915
  mep_bundle_insns (insns);
5916
  mep_reorg_repeat (insns);
5917
  if (optimize
5918
      && !profile_flag
5919
      && !profile_arc_flag
5920
      && TARGET_OPT_REPEAT
5921
      && (!mep_interrupt_p () || mep_interrupt_saved_reg (RPB_REGNO)))
5922
    mep_reorg_erepeat (insns);
5923
 
5924
  /* This may delete *insns so make sure it's last.  */
5925
  mep_reorg_noframe (insns);
5926
 
5927
  df_finish_pass (false);
5928
}
5929
 
5930
 
5931
 
5932
/*----------------------------------------------------------------------*/
5933
/* Builtins                                                             */
5934
/*----------------------------------------------------------------------*/
5935
 
5936
/* Element X gives the index into cgen_insns[] of the most general
5937
   implementation of intrinsic X.  Unimplemented intrinsics are
5938
   mapped to -1.  */
5939
int mep_intrinsic_insn[ARRAY_SIZE (cgen_intrinsics)];
5940
 
5941
/* Element X gives the index of another instruction that is mapped to
5942
   the same intrinsic as cgen_insns[X].  It is -1 when there is no other
5943
   instruction.
5944
 
5945
   Things are set up so that mep_intrinsic_chain[X] < X.  */
5946
static int mep_intrinsic_chain[ARRAY_SIZE (cgen_insns)];
5947
 
5948
/* The bitmask for the current ISA.  The ISA masks are declared
5949
   in mep-intrin.h.  */
5950
unsigned int mep_selected_isa;
5951
 
5952
struct mep_config {
5953
  const char *config_name;
5954
  unsigned int isa;
5955
};
5956
 
5957
static struct mep_config mep_configs[] = {
5958
#ifdef COPROC_SELECTION_TABLE
5959
  COPROC_SELECTION_TABLE,
5960
#endif
5961
  { 0, 0 }
5962
};
5963
 
5964
/* Initialize the global intrinsics variables above.  */
5965
 
5966
static void
5967
mep_init_intrinsics (void)
5968
{
5969
  size_t i;
5970
 
5971
  /* Set MEP_SELECTED_ISA to the ISA flag for this configuration.  */
5972
  mep_selected_isa = mep_configs[0].isa;
5973
  if (mep_config_string != 0)
5974
    for (i = 0; mep_configs[i].config_name; i++)
5975
      if (strcmp (mep_config_string, mep_configs[i].config_name) == 0)
5976
        {
5977
          mep_selected_isa = mep_configs[i].isa;
5978
          break;
5979
        }
5980
 
5981
  /* Assume all intrinsics are unavailable.  */
5982
  for (i = 0; i < ARRAY_SIZE (mep_intrinsic_insn); i++)
5983
    mep_intrinsic_insn[i] = -1;
5984
 
5985
  /* Build up the global intrinsic tables.  */
5986
  for (i = 0; i < ARRAY_SIZE (cgen_insns); i++)
5987
    if ((cgen_insns[i].isas & mep_selected_isa) != 0)
5988
      {
5989
        mep_intrinsic_chain[i] = mep_intrinsic_insn[cgen_insns[i].intrinsic];
5990
        mep_intrinsic_insn[cgen_insns[i].intrinsic] = i;
5991
      }
5992
  /* See whether we can directly move values between one coprocessor
5993
     register and another.  */
5994
  for (i = 0; i < ARRAY_SIZE (mep_cmov_insns); i++)
5995
    if (MEP_INTRINSIC_AVAILABLE_P (mep_cmov_insns[i]))
5996
      mep_have_copro_copro_moves_p = true;
5997
 
5998
  /* See whether we can directly move values between core and
5999
     coprocessor registers.  */
6000
  mep_have_core_copro_moves_p = (MEP_INTRINSIC_AVAILABLE_P (mep_cmov1)
6001
                                 && MEP_INTRINSIC_AVAILABLE_P (mep_cmov2));
6002
 
6003
  mep_have_core_copro_moves_p = 1;
6004
}
6005
 
6006
/* Declare all available intrinsic functions.  Called once only.  */
6007
 
6008
static tree cp_data_bus_int_type_node;
6009
static tree opaque_vector_type_node;
6010
static tree v8qi_type_node;
6011
static tree v4hi_type_node;
6012
static tree v2si_type_node;
6013
static tree v8uqi_type_node;
6014
static tree v4uhi_type_node;
6015
static tree v2usi_type_node;
6016
 
6017
static tree
6018
mep_cgen_regnum_to_type (enum cgen_regnum_operand_type cr)
6019
{
6020
  switch (cr)
6021
    {
6022
    case cgen_regnum_operand_type_POINTER:      return ptr_type_node;
6023
    case cgen_regnum_operand_type_LONG:         return long_integer_type_node;
6024
    case cgen_regnum_operand_type_ULONG:        return long_unsigned_type_node;
6025
    case cgen_regnum_operand_type_SHORT:        return short_integer_type_node;
6026
    case cgen_regnum_operand_type_USHORT:       return short_unsigned_type_node;
6027
    case cgen_regnum_operand_type_CHAR:         return char_type_node;
6028
    case cgen_regnum_operand_type_UCHAR:        return unsigned_char_type_node;
6029
    case cgen_regnum_operand_type_SI:           return intSI_type_node;
6030
    case cgen_regnum_operand_type_DI:           return intDI_type_node;
6031
    case cgen_regnum_operand_type_VECTOR:       return opaque_vector_type_node;
6032
    case cgen_regnum_operand_type_V8QI:         return v8qi_type_node;
6033
    case cgen_regnum_operand_type_V4HI:         return v4hi_type_node;
6034
    case cgen_regnum_operand_type_V2SI:         return v2si_type_node;
6035
    case cgen_regnum_operand_type_V8UQI:        return v8uqi_type_node;
6036
    case cgen_regnum_operand_type_V4UHI:        return v4uhi_type_node;
6037
    case cgen_regnum_operand_type_V2USI:        return v2usi_type_node;
6038
    case cgen_regnum_operand_type_CP_DATA_BUS_INT: return cp_data_bus_int_type_node;
6039
    default:
6040
      return void_type_node;
6041
    }
6042
}
6043
 
6044
static void
6045
mep_init_builtins (void)
6046
{
6047
  size_t i;
6048
 
6049
  if (TARGET_64BIT_CR_REGS)
6050
    cp_data_bus_int_type_node = long_long_integer_type_node;
6051
  else
6052
    cp_data_bus_int_type_node = long_integer_type_node;
6053
 
6054
  opaque_vector_type_node = build_opaque_vector_type (intQI_type_node, 8);
6055
  v8qi_type_node = build_vector_type (intQI_type_node, 8);
6056
  v4hi_type_node = build_vector_type (intHI_type_node, 4);
6057
  v2si_type_node = build_vector_type (intSI_type_node, 2);
6058
  v8uqi_type_node = build_vector_type (unsigned_intQI_type_node, 8);
6059
  v4uhi_type_node = build_vector_type (unsigned_intHI_type_node, 4);
6060
  v2usi_type_node = build_vector_type (unsigned_intSI_type_node, 2);
6061
 
6062
  (*lang_hooks.decls.pushdecl)
6063
    (build_decl (BUILTINS_LOCATION, TYPE_DECL, get_identifier ("cp_data_bus_int"),
6064
                 cp_data_bus_int_type_node));
6065
 
6066
  (*lang_hooks.decls.pushdecl)
6067
    (build_decl (BUILTINS_LOCATION, TYPE_DECL, get_identifier ("cp_vector"),
6068
                 opaque_vector_type_node));
6069
 
6070
  (*lang_hooks.decls.pushdecl)
6071
    (build_decl (BUILTINS_LOCATION, TYPE_DECL, get_identifier ("cp_v8qi"),
6072
                 v8qi_type_node));
6073
  (*lang_hooks.decls.pushdecl)
6074
    (build_decl (BUILTINS_LOCATION, TYPE_DECL, get_identifier ("cp_v4hi"),
6075
                 v4hi_type_node));
6076
  (*lang_hooks.decls.pushdecl)
6077
    (build_decl (BUILTINS_LOCATION, TYPE_DECL, get_identifier ("cp_v2si"),
6078
                 v2si_type_node));
6079
 
6080
  (*lang_hooks.decls.pushdecl)
6081
    (build_decl (BUILTINS_LOCATION, TYPE_DECL, get_identifier ("cp_v8uqi"),
6082
                 v8uqi_type_node));
6083
  (*lang_hooks.decls.pushdecl)
6084
    (build_decl (BUILTINS_LOCATION, TYPE_DECL, get_identifier ("cp_v4uhi"),
6085
                 v4uhi_type_node));
6086
  (*lang_hooks.decls.pushdecl)
6087
    (build_decl (BUILTINS_LOCATION, TYPE_DECL, get_identifier ("cp_v2usi"),
6088
                 v2usi_type_node));
6089
 
6090
  /* Intrinsics like mep_cadd3 are implemented with two groups of
6091
     instructions, one which uses UNSPECs and one which uses a specific
6092
     rtl code such as PLUS.  Instructions in the latter group belong
6093
     to GROUP_KNOWN_CODE.
6094
 
6095
     In such cases, the intrinsic will have two entries in the global
6096
     tables above.  The unspec form is accessed using builtin functions
6097
     while the specific form is accessed using the mep_* enum in
6098
     mep-intrin.h.
6099
 
6100
     The idea is that __cop arithmetic and builtin functions have
6101
     different optimization requirements.  If mep_cadd3() appears in
6102
     the source code, the user will surely except gcc to use cadd3
6103
     rather than a work-alike such as add3.  However, if the user
6104
     just writes "a + b", where a or b are __cop variables, it is
6105
     reasonable for gcc to choose a core instruction rather than
6106
     cadd3 if it believes that is more optimal.  */
6107
  for (i = 0; i < ARRAY_SIZE (cgen_insns); i++)
6108
    if ((cgen_insns[i].groups & GROUP_KNOWN_CODE) == 0
6109
        && mep_intrinsic_insn[cgen_insns[i].intrinsic] >= 0)
6110
      {
6111
        tree ret_type = void_type_node;
6112
        tree bi_type;
6113
 
6114
        if (i > 0 && cgen_insns[i].intrinsic == cgen_insns[i-1].intrinsic)
6115
          continue;
6116
 
6117
        if (cgen_insns[i].cret_p)
6118
          ret_type = mep_cgen_regnum_to_type (cgen_insns[i].regnums[0].type);
6119
 
6120
        bi_type = build_function_type_list (ret_type, NULL_TREE);
6121
        add_builtin_function (cgen_intrinsics[cgen_insns[i].intrinsic],
6122
                              bi_type,
6123
                              cgen_insns[i].intrinsic, BUILT_IN_MD, NULL, NULL);
6124
      }
6125
}
6126
 
6127
/* Report the unavailablity of the given intrinsic.  */
6128
 
6129
#if 1
6130
static void
6131
mep_intrinsic_unavailable (int intrinsic)
6132
{
6133
  static int already_reported_p[ARRAY_SIZE (cgen_intrinsics)];
6134
 
6135
  if (already_reported_p[intrinsic])
6136
    return;
6137
 
6138
  if (mep_intrinsic_insn[intrinsic] < 0)
6139
    error ("coprocessor intrinsic %qs is not available in this configuration",
6140
           cgen_intrinsics[intrinsic]);
6141
  else if (CGEN_CURRENT_GROUP == GROUP_VLIW)
6142
    error ("%qs is not available in VLIW functions",
6143
           cgen_intrinsics[intrinsic]);
6144
  else
6145
    error ("%qs is not available in non-VLIW functions",
6146
           cgen_intrinsics[intrinsic]);
6147
 
6148
  already_reported_p[intrinsic] = 1;
6149
}
6150
#endif
6151
 
6152
 
6153
/* See if any implementation of INTRINSIC is available to the
6154
   current function.  If so, store the most general implementation
6155
   in *INSN_PTR and return true.  Return false otherwise.  */
6156
 
6157
static bool
6158
mep_get_intrinsic_insn (int intrinsic ATTRIBUTE_UNUSED, const struct cgen_insn **insn_ptr ATTRIBUTE_UNUSED)
6159
{
6160
  int i;
6161
 
6162
  i = mep_intrinsic_insn[intrinsic];
6163
  while (i >= 0 && !CGEN_ENABLE_INSN_P (i))
6164
    i = mep_intrinsic_chain[i];
6165
 
6166
  if (i >= 0)
6167
    {
6168
      *insn_ptr = &cgen_insns[i];
6169
      return true;
6170
    }
6171
  return false;
6172
}
6173
 
6174
 
6175
/* Like mep_get_intrinsic_insn, but with extra handling for moves.
6176
   If INTRINSIC is mep_cmov, but there is no pure CR <- CR move insn,
6177
   try using a work-alike instead.  In this case, the returned insn
6178
   may have three operands rather than two.  */
6179
 
6180
static bool
6181
mep_get_move_insn (int intrinsic, const struct cgen_insn **cgen_insn)
6182
{
6183
  size_t i;
6184
 
6185
  if (intrinsic == mep_cmov)
6186
    {
6187
      for (i = 0; i < ARRAY_SIZE (mep_cmov_insns); i++)
6188
        if (mep_get_intrinsic_insn (mep_cmov_insns[i], cgen_insn))
6189
          return true;
6190
      return false;
6191
    }
6192
  return mep_get_intrinsic_insn (intrinsic, cgen_insn);
6193
}
6194
 
6195
 
6196
/* If ARG is a register operand that is the same size as MODE, convert it
6197
   to MODE using a subreg.  Otherwise return ARG as-is.  */
6198
 
6199
static rtx
6200
mep_convert_arg (enum machine_mode mode, rtx arg)
6201
{
6202
  if (GET_MODE (arg) != mode
6203
      && register_operand (arg, VOIDmode)
6204
      && GET_MODE_SIZE (GET_MODE (arg)) == GET_MODE_SIZE (mode))
6205
    return simplify_gen_subreg (mode, arg, GET_MODE (arg), 0);
6206
  return arg;
6207
}
6208
 
6209
 
6210
/* Apply regnum conversions to ARG using the description given by REGNUM.
6211
   Return the new argument on success and null on failure.  */
6212
 
6213
static rtx
6214
mep_convert_regnum (const struct cgen_regnum_operand *regnum, rtx arg)
6215
{
6216
  if (regnum->count == 0)
6217
    return arg;
6218
 
6219
  if (GET_CODE (arg) != CONST_INT
6220
      || INTVAL (arg) < 0
6221
      || INTVAL (arg) >= regnum->count)
6222
    return 0;
6223
 
6224
  return gen_rtx_REG (SImode, INTVAL (arg) + regnum->base);
6225
}
6226
 
6227
 
6228
/* Try to make intrinsic argument ARG match the given operand.
6229
   UNSIGNED_P is true if the argument has an unsigned type.  */
6230
 
6231
static rtx
6232
mep_legitimize_arg (const struct insn_operand_data *operand, rtx arg,
6233
                    int unsigned_p)
6234
{
6235
  if (GET_CODE (arg) == CONST_INT)
6236
    {
6237
      /* CONST_INTs can only be bound to integer operands.  */
6238
      if (GET_MODE_CLASS (operand->mode) != MODE_INT)
6239
        return 0;
6240
    }
6241
  else if (GET_CODE (arg) == CONST_DOUBLE)
6242
    /* These hold vector constants.  */;
6243
  else if (GET_MODE_SIZE (GET_MODE (arg)) != GET_MODE_SIZE (operand->mode))
6244
    {
6245
      /* If the argument is a different size from what's expected, we must
6246
         have a value in the right mode class in order to convert it.  */
6247
      if (GET_MODE_CLASS (operand->mode) != GET_MODE_CLASS (GET_MODE (arg)))
6248
        return 0;
6249
 
6250
      /* If the operand is an rvalue, promote or demote it to match the
6251
         operand's size.  This might not need extra instructions when
6252
         ARG is a register value.  */
6253
      if (operand->constraint[0] != '=')
6254
        arg = convert_to_mode (operand->mode, arg, unsigned_p);
6255
    }
6256
 
6257
  /* If the operand is an lvalue, bind the operand to a new register.
6258
     The caller will copy this value into ARG after the main
6259
     instruction.  By doing this always, we produce slightly more
6260
     optimal code.  */
6261
  /* But not for control registers.  */
6262
  if (operand->constraint[0] == '='
6263
      && (! REG_P (arg)
6264
          || ! (CONTROL_REGNO_P (REGNO (arg))
6265
                || CCR_REGNO_P (REGNO (arg))
6266
                || CR_REGNO_P (REGNO (arg)))
6267
          ))
6268
    return gen_reg_rtx (operand->mode);
6269
 
6270
  /* Try simple mode punning.  */
6271
  arg = mep_convert_arg (operand->mode, arg);
6272
  if (operand->predicate (arg, operand->mode))
6273
    return arg;
6274
 
6275
  /* See if forcing the argument into a register will make it match.  */
6276
  if (GET_CODE (arg) == CONST_INT || GET_CODE (arg) == CONST_DOUBLE)
6277
    arg = force_reg (operand->mode, arg);
6278
  else
6279
    arg = mep_convert_arg (operand->mode, force_reg (GET_MODE (arg), arg));
6280
  if (operand->predicate (arg, operand->mode))
6281
    return arg;
6282
 
6283
  return 0;
6284
}
6285
 
6286
 
6287
/* Report that ARG cannot be passed to argument ARGNUM of intrinsic
6288
   function FNNAME.  OPERAND describes the operand to which ARGNUM
6289
   is mapped.  */
6290
 
6291
static void
6292
mep_incompatible_arg (const struct insn_operand_data *operand, rtx arg,
6293
                      int argnum, tree fnname)
6294
{
6295
  size_t i;
6296
 
6297
  if (GET_CODE (arg) == CONST_INT)
6298
    for (i = 0; i < ARRAY_SIZE (cgen_immediate_predicates); i++)
6299
      if (operand->predicate == cgen_immediate_predicates[i].predicate)
6300
        {
6301
          const struct cgen_immediate_predicate *predicate;
6302
          HOST_WIDE_INT argval;
6303
 
6304
          predicate = &cgen_immediate_predicates[i];
6305
          argval = INTVAL (arg);
6306
          if (argval < predicate->lower || argval >= predicate->upper)
6307
            error ("argument %d of %qE must be in the range %d...%d",
6308
                   argnum, fnname, predicate->lower, predicate->upper - 1);
6309
          else
6310
            error ("argument %d of %qE must be a multiple of %d",
6311
                   argnum, fnname, predicate->align);
6312
          return;
6313
        }
6314
 
6315
  error ("incompatible type for argument %d of %qE", argnum, fnname);
6316
}
6317
 
6318
static rtx
6319
mep_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
6320
                    rtx subtarget ATTRIBUTE_UNUSED,
6321
                    enum machine_mode mode ATTRIBUTE_UNUSED,
6322
                    int ignore ATTRIBUTE_UNUSED)
6323
{
6324
  rtx pat, op[10], arg[10];
6325
  unsigned int a;
6326
  int opindex, unsigned_p[10];
6327
  tree fndecl, args;
6328
  unsigned int n_args;
6329
  tree fnname;
6330
  const struct cgen_insn *cgen_insn;
6331
  const struct insn_data_d *idata;
6332
  unsigned int first_arg = 0;
6333
  unsigned int builtin_n_args;
6334
 
6335
  fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
6336
  fnname = DECL_NAME (fndecl);
6337
 
6338
  /* Find out which instruction we should emit.  Note that some coprocessor
6339
     intrinsics may only be available in VLIW mode, or only in normal mode.  */
6340
  if (!mep_get_intrinsic_insn (DECL_FUNCTION_CODE (fndecl), &cgen_insn))
6341
    {
6342
      mep_intrinsic_unavailable (DECL_FUNCTION_CODE (fndecl));
6343
      return NULL_RTX;
6344
    }
6345
  idata = &insn_data[cgen_insn->icode];
6346
 
6347
  builtin_n_args = cgen_insn->num_args;
6348
 
6349
  if (cgen_insn->cret_p)
6350
    {
6351
      if (cgen_insn->cret_p > 1)
6352
        builtin_n_args ++;
6353
      first_arg = 1;
6354
      mep_cgen_regnum_to_type (cgen_insn->regnums[0].type);
6355
      builtin_n_args --;
6356
    }
6357
 
6358
  /* Evaluate each argument.  */
6359
  n_args = call_expr_nargs (exp);
6360
 
6361
  if (n_args < builtin_n_args)
6362
    {
6363
      error ("too few arguments to %qE", fnname);
6364
      return NULL_RTX;
6365
    }
6366
  if (n_args > builtin_n_args)
6367
    {
6368
      error ("too many arguments to %qE", fnname);
6369
      return NULL_RTX;
6370
    }
6371
 
6372
  for (a = first_arg; a < builtin_n_args + first_arg; a++)
6373
    {
6374
      tree value;
6375
 
6376
      args = CALL_EXPR_ARG (exp, a - first_arg);
6377
 
6378
      value = args;
6379
 
6380
#if 0
6381
      if (cgen_insn->regnums[a].reference_p)
6382
        {
6383
          if (TREE_CODE (value) != ADDR_EXPR)
6384
            {
6385
              debug_tree(value);
6386
              error ("argument %d of %qE must be an address", a+1, fnname);
6387
              return NULL_RTX;
6388
            }
6389
          value = TREE_OPERAND (value, 0);
6390
        }
6391
#endif
6392
 
6393
      /* If the argument has been promoted to int, get the unpromoted
6394
         value.  This is necessary when sub-int memory values are bound
6395
         to reference parameters.  */
6396
      if (TREE_CODE (value) == NOP_EXPR
6397
          && TREE_TYPE (value) == integer_type_node
6398
          && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0)))
6399
          && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))
6400
              < TYPE_PRECISION (TREE_TYPE (value))))
6401
        value = TREE_OPERAND (value, 0);
6402
 
6403
      /* If the argument has been promoted to double, get the unpromoted
6404
         SFmode value.  This is necessary for FMAX support, for example.  */
6405
      if (TREE_CODE (value) == NOP_EXPR
6406
          && SCALAR_FLOAT_TYPE_P (TREE_TYPE (value))
6407
          && SCALAR_FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0)))
6408
          && TYPE_MODE (TREE_TYPE (value)) == DFmode
6409
          && TYPE_MODE (TREE_TYPE (TREE_OPERAND (value, 0))) == SFmode)
6410
        value = TREE_OPERAND (value, 0);
6411
 
6412
      unsigned_p[a] = TYPE_UNSIGNED (TREE_TYPE (value));
6413
      arg[a] = expand_expr (value, NULL, VOIDmode, EXPAND_NORMAL);
6414
      arg[a] = mep_convert_regnum (&cgen_insn->regnums[a], arg[a]);
6415
      if (cgen_insn->regnums[a].reference_p)
6416
        {
6417
          tree pointed_to = TREE_TYPE (TREE_TYPE (value));
6418
          enum machine_mode pointed_mode = TYPE_MODE (pointed_to);
6419
 
6420
          arg[a] = gen_rtx_MEM (pointed_mode, arg[a]);
6421
        }
6422
      if (arg[a] == 0)
6423
        {
6424
          error ("argument %d of %qE must be in the range %d...%d",
6425
                 a + 1, fnname, 0, cgen_insn->regnums[a].count - 1);
6426
          return NULL_RTX;
6427
        }
6428
    }
6429
 
6430
  for (a = 0; a < first_arg; a++)
6431
    {
6432
      if (a == 0 && target && GET_MODE (target) == idata->operand[0].mode)
6433
        arg[a] = target;
6434
      else
6435
        arg[a] = gen_reg_rtx (idata->operand[0].mode);
6436
    }
6437
 
6438
  /* Convert the arguments into a form suitable for the intrinsic.
6439
     Report an error if this isn't possible.  */
6440
  for (opindex = 0; opindex < idata->n_operands; opindex++)
6441
    {
6442
      a = cgen_insn->op_mapping[opindex];
6443
      op[opindex] = mep_legitimize_arg (&idata->operand[opindex],
6444
                                        arg[a], unsigned_p[a]);
6445
      if (op[opindex] == 0)
6446
        {
6447
          mep_incompatible_arg (&idata->operand[opindex],
6448
                                arg[a], a + 1 - first_arg, fnname);
6449
          return NULL_RTX;
6450
        }
6451
    }
6452
 
6453
  /* Emit the instruction.  */
6454
  pat = idata->genfun (op[0], op[1], op[2], op[3], op[4],
6455
                       op[5], op[6], op[7], op[8], op[9]);
6456
 
6457
  if (GET_CODE (pat) == SET
6458
      && GET_CODE (SET_DEST (pat)) == PC
6459
      && GET_CODE (SET_SRC (pat)) == IF_THEN_ELSE)
6460
    emit_jump_insn (pat);
6461
  else
6462
    emit_insn (pat);
6463
 
6464
  /* Copy lvalues back to their final locations.  */
6465
  for (opindex = 0; opindex < idata->n_operands; opindex++)
6466
    if (idata->operand[opindex].constraint[0] == '=')
6467
      {
6468
        a = cgen_insn->op_mapping[opindex];
6469
        if (a >= first_arg)
6470
          {
6471
            if (GET_MODE_CLASS (GET_MODE (arg[a]))
6472
                != GET_MODE_CLASS (GET_MODE (op[opindex])))
6473
              emit_move_insn (arg[a], gen_lowpart (GET_MODE (arg[a]),
6474
                                                   op[opindex]));
6475
            else
6476
              {
6477
                /* First convert the operand to the right mode, then copy it
6478
                   into the destination.  Doing the conversion as a separate
6479
                   step (rather than using convert_move) means that we can
6480
                   avoid creating no-op moves when ARG[A] and OP[OPINDEX]
6481
                   refer to the same register.  */
6482
                op[opindex] = convert_to_mode (GET_MODE (arg[a]),
6483
                                               op[opindex], unsigned_p[a]);
6484
                if (!rtx_equal_p (arg[a], op[opindex]))
6485
                  emit_move_insn (arg[a], op[opindex]);
6486
              }
6487
          }
6488
      }
6489
 
6490
  if (first_arg > 0 && target && target != op[0])
6491
    {
6492
      emit_move_insn (target, op[0]);
6493
    }
6494
 
6495
  return target;
6496
}
6497
 
6498
static bool
6499
mep_vector_mode_supported_p (enum machine_mode mode ATTRIBUTE_UNUSED)
6500
{
6501
  return false;
6502
}
6503
 
6504
/* A subroutine of global_reg_mentioned_p, returns 1 if *LOC mentions
6505
   a global register.  */
6506
 
6507
static int
6508
global_reg_mentioned_p_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
6509
{
6510
  int regno;
6511
  rtx x = *loc;
6512
 
6513
  if (! x)
6514
    return 0;
6515
 
6516
  switch (GET_CODE (x))
6517
    {
6518
    case SUBREG:
6519
      if (REG_P (SUBREG_REG (x)))
6520
        {
6521
          if (REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER
6522
              && global_regs[subreg_regno (x)])
6523
            return 1;
6524
          return 0;
6525
        }
6526
      break;
6527
 
6528
    case REG:
6529
      regno = REGNO (x);
6530
      if (regno < FIRST_PSEUDO_REGISTER && global_regs[regno])
6531
        return 1;
6532
      return 0;
6533
 
6534
    case SCRATCH:
6535
    case PC:
6536
    case CC0:
6537
    case CONST_INT:
6538
    case CONST_DOUBLE:
6539
    case CONST:
6540
    case LABEL_REF:
6541
      return 0;
6542
 
6543
    case CALL:
6544
      /* A non-constant call might use a global register.  */
6545
      return 1;
6546
 
6547
    default:
6548
      break;
6549
    }
6550
 
6551
  return 0;
6552
}
6553
 
6554
/* Returns nonzero if X mentions a global register.  */
6555
 
6556
static int
6557
global_reg_mentioned_p (rtx x)
6558
{
6559
  if (INSN_P (x))
6560
    {
6561
      if (CALL_P (x))
6562
        {
6563
          if (! RTL_CONST_OR_PURE_CALL_P (x))
6564
            return 1;
6565
          x = CALL_INSN_FUNCTION_USAGE (x);
6566
          if (x == 0)
6567
            return 0;
6568
        }
6569
      else
6570
        x = PATTERN (x);
6571
    }
6572
 
6573
  return for_each_rtx (&x, global_reg_mentioned_p_1, NULL);
6574
}
6575
/* Scheduling hooks for VLIW mode.
6576
 
6577
   Conceptually this is very simple: we have a two-pack architecture
6578
   that takes one core insn and one coprocessor insn to make up either
6579
   a 32- or 64-bit instruction word (depending on the option bit set in
6580
   the chip).  I.e. in VL32 mode, we can pack one 16-bit core insn and
6581
   one 16-bit cop insn; in VL64 mode we can pack one 16-bit core insn
6582
   and one 48-bit cop insn or two 32-bit core/cop insns.
6583
 
6584
   In practice, instruction selection will be a bear.  Consider in
6585
   VL64 mode the following insns
6586
 
6587
        add $1, 1
6588
        cmov $cr0, $0
6589
 
6590
   these cannot pack, since the add is a 16-bit core insn and cmov
6591
   is a 32-bit cop insn.  However,
6592
 
6593
        add3 $1, $1, 1
6594
        cmov $cr0, $0
6595
 
6596
   packs just fine.  For good VLIW code generation in VL64 mode, we
6597
   will have to have 32-bit alternatives for many of the common core
6598
   insns.  Not implemented.  */
6599
 
6600
static int
6601
mep_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
6602
{
6603
  int cost_specified;
6604
 
6605
  if (REG_NOTE_KIND (link) != 0)
6606
    {
6607
      /* See whether INSN and DEP_INSN are intrinsics that set the same
6608
         hard register.  If so, it is more important to free up DEP_INSN
6609
         than it is to free up INSN.
6610
 
6611
         Note that intrinsics like mep_mulr are handled differently from
6612
         the equivalent mep.md patterns.  In mep.md, if we don't care
6613
         about the value of $lo and $hi, the pattern will just clobber
6614
         the registers, not set them.  Since clobbers don't count as
6615
         output dependencies, it is often possible to reorder two mulrs,
6616
         even after reload.
6617
 
6618
         In contrast, mep_mulr() sets both $lo and $hi to specific values,
6619
         so any pair of mep_mulr()s will be inter-dependent.   We should
6620
         therefore give the first mep_mulr() a higher priority.  */
6621
      if (REG_NOTE_KIND (link) == REG_DEP_OUTPUT
6622
          && global_reg_mentioned_p (PATTERN (insn))
6623
          && global_reg_mentioned_p (PATTERN (dep_insn)))
6624
        return 1;
6625
 
6626
      /* If the dependence is an anti or output dependence, assume it
6627
         has no cost.  */
6628
      return 0;
6629
    }
6630
 
6631
  /* If we can't recognize the insns, we can't really do anything.  */
6632
  if (recog_memoized (dep_insn) < 0)
6633
    return cost;
6634
 
6635
  /* The latency attribute doesn't apply to MeP-h1: we use the stall
6636
     attribute instead.  */
6637
  if (!TARGET_H1)
6638
    {
6639
      cost_specified = get_attr_latency (dep_insn);
6640
      if (cost_specified != 0)
6641
        return cost_specified;
6642
    }
6643
 
6644
  return cost;
6645
}
6646
 
6647
/* ??? We don't properly compute the length of a load/store insn,
6648
   taking into account the addressing mode.  */
6649
 
6650
static int
6651
mep_issue_rate (void)
6652
{
6653
  return TARGET_IVC2 ? 3 : 2;
6654
}
6655
 
6656
/* Return true if function DECL was declared with the vliw attribute.  */
6657
 
6658
bool
6659
mep_vliw_function_p (tree decl)
6660
{
6661
  return lookup_attribute ("vliw", TYPE_ATTRIBUTES (TREE_TYPE (decl))) != 0;
6662
}
6663
 
6664
static rtx
6665
mep_find_ready_insn (rtx *ready, int nready, enum attr_slot slot, int length)
6666
{
6667
  int i;
6668
 
6669
  for (i = nready - 1; i >= 0; --i)
6670
    {
6671
      rtx insn = ready[i];
6672
      if (recog_memoized (insn) >= 0
6673
          && get_attr_slot (insn) == slot
6674
          && get_attr_length (insn) == length)
6675
        return insn;
6676
    }
6677
 
6678
  return NULL_RTX;
6679
}
6680
 
6681
static void
6682
mep_move_ready_insn (rtx *ready, int nready, rtx insn)
6683
{
6684
  int i;
6685
 
6686
  for (i = 0; i < nready; ++i)
6687
    if (ready[i] == insn)
6688
      {
6689
        for (; i < nready - 1; ++i)
6690
          ready[i] = ready[i + 1];
6691
        ready[i] = insn;
6692
        return;
6693
      }
6694
 
6695
  gcc_unreachable ();
6696
}
6697
 
6698
static void
6699
mep_print_sched_insn (FILE *dump, rtx insn)
6700
{
6701
  const char *slots = "none";
6702
  const char *name = NULL;
6703
  int code;
6704
  char buf[30];
6705
 
6706
  if (GET_CODE (PATTERN (insn)) == SET
6707
      || GET_CODE (PATTERN (insn)) == PARALLEL)
6708
    {
6709
      switch (get_attr_slots (insn))
6710
        {
6711
        case SLOTS_CORE: slots = "core"; break;
6712
        case SLOTS_C3: slots = "c3"; break;
6713
        case SLOTS_P0: slots = "p0"; break;
6714
        case SLOTS_P0_P0S: slots = "p0,p0s"; break;
6715
        case SLOTS_P0_P1: slots = "p0,p1"; break;
6716
        case SLOTS_P0S: slots = "p0s"; break;
6717
        case SLOTS_P0S_P1: slots = "p0s,p1"; break;
6718
        case SLOTS_P1: slots = "p1"; break;
6719
        default:
6720
          sprintf(buf, "%d", get_attr_slots (insn));
6721
          slots = buf;
6722
          break;
6723
        }
6724
    }
6725
  if (GET_CODE (PATTERN (insn)) == USE)
6726
    slots = "use";
6727
 
6728
  code = INSN_CODE (insn);
6729
  if (code >= 0)
6730
    name = get_insn_name (code);
6731
  if (!name)
6732
    name = "{unknown}";
6733
 
6734
  fprintf (dump,
6735
           "insn %4d %4d  %8s  %s\n",
6736
           code,
6737
           INSN_UID (insn),
6738
           name,
6739
           slots);
6740
}
6741
 
6742
static int
6743
mep_sched_reorder (FILE *dump ATTRIBUTE_UNUSED,
6744
                   int sched_verbose ATTRIBUTE_UNUSED, rtx *ready,
6745
                   int *pnready, int clock ATTRIBUTE_UNUSED)
6746
{
6747
  int nready = *pnready;
6748
  rtx core_insn, cop_insn;
6749
  int i;
6750
 
6751
  if (dump && sched_verbose > 1)
6752
    {
6753
      fprintf (dump, "\nsched_reorder: clock %d nready %d\n", clock, nready);
6754
      for (i=0; i<nready; i++)
6755
        mep_print_sched_insn (dump, ready[i]);
6756
      fprintf (dump, "\n");
6757
    }
6758
 
6759
  if (!mep_vliw_function_p (cfun->decl))
6760
    return 1;
6761
  if (nready < 2)
6762
    return 1;
6763
 
6764
  /* IVC2 uses a DFA to determine what's ready and what's not. */
6765
  if (TARGET_IVC2)
6766
    return nready;
6767
 
6768
  /* We can issue either a core or coprocessor instruction.
6769
     Look for a matched pair of insns to reorder.  If we don't
6770
     find any, don't second-guess the scheduler's priorities.  */
6771
 
6772
  if ((core_insn = mep_find_ready_insn (ready, nready, SLOT_CORE, 2))
6773
      && (cop_insn = mep_find_ready_insn (ready, nready, SLOT_COP,
6774
                                          TARGET_OPT_VL64 ? 6 : 2)))
6775
    ;
6776
  else if (TARGET_OPT_VL64
6777
           && (core_insn = mep_find_ready_insn (ready, nready, SLOT_CORE, 4))
6778
           && (cop_insn = mep_find_ready_insn (ready, nready, SLOT_COP, 4)))
6779
    ;
6780
  else
6781
    /* We didn't find a pair.  Issue the single insn at the head
6782
       of the ready list.  */
6783
    return 1;
6784
 
6785
  /* Reorder the two insns first.  */
6786
  mep_move_ready_insn (ready, nready, core_insn);
6787
  mep_move_ready_insn (ready, nready - 1, cop_insn);
6788
  return 2;
6789
}
6790
 
6791
/* A for_each_rtx callback.  Return true if *X is a register that is
6792
   set by insn PREV.  */
6793
 
6794
static int
6795
mep_store_find_set (rtx *x, void *prev)
6796
{
6797
  return REG_P (*x) && reg_set_p (*x, (const_rtx) prev);
6798
}
6799
 
6800
/* Like mep_store_bypass_p, but takes a pattern as the second argument,
6801
   not the containing insn.  */
6802
 
6803
static bool
6804
mep_store_data_bypass_1 (rtx prev, rtx pat)
6805
{
6806
  /* Cope with intrinsics like swcpa.  */
6807
  if (GET_CODE (pat) == PARALLEL)
6808
    {
6809
      int i;
6810
 
6811
      for (i = 0; i < XVECLEN (pat, 0); i++)
6812
        if (mep_store_data_bypass_p (prev, XVECEXP (pat, 0, i)))
6813
          return true;
6814
 
6815
      return false;
6816
    }
6817
 
6818
  /* Check for some sort of store.  */
6819
  if (GET_CODE (pat) != SET
6820
      || GET_CODE (SET_DEST (pat)) != MEM)
6821
    return false;
6822
 
6823
  /* Intrinsics use patterns of the form (set (mem (scratch)) (unspec ...)).
6824
     The first operand to the unspec is the store data and the other operands
6825
     are used to calculate the address.  */
6826
  if (GET_CODE (SET_SRC (pat)) == UNSPEC)
6827
    {
6828
      rtx src;
6829
      int i;
6830
 
6831
      src = SET_SRC (pat);
6832
      for (i = 1; i < XVECLEN (src, 0); i++)
6833
        if (for_each_rtx (&XVECEXP (src, 0, i), mep_store_find_set, prev))
6834
          return false;
6835
 
6836
      return true;
6837
    }
6838
 
6839
  /* Otherwise just check that PREV doesn't modify any register mentioned
6840
     in the memory destination.  */
6841
  return !for_each_rtx (&SET_DEST (pat), mep_store_find_set, prev);
6842
}
6843
 
6844
/* Return true if INSN is a store instruction and if the store address
6845
   has no true dependence on PREV.  */
6846
 
6847
bool
6848
mep_store_data_bypass_p (rtx prev, rtx insn)
6849
{
6850
  return INSN_P (insn) ? mep_store_data_bypass_1 (prev, PATTERN (insn)) : false;
6851
}
6852
 
6853
/* A for_each_rtx subroutine of mep_mul_hilo_bypass_p.  Return 1 if *X
6854
   is a register other than LO or HI and if PREV sets *X.  */
6855
 
6856
static int
6857
mep_mul_hilo_bypass_1 (rtx *x, void *prev)
6858
{
6859
  return (REG_P (*x)
6860
          && REGNO (*x) != LO_REGNO
6861
          && REGNO (*x) != HI_REGNO
6862
          && reg_set_p (*x, (const_rtx) prev));
6863
}
6864
 
6865
/* Return true if, apart from HI/LO, there are no true dependencies
6866
   between multiplication instructions PREV and INSN.  */
6867
 
6868
bool
6869
mep_mul_hilo_bypass_p (rtx prev, rtx insn)
6870
{
6871
  rtx pat;
6872
 
6873
  pat = PATTERN (insn);
6874
  if (GET_CODE (pat) == PARALLEL)
6875
    pat = XVECEXP (pat, 0, 0);
6876
  return (GET_CODE (pat) == SET
6877
          && !for_each_rtx (&SET_SRC (pat), mep_mul_hilo_bypass_1, prev));
6878
}
6879
 
6880
/* Return true if INSN is an ldc instruction that issues to the
6881
   MeP-h1 integer pipeline.  This is true for instructions that
6882
   read from PSW, LP, SAR, HI and LO.  */
6883
 
6884
bool
6885
mep_ipipe_ldc_p (rtx insn)
6886
{
6887
  rtx pat, src;
6888
 
6889
  pat = PATTERN (insn);
6890
 
6891
  /* Cope with instrinsics that set both a hard register and its shadow.
6892
     The set of the hard register comes first.  */
6893
  if (GET_CODE (pat) == PARALLEL)
6894
    pat = XVECEXP (pat, 0, 0);
6895
 
6896
  if (GET_CODE (pat) == SET)
6897
    {
6898
      src = SET_SRC (pat);
6899
 
6900
      /* Cope with intrinsics.  The first operand to the unspec is
6901
         the source register.  */
6902
      if (GET_CODE (src) == UNSPEC || GET_CODE (src) == UNSPEC_VOLATILE)
6903
        src = XVECEXP (src, 0, 0);
6904
 
6905
      if (REG_P (src))
6906
        switch (REGNO (src))
6907
          {
6908
          case PSW_REGNO:
6909
          case LP_REGNO:
6910
          case SAR_REGNO:
6911
          case HI_REGNO:
6912
          case LO_REGNO:
6913
            return true;
6914
          }
6915
    }
6916
  return false;
6917
}
6918
 
6919
/* Create a VLIW bundle from core instruction CORE and coprocessor
6920
   instruction COP.  COP always satisfies INSN_P, but CORE can be
6921
   either a new pattern or an existing instruction.
6922
 
6923
   Emit the bundle in place of COP and return it.  */
6924
 
6925
static rtx
6926
mep_make_bundle (rtx core, rtx cop)
6927
{
6928
  rtx insn;
6929
 
6930
  /* If CORE is an existing instruction, remove it, otherwise put
6931
     the new pattern in an INSN harness.  */
6932
  if (INSN_P (core))
6933
    remove_insn (core);
6934
  else
6935
    core = make_insn_raw (core);
6936
 
6937
  /* Generate the bundle sequence and replace COP with it.  */
6938
  insn = gen_rtx_SEQUENCE (VOIDmode, gen_rtvec (2, core, cop));
6939
  insn = emit_insn_after (insn, cop);
6940
  remove_insn (cop);
6941
 
6942
  /* Set up the links of the insns inside the SEQUENCE.  */
6943
  PREV_INSN (core) = PREV_INSN (insn);
6944
  NEXT_INSN (core) = cop;
6945
  PREV_INSN (cop) = core;
6946
  NEXT_INSN (cop) = NEXT_INSN (insn);
6947
 
6948
  /* Set the VLIW flag for the coprocessor instruction.  */
6949
  PUT_MODE (core, VOIDmode);
6950
  PUT_MODE (cop, BImode);
6951
 
6952
  /* Derive a location for the bundle.  Individual instructions cannot
6953
     have their own location because there can be no assembler labels
6954
     between CORE and COP.  */
6955
  INSN_LOCATOR (insn) = INSN_LOCATOR (INSN_LOCATOR (core) ? core : cop);
6956
  INSN_LOCATOR (core) = 0;
6957
  INSN_LOCATOR (cop) = 0;
6958
 
6959
  return insn;
6960
}
6961
 
6962
/* A helper routine for ms1_insn_dependent_p called through note_stores.  */
6963
 
6964
static void
6965
mep_insn_dependent_p_1 (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data)
6966
{
6967
  rtx * pinsn = (rtx *) data;
6968
 
6969
  if (*pinsn && reg_mentioned_p (x, *pinsn))
6970
    *pinsn = NULL_RTX;
6971
}
6972
 
6973
/* Return true if anything in insn X is (anti,output,true) dependent on
6974
   anything in insn Y.  */
6975
 
6976
static int
6977
mep_insn_dependent_p (rtx x, rtx y)
6978
{
6979
  rtx tmp;
6980
 
6981
  gcc_assert (INSN_P (x));
6982
  gcc_assert (INSN_P (y));
6983
 
6984
  tmp = PATTERN (y);
6985
  note_stores (PATTERN (x), mep_insn_dependent_p_1, &tmp);
6986
  if (tmp == NULL_RTX)
6987
    return 1;
6988
 
6989
  tmp = PATTERN (x);
6990
  note_stores (PATTERN (y), mep_insn_dependent_p_1, &tmp);
6991
  if (tmp == NULL_RTX)
6992
    return 1;
6993
 
6994
  return 0;
6995
}
6996
 
6997
static int
6998
core_insn_p (rtx insn)
6999
{
7000
  if (GET_CODE (PATTERN (insn)) == USE)
7001
    return 0;
7002
  if (get_attr_slot (insn) == SLOT_CORE)
7003
    return 1;
7004
  return 0;
7005
}
7006
 
7007
/* Mark coprocessor instructions that can be bundled together with
7008
   the immediately preceeding core instruction.  This is later used
7009
   to emit the "+" that tells the assembler to create a VLIW insn.
7010
 
7011
   For unbundled insns, the assembler will automatically add coprocessor
7012
   nops, and 16-bit core nops.  Due to an apparent oversight in the
7013
   spec, the assembler will _not_ automatically add 32-bit core nops,
7014
   so we have to emit those here.
7015
 
7016
   Called from mep_insn_reorg.  */
7017
 
7018
static void
7019
mep_bundle_insns (rtx insns)
7020
{
7021
  rtx insn, last = NULL_RTX, first = NULL_RTX;
7022
  int saw_scheduling = 0;
7023
 
7024
  /* Only do bundling if we're in vliw mode.  */
7025
  if (!mep_vliw_function_p (cfun->decl))
7026
    return;
7027
 
7028
  /* The first insn in a bundle are TImode, the remainder are
7029
     VOIDmode.  After this function, the first has VOIDmode and the
7030
     rest have BImode.  */
7031
 
7032
  /* Note: this doesn't appear to be true for JUMP_INSNs.  */
7033
 
7034
  /* First, move any NOTEs that are within a bundle, to the beginning
7035
     of the bundle.  */
7036
  for (insn = insns; insn ; insn = NEXT_INSN (insn))
7037
    {
7038
      if (NOTE_P (insn) && first)
7039
        /* Don't clear FIRST.  */;
7040
 
7041
      else if (NONJUMP_INSN_P (insn) && GET_MODE (insn) == TImode)
7042
        first = insn;
7043
 
7044
      else if (NONJUMP_INSN_P (insn) && GET_MODE (insn) == VOIDmode && first)
7045
        {
7046
          rtx note, prev;
7047
 
7048
          /* INSN is part of a bundle; FIRST is the first insn in that
7049
             bundle.  Move all intervening notes out of the bundle.
7050
             In addition, since the debug pass may insert a label
7051
             whenever the current line changes, set the location info
7052
             for INSN to match FIRST.  */
7053
 
7054
          INSN_LOCATOR (insn) = INSN_LOCATOR (first);
7055
 
7056
          note = PREV_INSN (insn);
7057
          while (note && note != first)
7058
            {
7059
              prev = PREV_INSN (note);
7060
 
7061
              if (NOTE_P (note))
7062
                {
7063
                  /* Remove NOTE from here... */
7064
                  PREV_INSN (NEXT_INSN (note)) = PREV_INSN (note);
7065
                  NEXT_INSN (PREV_INSN (note)) = NEXT_INSN (note);
7066
                  /* ...and put it in here.  */
7067
                  NEXT_INSN (note) = first;
7068
                  PREV_INSN (note) = PREV_INSN (first);
7069
                  NEXT_INSN (PREV_INSN (note)) = note;
7070
                  PREV_INSN (NEXT_INSN (note)) = note;
7071
                }
7072
 
7073
              note = prev;
7074
            }
7075
        }
7076
 
7077
      else if (!NONJUMP_INSN_P (insn))
7078
        first = 0;
7079
    }
7080
 
7081
  /* Now fix up the bundles.  */
7082
  for (insn = insns; insn ; insn = NEXT_INSN (insn))
7083
    {
7084
      if (NOTE_P (insn))
7085
        continue;
7086
 
7087
      if (!NONJUMP_INSN_P (insn))
7088
        {
7089
          last = 0;
7090
          continue;
7091
        }
7092
 
7093
      /* If we're not optimizing enough, there won't be scheduling
7094
         info.  We detect that here.  */
7095
      if (GET_MODE (insn) == TImode)
7096
        saw_scheduling = 1;
7097
      if (!saw_scheduling)
7098
        continue;
7099
 
7100
      if (TARGET_IVC2)
7101
        {
7102
          rtx core_insn = NULL_RTX;
7103
 
7104
          /* IVC2 slots are scheduled by DFA, so we just accept
7105
             whatever the scheduler gives us.  However, we must make
7106
             sure the core insn (if any) is the first in the bundle.
7107
             The IVC2 assembler can insert whatever NOPs are needed,
7108
             and allows a COP insn to be first.  */
7109
 
7110
          if (NONJUMP_INSN_P (insn)
7111
              && GET_CODE (PATTERN (insn)) != USE
7112
              && GET_MODE (insn) == TImode)
7113
            {
7114
              for (last = insn;
7115
                   NEXT_INSN (last)
7116
                     && GET_MODE (NEXT_INSN (last)) == VOIDmode
7117
                     && NONJUMP_INSN_P (NEXT_INSN (last));
7118
                   last = NEXT_INSN (last))
7119
                {
7120
                  if (core_insn_p (last))
7121
                    core_insn = last;
7122
                }
7123
              if (core_insn_p (last))
7124
                core_insn = last;
7125
 
7126
              if (core_insn && core_insn != insn)
7127
                {
7128
                  /* Swap core insn to first in the bundle.  */
7129
 
7130
                  /* Remove core insn.  */
7131
                  if (PREV_INSN (core_insn))
7132
                    NEXT_INSN (PREV_INSN (core_insn)) = NEXT_INSN (core_insn);
7133
                  if (NEXT_INSN (core_insn))
7134
                    PREV_INSN (NEXT_INSN (core_insn)) = PREV_INSN (core_insn);
7135
 
7136
                  /* Re-insert core insn.  */
7137
                  PREV_INSN (core_insn) = PREV_INSN (insn);
7138
                  NEXT_INSN (core_insn) = insn;
7139
 
7140
                  if (PREV_INSN (core_insn))
7141
                    NEXT_INSN (PREV_INSN (core_insn)) = core_insn;
7142
                  PREV_INSN (insn) = core_insn;
7143
 
7144
                  PUT_MODE (core_insn, TImode);
7145
                  PUT_MODE (insn, VOIDmode);
7146
                }
7147
            }
7148
 
7149
          /* The first insn has TImode, the rest have VOIDmode */
7150
          if (GET_MODE (insn) == TImode)
7151
            PUT_MODE (insn, VOIDmode);
7152
          else
7153
            PUT_MODE (insn, BImode);
7154
          continue;
7155
        }
7156
 
7157
      PUT_MODE (insn, VOIDmode);
7158
      if (recog_memoized (insn) >= 0
7159
          && get_attr_slot (insn) == SLOT_COP)
7160
        {
7161
          if (GET_CODE (insn) == JUMP_INSN
7162
              || ! last
7163
              || recog_memoized (last) < 0
7164
              || get_attr_slot (last) != SLOT_CORE
7165
              || (get_attr_length (insn)
7166
                  != (TARGET_OPT_VL64 ? 8 : 4) - get_attr_length (last))
7167
              || mep_insn_dependent_p (insn, last))
7168
            {
7169
              switch (get_attr_length (insn))
7170
                {
7171
                case 8:
7172
                  break;
7173
                case 6:
7174
                  insn = mep_make_bundle (gen_nop (), insn);
7175
                  break;
7176
                case 4:
7177
                  if (TARGET_OPT_VL64)
7178
                    insn = mep_make_bundle (gen_nop32 (), insn);
7179
                  break;
7180
                case 2:
7181
                  if (TARGET_OPT_VL64)
7182
                    error ("2 byte cop instructions are"
7183
                           " not allowed in 64-bit VLIW mode");
7184
                  else
7185
                    insn = mep_make_bundle (gen_nop (), insn);
7186
                  break;
7187
                default:
7188
                  error ("unexpected %d byte cop instruction",
7189
                         get_attr_length (insn));
7190
                  break;
7191
                }
7192
            }
7193
          else
7194
            insn = mep_make_bundle (last, insn);
7195
        }
7196
 
7197
      last = insn;
7198
    }
7199
}
7200
 
7201
 
7202
/* Try to instantiate INTRINSIC with the operands given in OPERANDS.
7203
   Return true on success.  This function can fail if the intrinsic
7204
   is unavailable or if the operands don't satisfy their predicates.  */
7205
 
7206
bool
7207
mep_emit_intrinsic (int intrinsic, const rtx *operands)
7208
{
7209
  const struct cgen_insn *cgen_insn;
7210
  const struct insn_data_d *idata;
7211
  rtx newop[10];
7212
  int i;
7213
 
7214
  if (!mep_get_intrinsic_insn (intrinsic, &cgen_insn))
7215
    return false;
7216
 
7217
  idata = &insn_data[cgen_insn->icode];
7218
  for (i = 0; i < idata->n_operands; i++)
7219
    {
7220
      newop[i] = mep_convert_arg (idata->operand[i].mode, operands[i]);
7221
      if (!idata->operand[i].predicate (newop[i], idata->operand[i].mode))
7222
        return false;
7223
    }
7224
 
7225
  emit_insn (idata->genfun (newop[0], newop[1], newop[2],
7226
                            newop[3], newop[4], newop[5],
7227
                            newop[6], newop[7], newop[8]));
7228
 
7229
  return true;
7230
}
7231
 
7232
 
7233
/* Apply the given unary intrinsic to OPERANDS[1] and store it on
7234
   OPERANDS[0].  Report an error if the instruction could not
7235
   be synthesized.  OPERANDS[1] is a register_operand.  For sign
7236
   and zero extensions, it may be smaller than SImode.  */
7237
 
7238
bool
7239
mep_expand_unary_intrinsic (int ATTRIBUTE_UNUSED intrinsic,
7240
                            rtx * operands ATTRIBUTE_UNUSED)
7241
{
7242
  return false;
7243
}
7244
 
7245
 
7246
/* Likewise, but apply a binary operation to OPERANDS[1] and
7247
   OPERANDS[2].  OPERANDS[1] is a register_operand, OPERANDS[2]
7248
   can be a general_operand.
7249
 
7250
   IMMEDIATE and IMMEDIATE3 are intrinsics that take an immediate
7251
   third operand.  REG and REG3 take register operands only.  */
7252
 
7253
bool
7254
mep_expand_binary_intrinsic (int ATTRIBUTE_UNUSED immediate,
7255
                             int ATTRIBUTE_UNUSED immediate3,
7256
                             int ATTRIBUTE_UNUSED reg,
7257
                             int ATTRIBUTE_UNUSED reg3,
7258
                             rtx * operands ATTRIBUTE_UNUSED)
7259
{
7260
  return false;
7261
}
7262
 
7263
static bool
7264
mep_rtx_cost (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
7265
              int opno ATTRIBUTE_UNUSED, int *total,
7266
              bool ATTRIBUTE_UNUSED speed_t)
7267
{
7268
  switch (code)
7269
    {
7270
    case CONST_INT:
7271
      if (INTVAL (x) >= -128 && INTVAL (x) < 127)
7272
        *total = 0;
7273
      else if (INTVAL (x) >= -32768 && INTVAL (x) < 65536)
7274
        *total = 1;
7275
      else
7276
        *total = 3;
7277
      return true;
7278
 
7279
    case SYMBOL_REF:
7280
      *total = optimize_size ? COSTS_N_INSNS (0) : COSTS_N_INSNS (1);
7281
      return true;
7282
 
7283
    case MULT:
7284
      *total = (GET_CODE (XEXP (x, 1)) == CONST_INT
7285
                ? COSTS_N_INSNS (3)
7286
                : COSTS_N_INSNS (2));
7287
      return true;
7288
    }
7289
  return false;
7290
}
7291
 
7292
static int
7293
mep_address_cost (rtx addr ATTRIBUTE_UNUSED, bool ATTRIBUTE_UNUSED speed_p)
7294
{
7295
  return 1;
7296
}
7297
 
7298
static void
7299
mep_asm_init_sections (void)
7300
{
7301
  based_section
7302
    = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
7303
                           "\t.section .based,\"aw\"");
7304
 
7305
  tinybss_section
7306
    = get_unnamed_section (SECTION_WRITE | SECTION_BSS, output_section_asm_op,
7307
                           "\t.section .sbss,\"aw\"");
7308
 
7309
  sdata_section
7310
    = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
7311
                           "\t.section .sdata,\"aw\",@progbits");
7312
 
7313
  far_section
7314
    = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
7315
                           "\t.section .far,\"aw\"");
7316
 
7317
  farbss_section
7318
    = get_unnamed_section (SECTION_WRITE | SECTION_BSS, output_section_asm_op,
7319
                           "\t.section .farbss,\"aw\"");
7320
 
7321
  frodata_section
7322
    = get_unnamed_section (0, output_section_asm_op,
7323
                           "\t.section .frodata,\"a\"");
7324
 
7325
  srodata_section
7326
    = get_unnamed_section (0, output_section_asm_op,
7327
                           "\t.section .srodata,\"a\"");
7328
 
7329
  vtext_section
7330
    = get_unnamed_section (SECTION_CODE | SECTION_MEP_VLIW, output_section_asm_op,
7331
                           "\t.section .vtext,\"axv\"\n\t.vliw");
7332
 
7333
  vftext_section
7334
    = get_unnamed_section (SECTION_CODE | SECTION_MEP_VLIW, output_section_asm_op,
7335
                           "\t.section .vftext,\"axv\"\n\t.vliw");
7336
 
7337
  ftext_section
7338
    = get_unnamed_section (SECTION_CODE, output_section_asm_op,
7339
                           "\t.section .ftext,\"ax\"\n\t.core");
7340
 
7341
}
7342
 
7343
/* Initialize the GCC target structure.  */
7344
 
7345
#undef  TARGET_ASM_FUNCTION_PROLOGUE
7346
#define TARGET_ASM_FUNCTION_PROLOGUE    mep_start_function
7347
#undef  TARGET_ATTRIBUTE_TABLE
7348
#define TARGET_ATTRIBUTE_TABLE          mep_attribute_table
7349
#undef  TARGET_COMP_TYPE_ATTRIBUTES
7350
#define TARGET_COMP_TYPE_ATTRIBUTES     mep_comp_type_attributes
7351
#undef  TARGET_INSERT_ATTRIBUTES
7352
#define TARGET_INSERT_ATTRIBUTES        mep_insert_attributes
7353
#undef  TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P
7354
#define TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P   mep_function_attribute_inlinable_p
7355
#undef  TARGET_CAN_INLINE_P
7356
#define TARGET_CAN_INLINE_P             mep_can_inline_p
7357
#undef  TARGET_SECTION_TYPE_FLAGS
7358
#define TARGET_SECTION_TYPE_FLAGS       mep_section_type_flags
7359
#undef  TARGET_ASM_NAMED_SECTION
7360
#define TARGET_ASM_NAMED_SECTION        mep_asm_named_section
7361
#undef  TARGET_INIT_BUILTINS
7362
#define TARGET_INIT_BUILTINS            mep_init_builtins
7363
#undef  TARGET_EXPAND_BUILTIN
7364
#define TARGET_EXPAND_BUILTIN           mep_expand_builtin
7365
#undef  TARGET_SCHED_ADJUST_COST
7366
#define TARGET_SCHED_ADJUST_COST        mep_adjust_cost
7367
#undef  TARGET_SCHED_ISSUE_RATE
7368
#define TARGET_SCHED_ISSUE_RATE         mep_issue_rate
7369
#undef  TARGET_SCHED_REORDER
7370
#define TARGET_SCHED_REORDER            mep_sched_reorder
7371
#undef  TARGET_STRIP_NAME_ENCODING
7372
#define TARGET_STRIP_NAME_ENCODING      mep_strip_name_encoding
7373
#undef  TARGET_ASM_SELECT_SECTION
7374
#define TARGET_ASM_SELECT_SECTION       mep_select_section
7375
#undef  TARGET_ASM_UNIQUE_SECTION
7376
#define TARGET_ASM_UNIQUE_SECTION       mep_unique_section
7377
#undef  TARGET_ENCODE_SECTION_INFO
7378
#define TARGET_ENCODE_SECTION_INFO      mep_encode_section_info
7379
#undef  TARGET_FUNCTION_OK_FOR_SIBCALL
7380
#define TARGET_FUNCTION_OK_FOR_SIBCALL  mep_function_ok_for_sibcall
7381
#undef  TARGET_RTX_COSTS
7382
#define TARGET_RTX_COSTS                mep_rtx_cost
7383
#undef  TARGET_ADDRESS_COST
7384
#define TARGET_ADDRESS_COST             mep_address_cost
7385
#undef  TARGET_MACHINE_DEPENDENT_REORG
7386
#define TARGET_MACHINE_DEPENDENT_REORG  mep_reorg
7387
#undef  TARGET_SETUP_INCOMING_VARARGS
7388
#define TARGET_SETUP_INCOMING_VARARGS   mep_setup_incoming_varargs
7389
#undef  TARGET_PASS_BY_REFERENCE
7390
#define TARGET_PASS_BY_REFERENCE        mep_pass_by_reference
7391
#undef  TARGET_FUNCTION_ARG
7392
#define TARGET_FUNCTION_ARG             mep_function_arg
7393
#undef  TARGET_FUNCTION_ARG_ADVANCE
7394
#define TARGET_FUNCTION_ARG_ADVANCE     mep_function_arg_advance
7395
#undef  TARGET_VECTOR_MODE_SUPPORTED_P
7396
#define TARGET_VECTOR_MODE_SUPPORTED_P  mep_vector_mode_supported_p
7397
#undef  TARGET_OPTION_OVERRIDE
7398
#define TARGET_OPTION_OVERRIDE          mep_option_override
7399
#undef  TARGET_ALLOCATE_INITIAL_VALUE
7400
#define TARGET_ALLOCATE_INITIAL_VALUE   mep_allocate_initial_value
7401
#undef  TARGET_ASM_INIT_SECTIONS
7402
#define TARGET_ASM_INIT_SECTIONS        mep_asm_init_sections
7403
#undef  TARGET_RETURN_IN_MEMORY
7404
#define TARGET_RETURN_IN_MEMORY         mep_return_in_memory
7405
#undef  TARGET_NARROW_VOLATILE_BITFIELD
7406
#define TARGET_NARROW_VOLATILE_BITFIELD mep_narrow_volatile_bitfield
7407
#undef  TARGET_EXPAND_BUILTIN_SAVEREGS
7408
#define TARGET_EXPAND_BUILTIN_SAVEREGS  mep_expand_builtin_saveregs
7409
#undef  TARGET_BUILD_BUILTIN_VA_LIST
7410
#define TARGET_BUILD_BUILTIN_VA_LIST    mep_build_builtin_va_list
7411
#undef  TARGET_EXPAND_BUILTIN_VA_START
7412
#define TARGET_EXPAND_BUILTIN_VA_START  mep_expand_va_start
7413
#undef  TARGET_GIMPLIFY_VA_ARG_EXPR
7414
#define TARGET_GIMPLIFY_VA_ARG_EXPR     mep_gimplify_va_arg_expr
7415
#undef  TARGET_CAN_ELIMINATE
7416
#define TARGET_CAN_ELIMINATE            mep_can_eliminate
7417
#undef  TARGET_CONDITIONAL_REGISTER_USAGE
7418
#define TARGET_CONDITIONAL_REGISTER_USAGE       mep_conditional_register_usage
7419
#undef  TARGET_TRAMPOLINE_INIT
7420
#define TARGET_TRAMPOLINE_INIT          mep_trampoline_init
7421
#undef  TARGET_LEGITIMATE_CONSTANT_P
7422
#define TARGET_LEGITIMATE_CONSTANT_P    mep_legitimate_constant_p
7423
 
7424
struct gcc_target targetm = TARGET_INITIALIZER;
7425
 
7426
#include "gt-mep.h"

powered by: WebSVN 2.1.0

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