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

Subversion Repositories openrisc

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

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 709 jeremybenn
/* Subroutines used for code generation on Renesas RL78 processors.
2
   Copyright (C) 2011 Free Software Foundation, Inc.
3
   Contributed by Red Hat.
4
 
5
   This file is part of GCC.
6
 
7
   GCC is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 3, or (at your option)
10
   any later version.
11
 
12
   GCC is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with GCC; see the file COPYING3.  If not see
19
   <http://www.gnu.org/licenses/>.  */
20
 
21
#include "config.h"
22
#include "system.h"
23
#include "coretypes.h"
24
#include "tm.h"
25
#include "tree.h"
26
#include "rtl.h"
27
#include "regs.h"
28
#include "hard-reg-set.h"
29
#include "insn-config.h"
30
#include "conditions.h"
31
#include "output.h"
32
#include "insn-attr.h"
33
#include "flags.h"
34
#include "function.h"
35
#include "expr.h"
36
#include "optabs.h"
37
#include "libfuncs.h"
38
#include "recog.h"
39
#include "diagnostic-core.h"
40
#include "toplev.h"
41
#include "reload.h"
42
#include "df.h"
43
#include "ggc.h"
44
#include "tm_p.h"
45
#include "debug.h"
46
#include "target.h"
47
#include "target-def.h"
48
#include "langhooks.h"
49
#include "rl78-protos.h"
50
#include "tree-pass.h"
51
 
52
static inline bool is_interrupt_func (const_tree decl);
53
static inline bool is_brk_interrupt_func (const_tree decl);
54
static void rl78_reorg (void);
55
 
56
 
57
/* Debugging statements are tagged with DEBUG0 only so that they can
58
   be easily enabled individually, by replacing the '0' with '1' as
59
   needed.  */
60
#define DEBUG0 0
61
#define DEBUG1 1
62
 
63
/* REGISTER_NAMES has the names for individual 8-bit registers, but
64
   these have the names we need to use when referring to 16-bit
65
   register pairs.  */
66
static const char * const word_regnames[] =
67
{
68
  "ax", "AX", "bc", "BC", "de", "DE", "hl", "HL",
69
  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
70
  "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
71
  "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
72
  "sp", "ap", "psw", "es", "cs"
73
};
74
 
75
struct GTY(()) machine_function
76
{
77
  /* If set, the rest of the fields have been computed.  */
78
  int computed;
79
  /* Which register pairs need to be pushed in the prologue.  */
80
  int need_to_push [FIRST_PSEUDO_REGISTER / 2];
81
 
82
  /* These fields describe the frame layout...  */
83
  /* arg pointer */
84
  /* 4 bytes for saved PC */
85
  int framesize_regs;
86
  /* frame pointer */
87
  int framesize_locals;
88
  int framesize_outgoing;
89
  /* stack pointer */
90
  int framesize;
91
 
92
  /* If set, recog is allowed to match against the "real" patterns.  */
93
  int real_insns_ok;
94
  /* If set, recog is allowed to match against the "virtual" patterns.  */
95
  int virt_insns_ok;
96
  /* Set if the current function needs to clean up any trampolines.  */
97
  int trampolines_used;
98
};
99
 
100
/* This is our init_machine_status, as set in
101
   rl78_option_override.  */
102
static struct machine_function *
103
rl78_init_machine_status (void)
104
{
105
  struct machine_function *m;
106
 
107
  m = ggc_alloc_cleared_machine_function ();
108
  m->virt_insns_ok = 1;
109
 
110
  return m;
111
}
112
 
113
/* Returns whether to run the devirtualization pass.  */
114
static bool
115
devirt_gate (void)
116
{
117
  return true;
118
}
119
 
120
/* Runs the devirtualization pass.  */
121
static unsigned int
122
devirt_pass (void)
123
{
124
  rl78_reorg ();
125
  return 0;
126
}
127
 
128
/* This pass converts virtual instructions using virtual registers, to
129
   real instructions using real registers.  Rather than run it as
130
   reorg, we reschedule it before vartrack to help with debugging.  */
131
static struct opt_pass rl78_devirt_pass =
132
{
133
  RTL_PASS,
134
  "devirt",
135
  devirt_gate,
136
  devirt_pass,
137
  NULL,
138
  NULL,
139
  212,
140
  TV_MACH_DEP,
141
  0, 0, 0,
142
  0,
143
  TODO_dump_func
144
};
145
 
146
static struct register_pass_info rl78_devirt_info =
147
{
148
  & rl78_devirt_pass,
149
  "vartrack",
150
  1,
151
  PASS_POS_INSERT_BEFORE
152
};
153
 
154
#undef  TARGET_ASM_FILE_START
155
#define TARGET_ASM_FILE_START rl78_asm_file_start
156
 
157
static void
158
rl78_asm_file_start (void)
159
{
160
  int i;
161
 
162
  for (i = 0; i < 8; i++)
163
    {
164
      fprintf (asm_out_file, "r%d\t=\t0x%x\n", 8 + i, 0xffef0 + i);
165
      fprintf (asm_out_file, "r%d\t=\t0x%x\n", 16 + i, 0xffee8 + i);
166
    }
167
 
168
  register_pass (& rl78_devirt_info);
169
}
170
 
171
 
172
#undef  TARGET_OPTION_OVERRIDE
173
#define TARGET_OPTION_OVERRIDE          rl78_option_override
174
 
175
static void
176
rl78_option_override (void)
177
{
178
  flag_omit_frame_pointer = 1;
179
  flag_no_function_cse = 1;
180
  flag_split_wide_types = 0;
181
 
182
  init_machine_status = rl78_init_machine_status;
183
}
184
 
185
/* Most registers are 8 bits.  Some are 16 bits because, for example,
186
   gcc doesn't like dealing with $FP as a register pair.  This table
187
   maps register numbers to size in bytes.  */
188
static const int register_sizes[] =
189
{
190
  1, 1, 1, 1, 1, 1, 1, 1,
191
  1, 1, 1, 1, 1, 1, 1, 1,
192
  1, 1, 1, 1, 1, 1, 2, 1,
193
  1, 1, 1, 1, 1, 1, 1, 1,
194
  2, 2, 1, 1, 1
195
};
196
 
197
/* Predicates used in the MD patterns.  This one is true when virtual
198
   insns may be matched, which typically means before (or during) the
199
   devirt pass.  */
200
bool
201
rl78_virt_insns_ok (void)
202
{
203
  if (cfun)
204
    return cfun->machine->virt_insns_ok;
205
  return true;
206
}
207
 
208
/* Predicates used in the MD patterns.  This one is true when real
209
   insns may be matched, which typically means after (or during) the
210
   devirt pass.  */
211
bool
212
rl78_real_insns_ok (void)
213
{
214
  if (cfun)
215
    return cfun->machine->real_insns_ok;
216
  return false;
217
}
218
 
219
/* Implements HARD_REGNO_NREGS.  */
220
int
221
rl78_hard_regno_nregs (int regno, enum machine_mode mode)
222
{
223
  int rs = register_sizes[regno];
224
  if (rs < 1)
225
    rs = 1;
226
  return ((GET_MODE_SIZE (mode) + rs - 1) / rs);
227
}
228
 
229
/* Implements HARD_REGNO_MODE_OK.  */
230
int
231
rl78_hard_regno_mode_ok (int regno, enum machine_mode mode)
232
{
233
  int s = GET_MODE_SIZE (mode);
234
 
235
  if (s < 1)
236
    return 0;
237
  /* These are not to be used by gcc.  */
238
  if (regno == 23 || regno == ES_REG || regno == CS_REG)
239
    return 0;
240
  /* $fp can alway sbe accessed as a 16-bit value.  */
241
  if (regno == FP_REG && s == 2)
242
    return 1;
243
  if (regno < SP_REG)
244
    {
245
      /* Since a reg-reg move is really a reg-mem move, we must
246
         enforce alignment.  */
247
      if (s > 1 && (regno % 2))
248
        return 0;
249
      return 1;
250
    }
251
  if (s == CC_REGNUM)
252
    return (mode == BImode);
253
  /* All other registers must be accessed in their natural sizes.  */
254
  if (s == register_sizes [regno])
255
    return 1;
256
  return 0;
257
}
258
 
259
/* Simplify_gen_subreg() doesn't handle memory references the way we
260
   need it to below, so we use this function for when we must get a
261
   valid subreg in a "natural" state.  */
262
static rtx
263
rl78_subreg (enum machine_mode mode, rtx r, enum machine_mode omode, int byte)
264
{
265
  if (GET_CODE (r) == MEM)
266
    return adjust_address (r, mode, byte);
267
  else
268
    return simplify_gen_subreg (mode, r, omode, byte);
269
}
270
 
271
/* Used by movsi.  Split SImode moves into two HImode moves, using
272
   appropriate patterns for the upper and lower halves of symbols.  */
273
void
274
rl78_expand_movsi (rtx *operands)
275
{
276
  rtx op00, op02, op10, op12;
277
 
278
  op00 = rl78_subreg (HImode, operands[0], SImode, 0);
279
  op02 = rl78_subreg (HImode, operands[0], SImode, 2);
280
  if (GET_CODE (operands[1]) == CONST
281
      || GET_CODE (operands[1]) == SYMBOL_REF)
282
    {
283
      op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
284
      op10 = gen_rtx_CONST (HImode, op10);
285
      op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
286
      op12 = gen_rtx_CONST (HImode, op12);
287
    }
288
  else
289
    {
290
      op10 = rl78_subreg (HImode, operands[1], SImode, 0);
291
      op12 = rl78_subreg (HImode, operands[1], SImode, 2);
292
    }
293
 
294
  if (rtx_equal_p (operands[0], operands[1]))
295
    ;
296
  else if (rtx_equal_p (op00, op12))
297
    {
298
      emit_move_insn (op02, op12);
299
      emit_move_insn (op00, op10);
300
    }
301
  else
302
    {
303
      emit_move_insn (op00, op10);
304
      emit_move_insn (op02, op12);
305
    }
306
}
307
 
308
/* Used by various two-operand expanders which cannot accept all
309
   operands in the "far" namespace.  Force some such operands into
310
   registers so that each pattern has at most one far operand.  */
311
int
312
rl78_force_nonfar_2 (rtx *operands, rtx (*gen)(rtx,rtx))
313
{
314
  int did = 0;
315
  rtx temp_reg = NULL;
316
 
317
  /* FIXME: in the future, be smarter about only doing this if the
318
     other operand is also far, assuming the devirtualizer can also
319
     handle that.  */
320
  if (rl78_far_p (operands[0]))
321
    {
322
      temp_reg = operands[0];
323
      operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
324
      did = 1;
325
    }
326
  if (!did)
327
    return 0;
328
 
329
  emit_insn (gen (operands[0], operands[1]));
330
  if (temp_reg)
331
    emit_move_insn (temp_reg, operands[0]);
332
  return 1;
333
}
334
 
335
/* Likewise, but for three-operand expanders.  */
336
int
337
rl78_force_nonfar_3 (rtx *operands, rtx (*gen)(rtx,rtx,rtx))
338
{
339
  int did = 0;
340
  rtx temp_reg = NULL;
341
 
342
  /* FIXME: Likewise.  */
343
  if (rl78_far_p (operands[1]))
344
    {
345
      rtx temp_reg = gen_reg_rtx (GET_MODE (operands[1]));
346
      emit_move_insn (temp_reg, operands[1]);
347
      operands[1] = temp_reg;
348
      did = 1;
349
    }
350
  if (rl78_far_p (operands[0]))
351
    {
352
      temp_reg = operands[0];
353
      operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
354
      did = 1;
355
    }
356
  if (!did)
357
    return 0;
358
 
359
  emit_insn (gen (operands[0], operands[1], operands[2]));
360
  if (temp_reg)
361
    emit_move_insn (temp_reg, operands[0]);
362
  return 1;
363
}
364
 
365
#undef  TARGET_CAN_ELIMINATE
366
#define TARGET_CAN_ELIMINATE            rl78_can_eliminate
367
 
368
static bool
369
rl78_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to ATTRIBUTE_UNUSED)
370
{
371
  return true;
372
}
373
 
374
/* Returns nonzero if the given register needs to be saved by the
375
   current function.  */
376
static int
377
need_to_save (int regno)
378
{
379
  if (is_interrupt_func (cfun->decl))
380
    {
381
      if (regno < 8)
382
        return 1; /* don't know what devirt will need */
383
      if (regno > 23)
384
        return 0; /* don't need to save interrupt registers */
385
      if (current_function_is_leaf)
386
        {
387
          return df_regs_ever_live_p (regno);
388
        }
389
      else
390
        return 1;
391
    }
392
  if (regno == FRAME_POINTER_REGNUM && frame_pointer_needed)
393
    return 1;
394
  if (fixed_regs[regno])
395
    return 0;
396
  if (crtl->calls_eh_return)
397
    return 1;
398
  if (df_regs_ever_live_p (regno)
399
      && !call_used_regs[regno])
400
    return 1;
401
  return 0;
402
}
403
 
404
/* We use this to wrap all emitted insns in the prologue.  */
405
static rtx
406
F (rtx x)
407
{
408
  RTX_FRAME_RELATED_P (x) = 1;
409
  return x;
410
}
411
 
412
/* Compute all the frame-related fields in our machine_function
413
   structure.  */
414
static void
415
rl78_compute_frame_info (void)
416
{
417
  int i;
418
 
419
  cfun->machine->computed = 1;
420
  cfun->machine->framesize_regs = 0;
421
  cfun->machine->framesize_locals = get_frame_size ();
422
  cfun->machine->framesize_outgoing = crtl->outgoing_args_size;
423
 
424
  for (i = 0; i < 16; i ++)
425
    if (need_to_save (i * 2) || need_to_save (i * 2 + 1))
426
      {
427
        cfun->machine->need_to_push [i] = 1;
428
        cfun->machine->framesize_regs += 2;
429
      }
430
    else
431
      cfun->machine->need_to_push [i] = 0;
432
 
433
  if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1)
434
    cfun->machine->framesize_locals ++;
435
 
436
  cfun->machine->framesize = (cfun->machine->framesize_regs
437
                              + cfun->machine->framesize_locals
438
                              + cfun->machine->framesize_outgoing);
439
}
440
 
441
/* Returns true if the provided function has the specified attribute.  */
442
static inline bool
443
has_func_attr (const_tree decl, const char * func_attr)
444
{
445
  if (decl == NULL_TREE)
446
    decl = current_function_decl;
447
 
448
  return lookup_attribute (func_attr, DECL_ATTRIBUTES (decl)) != NULL_TREE;
449
}
450
 
451
/* Returns true if the provided function has the "interrupt" attribute.  */
452
static inline bool
453
is_interrupt_func (const_tree decl)
454
{
455
  return has_func_attr (decl, "interrupt") || has_func_attr (decl, "brk_interrupt");
456
}
457
 
458
/* Returns true if the provided function has the "brk_interrupt" attribute.  */
459
static inline bool
460
is_brk_interrupt_func (const_tree decl)
461
{
462
  return has_func_attr (decl, "brk_interrupt");
463
}
464
 
465
/* Check "interrupt" attributes.  */
466
static tree
467
rl78_handle_func_attribute (tree * node,
468
                          tree   name,
469
                          tree   args,
470
                          int    flags ATTRIBUTE_UNUSED,
471
                          bool * no_add_attrs)
472
{
473
  gcc_assert (DECL_P (* node));
474
  gcc_assert (args == NULL_TREE);
475
 
476
  if (TREE_CODE (* node) != FUNCTION_DECL)
477
    {
478
      warning (OPT_Wattributes, "%qE attribute only applies to functions",
479
               name);
480
      * no_add_attrs = true;
481
    }
482
 
483
  /* FIXME: We ought to check that the interrupt and exception
484
     handler attributes have been applied to void functions.  */
485
  return NULL_TREE;
486
}
487
 
488
#undef  TARGET_ATTRIBUTE_TABLE
489
#define TARGET_ATTRIBUTE_TABLE          rl78_attribute_table
490
 
491
/* Table of RL78-specific attributes.  */
492
const struct attribute_spec rl78_attribute_table[] =
493
{
494
  /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
495
     affects_type_identity.  */
496
  { "interrupt",      0, 0, true, false, false, rl78_handle_func_attribute,
497
    false },
498
  { "brk_interrupt",  0, 0, true, false, false, rl78_handle_func_attribute,
499
    false },
500
  { NULL,             0, 0, false, false, false, NULL, false }
501
};
502
 
503
 
504
 
505
/* Break down an address RTX into its component base/index/addend
506
   portions and return TRUE if the address is of a valid form, else
507
   FALSE.  */
508
static bool
509
characterize_address (rtx x, rtx *base, rtx *index, rtx *addend)
510
{
511
  *base = NULL_RTX;
512
  *index = NULL_RTX;
513
  *addend = NULL_RTX;
514
 
515
  if (GET_CODE (x) == REG)
516
    {
517
      *base = x;
518
      return true;
519
    }
520
 
521
  /* We sometimes get these without the CONST wrapper */
522
  if (GET_CODE (x) == PLUS
523
      && GET_CODE (XEXP (x, 0)) == SYMBOL_REF
524
      && GET_CODE (XEXP (x, 1)) == CONST_INT)
525
    {
526
      *addend = x;
527
      return true;
528
    }
529
 
530
  if (GET_CODE (x) == PLUS)
531
    {
532
      *base = XEXP (x, 0);
533
      x = XEXP (x, 1);
534
 
535
      if (GET_CODE (*base) != REG
536
          && GET_CODE (x) == REG)
537
        {
538
          rtx tmp = *base;
539
          *base = x;
540
          x = tmp;
541
        }
542
 
543
      if (GET_CODE (*base) != REG)
544
        return false;
545
 
546
      if (GET_CODE (x) == ZERO_EXTEND
547
          && GET_CODE (XEXP (x, 0)) == REG)
548
        {
549
          *index = XEXP (x, 0);
550
          return false;
551
        }
552
    }
553
 
554
  switch (GET_CODE (x))
555
    {
556
    case PLUS:
557
      if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
558
          && GET_CODE (XEXP (x, 0)) == CONST_INT)
559
        {
560
          *addend = x;
561
          return true;
562
        }
563
      /* fall through */
564
    case MEM:
565
    case REG:
566
      return false;
567
 
568
    case CONST:
569
    case SYMBOL_REF:
570
    case CONST_INT:
571
      *addend = x;
572
      return true;
573
 
574
    default:
575
      return false;
576
    }
577
 
578
  return false;
579
}
580
 
581
/* Used by the Whb constraint.  Match addresses that use HL+B or HL+C
582
   addressing.  */
583
bool
584
rl78_hl_b_c_addr_p (rtx op)
585
{
586
  rtx hl, bc;
587
 
588
  if (GET_CODE (op) != PLUS)
589
    return false;
590
  hl = XEXP (op, 0);
591
  bc = XEXP (op, 1);
592
  if (GET_CODE (hl) == ZERO_EXTEND)
593
    {
594
      rtx tmp = hl;
595
      hl = bc;
596
      bc = tmp;
597
    }
598
  if (GET_CODE (hl) != REG)
599
    return false;
600
  if (GET_CODE (bc) != ZERO_EXTEND)
601
    return false;
602
  bc = XEXP (bc, 0);
603
  if (GET_CODE (bc) != REG)
604
    return false;
605
  if (REGNO (hl) != HL_REG)
606
    return false;
607
  if (REGNO (bc) != B_REG && REGNO (bc) != C_REG)
608
    return false;
609
 
610
  return true;
611
}
612
 
613
#define REG_IS(r, regno) (((r) == (regno)) || ((r) >= FIRST_PSEUDO_REGISTER && !(strict)))
614
 
615
/* Used in various constraints and predicates to match operands in the
616
   "far" address space.  */
617
int
618
rl78_far_p (rtx x)
619
{
620
  if (GET_CODE (x) != MEM)
621
    return 0;
622
#if DEBUG0
623
  fprintf(stderr, "\033[35mrl78_far_p: "); debug_rtx(x);
624
  fprintf(stderr, " = %d\033[0m\n", MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR);
625
#endif
626
  return MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR;
627
}
628
 
629
/* Return the appropriate mode for a named address pointer.  */
630
#undef TARGET_ADDR_SPACE_POINTER_MODE
631
#define TARGET_ADDR_SPACE_POINTER_MODE rl78_addr_space_pointer_mode
632
static enum machine_mode
633
rl78_addr_space_pointer_mode (addr_space_t addrspace)
634
{
635
  switch (addrspace)
636
    {
637
    case ADDR_SPACE_GENERIC:
638
      return HImode;
639
    case ADDR_SPACE_FAR:
640
      return SImode;
641
    default:
642
      gcc_unreachable ();
643
    }
644
}
645
 
646
/* Return the appropriate mode for a named address address.  */
647
#undef TARGET_ADDR_SPACE_ADDRESS_MODE
648
#define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode
649
static enum machine_mode
650
rl78_addr_space_address_mode (addr_space_t addrspace)
651
{
652
  switch (addrspace)
653
    {
654
    case ADDR_SPACE_GENERIC:
655
      return HImode;
656
    case ADDR_SPACE_FAR:
657
      return SImode;
658
    default:
659
      gcc_unreachable ();
660
    }
661
}
662
 
663
#undef  TARGET_LEGITIMATE_CONSTANT_P
664
#define TARGET_LEGITIMATE_CONSTANT_P            rl78_is_legitimate_constant
665
 
666
static bool
667
rl78_is_legitimate_constant (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED)
668
{
669
  return true;
670
}
671
 
672
#undef  TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
673
#define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P  rl78_as_legitimate_address
674
 
675
bool
676
rl78_as_legitimate_address (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x,
677
                            bool strict ATTRIBUTE_UNUSED, addr_space_t as ATTRIBUTE_UNUSED)
678
{
679
  rtx base, index, addend;
680
 
681
  if (as == ADDR_SPACE_GENERIC
682
      && GET_MODE (x) == SImode)
683
    return false;
684
 
685
  if (! characterize_address (x, &base, &index, &addend))
686
    return false;
687
 
688
  if (base && index)
689
    {
690
      int ir = REGNO (index);
691
      int br = REGNO (base);
692
 
693
#define OK(test, debug) if (test) { /*fprintf(stderr, "%d: OK %s\n", __LINE__, debug);*/ return true; }
694
      OK (REG_IS (br, HL_REG) && REG_IS (ir, B_REG), "[hl+b]");
695
      OK (REG_IS (br, HL_REG) && REG_IS (ir, C_REG), "[hl+c]");
696
      return false;
697
    }
698
 
699
  if (strict && base && GET_CODE (base) == REG && REGNO (base) >= FIRST_PSEUDO_REGISTER)
700
    return false;
701
 
702
  return true;
703
}
704
 
705
/* Determine if one named address space is a subset of another.  */
706
#undef  TARGET_ADDR_SPACE_SUBSET_P
707
#define TARGET_ADDR_SPACE_SUBSET_P rl78_addr_space_subset_p
708
static bool
709
rl78_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
710
{
711
  gcc_assert (subset == ADDR_SPACE_GENERIC || subset == ADDR_SPACE_FAR);
712
  gcc_assert (superset == ADDR_SPACE_GENERIC || superset == ADDR_SPACE_FAR);
713
 
714
  if (subset == superset)
715
    return true;
716
 
717
  else
718
    return (subset == ADDR_SPACE_GENERIC && superset == ADDR_SPACE_FAR);
719
}
720
 
721
#undef  TARGET_ADDR_SPACE_CONVERT
722
#define TARGET_ADDR_SPACE_CONVERT rl78_addr_space_convert
723
/* Convert from one address space to another.  */
724
static rtx
725
rl78_addr_space_convert (rtx op, tree from_type, tree to_type)
726
{
727
  addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
728
  addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
729
  rtx result;
730
 
731
  gcc_assert (from_as == ADDR_SPACE_GENERIC || from_as == ADDR_SPACE_FAR);
732
  gcc_assert (to_as == ADDR_SPACE_GENERIC || to_as == ADDR_SPACE_FAR);
733
 
734
  if (to_as == ADDR_SPACE_GENERIC && from_as == ADDR_SPACE_FAR)
735
    {
736
      /* This is unpredictable, as we're truncating off usable address
737
         bits.  */
738
 
739
      result = gen_reg_rtx (HImode);
740
      emit_move_insn (result, simplify_subreg (HImode, op, SImode, 0));
741
      return result;
742
    }
743
  else if (to_as == ADDR_SPACE_FAR && from_as == ADDR_SPACE_GENERIC)
744
    {
745
      /* This always works.  */
746
      result = gen_reg_rtx (SImode);
747
      debug_rtx(result);
748
      debug_rtx(op);
749
      emit_move_insn (rl78_subreg (HImode, result, SImode, 0), op);
750
      emit_move_insn (rl78_subreg (HImode, result, SImode, 2), const0_rtx);
751
      return result;
752
    }
753
  else
754
    gcc_unreachable ();
755
}
756
 
757
/* Implements REGNO_MODE_CODE_OK_FOR_BASE_P.  */
758
bool
759
rl78_regno_mode_code_ok_for_base_p (int regno, enum machine_mode mode ATTRIBUTE_UNUSED,
760
                                    addr_space_t address_space ATTRIBUTE_UNUSED,
761
                                    int outer_code ATTRIBUTE_UNUSED, int index_code)
762
{
763
  if (regno < 24 && regno >= 16)
764
    return true;
765
  if (index_code == REG)
766
    return (regno == HL_REG);
767
  if (regno == C_REG || regno == B_REG || regno == E_REG || regno == L_REG)
768
    return true;
769
  return false;
770
}
771
 
772
/* Implements MODE_CODE_BASE_REG_CLASS.  */
773
enum reg_class
774
rl78_mode_code_base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED,
775
                               addr_space_t address_space ATTRIBUTE_UNUSED,
776
                               int outer_code ATTRIBUTE_UNUSED,
777
                               int index_code ATTRIBUTE_UNUSED)
778
{
779
  return V_REGS;
780
}
781
 
782
/* Implements INITIAL_ELIMINATION_OFFSET.  The frame layout is
783
   described in the machine_Function struct definition, above.  */
784
int
785
rl78_initial_elimination_offset (int from, int to)
786
{
787
  int rv = 0; /* as if arg to arg */
788
 
789
  rl78_compute_frame_info ();
790
 
791
  switch (to)
792
    {
793
    case STACK_POINTER_REGNUM:
794
      rv += cfun->machine->framesize_outgoing;
795
      rv += cfun->machine->framesize_locals;
796
      /* Fall through.  */
797
    case FRAME_POINTER_REGNUM:
798
      rv += cfun->machine->framesize_regs;
799
      rv += 4;
800
      break;
801
    default:
802
      gcc_unreachable ();
803
    }
804
 
805
  switch (from)
806
    {
807
    case FRAME_POINTER_REGNUM:
808
      rv -= 4;
809
      rv -= cfun->machine->framesize_regs;
810
    case ARG_POINTER_REGNUM:
811
      break;
812
    default:
813
      gcc_unreachable ();
814
    }
815
 
816
  return rv;
817
}
818
 
819
/* Expand the function prologue (from the prologue pattern).  */
820
void
821
rl78_expand_prologue (void)
822
{
823
  int i, fs;
824
  rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
825
  int rb = 0;
826
 
827
  if (!cfun->machine->computed)
828
    rl78_compute_frame_info ();
829
 
830
  for (i = 0; i < 16; i++)
831
    if (cfun->machine->need_to_push [i])
832
      {
833
        int need_bank = i/4;
834
        if (need_bank != rb)
835
          {
836
            emit_insn (gen_sel_rb (GEN_INT (need_bank)));
837
            rb = need_bank;
838
          }
839
        F (emit_insn (gen_push (gen_rtx_REG (HImode, i*2))));
840
      }
841
  if (rb != 0)
842
    emit_insn (gen_sel_rb (GEN_INT (0)));
843
 
844
  if (frame_pointer_needed)
845
    F (emit_move_insn (gen_rtx_REG (HImode, FRAME_POINTER_REGNUM),
846
                       gen_rtx_REG (HImode, STACK_POINTER_REGNUM)));
847
 
848
  fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
849
  while (fs > 0)
850
    {
851
      int fs_byte = (fs > 254) ? 254 : fs;
852
      F (emit_insn (gen_subhi3 (sp, sp, GEN_INT (fs_byte))));
853
      fs -= fs_byte;
854
    }
855
}
856
 
857
/* Expand the function epilogue (from the epilogue pattern).  */
858
void
859
rl78_expand_epilogue (void)
860
{
861
  int i, fs;
862
  rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
863
  int rb = 0;
864
 
865
  if (frame_pointer_needed)
866
    {
867
      emit_move_insn (gen_rtx_REG (HImode, STACK_POINTER_REGNUM),
868
                      gen_rtx_REG (HImode, FRAME_POINTER_REGNUM));
869
    }
870
  else
871
    {
872
      fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
873
      while (fs > 0)
874
        {
875
          int fs_byte = (fs > 254) ? 254 : fs;
876
 
877
          emit_insn (gen_addhi3 (sp, sp, GEN_INT (fs_byte)));
878
          fs -= fs_byte;
879
        }
880
    }
881
 
882
  for (i = 15; i >= 0; i--)
883
    if (cfun->machine->need_to_push [i])
884
      {
885
        int need_bank = i / 4;
886
 
887
        if (need_bank != rb)
888
          {
889
            emit_insn (gen_sel_rb (GEN_INT (need_bank)));
890
            rb = need_bank;
891
          }
892
        emit_insn (gen_pop (gen_rtx_REG (HImode, i * 2)));
893
      }
894
 
895
  if (rb != 0)
896
    emit_insn (gen_sel_rb (GEN_INT (0)));
897
 
898
  if (cfun->machine->trampolines_used)
899
    emit_insn (gen_trampoline_uninit ());
900
 
901
  if (is_brk_interrupt_func (cfun->decl))
902
    emit_jump_insn (gen_brk_interrupt_return ());
903
  else if (is_interrupt_func (cfun->decl))
904
    emit_jump_insn (gen_interrupt_return ());
905
  else
906
    emit_jump_insn (gen_rl78_return ());
907
}
908
 
909
/* Likewise, for exception handlers.  */
910
void
911
rl78_expand_eh_epilogue (rtx x ATTRIBUTE_UNUSED)
912
{
913
  /* FIXME - replace this with an indirect jump with stack adjust.  */
914
  emit_jump_insn (gen_rl78_return ());
915
}
916
 
917
#undef  TARGET_ASM_FUNCTION_PROLOGUE
918
#define TARGET_ASM_FUNCTION_PROLOGUE    rl78_start_function
919
 
920
/* We don't use this to actually emit the function prologue.  We use
921
   this to insert a comment in the asm file describing the
922
   function.  */
923
static void
924
rl78_start_function (FILE *file, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED)
925
{
926
  int i;
927
 
928
  if (cfun->machine->framesize == 0)
929
    return;
930
  fprintf (file, "\t; start of function\n");
931
 
932
  if (cfun->machine->framesize_regs)
933
    {
934
      fprintf (file, "\t; push %d:", cfun->machine->framesize_regs);
935
      for (i = 0; i < 16; i ++)
936
        if (cfun->machine->need_to_push[i])
937
          fprintf (file, " %s", word_regnames[i*2]);
938
      fprintf(file, "\n");
939
    }
940
 
941
  if (frame_pointer_needed)
942
    fprintf (file, "\t; $fp points here (r22)\n");
943
 
944
  if (cfun->machine->framesize_locals)
945
    fprintf (file, "\t; locals: %d byte%s\n", cfun->machine->framesize_locals,
946
             cfun->machine->framesize_locals == 1 ? "" : "s");
947
 
948
  if (cfun->machine->framesize_outgoing)
949
    fprintf (file, "\t; outgoing: %d byte%s\n", cfun->machine->framesize_outgoing,
950
             cfun->machine->framesize_outgoing == 1 ? "" : "s");
951
}
952
 
953
/* Return an RTL describing where a function return value of type RET_TYPE
954
   is held.  */
955
 
956
#undef  TARGET_FUNCTION_VALUE
957
#define TARGET_FUNCTION_VALUE           rl78_function_value
958
 
959
static rtx
960
rl78_function_value (const_tree ret_type,
961
                     const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
962
                     bool       outgoing ATTRIBUTE_UNUSED)
963
{
964
  enum machine_mode mode = TYPE_MODE (ret_type);
965
 
966
  return gen_rtx_REG (mode, 8);
967
}
968
 
969
#undef  TARGET_PROMOTE_FUNCTION_MODE
970
#define TARGET_PROMOTE_FUNCTION_MODE rl78_promote_function_mode
971
 
972
static enum machine_mode
973
rl78_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
974
                            enum machine_mode mode,
975
                            int *punsignedp ATTRIBUTE_UNUSED,
976
                            const_tree funtype ATTRIBUTE_UNUSED, int for_return ATTRIBUTE_UNUSED)
977
{
978
  return mode;
979
}
980
 
981
/* Return an RTL expression describing the register holding a function
982
   parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
983
   be passed on the stack.  CUM describes the previous parameters to the
984
   function and NAMED is false if the parameter is part of a variable
985
   parameter list, or the last named parameter before the start of a
986
   variable parameter list.  */
987
 
988
#undef  TARGET_FUNCTION_ARG
989
#define TARGET_FUNCTION_ARG             rl78_function_arg
990
 
991
static rtx
992
rl78_function_arg (cumulative_args_t cum_v ATTRIBUTE_UNUSED,
993
                   enum machine_mode mode ATTRIBUTE_UNUSED,
994
                   const_tree type ATTRIBUTE_UNUSED,
995
                   bool named ATTRIBUTE_UNUSED)
996
{
997
  return NULL_RTX;
998
}
999
 
1000
#undef  TARGET_FUNCTION_ARG_ADVANCE
1001
#define TARGET_FUNCTION_ARG_ADVANCE     rl78_function_arg_advance
1002
 
1003
static void
1004
rl78_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode, const_tree type,
1005
                           bool named ATTRIBUTE_UNUSED)
1006
{
1007
  int rounded_size;
1008
  CUMULATIVE_ARGS * cum = get_cumulative_args (cum_v);
1009
 
1010
  rounded_size = ((mode == BLKmode)
1011
                  ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
1012
  if (rounded_size & 1)
1013
    rounded_size ++;
1014
  (*cum) += rounded_size;
1015
}
1016
 
1017
#undef  TARGET_FUNCTION_ARG_BOUNDARY
1018
#define TARGET_FUNCTION_ARG_BOUNDARY rl78_function_arg_boundary
1019
 
1020
static unsigned int
1021
rl78_function_arg_boundary (enum machine_mode mode ATTRIBUTE_UNUSED,
1022
                            const_tree type ATTRIBUTE_UNUSED)
1023
{
1024
  return 16;
1025
}
1026
 
1027
/* Supported modifier letters:
1028
 
1029
   A - address of a MEM
1030
   S - SADDR form of a real register
1031
   v - real register corresponding to a virtual register
1032
   m - minus - negative of CONST_INT value.
1033
   c - inverse of a conditional (NE vs EQ for example)
1034
 
1035
   h - bottom HI of an SI
1036
   H - top HI of an SI
1037
   q - bottom QI of an HI
1038
   Q - top QI of an HI
1039
   e - third QI of an SI (i.e. where the ES register gets values from)
1040
 
1041
*/
1042
 
1043
/* Implements the bulk of rl78_print_operand, below.  We do it this
1044
   way because we need to test for a constant at the top level and
1045
   insert the '#', but not test for it anywhere else as we recurse
1046
   down into the operand.  */
1047
static void
1048
rl78_print_operand_1 (FILE * file, rtx op, int letter)
1049
{
1050
  int need_paren;
1051
 
1052
  switch (GET_CODE (op))
1053
    {
1054
    case MEM:
1055
      if (letter == 'A')
1056
        rl78_print_operand_1 (file, XEXP (op, 0), letter);
1057
      else
1058
        {
1059
          if (rl78_far_p (op))
1060
            fprintf(file, "es:");
1061
          if (letter == 'H')
1062
            {
1063
              op = adjust_address (op, HImode, 2);
1064
              letter = 0;
1065
            }
1066
          if (letter == 'h')
1067
            {
1068
              op = adjust_address (op, HImode, 0);
1069
              letter = 0;
1070
            }
1071
          if (letter == 'Q')
1072
            {
1073
              op = adjust_address (op, QImode, 1);
1074
              letter = 0;
1075
            }
1076
          if (letter == 'q')
1077
            {
1078
              op = adjust_address (op, QImode, 0);
1079
              letter = 0;
1080
            }
1081
          if (letter == 'e')
1082
            {
1083
              op = adjust_address (op, QImode, 2);
1084
              letter = 0;
1085
            }
1086
          if (CONSTANT_P (XEXP (op, 0)))
1087
            {
1088
              fprintf(file, "!");
1089
              rl78_print_operand_1 (file, XEXP (op, 0), letter);
1090
            }
1091
          else if (GET_CODE (XEXP (op, 0)) == PLUS
1092
                   && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF)
1093
            {
1094
              fprintf(file, "!");
1095
              rl78_print_operand_1 (file, XEXP (op, 0), letter);
1096
            }
1097
          else if (GET_CODE (XEXP (op, 0)) == PLUS
1098
                   && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
1099
                   && REGNO (XEXP (XEXP (op, 0), 0)) == 2)
1100
            {
1101
              rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 1), 'u');
1102
              fprintf(file, "[");
1103
              rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 0), 0);
1104
              fprintf(file, "]");
1105
            }
1106
          else
1107
            {
1108
              fprintf(file, "[");
1109
              rl78_print_operand_1 (file, XEXP (op, 0), letter);
1110
              fprintf(file, "]");
1111
            }
1112
        }
1113
      break;
1114
 
1115
    case REG:
1116
      if (letter == 'Q')
1117
        fprintf (file, "%s", reg_names [REGNO (op) | 1]);
1118
      else if (letter == 'H')
1119
        fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1120
      else if (letter == 'q')
1121
        fprintf (file, "%s", reg_names [REGNO (op) & ~1]);
1122
      else if (letter == 'e')
1123
        fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1124
      else if (letter == 'S')
1125
        fprintf (file, "0x%x", 0xffef8 + REGNO (op));
1126
      else if (GET_MODE (op) == HImode
1127
               && ! (REGNO (op) & ~0xfe))
1128
        {
1129
          if (letter == 'v')
1130
            fprintf (file, "%s", word_regnames [REGNO (op) % 8]);
1131
          else
1132
            fprintf (file, "%s", word_regnames [REGNO (op)]);
1133
        }
1134
      else
1135
        fprintf (file, "%s", reg_names [REGNO (op)]);
1136
      break;
1137
 
1138
    case CONST_INT:
1139
      if (letter == 'Q')
1140
        fprintf (file, "%ld", INTVAL (op) >> 8);
1141
      else if (letter == 'H')
1142
        fprintf (file, "%ld", INTVAL (op) >> 16);
1143
      else if (letter == 'q')
1144
        fprintf (file, "%ld", INTVAL (op) & 0xff);
1145
      else if (letter == 'h')
1146
        fprintf (file, "%ld", INTVAL (op) & 0xffff);
1147
      else if (letter == 'e')
1148
        fprintf (file, "%ld", (INTVAL (op) >> 16) & 0xff);
1149
      else if (letter == 'm')
1150
        fprintf (file, "%ld", - INTVAL (op));
1151
      else
1152
        fprintf(file, "%ld", INTVAL (op));
1153
      break;
1154
 
1155
    case CONST:
1156
      rl78_print_operand_1 (file, XEXP (op, 0), letter);
1157
      break;
1158
 
1159
    case ZERO_EXTRACT:
1160
      {
1161
        int bits = INTVAL (XEXP (op, 1));
1162
        int ofs = INTVAL (XEXP (op, 2));
1163
        if (bits == 16 && ofs == 0)
1164
          fprintf (file, "%%lo16(");
1165
        else if (bits == 16 && ofs == 16)
1166
          fprintf (file, "%%hi16(");
1167
        else if (bits == 8 && ofs == 16)
1168
          fprintf (file, "%%hi8(");
1169
        else
1170
          gcc_unreachable ();
1171
        rl78_print_operand_1 (file, XEXP (op, 0), 0);
1172
        fprintf (file, ")");
1173
      }
1174
      break;
1175
 
1176
    case ZERO_EXTEND:
1177
      if (GET_CODE (XEXP (op, 0)) == REG)
1178
        fprintf (file, "%s", reg_names [REGNO (XEXP (op, 0))]);
1179
      else
1180
        print_rtl (file, op);
1181
      break;
1182
 
1183
    case PLUS:
1184
      need_paren = 0;
1185
      if (letter == 'H')
1186
        {
1187
          fprintf (file, "%%hi16(");
1188
          need_paren = 1;
1189
          letter = 0;
1190
        }
1191
      if (letter == 'h')
1192
        {
1193
          fprintf (file, "%%lo16(");
1194
          need_paren = 1;
1195
          letter = 0;
1196
        }
1197
      if (letter == 'e')
1198
        {
1199
          fprintf (file, "%%hi8(");
1200
          need_paren = 1;
1201
          letter = 0;
1202
        }
1203
      if (letter == 'q' || letter == 'Q')
1204
        output_operand_lossage ("q/Q modifiers invalid for symbol references");
1205
 
1206
      if (GET_CODE (XEXP (op, 0)) == ZERO_EXTEND)
1207
        {
1208
          rl78_print_operand_1 (file, XEXP (op, 1), letter);
1209
          fprintf (file, "+");
1210
          rl78_print_operand_1 (file, XEXP (op, 0), letter);
1211
        }
1212
      else
1213
        {
1214
          rl78_print_operand_1 (file, XEXP (op, 0), letter);
1215
          fprintf (file, "+");
1216
          rl78_print_operand_1 (file, XEXP (op, 1), letter);
1217
        }
1218
      if (need_paren)
1219
        fprintf (file, ")");
1220
      break;
1221
 
1222
    case SYMBOL_REF:
1223
      need_paren = 0;
1224
      if (letter == 'H')
1225
        {
1226
          fprintf (file, "%%hi16(");
1227
          need_paren = 1;
1228
          letter = 0;
1229
        }
1230
      if (letter == 'h')
1231
        {
1232
          fprintf (file, "%%lo16(");
1233
          need_paren = 1;
1234
          letter = 0;
1235
        }
1236
      if (letter == 'e')
1237
        {
1238
          fprintf (file, "%%hi8(");
1239
          need_paren = 1;
1240
          letter = 0;
1241
        }
1242
      if (letter == 'q' || letter == 'Q')
1243
        output_operand_lossage ("q/Q modifiers invalid for symbol references");
1244
 
1245
      output_addr_const (file, op);
1246
      if (need_paren)
1247
        fprintf (file, ")");
1248
      break;
1249
 
1250
    case CODE_LABEL:
1251
    case LABEL_REF:
1252
      output_asm_label (op);
1253
      break;
1254
 
1255
    case LTU:
1256
      fprintf (file, letter == 'c' ? "nc" : "c");
1257
      break;
1258
    case LEU:
1259
      fprintf (file, letter == 'c' ? "h" : "nh");
1260
      break;
1261
    case GEU:
1262
      fprintf (file, letter == 'c' ? "c" : "nc");
1263
      break;
1264
    case GTU:
1265
      fprintf (file, letter == 'c' ? "nh" : "h");
1266
      break;
1267
    case EQ:
1268
      fprintf (file, letter == 'c' ? "nz" : "z");
1269
      break;
1270
    case NE:
1271
      fprintf (file, letter == 'c' ? "z" : "nz");
1272
      break;
1273
 
1274
    default:
1275
      fprintf (file, "(%s)", GET_RTX_NAME (GET_CODE (op)));
1276
      break;
1277
    }
1278
}
1279
 
1280
#undef  TARGET_PRINT_OPERAND
1281
#define TARGET_PRINT_OPERAND            rl78_print_operand
1282
 
1283
static void
1284
rl78_print_operand (FILE * file, rtx op, int letter)
1285
{
1286
  if (CONSTANT_P (op) && letter != 'u')
1287
    fprintf (file, "#");
1288
  rl78_print_operand_1 (file, op, letter);
1289
}
1290
 
1291
#undef  TARGET_TRAMPOLINE_INIT
1292
#define TARGET_TRAMPOLINE_INIT rl78_trampoline_init
1293
 
1294
/* Note that the RL78's addressing makes it very difficult to do
1295
   trampolines on the stack.  So, libgcc has a small pool of
1296
   trampolines from which one is allocated to this task.  */
1297
static void
1298
rl78_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
1299
{
1300
  rtx mov_addr, thunk_addr;
1301
  rtx function = XEXP (DECL_RTL (fndecl), 0);
1302
 
1303
  mov_addr = adjust_address (m_tramp, HImode, 0);
1304
  thunk_addr = gen_reg_rtx (HImode);
1305
 
1306
  function = force_reg (HImode, function);
1307
  static_chain = force_reg (HImode, static_chain);
1308
 
1309
  emit_insn (gen_trampoline_init (thunk_addr, function, static_chain));
1310
  emit_move_insn (mov_addr, thunk_addr);
1311
 
1312
  cfun->machine->trampolines_used = 1;
1313
}
1314
 
1315
#undef  TARGET_TRAMPOLINE_ADJUST_ADDRESS
1316
#define TARGET_TRAMPOLINE_ADJUST_ADDRESS rl78_trampoline_adjust_address
1317
 
1318
static rtx
1319
rl78_trampoline_adjust_address (rtx m_tramp)
1320
{
1321
  rtx x = gen_rtx_MEM (HImode, m_tramp);
1322
  return x;
1323
}
1324
 
1325
/* Expander for cbranchqi4 and cbranchhi4.  RL78 is missing some of
1326
   the "normal" compares, specifically, it only has unsigned compares,
1327
   so we must synthesize the missing ones.  */
1328
void
1329
rl78_expand_compare (rtx *operands)
1330
{
1331
  /* RL78 does not have signed comparisons.  We must modify the
1332
     operands to be in the unsigned range, and emit an unsigned
1333
     comparison.  */
1334
 
1335
  enum machine_mode mode;
1336
  rtx high_bit;
1337
  int i;
1338
  RTX_CODE new_cond;
1339
 
1340
  switch (GET_CODE (operands[0]))
1341
    {
1342
    case GE:
1343
      new_cond = GEU;
1344
      break;
1345
    case LE:
1346
      new_cond = LEU;
1347
      break;
1348
    case GT:
1349
      new_cond = GTU;
1350
      break;
1351
    case LT:
1352
      new_cond = LTU;
1353
      break;
1354
    default:
1355
      return;
1356
    }
1357
 
1358
#if DEBUG0
1359
  fprintf (stderr, "\033[38;5;129mrl78_expand_compare\n");
1360
  debug_rtx (operands[0]);
1361
  fprintf (stderr, "\033[0m");
1362
#endif
1363
 
1364
  mode = GET_MODE (operands[1]);
1365
  if (mode == VOIDmode)
1366
    mode = GET_MODE (operands[2]);
1367
  high_bit = GEN_INT (~0 << (GET_MODE_BITSIZE (mode) - 1));
1368
 
1369
  /* 0: conditional 1,2: operands */
1370
  for (i = 1; i <= 2; i ++)
1371
    {
1372
      rtx r = operands[i];
1373
 
1374
      if (GET_CODE (r) == CONST_INT)
1375
        r = GEN_INT (INTVAL (r) ^ INTVAL (high_bit));
1376
      else
1377
        {
1378
          r = gen_rtx_PLUS (mode, operands[i], high_bit);
1379
          r = copy_to_mode_reg (mode, r);
1380
        }
1381
      operands[i] = r;
1382
    }
1383
 
1384
  operands[0] = gen_rtx_fmt_ee (new_cond, GET_MODE (operands[0]), operands[1], operands[2]);
1385
 
1386
#if DEBUG0
1387
  fprintf (stderr, "\033[38;5;142mrl78_expand_compare\n");
1388
  debug_rtx (operands[0]);
1389
  fprintf (stderr, "\033[0m");
1390
#endif
1391
}
1392
 
1393
 
1394
 
1395
/* Define this to 1 if you are debugging the peephole optimizers.  */
1396
#define DEBUG_PEEP 0
1397
 
1398
/* Predicate used to enable the peephole2 patterns in rl78-virt.md.
1399
   The default "word" size is a byte so we can effectively use all the
1400
   registers, but we want to do 16-bit moves whenever possible.  This
1401
   function determines when such a move is an option.  */
1402
bool
1403
rl78_peep_movhi_p (rtx *operands)
1404
{
1405
  int i;
1406
  rtx m, a;
1407
 
1408
  /* (set (op0) (op1))
1409
     (set (op2) (op3)) */
1410
 
1411
#if DEBUG_PEEP
1412
  fprintf (stderr, "\033[33m");
1413
  debug_rtx(operands[0]);
1414
  debug_rtx(operands[1]);
1415
  debug_rtx(operands[2]);
1416
  debug_rtx(operands[3]);
1417
  fprintf (stderr, "\033[0m");
1418
#endif
1419
 
1420
  if (rtx_equal_p (operands[0], operands[3]))
1421
    {
1422
#if DEBUG_PEEP
1423
      fprintf (stderr, "no peep: overlapping\n");
1424
#endif
1425
      return false;
1426
    }
1427
 
1428
  for (i = 0; i < 2; i ++)
1429
    {
1430
      if (GET_CODE (operands[i]) != GET_CODE (operands[i+2]))
1431
        {
1432
#if DEBUG_PEEP
1433
          fprintf (stderr, "no peep: different codes\n");
1434
#endif
1435
          return false;
1436
        }
1437
      if (GET_MODE (operands[i]) != GET_MODE (operands[i+2]))
1438
        {
1439
#if DEBUG_PEEP
1440
          fprintf (stderr, "no peep: different modes\n");
1441
#endif
1442
          return false;
1443
        }
1444
 
1445
      switch (GET_CODE (operands[i]))
1446
        {
1447
        case REG:
1448
          /*   LSB                      MSB  */
1449
          if (REGNO (operands[i]) + 1 != REGNO (operands[i+2])
1450
              || GET_MODE (operands[i]) != QImode)
1451
            {
1452
#if DEBUG_PEEP
1453
              fprintf (stderr, "no peep: wrong regnos %d %d %d\n",
1454
                       REGNO (operands[i]), REGNO (operands[i+2]),
1455
                       i);
1456
#endif
1457
              return false;
1458
            }
1459
          if (! rl78_hard_regno_mode_ok (REGNO (operands[i]), HImode))
1460
            {
1461
#if DEBUG_PEEP
1462
              fprintf (stderr, "no peep: reg %d not HI\n", REGNO (operands[i]));
1463
#endif
1464
              return false;
1465
            }
1466
          break;
1467
 
1468
        case CONST_INT:
1469
          break;
1470
 
1471
        case MEM:
1472
          if (GET_MODE (operands[i]) != QImode)
1473
            return false;
1474
          if (MEM_ALIGN (operands[i]) < 16)
1475
            return false;
1476
          a = XEXP (operands[i], 0);
1477
          if (GET_CODE (a) == CONST)
1478
            a = XEXP (a, 0);
1479
          if (GET_CODE (a) == PLUS)
1480
            a = XEXP (a, 1);
1481
          if (GET_CODE (a) == CONST_INT
1482
              && INTVAL (a) & 1)
1483
            {
1484
#if DEBUG_PEEP
1485
              fprintf (stderr, "no peep: misaligned mem %d\n", i);
1486
              debug_rtx (operands[i]);
1487
#endif
1488
              return false;
1489
            }
1490
          m = adjust_address (operands[i], QImode, 1);
1491
          if (! rtx_equal_p (m, operands[i+2]))
1492
            {
1493
#if DEBUG_PEEP
1494
              fprintf (stderr, "no peep: wrong mem %d\n", i);
1495
              debug_rtx(m);
1496
              debug_rtx (operands[i+2]);
1497
#endif
1498
              return false;
1499
            }
1500
          break;
1501
 
1502
        default:
1503
#if DEBUG_PEEP
1504
          fprintf (stderr, "no peep: wrong rtx %d\n", i);
1505
#endif
1506
          return false;
1507
        }
1508
    }
1509
#if DEBUG_PEEP
1510
  fprintf (stderr, "\033[32mpeep!\033[0m\n");
1511
#endif
1512
  return true;
1513
}
1514
 
1515
/* Likewise, when a peephole is activated, this function helps compute
1516
   the new operands.  */
1517
void
1518
rl78_setup_peep_movhi (rtx *operands)
1519
{
1520
  int i;
1521
 
1522
  for (i = 0; i < 2; i ++)
1523
    {
1524
      switch (GET_CODE (operands[i]))
1525
        {
1526
        case REG:
1527
          operands[i+4] = gen_rtx_REG (HImode, REGNO (operands[i]));
1528
          break;
1529
 
1530
        case CONST_INT:
1531
          operands[i+4] = GEN_INT ((INTVAL (operands[i]) & 0xff) + ((char)INTVAL (operands[i+2])) * 256);
1532
          break;
1533
 
1534
        case MEM:
1535
          operands[i+4] = adjust_address (operands[i], HImode, 0);
1536
          break;
1537
 
1538
        default:
1539
          break;
1540
        }
1541
    }
1542
}
1543
 
1544
/*
1545
        How Devirtualization works in the RL78 GCC port
1546
 
1547
Background
1548
 
1549
The RL78 is an 8-bit port with some 16-bit operations.  It has 32
1550
bytes of register space, in four banks, memory-mapped.  One bank is
1551
the "selected" bank and holds the registers used for primary
1552
operations.  Since the registers are memory mapped, often you can
1553
still refer to the unselected banks via memory accesses.
1554
 
1555
Virtual Registers
1556
 
1557
The GCC port uses bank 0 as the "selected" registers (A, X, BC, etc)
1558
and refers to the other banks via their memory addresses, although
1559
they're treated as regular registers internally.  These "virtual"
1560
registers are R8 through R23 (bank3 is reserved for asm-based
1561
interrupt handlers).
1562
 
1563
There are four machine description files:
1564
 
1565
rl78.md        - common register-independent patterns and definitions
1566
rl78-expand.md - expanders
1567
rl78-virt.md   - patterns that match BEFORE devirtualization
1568
rl78-real.md   - patterns that match AFTER devirtualization
1569
 
1570
At least through register allocation and reload, gcc is told that it
1571
can do pretty much anything - but may only use the virtual registers.
1572
GCC cannot properly create the varying addressing modes that the RL78
1573
supports in an efficient way.
1574
 
1575
Sometime after reload, the RL78 backend "devirtualizes" the RTL.  It
1576
uses the "valloc" attribute in rl78-virt.md for determining the rules
1577
by which it will replace virtual registers with real registers (or
1578
not) and how to make up addressing modes.  For example, insns tagged
1579
with "ro1" have a single read-only parameter, which may need to be
1580
moved from memory/constant/vreg to a suitable real register.  As part
1581
of devirtualization, a flag is toggled, disabling the rl78-virt.md
1582
patterns and enabling the rl78-real.md patterns.  The new patterns'
1583
constraints are used to determine the real registers used.  NOTE:
1584
patterns in rl78-virt.md essentially ignore the constrains and rely on
1585
predicates, where the rl78-real.md ones essentially ignore the
1586
predicates and rely on the constraints.
1587
 
1588
The devirtualization pass is scheduled via the pass manager (despite
1589
being called "rl78_reorg") so it can be scheduled prior to var-track
1590
(the idea is to let gdb know about the new registers).  Ideally, it
1591
would be scheduled right after pro/epilogue generation, so the
1592
post-reload optimizers could operate on the real registers, but when I
1593
tried that there were some issues building the target libraries.
1594
 
1595
During devirtualization, a simple register move optimizer is run.  It
1596
would be better to run a full CSE/propogation pass on it through, or
1597
re-run regmove, but that has not yet been attempted.
1598
 
1599
 */
1600
#define DEBUG_ALLOC 0
1601
 
1602
/* Rescans an insn to see if it's recognized again.  This is done
1603
   carefully to ensure that all the constraint information is accurate
1604
   for the newly matched insn.  */
1605
static bool
1606
insn_ok_now (rtx insn)
1607
{
1608
  INSN_CODE (insn) = -1;
1609
  if (recog (PATTERN (insn), insn, 0) > -1)
1610
    {
1611
      extract_insn (insn);
1612
      if (constrain_operands (1))
1613
        {
1614
#if DEBUG_ALLOC
1615
          fprintf (stderr, "\033[32m");
1616
          debug_rtx (insn);
1617
          fprintf (stderr, "\033[0m");
1618
#endif
1619
          return true;
1620
        }
1621
    }
1622
  else
1623
    {
1624
      fprintf (stderr, "\033[41;30m Unrecognized insn \033[0m\n");
1625
      debug_rtx (insn);
1626
      gcc_unreachable ();
1627
    }
1628
#if DEBUG_ALLOC
1629
  fprintf (stderr, "\033[31m");
1630
  debug_rtx (insn);
1631
  fprintf (stderr, "\033[0m");
1632
#endif
1633
  return false;
1634
}
1635
 
1636
#if DEBUG_ALLOC
1637
#define WORKED fprintf (stderr, "\033[48;5;22m Worked at line %d \033[0m\n", __LINE__)
1638
#define FAILEDSOFAR fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__)
1639
#define FAILED fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__), gcc_unreachable()
1640
#define MAYBE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } else { FAILEDSOFAR; }
1641
#else
1642
#define WORKED
1643
#define FAILEDSOFAR
1644
#define FAILED gcc_unreachable ()
1645
#define MAYBE_OK(insn) if (insn_ok_now (insn)) return;
1646
#endif
1647
 
1648
/* Registers into which we move the contents of virtual registers.  */
1649
#define X gen_rtx_REG (QImode, 0)
1650
#define A gen_rtx_REG (QImode, 1)
1651
#define C gen_rtx_REG (QImode, 2)
1652
#define B gen_rtx_REG (QImode, 3)
1653
#define E gen_rtx_REG (QImode, 4)
1654
#define D gen_rtx_REG (QImode, 5)
1655
#define L gen_rtx_REG (QImode, 6)
1656
#define H gen_rtx_REG (QImode, 7)
1657
 
1658
#define AX gen_rtx_REG (HImode, 0)
1659
#define BC gen_rtx_REG (HImode, 2)
1660
#define DE gen_rtx_REG (HImode, 4)
1661
#define HL gen_rtx_REG (HImode, 6)
1662
 
1663
#define OP(x) (*recog_data.operand_loc[x])
1664
 
1665
/* Returns TRUE if R is a virtual register.  */
1666
static bool
1667
is_virtual_register (rtx r)
1668
{
1669
  return (GET_CODE (r) == REG
1670
          && REGNO (r) >= 8
1671
          && REGNO (r) < 24);
1672
}
1673
 
1674
/* In all these alloc routines, we expect the following: the insn
1675
   pattern is unshared, the insn was previously recognized and failed
1676
   due to predicates or constraints, and the operand data is in
1677
   recog_data.  */
1678
 
1679
static int virt_insn_was_frame;
1680
 
1681
/* Hook for all insns we emit.  Re-mark them as FRAME_RELATED if
1682
   needed.  */
1683
static rtx
1684
EM2 (int line ATTRIBUTE_UNUSED, rtx r)
1685
{
1686
#if DEBUG_ALLOC
1687
  fprintf (stderr, "\033[36m%d: ", line);
1688
  debug_rtx(r);
1689
  fprintf (stderr, "\033[0m");
1690
#endif
1691
  /*SCHED_GROUP_P (r) = 1;*/
1692
  if (virt_insn_was_frame)
1693
    RTX_FRAME_RELATED_P (r) = 1;
1694
  return r;
1695
}
1696
 
1697
#define EM(x) EM2 (__LINE__, x)
1698
 
1699
/* Return a suitable RTX for the low half of a __far address.  */
1700
static rtx
1701
rl78_lo16 (rtx addr)
1702
{
1703
  if (GET_CODE (addr) == SYMBOL_REF
1704
      || GET_CODE (addr) == CONST)
1705
    {
1706
      rtx r = gen_rtx_ZERO_EXTRACT (HImode, addr, GEN_INT (16), GEN_INT (0));
1707
      r = gen_rtx_CONST (HImode, r);
1708
      return r;
1709
    }
1710
  return rl78_subreg (HImode, addr, SImode, 0);
1711
}
1712
 
1713
/* Return a suitable RTX for the high half's lower byte of a __far address.  */
1714
static rtx
1715
rl78_hi8 (rtx addr)
1716
{
1717
  if (GET_CODE (addr) == SYMBOL_REF
1718
      || GET_CODE (addr) == CONST)
1719
    {
1720
      rtx r = gen_rtx_ZERO_EXTRACT (QImode, addr, GEN_INT (8), GEN_INT (16));
1721
      r = gen_rtx_CONST (QImode, r);
1722
      return r;
1723
    }
1724
  return rl78_subreg (QImode, addr, SImode, 2);
1725
}
1726
 
1727
/* Copy any register values into real registers and return an RTX for
1728
   the same memory, now addressed by real registers.  Any needed insns
1729
   are emitted before BEFORE.  */
1730
static rtx
1731
transcode_memory_rtx (rtx m, rtx newbase, rtx before)
1732
{
1733
  rtx base, index, addendr;
1734
  int addend = 0;
1735
 
1736
  if (GET_CODE (m) != MEM)
1737
    return m;
1738
 
1739
  if (GET_MODE (XEXP (m, 0)) == SImode)
1740
    {
1741
      rtx seg = rl78_hi8 (XEXP (m, 0));
1742
#if DEBUG_ALLOC
1743
      fprintf (stderr, "setting ES:\n");
1744
      debug_rtx(seg);
1745
#endif
1746
      emit_insn_before (EM(gen_movqi (A, seg)), before);
1747
      emit_insn_before (EM(gen_movqi_es (A)), before);
1748
      m = change_address (m, GET_MODE (m), rl78_lo16 (XEXP (m, 0)));
1749
    }
1750
 
1751
  characterize_address (XEXP (m, 0), &base, &index, &addendr);
1752
  gcc_assert (index == NULL_RTX);
1753
 
1754
#if DEBUG_ALLOC
1755
  fprintf (stderr, "\033[33m"); debug_rtx(m); fprintf (stderr, "\033[0m");
1756
  debug_rtx (base);
1757
#endif
1758
  if (base == NULL_RTX)
1759
    return m;
1760
 
1761
  if (addendr && GET_CODE (addendr) == CONST_INT)
1762
    addend = INTVAL (addendr);
1763
 
1764
  if (REGNO (base) == SP_REG)
1765
    {
1766
      if (addend >= 0 && addend  <= 255)
1767
        return m;
1768
    }
1769
 
1770
  /* BASE should be a virtual register.  We copy it to NEWBASE.  If
1771
     the addend is out of range for DE/HL, we use AX to compute the full
1772
     address.  */
1773
 
1774
  if (addend < 0
1775
      || (addend > 255 && REGNO (newbase) != 2)
1776
      || (addendr && GET_CODE (addendr) != CONST_INT))
1777
    {
1778
      /* mov ax, vreg
1779
         add ax, #imm
1780
         mov hl, ax     */
1781
      EM (emit_insn_before (gen_movhi (AX, base), before));
1782
      EM (emit_insn_before (gen_addhi3 (AX, AX, addendr), before));
1783
      EM (emit_insn_before (gen_movhi (newbase, AX), before));
1784
      base = newbase;
1785
      addend = 0;
1786
    }
1787
  else
1788
    {
1789
      EM (emit_insn_before (gen_movhi (newbase, base), before));
1790
      base = newbase;
1791
    }
1792
 
1793
  if (addend)
1794
    base = gen_rtx_PLUS (HImode, base, GEN_INT (addend));
1795
 
1796
#if DEBUG_ALLOC
1797
  fprintf (stderr, "\033[33m");
1798
  debug_rtx (m);
1799
#endif
1800
  m = change_address (m, GET_MODE (m), base);
1801
#if DEBUG_ALLOC
1802
  debug_rtx (m);
1803
  fprintf (stderr, "\033[0m");
1804
#endif
1805
  return m;
1806
}
1807
 
1808
/* Copy SRC to accumulator (A or AX), placing any generated insns
1809
   before BEFORE.  Returns accumulator RTX.  */
1810
 
1811
static rtx
1812
move_to_acc (int opno, rtx before)
1813
{
1814
  rtx src = OP(opno);
1815
  enum machine_mode mode = GET_MODE (src);
1816
 
1817
  if (GET_CODE (src) == REG
1818
      && REGNO (src) < 2)
1819
    return src;
1820
 
1821
  if (mode == VOIDmode)
1822
    mode = recog_data.operand_mode[opno];
1823
 
1824
  if (mode == QImode)
1825
    {
1826
      EM (emit_insn_before (gen_movqi (A, src), before));
1827
      return A;
1828
    }
1829
  else
1830
    {
1831
      EM (emit_insn_before (gen_movhi (AX, src), before));
1832
      return AX;
1833
    }
1834
}
1835
 
1836
/* Copy accumulator (A or AX) to DEST, placing any generated insns
1837
   after AFTER.  Returns accumulator RTX.  */
1838
 
1839
static rtx
1840
move_from_acc (rtx dest, rtx after)
1841
{
1842
  enum machine_mode mode = GET_MODE (dest);
1843
 
1844
  if (REG_P (dest) && REGNO (dest) < 2)
1845
    return dest;
1846
 
1847
  if (mode == QImode)
1848
    {
1849
      EM (emit_insn_after (gen_movqi (dest, A), after));
1850
      return A;
1851
    }
1852
  else
1853
    {
1854
      EM (emit_insn_after (gen_movhi (dest, AX), after));
1855
      return AX;
1856
    }
1857
}
1858
 
1859
/* Copy accumulator (A or AX) to REGNO, placing any generated insns
1860
   before BEFORE.  Returns reg RTX.  */
1861
 
1862
static rtx
1863
move_acc_to_reg (rtx acc, int regno, rtx before)
1864
{
1865
  enum machine_mode mode = GET_MODE (acc);
1866
  rtx reg;
1867
 
1868
  reg = gen_rtx_REG (mode, regno);
1869
 
1870
  if (mode == QImode)
1871
    {
1872
      EM (emit_insn_before (gen_movqi (reg, A), before));
1873
      return reg;
1874
    }
1875
  else
1876
    {
1877
      EM (emit_insn_before (gen_movhi (reg, AX), before));
1878
      return reg;
1879
    }
1880
}
1881
 
1882
/* Copy SRC to X, placing any generated insns before BEFORE.
1883
   Returns X RTX.  */
1884
 
1885
static rtx
1886
move_to_x (int opno, rtx before)
1887
{
1888
  rtx src = OP(opno);
1889
  enum machine_mode mode = GET_MODE (src);
1890
  rtx reg;
1891
 
1892
  if (mode == VOIDmode)
1893
    mode = recog_data.operand_mode[opno];
1894
  reg = (mode == QImode) ? X : AX;
1895
 
1896
  if (mode == QImode || ! is_virtual_register (OP (opno)))
1897
    {
1898
      OP(opno) = move_to_acc (opno, before);
1899
      OP(opno) = move_acc_to_reg (OP(opno), X_REG, before);
1900
      return reg;
1901
    }
1902
 
1903
  if (mode == QImode)
1904
    EM (emit_insn_before (gen_movqi (reg, src), before));
1905
  else
1906
    EM (emit_insn_before (gen_movhi (reg, src), before));
1907
 
1908
  return reg;
1909
}
1910
 
1911
/* Copy OP(opno) to H or HL, placing any generated insns before BEFORE.
1912
   Returns H/HL RTX.  */
1913
 
1914
static rtx
1915
move_to_hl (int opno, rtx before)
1916
{
1917
  rtx src = OP (opno);
1918
  enum machine_mode mode = GET_MODE (src);
1919
  rtx reg;
1920
 
1921
  if (mode == VOIDmode)
1922
    mode = recog_data.operand_mode[opno];
1923
  reg = (mode == QImode) ? L : HL;
1924
 
1925
  if (mode == QImode || ! is_virtual_register (OP (opno)))
1926
    {
1927
      OP (opno) = move_to_acc (opno, before);
1928
      OP (opno) = move_acc_to_reg (OP (opno), L_REG, before);
1929
      return reg;
1930
    }
1931
 
1932
  if (mode == QImode)
1933
    EM (emit_insn_before (gen_movqi (reg, src), before));
1934
  else
1935
    EM (emit_insn_before (gen_movhi (reg, src), before));
1936
 
1937
  return reg;
1938
}
1939
 
1940
/* Copy OP(opno) to E or DE, placing any generated insns before BEFORE.
1941
   Returns E/DE RTX.  */
1942
 
1943
static rtx
1944
move_to_de (int opno, rtx before)
1945
{
1946
  rtx src = OP (opno);
1947
  enum machine_mode mode = GET_MODE (src);
1948
  rtx reg;
1949
 
1950
  if (mode == VOIDmode)
1951
    mode = recog_data.operand_mode[opno];
1952
 
1953
  reg = (mode == QImode) ? E : DE;
1954
 
1955
  if (mode == QImode || ! is_virtual_register (OP (opno)))
1956
    {
1957
      OP (opno) = move_to_acc (opno, before);
1958
      OP (opno) = move_acc_to_reg (OP (opno), E_REG, before);
1959
    }
1960
  else
1961
    {
1962
      rtx move = mode == QImode ? gen_movqi (reg, src) : gen_movhi (reg, src);
1963
 
1964
      EM (emit_insn_before (move, before));
1965
    }
1966
 
1967
  return reg;
1968
}
1969
 
1970
/* Devirtualize an insn of the form (SET (op) (unop (op))).  */
1971
static void
1972
rl78_alloc_physical_registers_op1 (rtx insn)
1973
{
1974
  /* op[0] = func op[1] */
1975
 
1976
  /* We first try using A as the destination, then copying it
1977
     back.  */
1978
  if (rtx_equal_p (OP(0), OP(1)))
1979
    {
1980
      OP(0) =
1981
      OP(1) = transcode_memory_rtx (OP(1), DE, insn);
1982
    }
1983
  else
1984
    {
1985
      OP(0) = transcode_memory_rtx (OP(0), BC, insn);
1986
      OP(1) = transcode_memory_rtx (OP(1), HL, insn);
1987
    }
1988
 
1989
  MAYBE_OK (insn);
1990
 
1991
  OP(0) = move_from_acc (OP(0), insn);
1992
 
1993
  MAYBE_OK (insn);
1994
 
1995
  /* Try copying the src to acc first, then.  This is for, for
1996
     example, ZERO_EXTEND or NOT.  */
1997
  OP(1) = move_to_acc (1, insn);
1998
 
1999
  MAYBE_OK (insn);
2000
 
2001
  FAILED;
2002
}
2003
 
2004
/* Devirtualize an insn of the form (SET (op) (unop (op) (op))).  */
2005
static void
2006
rl78_alloc_physical_registers_op2 (rtx insn)
2007
{
2008
  /* op[0] = op[1] func op[2] */
2009
  rtx prev = prev_nonnote_nondebug_insn (insn);
2010
  rtx first;
2011
  bool hl_used;
2012
 
2013
  if (rtx_equal_p (OP(0), OP(1)))
2014
    {
2015
      OP(0) =
2016
      OP(1) = transcode_memory_rtx (OP(1), DE, insn);
2017
      prev = next_nonnote_nondebug_insn (prev);
2018
      OP(2) = transcode_memory_rtx (OP(2), HL, insn);
2019
      prev = prev_nonnote_nondebug_insn (prev);
2020
    }
2021
  else if (rtx_equal_p (OP(0), OP(2)))
2022
    {
2023
      OP(1) = transcode_memory_rtx (OP(1), DE, insn);
2024
      prev = next_nonnote_nondebug_insn (prev);
2025
      OP(0) =
2026
      OP(2) = transcode_memory_rtx (OP(2), HL, insn);
2027
      prev = prev_nonnote_nondebug_insn (prev);
2028
    }
2029
  else
2030
    {
2031
      OP(0) = transcode_memory_rtx (OP(0), BC, insn);
2032
      OP(1) = transcode_memory_rtx (OP(1), DE, insn);
2033
      prev = next_nonnote_nondebug_insn (prev);
2034
      OP(2) = transcode_memory_rtx (OP(2), HL, insn);
2035
    }
2036
 
2037
  MAYBE_OK (insn);
2038
 
2039
  prev = prev_nonnote_nondebug_insn (insn);
2040
  if (recog_data.constraints[1][0] == '%'
2041
      && is_virtual_register (OP (1))
2042
      && ! is_virtual_register (OP (2))
2043
      && ! CONSTANT_P (OP (2)))
2044
    {
2045
      rtx tmp = OP (1);
2046
      OP (1) = OP (2);
2047
      OP (2) = tmp;
2048
    }
2049
 
2050
  /* Make a note of wether (H)L is being used.  It matters
2051
     because if OP(2) alsoneeds reloading, then we must take
2052
     care not to corrupt HL.  */
2053
  hl_used = reg_mentioned_p (L, OP (0)) || reg_mentioned_p (L, OP (1));
2054
 
2055
  OP(0) = move_from_acc (OP (0), insn);
2056
  OP(1) = move_to_acc (1, insn);
2057
 
2058
  MAYBE_OK (insn);
2059
 
2060
  /* We have to copy op2 to HL, but that involves AX, which
2061
     already has a live value.  Emit it before those insns.  */
2062
 
2063
  if (prev)
2064
    first = next_nonnote_nondebug_insn (prev);
2065
  else
2066
    for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
2067
      ;
2068
 
2069
  OP (2) = hl_used ? move_to_de (2, first) : move_to_hl (2, first);
2070
 
2071
  MAYBE_OK (insn);
2072
 
2073
  FAILED;
2074
}
2075
 
2076
/* Devirtualize an insn of the form (SET () (unop (op))).  */
2077
 
2078
static void
2079
rl78_alloc_physical_registers_ro1 (rtx insn)
2080
{
2081
  /* (void) op[0] */
2082
  OP(0) = transcode_memory_rtx (OP(0), BC, insn);
2083
 
2084
  MAYBE_OK (insn);
2085
 
2086
  OP(0) = move_to_acc (0, insn);
2087
 
2088
  MAYBE_OK (insn);
2089
 
2090
  FAILED;
2091
}
2092
 
2093
/* Devirtualize a compare insn.  */
2094
static void
2095
rl78_alloc_physical_registers_cmp (rtx insn)
2096
{
2097
  /* op[1] cmp_op[0] op[2] */
2098
  rtx prev = prev_nonnote_nondebug_insn (insn);
2099
  rtx first;
2100
 
2101
  OP(1) = transcode_memory_rtx (OP(1), DE, insn);
2102
  OP(2) = transcode_memory_rtx (OP(2), HL, insn);
2103
 
2104
  MAYBE_OK (insn);
2105
 
2106
  OP(1) = move_to_acc (1, insn);
2107
 
2108
  MAYBE_OK (insn);
2109
 
2110
  /* We have to copy op2 to HL, but that involves the acc, which
2111
     already has a live value.  Emit it before those insns.  */
2112
 
2113
  if (prev)
2114
    first = next_nonnote_nondebug_insn (prev);
2115
  else
2116
    for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
2117
      ;
2118
  OP(2) = move_to_hl (2, first);
2119
 
2120
  MAYBE_OK (insn);
2121
 
2122
  FAILED;
2123
}
2124
 
2125
/* Like op2, but AX = A op X.  */
2126
static void
2127
rl78_alloc_physical_registers_umul (rtx insn)
2128
{
2129
  /* op[0] = op[1] func op[2] */
2130
  rtx prev = prev_nonnote_nondebug_insn (insn);
2131
  rtx first;
2132
 
2133
  OP(0) = transcode_memory_rtx (OP(0), BC, insn);
2134
  OP(1) = transcode_memory_rtx (OP(1), DE, insn);
2135
  OP(2) = transcode_memory_rtx (OP(2), HL, insn);
2136
 
2137
  MAYBE_OK (insn);
2138
 
2139
  if (recog_data.constraints[1][0] == '%'
2140
      && is_virtual_register (OP(1))
2141
      && !is_virtual_register (OP(2))
2142
      && !CONSTANT_P (OP(2)))
2143
    {
2144
      rtx tmp = OP(1);
2145
      OP(1) = OP(2);
2146
      OP(2) = tmp;
2147
    }
2148
 
2149
  OP(0) = move_from_acc (OP(0), insn);
2150
  OP(1) = move_to_acc (1, insn);
2151
 
2152
  MAYBE_OK (insn);
2153
 
2154
  /* We have to copy op2 to X, but that involves the acc, which
2155
     already has a live value.  Emit it before those insns.  */
2156
 
2157
  if (prev)
2158
    first = next_nonnote_nondebug_insn (prev);
2159
  else
2160
    for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
2161
      ;
2162
  OP(2) = move_to_x (2, first);
2163
 
2164
  MAYBE_OK (insn);
2165
 
2166
  FAILED;
2167
}
2168
 
2169
/* Scan all insns and devirtualize them.  */
2170
static void
2171
rl78_alloc_physical_registers (void)
2172
{
2173
  /* During most of the compile, gcc is dealing with virtual
2174
     registers.  At this point, we need to assign physical registers
2175
     to the vitual ones, and copy in/out as needed.  */
2176
 
2177
  rtx insn, curr;
2178
  enum attr_valloc valloc_method;
2179
 
2180
  for (insn = get_insns (); insn; insn = curr)
2181
    {
2182
      int i;
2183
 
2184
      curr = next_nonnote_nondebug_insn (insn);
2185
 
2186
      if (INSN_P (insn)
2187
          && (GET_CODE (PATTERN (insn)) == SET
2188
              || GET_CODE (PATTERN (insn)) == CALL)
2189
          && INSN_CODE (insn) == -1)
2190
        {
2191
          if (GET_CODE (SET_SRC (PATTERN (insn))) == ASM_OPERANDS)
2192
            continue;
2193
          i = recog (PATTERN (insn), insn, 0);
2194
          if (i == -1)
2195
            {
2196
              debug_rtx (insn);
2197
              gcc_unreachable ();
2198
            }
2199
          INSN_CODE (insn) = i;
2200
        }
2201
    }
2202
 
2203
  cfun->machine->virt_insns_ok = 0;
2204
  cfun->machine->real_insns_ok = 1;
2205
 
2206
  for (insn = get_insns (); insn; insn = curr)
2207
    {
2208
      curr = insn ? next_nonnote_nondebug_insn (insn) : NULL;
2209
 
2210
      if (!INSN_P (insn))
2211
        continue;
2212
      if (GET_CODE (PATTERN (insn)) != SET
2213
          && GET_CODE (PATTERN (insn)) != CALL)
2214
          continue;
2215
 
2216
      if (GET_CODE (SET_SRC (PATTERN (insn))) == ASM_OPERANDS)
2217
        continue;
2218
 
2219
      valloc_method = get_attr_valloc (insn);
2220
 
2221
      PATTERN (insn)= copy_rtx_if_shared (PATTERN (insn));
2222
 
2223
      if (insn_ok_now (insn))
2224
        continue;
2225
 
2226
      INSN_CODE (insn) = -1;
2227
 
2228
      if (RTX_FRAME_RELATED_P (insn))
2229
        virt_insn_was_frame = 1;
2230
      else
2231
        virt_insn_was_frame = 0;
2232
 
2233
      switch (valloc_method)
2234
        {
2235
        case VALLOC_OP1:
2236
          rl78_alloc_physical_registers_op1 (insn);
2237
          break;
2238
        case VALLOC_OP2:
2239
          rl78_alloc_physical_registers_op2 (insn);
2240
          break;
2241
        case VALLOC_RO1:
2242
          rl78_alloc_physical_registers_ro1 (insn);
2243
          break;
2244
        case VALLOC_CMP:
2245
          rl78_alloc_physical_registers_cmp (insn);
2246
          break;
2247
        case VALLOC_UMUL:
2248
          rl78_alloc_physical_registers_umul (insn);
2249
          break;
2250
        case VALLOC_MACAX:
2251
          /* Macro that clobbers AX */
2252
          break;
2253
        }
2254
    }
2255
#if DEBUG_ALLOC
2256
  fprintf (stderr, "\033[0m");
2257
#endif
2258
}
2259
 
2260
/* Add REG_DEAD notes using DEAD[reg] for rtx S which is part of INSN.
2261
   This function scans for uses of registers; the last use (i.e. first
2262
   encounter when scanning backwards) triggers a REG_DEAD note if the
2263
   reg was previously in DEAD[].  */
2264
static void
2265
rl78_note_reg_uses (char *dead, rtx s, rtx insn)
2266
{
2267
  const char *fmt;
2268
  int i, r;
2269
  enum rtx_code code;
2270
 
2271
  if (!s)
2272
    return;
2273
 
2274
  code = GET_CODE (s);
2275
 
2276
  switch (code)
2277
    {
2278
      /* Compare registers by number.  */
2279
    case REG:
2280
      r = REGNO (s);
2281
      if (dump_file)
2282
        {
2283
          fprintf (dump_file, "note use reg %d size %d on insn %d\n",
2284
                   r, GET_MODE_SIZE (GET_MODE (s)), INSN_UID (insn));
2285
          print_rtl_single (dump_file, s);
2286
        }
2287
      if (dead [r])
2288
        add_reg_note (insn, REG_DEAD, gen_rtx_REG (GET_MODE (s), r));
2289
      for (i = 0; i < GET_MODE_SIZE (GET_MODE (s)); i ++)
2290
        dead [r + i] = 0;
2291
      return;
2292
 
2293
      /* These codes have no constituent expressions
2294
         and are unique.  */
2295
    case SCRATCH:
2296
    case CC0:
2297
    case PC:
2298
      return;
2299
 
2300
    case CONST_INT:
2301
    case CONST_VECTOR:
2302
    case CONST_DOUBLE:
2303
    case CONST_FIXED:
2304
      /* These are kept unique for a given value.  */
2305
      return;
2306
 
2307
    default:
2308
      break;
2309
    }
2310
 
2311
  fmt = GET_RTX_FORMAT (code);
2312
 
2313
  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
2314
    {
2315
      if (fmt[i] == 'E')
2316
        {
2317
          int j;
2318
          for (j = XVECLEN (s, i) - 1; j >= 0; j--)
2319
            rl78_note_reg_uses (dead, XVECEXP (s, i, j), insn);
2320
        }
2321
      else if (fmt[i] == 'e')
2322
        rl78_note_reg_uses (dead, XEXP (s, i), insn);
2323
    }
2324
}
2325
 
2326
/* Like the previous function, but scan for SETs instead.  */
2327
static void
2328
rl78_note_reg_set (char *dead, rtx d, rtx insn)
2329
{
2330
  int r, i;
2331
 
2332
  if (GET_CODE (d) != REG)
2333
    return;
2334
 
2335
  r = REGNO (d);
2336
  if (dead [r])
2337
    add_reg_note (insn, REG_UNUSED, gen_rtx_REG (GET_MODE (d), r));
2338
  if (dump_file)
2339
    fprintf (dump_file, "note set reg %d size %d\n", r, GET_MODE_SIZE (GET_MODE (d)));
2340
  for (i = 0; i < GET_MODE_SIZE (GET_MODE (d)); i ++)
2341
    dead [r + i] = 1;
2342
}
2343
 
2344
/* This is a rather crude register death pass.  Death status is reset
2345
   at every jump or call insn.  */
2346
static void
2347
rl78_calculate_death_notes (void)
2348
{
2349
  char dead[FIRST_PSEUDO_REGISTER];
2350
  rtx insn, p, s, d;
2351
  int i;
2352
 
2353
  memset (dead, 0, sizeof (dead));
2354
 
2355
  for (insn = get_last_insn ();
2356
       insn;
2357
       insn = prev_nonnote_nondebug_insn (insn))
2358
    {
2359
      if (dump_file)
2360
        {
2361
          fprintf (dump_file, "\n--------------------------------------------------");
2362
          fprintf (dump_file, "\nDead:");
2363
          for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
2364
            if (dead[i])
2365
              fprintf(dump_file, " %s", reg_names[i]);
2366
          fprintf (dump_file, "\n");
2367
          print_rtl_single (dump_file, insn);
2368
        }
2369
 
2370
      switch (GET_CODE (insn))
2371
        {
2372
        case INSN:
2373
          p = PATTERN (insn);
2374
          switch (GET_CODE (p))
2375
            {
2376
            case SET:
2377
              s = SET_SRC (p);
2378
              d = SET_DEST (p);
2379
              rl78_note_reg_set (dead, d, insn);
2380
              rl78_note_reg_uses (dead, s, insn);
2381
              break;
2382
 
2383
            case USE:
2384
              rl78_note_reg_uses (dead, p, insn);
2385
              break;
2386
 
2387
            default:
2388
              break;
2389
            }
2390
          break;
2391
 
2392
        case JUMP_INSN:
2393
          if (INSN_CODE (insn) == CODE_FOR_rl78_return)
2394
            {
2395
              memset (dead, 1, sizeof (dead));
2396
              /* We expect a USE just prior to this, which will mark
2397
                 the actual return registers.  The USE will have a
2398
                 death note, but we aren't going to be modifying it
2399
                 after this pass.  */
2400
              break;
2401
            }
2402
        case CALL_INSN:
2403
          memset (dead, 0, sizeof (dead));
2404
          break;
2405
 
2406
        default:
2407
          break;
2408
        }
2409
      if (dump_file)
2410
        print_rtl_single (dump_file, insn);
2411
    }
2412
}
2413
 
2414
/* Helper function to reset the origins in RP and the age in AGE for
2415
   all registers.  */
2416
static void
2417
reset_origins (int *rp, int *age)
2418
{
2419
  int i;
2420
  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2421
    {
2422
      rp[i] = i;
2423
      age[i] = 0;
2424
    }
2425
}
2426
 
2427
/* The idea behind this optimization is to look for cases where we
2428
   move data from A to B to C, and instead move from A to B, and A to
2429
   C.  If B is a virtual register or memory, this is a big win on its
2430
   own.  If B turns out to be unneeded after this, it's a bigger win.
2431
   For each register, we try to determine where it's value originally
2432
   came from, if it's propogated purely through moves (and not
2433
   computes).  The ORIGINS[] array has the regno for the "origin" of
2434
   the value in the [regno] it's indexed by.  */
2435
static void
2436
rl78_propogate_register_origins (void)
2437
{
2438
  int origins[FIRST_PSEUDO_REGISTER];
2439
  int age[FIRST_PSEUDO_REGISTER];
2440
  int i;
2441
  rtx insn, ninsn = NULL_RTX;
2442
  rtx pat;
2443
 
2444
  reset_origins (origins, age);
2445
 
2446
  for (insn = get_insns (); insn; insn = ninsn)
2447
    {
2448
      ninsn = next_nonnote_nondebug_insn (insn);
2449
 
2450
      if (dump_file)
2451
        {
2452
          fprintf (dump_file, "\n");
2453
          fprintf (dump_file, "Origins:");
2454
          for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
2455
            if (origins[i] != i)
2456
              fprintf (dump_file, " r%d=r%d", i, origins[i]);
2457
          fprintf (dump_file, "\n");
2458
          print_rtl_single (dump_file, insn);
2459
        }
2460
 
2461
      switch (GET_CODE (insn))
2462
        {
2463
        case CODE_LABEL:
2464
        case BARRIER:
2465
        case CALL_INSN:
2466
        case JUMP_INSN:
2467
          reset_origins (origins, age);
2468
          break;
2469
 
2470
        default:
2471
          break;
2472
 
2473
        case INSN:
2474
          pat = PATTERN (insn);
2475
 
2476
          if (GET_CODE (pat) == PARALLEL)
2477
            {
2478
              rtx clobber = XVECEXP (pat, 0, 1);
2479
              pat = XVECEXP (pat, 0, 0);
2480
              if (GET_CODE (clobber) == CLOBBER)
2481
                {
2482
                  int cr = REGNO (XEXP (clobber, 0));
2483
                  int mb = GET_MODE_SIZE (GET_MODE (XEXP (clobber, 0)));
2484
                  if (dump_file)
2485
                    fprintf (dump_file, "reset origins of %d regs at %d\n", mb, cr);
2486
                  for (i = 0; i < mb; i++)
2487
                    {
2488
                      origins[cr + i] = cr + i;
2489
                      age[cr + i] = 0;
2490
                    }
2491
                }
2492
              else
2493
                break;
2494
            }
2495
 
2496
          if (GET_CODE (pat) == SET)
2497
            {
2498
              rtx src = SET_SRC (pat);
2499
              rtx dest = SET_DEST (pat);
2500
              int mb = GET_MODE_SIZE (GET_MODE (dest));
2501
 
2502
              if (GET_CODE (dest) == REG)
2503
                {
2504
                  int dr = REGNO (dest);
2505
 
2506
                  if (GET_CODE (src) == REG)
2507
                    {
2508
                      int sr = REGNO (src);
2509
                      int same = 1;
2510
                      int best_age, best_reg;
2511
 
2512
                      /* See if the copy is not needed.  */
2513
                      for (i = 0; i < mb; i ++)
2514
                        if (origins[dr + i] != origins[sr + i])
2515
                          same = 0;
2516
                      if (same)
2517
                        {
2518
                          if (dump_file)
2519
                            fprintf (dump_file, "deleting because dest already has correct value\n");
2520
                          delete_insn (insn);
2521
                          break;
2522
                        }
2523
 
2524
                      if (dr < 8 || sr >= 8)
2525
                        {
2526
                          int ar;
2527
 
2528
                          best_age = -1;
2529
                          best_reg = -1;
2530
                          /* See if the copy can be made from another
2531
                             bank 0 register instead, instead of the
2532
                             virtual src register.  */
2533
                          for (ar = 0; ar < 8; ar += mb)
2534
                            {
2535
                              same = 1;
2536
                              for (i = 0; i < mb; i ++)
2537
                                if (origins[ar + i] != origins[sr + i])
2538
                                  same = 0;
2539
 
2540
                              /* The chip has some reg-reg move limitations.  */
2541
                              if (mb == 1 && dr > 3)
2542
                                same = 0;
2543
 
2544
                              if (same)
2545
                                {
2546
                                  if (best_age == -1 || best_age > age[sr + i])
2547
                                    {
2548
                                      best_age = age[sr + i];
2549
                                      best_reg = sr;
2550
                                    }
2551
                                }
2552
                            }
2553
 
2554
                          if (best_reg != -1)
2555
                            {
2556
                              /* FIXME: copy debug info too.  */
2557
                              SET_SRC (pat) = gen_rtx_REG (GET_MODE (src), best_reg);
2558
                              sr = best_reg;
2559
                            }
2560
                        }
2561
 
2562
                      for (i = 0; i < mb; i++)
2563
                        {
2564
                          origins[dr + i] = origins[sr + i];
2565
                          age[dr + i] = age[sr + i] + 1;
2566
                        }
2567
                    }
2568
                  else
2569
                    {
2570
                      /* The destination is computed, its origin is itself.  */
2571
                      if (dump_file)
2572
                        fprintf (dump_file, "resetting origin of r%d for %d byte%s\n",
2573
                                 dr, mb, mb == 1 ? "" : "s");
2574
                      for (i = 0; i < mb; i ++)
2575
                        {
2576
                          origins[dr + i] = dr + i;
2577
                          age[dr + i] = 0;
2578
                        }
2579
                    }
2580
 
2581
                  /* Any registers marked with that reg as an origin are reset.  */
2582
                  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2583
                    if (origins[i] >= dr && origins[i] < dr + mb)
2584
                      {
2585
                        origins[i] = i;
2586
                        age[i] = 0;
2587
                      }
2588
                }
2589
 
2590
              /* Special case - our ADDSI3 macro uses AX */
2591
              if (get_attr_valloc (insn) == VALLOC_MACAX)
2592
                {
2593
                  if (dump_file)
2594
                    fprintf (dump_file, "Resetting origin of AX for macro.\n");
2595
                  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2596
                    if (i <= 1 || origins[i] <= 1)
2597
                      {
2598
                        origins[i] = i;
2599
                        age[i] = 0;
2600
                      }
2601
                }
2602
 
2603
              if (GET_CODE (src) == ASHIFT
2604
                  || GET_CODE (src) == ASHIFTRT
2605
                  || GET_CODE (src) == LSHIFTRT)
2606
                {
2607
                  rtx count = XEXP (src, 1);
2608
                  if (GET_CODE (count) == REG)
2609
                    {
2610
                      /* Special case - our pattern clobbers the count register.  */
2611
                      int r = REGNO (count);
2612
                      if (dump_file)
2613
                        fprintf (dump_file, "Resetting origin of r%d for shift.\n", r);
2614
                      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2615
                        if (i == r || origins[i] == r)
2616
                          {
2617
                            origins[i] = i;
2618
                            age[i] = 0;
2619
                          }
2620
                    }
2621
                }
2622
            }
2623
        }
2624
    }
2625
}
2626
 
2627
/* Remove any SETs where the destination is unneeded.  */
2628
static void
2629
rl78_remove_unused_sets (void)
2630
{
2631
  rtx insn, ninsn = NULL_RTX;
2632
  rtx dest;
2633
 
2634
  for (insn = get_insns (); insn; insn = ninsn)
2635
    {
2636
      ninsn = next_nonnote_nondebug_insn (insn);
2637
 
2638
      if ((insn = single_set (insn)) == NULL_RTX)
2639
        continue;
2640
 
2641
      dest = SET_DEST (insn);
2642
 
2643
      if (REGNO (dest) > 23)
2644
        continue;
2645
 
2646
      if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
2647
        delete_insn (insn);
2648
    }
2649
}
2650
 
2651
#undef  xTARGET_MACHINE_DEPENDENT_REORG
2652
#define xTARGET_MACHINE_DEPENDENT_REORG  rl78_reorg
2653
 
2654
/* This is the top of the devritualization pass.  */
2655
static void
2656
rl78_reorg (void)
2657
{
2658
  rl78_alloc_physical_registers ();
2659
 
2660
  if (dump_file)
2661
    {
2662
      fprintf (dump_file, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n");
2663
      print_rtl_with_bb (dump_file, get_insns ());
2664
    }
2665
 
2666
  rl78_propogate_register_origins ();
2667
  rl78_calculate_death_notes ();
2668
 
2669
  if (dump_file)
2670
    {
2671
      fprintf (dump_file, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n");
2672
      print_rtl_with_bb (dump_file, get_insns ());
2673
      fprintf (dump_file, "\n======================================================================\n");
2674
    }
2675
 
2676
  rl78_remove_unused_sets ();
2677
 
2678
  /* The code after devirtualizing has changed so much that at this point
2679
     we might as well just rescan everything.  Note that
2680
     df_rescan_all_insns is not going to help here because it does not
2681
     touch the artificial uses and defs.  */
2682
  df_finish_pass (true);
2683
  if (optimize > 1)
2684
    df_live_add_problem ();
2685
  df_scan_alloc (NULL);
2686
  df_scan_blocks ();
2687
 
2688
  if (optimize)
2689
    df_analyze ();
2690
}
2691
 
2692
#undef TARGET_RETURN_IN_MEMORY
2693
#define TARGET_RETURN_IN_MEMORY rl78_return_in_memory
2694
 
2695
static bool
2696
rl78_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
2697
{
2698
  const HOST_WIDE_INT size = int_size_in_bytes (type);
2699
  return (size == -1 || size > 8);
2700
}
2701
 
2702
 
2703
struct gcc_target targetm = TARGET_INITIALIZER;
2704
 
2705
#include "gt-rl78.h"

powered by: WebSVN 2.1.0

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