]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/rl78/rl78.c
decl.c, [...]: Remove redundant enum from machine_mode.
[thirdparty/gcc.git] / gcc / config / rl78 / rl78.c
1 /* Subroutines used for code generation on Renesas RL78 processors.
2 Copyright (C) 2011-2014 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 "varasm.h"
27 #include "stor-layout.h"
28 #include "calls.h"
29 #include "rtl.h"
30 #include "regs.h"
31 #include "hard-reg-set.h"
32 #include "insn-config.h"
33 #include "conditions.h"
34 #include "output.h"
35 #include "insn-attr.h"
36 #include "flags.h"
37 #include "hashtab.h"
38 #include "hash-set.h"
39 #include "vec.h"
40 #include "machmode.h"
41 #include "input.h"
42 #include "function.h"
43 #include "expr.h"
44 #include "optabs.h"
45 #include "libfuncs.h"
46 #include "recog.h"
47 #include "diagnostic-core.h"
48 #include "toplev.h"
49 #include "reload.h"
50 #include "dominance.h"
51 #include "cfg.h"
52 #include "cfgrtl.h"
53 #include "cfganal.h"
54 #include "lcm.h"
55 #include "cfgbuild.h"
56 #include "cfgcleanup.h"
57 #include "predict.h"
58 #include "basic-block.h"
59 #include "df.h"
60 #include "ggc.h"
61 #include "tm_p.h"
62 #include "debug.h"
63 #include "target.h"
64 #include "target-def.h"
65 #include "langhooks.h"
66 #include "rl78-protos.h"
67 #include "dumpfile.h"
68 #include "tree-pass.h"
69 #include "context.h"
70 #include "tm-constrs.h" /* for satisfies_constraint_*(). */
71 #include "insn-flags.h" /* for gen_*(). */
72 #include "builtins.h"
73 \f
74 static inline bool is_interrupt_func (const_tree decl);
75 static inline bool is_brk_interrupt_func (const_tree decl);
76 static void rl78_reorg (void);
77 \f
78
79 /* Debugging statements are tagged with DEBUG0 only so that they can
80 be easily enabled individually, by replacing the '0' with '1' as
81 needed. */
82 #define DEBUG0 0
83 #define DEBUG1 1
84
85 /* REGISTER_NAMES has the names for individual 8-bit registers, but
86 these have the names we need to use when referring to 16-bit
87 register pairs. */
88 static const char * const word_regnames[] =
89 {
90 "ax", "AX", "bc", "BC", "de", "DE", "hl", "HL",
91 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
92 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
93 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
94 "sp", "ap", "psw", "es", "cs"
95 };
96
97 struct GTY(()) machine_function
98 {
99 /* If set, the rest of the fields have been computed. */
100 int computed;
101 /* Which register pairs need to be pushed in the prologue. */
102 int need_to_push [FIRST_PSEUDO_REGISTER / 2];
103
104 /* These fields describe the frame layout... */
105 /* arg pointer */
106 /* 4 bytes for saved PC */
107 int framesize_regs;
108 /* frame pointer */
109 int framesize_locals;
110 int framesize_outgoing;
111 /* stack pointer */
112 int framesize;
113
114 /* If set, recog is allowed to match against the "real" patterns. */
115 int real_insns_ok;
116 /* If set, recog is allowed to match against the "virtual" patterns. */
117 int virt_insns_ok;
118 /* Set if the current function needs to clean up any trampolines. */
119 int trampolines_used;
120 };
121
122 /* This is our init_machine_status, as set in
123 rl78_option_override. */
124 static struct machine_function *
125 rl78_init_machine_status (void)
126 {
127 struct machine_function *m;
128
129 m = ggc_cleared_alloc<machine_function> ();
130 m->virt_insns_ok = 1;
131
132 return m;
133 }
134
135 /* This pass converts virtual instructions using virtual registers, to
136 real instructions using real registers. Rather than run it as
137 reorg, we reschedule it before vartrack to help with debugging. */
138 namespace {
139
140 const pass_data pass_data_rl78_devirt =
141 {
142 RTL_PASS, /* type */
143 "devirt", /* name */
144 OPTGROUP_NONE, /* optinfo_flags */
145 TV_MACH_DEP, /* tv_id */
146 0, /* properties_required */
147 0, /* properties_provided */
148 0, /* properties_destroyed */
149 0, /* todo_flags_start */
150 0, /* todo_flags_finish */
151 };
152
153 class pass_rl78_devirt : public rtl_opt_pass
154 {
155 public:
156 pass_rl78_devirt(gcc::context *ctxt)
157 : rtl_opt_pass(pass_data_rl78_devirt, ctxt)
158 {
159 }
160
161 /* opt_pass methods: */
162 virtual unsigned int execute (function *)
163 {
164 rl78_reorg ();
165 return 0;
166 }
167
168 };
169
170 } // anon namespace
171
172 rtl_opt_pass *
173 make_pass_rl78_devirt (gcc::context *ctxt)
174 {
175 return new pass_rl78_devirt (ctxt);
176 }
177
178 /* Redundant move elimination pass. Must be run after the basic block
179 reordering pass for the best effect. */
180
181 static unsigned int
182 move_elim_pass (void)
183 {
184 rtx_insn *insn, *ninsn;
185 rtx prev = NULL_RTX;
186
187 for (insn = get_insns (); insn; insn = ninsn)
188 {
189 rtx set;
190
191 ninsn = next_nonnote_nondebug_insn (insn);
192
193 if ((set = single_set (insn)) == NULL_RTX)
194 {
195 prev = NULL_RTX;
196 continue;
197 }
198
199 /* If we have two SET insns in a row (without anything
200 between them) and the source of the second one is the
201 destination of the first one, and vice versa, then we
202 can eliminate the second SET. */
203 if (prev
204 && rtx_equal_p (SET_DEST (prev), SET_SRC (set))
205 && rtx_equal_p (SET_DEST (set), SET_SRC (prev))
206 )
207 {
208 if (dump_file)
209 fprintf (dump_file, " Delete insn %d because it is redundant\n",
210 INSN_UID (insn));
211
212 delete_insn (insn);
213 prev = NULL_RTX;
214 }
215 else
216 prev = set;
217 }
218
219 if (dump_file)
220 print_rtl_with_bb (dump_file, get_insns (), 0);
221
222 return 0;
223 }
224
225 namespace {
226
227 const pass_data pass_data_rl78_move_elim =
228 {
229 RTL_PASS, /* type */
230 "move_elim", /* name */
231 OPTGROUP_NONE, /* optinfo_flags */
232 TV_MACH_DEP, /* tv_id */
233 0, /* properties_required */
234 0, /* properties_provided */
235 0, /* properties_destroyed */
236 0, /* todo_flags_start */
237 0, /* todo_flags_finish */
238 };
239
240 class pass_rl78_move_elim : public rtl_opt_pass
241 {
242 public:
243 pass_rl78_move_elim(gcc::context *ctxt)
244 : rtl_opt_pass(pass_data_rl78_move_elim, ctxt)
245 {
246 }
247
248 /* opt_pass methods: */
249 virtual unsigned int execute (function *) { return move_elim_pass (); }
250 };
251
252 } // anon namespace
253
254 rtl_opt_pass *
255 make_pass_rl78_move_elim (gcc::context *ctxt)
256 {
257 return new pass_rl78_move_elim (ctxt);
258 }
259
260 #undef TARGET_ASM_FILE_START
261 #define TARGET_ASM_FILE_START rl78_asm_file_start
262
263 static void
264 rl78_asm_file_start (void)
265 {
266 int i;
267
268 if (TARGET_G10)
269 {
270 /* The memory used is 0xffec8 to 0xffedf; real registers are in
271 0xffee0 to 0xffee7. */
272 for (i = 8; i < 32; i++)
273 fprintf (asm_out_file, "r%d\t=\t0x%x\n", i, 0xffec0 + i);
274 }
275 else
276 {
277 for (i = 0; i < 8; i++)
278 {
279 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 8 + i, 0xffef0 + i);
280 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 16 + i, 0xffee8 + i);
281 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 24 + i, 0xffee0 + i);
282 }
283 }
284
285 opt_pass *rl78_devirt_pass = make_pass_rl78_devirt (g);
286 static struct register_pass_info rl78_devirt_info =
287 {
288 rl78_devirt_pass,
289 "pro_and_epilogue",
290 1,
291 PASS_POS_INSERT_BEFORE
292 };
293
294 opt_pass *rl78_move_elim_pass = make_pass_rl78_move_elim (g);
295 static struct register_pass_info rl78_move_elim_info =
296 {
297 rl78_move_elim_pass,
298 "bbro",
299 1,
300 PASS_POS_INSERT_AFTER
301 };
302
303 register_pass (& rl78_devirt_info);
304 register_pass (& rl78_move_elim_info);
305 }
306
307 \f
308 #undef TARGET_OPTION_OVERRIDE
309 #define TARGET_OPTION_OVERRIDE rl78_option_override
310
311 static void
312 rl78_option_override (void)
313 {
314 flag_omit_frame_pointer = 1;
315 flag_no_function_cse = 1;
316 flag_split_wide_types = 0;
317
318 init_machine_status = rl78_init_machine_status;
319
320 if (TARGET_ALLREGS)
321 {
322 int i;
323
324 for (i = 24; i < 32; i++)
325 fixed_regs[i] = 0;
326 }
327 }
328
329 /* Most registers are 8 bits. Some are 16 bits because, for example,
330 gcc doesn't like dealing with $FP as a register pair (the second
331 half of $fp is also 2 to keep reload happy wrt register pairs, but
332 no register class includes it). This table maps register numbers
333 to size in bytes. */
334 static const int register_sizes[] =
335 {
336 1, 1, 1, 1, 1, 1, 1, 1,
337 1, 1, 1, 1, 1, 1, 1, 1,
338 1, 1, 1, 1, 1, 1, 2, 2,
339 1, 1, 1, 1, 1, 1, 1, 1,
340 2, 2, 1, 1, 1
341 };
342
343 /* Predicates used in the MD patterns. This one is true when virtual
344 insns may be matched, which typically means before (or during) the
345 devirt pass. */
346 bool
347 rl78_virt_insns_ok (void)
348 {
349 if (cfun)
350 return cfun->machine->virt_insns_ok;
351 return true;
352 }
353
354 /* Predicates used in the MD patterns. This one is true when real
355 insns may be matched, which typically means after (or during) the
356 devirt pass. */
357 bool
358 rl78_real_insns_ok (void)
359 {
360 if (cfun)
361 return cfun->machine->real_insns_ok;
362 return false;
363 }
364
365 /* Implements HARD_REGNO_NREGS. */
366 int
367 rl78_hard_regno_nregs (int regno, machine_mode mode)
368 {
369 int rs = register_sizes[regno];
370 if (rs < 1)
371 rs = 1;
372 return ((GET_MODE_SIZE (mode) + rs - 1) / rs);
373 }
374
375 /* Implements HARD_REGNO_MODE_OK. */
376 int
377 rl78_hard_regno_mode_ok (int regno, machine_mode mode)
378 {
379 int s = GET_MODE_SIZE (mode);
380
381 if (s < 1)
382 return 0;
383 /* These are not to be used by gcc. */
384 if (regno == 23 || regno == ES_REG || regno == CS_REG)
385 return 0;
386 /* $fp can always be accessed as a 16-bit value. */
387 if (regno == FP_REG && s == 2)
388 return 1;
389 if (regno < SP_REG)
390 {
391 /* Since a reg-reg move is really a reg-mem move, we must
392 enforce alignment. */
393 if (s > 1 && (regno % 2))
394 return 0;
395 return 1;
396 }
397 if (s == CC_REGNUM)
398 return (mode == BImode);
399 /* All other registers must be accessed in their natural sizes. */
400 if (s == register_sizes [regno])
401 return 1;
402 return 0;
403 }
404
405 /* Simplify_gen_subreg() doesn't handle memory references the way we
406 need it to below, so we use this function for when we must get a
407 valid subreg in a "natural" state. */
408 static rtx
409 rl78_subreg (machine_mode mode, rtx r, machine_mode omode, int byte)
410 {
411 if (GET_CODE (r) == MEM)
412 return adjust_address (r, mode, byte);
413 else
414 return simplify_gen_subreg (mode, r, omode, byte);
415 }
416
417 /* Used by movsi. Split SImode moves into two HImode moves, using
418 appropriate patterns for the upper and lower halves of symbols. */
419 void
420 rl78_expand_movsi (rtx *operands)
421 {
422 rtx op00, op02, op10, op12;
423
424 op00 = rl78_subreg (HImode, operands[0], SImode, 0);
425 op02 = rl78_subreg (HImode, operands[0], SImode, 2);
426 if (GET_CODE (operands[1]) == CONST
427 || GET_CODE (operands[1]) == SYMBOL_REF)
428 {
429 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
430 op10 = gen_rtx_CONST (HImode, op10);
431 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
432 op12 = gen_rtx_CONST (HImode, op12);
433 }
434 else
435 {
436 op10 = rl78_subreg (HImode, operands[1], SImode, 0);
437 op12 = rl78_subreg (HImode, operands[1], SImode, 2);
438 }
439
440 if (rtx_equal_p (operands[0], operands[1]))
441 ;
442 else if (rtx_equal_p (op00, op12))
443 {
444 emit_move_insn (op02, op12);
445 emit_move_insn (op00, op10);
446 }
447 else
448 {
449 emit_move_insn (op00, op10);
450 emit_move_insn (op02, op12);
451 }
452 }
453
454 /* Generate code to move an SImode value. */
455 void
456 rl78_split_movsi (rtx *operands)
457 {
458 rtx op00, op02, op10, op12;
459
460 op00 = rl78_subreg (HImode, operands[0], SImode, 0);
461 op02 = rl78_subreg (HImode, operands[0], SImode, 2);
462
463 if (GET_CODE (operands[1]) == CONST
464 || GET_CODE (operands[1]) == SYMBOL_REF)
465 {
466 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
467 op10 = gen_rtx_CONST (HImode, op10);
468 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
469 op12 = gen_rtx_CONST (HImode, op12);
470 }
471 else
472 {
473 op10 = rl78_subreg (HImode, operands[1], SImode, 0);
474 op12 = rl78_subreg (HImode, operands[1], SImode, 2);
475 }
476
477 if (rtx_equal_p (operands[0], operands[1]))
478 ;
479 else if (rtx_equal_p (op00, op12))
480 {
481 operands[2] = op02;
482 operands[4] = op12;
483 operands[3] = op00;
484 operands[5] = op10;
485 }
486 else
487 {
488 operands[2] = op00;
489 operands[4] = op10;
490 operands[3] = op02;
491 operands[5] = op12;
492 }
493 }
494
495 /* Used by various two-operand expanders which cannot accept all
496 operands in the "far" namespace. Force some such operands into
497 registers so that each pattern has at most one far operand. */
498 int
499 rl78_force_nonfar_2 (rtx *operands, rtx (*gen)(rtx,rtx))
500 {
501 int did = 0;
502 rtx temp_reg = NULL;
503
504 /* FIXME: in the future, be smarter about only doing this if the
505 other operand is also far, assuming the devirtualizer can also
506 handle that. */
507 if (rl78_far_p (operands[0]))
508 {
509 temp_reg = operands[0];
510 operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
511 did = 1;
512 }
513 if (!did)
514 return 0;
515
516 emit_insn (gen (operands[0], operands[1]));
517 if (temp_reg)
518 emit_move_insn (temp_reg, operands[0]);
519 return 1;
520 }
521
522 /* Likewise, but for three-operand expanders. */
523 int
524 rl78_force_nonfar_3 (rtx *operands, rtx (*gen)(rtx,rtx,rtx))
525 {
526 int did = 0;
527 rtx temp_reg = NULL;
528
529 /* FIXME: Likewise. */
530 if (rl78_far_p (operands[1]))
531 {
532 rtx temp_reg = gen_reg_rtx (GET_MODE (operands[1]));
533 emit_move_insn (temp_reg, operands[1]);
534 operands[1] = temp_reg;
535 did = 1;
536 }
537 if (rl78_far_p (operands[0]))
538 {
539 temp_reg = operands[0];
540 operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
541 did = 1;
542 }
543 if (!did)
544 return 0;
545
546 emit_insn (gen (operands[0], operands[1], operands[2]));
547 if (temp_reg)
548 emit_move_insn (temp_reg, operands[0]);
549 return 1;
550 }
551
552 #undef TARGET_CAN_ELIMINATE
553 #define TARGET_CAN_ELIMINATE rl78_can_eliminate
554
555 static bool
556 rl78_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to ATTRIBUTE_UNUSED)
557 {
558 return true;
559 }
560
561 /* Returns true if the given register needs to be saved by the
562 current function. */
563 static bool
564 need_to_save (unsigned int regno)
565 {
566 if (is_interrupt_func (cfun->decl))
567 {
568 /* We don't know what devirt will need */
569 if (regno < 8)
570 return true;
571
572 /* We don't need to save registers that have
573 been reserved for interrupt handlers. */
574 if (regno > 23)
575 return false;
576
577 /* If the handler is a non-leaf function then it may call
578 non-interrupt aware routines which will happily clobber
579 any call_used registers, so we have to preserve them. */
580 if (!crtl->is_leaf && call_used_regs[regno])
581 return true;
582
583 /* Otherwise we only have to save a register, call_used
584 or not, if it is used by this handler. */
585 return df_regs_ever_live_p (regno);
586 }
587
588 if (regno == FRAME_POINTER_REGNUM && frame_pointer_needed)
589 return true;
590 if (fixed_regs[regno])
591 return false;
592 if (crtl->calls_eh_return)
593 return true;
594 if (df_regs_ever_live_p (regno)
595 && !call_used_regs[regno])
596 return true;
597 return false;
598 }
599
600 /* We use this to wrap all emitted insns in the prologue. */
601 static rtx
602 F (rtx x)
603 {
604 RTX_FRAME_RELATED_P (x) = 1;
605 return x;
606 }
607
608 /* Compute all the frame-related fields in our machine_function
609 structure. */
610 static void
611 rl78_compute_frame_info (void)
612 {
613 int i;
614
615 cfun->machine->computed = 1;
616 cfun->machine->framesize_regs = 0;
617 cfun->machine->framesize_locals = get_frame_size ();
618 cfun->machine->framesize_outgoing = crtl->outgoing_args_size;
619
620 for (i = 0; i < 16; i ++)
621 if (need_to_save (i * 2) || need_to_save (i * 2 + 1))
622 {
623 cfun->machine->need_to_push [i] = 1;
624 cfun->machine->framesize_regs += 2;
625 }
626 else
627 cfun->machine->need_to_push [i] = 0;
628
629 if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1)
630 cfun->machine->framesize_locals ++;
631
632 cfun->machine->framesize = (cfun->machine->framesize_regs
633 + cfun->machine->framesize_locals
634 + cfun->machine->framesize_outgoing);
635 }
636 \f
637 /* Returns true if the provided function has the specified attribute. */
638 static inline bool
639 has_func_attr (const_tree decl, const char * func_attr)
640 {
641 if (decl == NULL_TREE)
642 decl = current_function_decl;
643
644 return lookup_attribute (func_attr, DECL_ATTRIBUTES (decl)) != NULL_TREE;
645 }
646
647 /* Returns true if the provided function has the "interrupt" attribute. */
648 static inline bool
649 is_interrupt_func (const_tree decl)
650 {
651 return has_func_attr (decl, "interrupt") || has_func_attr (decl, "brk_interrupt");
652 }
653
654 /* Returns true if the provided function has the "brk_interrupt" attribute. */
655 static inline bool
656 is_brk_interrupt_func (const_tree decl)
657 {
658 return has_func_attr (decl, "brk_interrupt");
659 }
660
661 /* Check "interrupt" attributes. */
662 static tree
663 rl78_handle_func_attribute (tree * node,
664 tree name,
665 tree args,
666 int flags ATTRIBUTE_UNUSED,
667 bool * no_add_attrs)
668 {
669 gcc_assert (DECL_P (* node));
670 gcc_assert (args == NULL_TREE);
671
672 if (TREE_CODE (* node) != FUNCTION_DECL)
673 {
674 warning (OPT_Wattributes, "%qE attribute only applies to functions",
675 name);
676 * no_add_attrs = true;
677 }
678
679 /* FIXME: We ought to check that the interrupt and exception
680 handler attributes have been applied to void functions. */
681 return NULL_TREE;
682 }
683
684 #undef TARGET_ATTRIBUTE_TABLE
685 #define TARGET_ATTRIBUTE_TABLE rl78_attribute_table
686
687 /* Table of RL78-specific attributes. */
688 const struct attribute_spec rl78_attribute_table[] =
689 {
690 /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
691 affects_type_identity. */
692 { "interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
693 false },
694 { "brk_interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
695 false },
696 { "naked", 0, 0, true, false, false, rl78_handle_func_attribute,
697 false },
698 { NULL, 0, 0, false, false, false, NULL, false }
699 };
700
701
702 \f
703 /* Break down an address RTX into its component base/index/addend
704 portions and return TRUE if the address is of a valid form, else
705 FALSE. */
706 static bool
707 characterize_address (rtx x, rtx *base, rtx *index, rtx *addend)
708 {
709 *base = NULL_RTX;
710 *index = NULL_RTX;
711 *addend = NULL_RTX;
712
713 if (GET_CODE (x) == UNSPEC
714 && XINT (x, 1) == UNS_ES_ADDR)
715 x = XVECEXP (x, 0, 1);
716
717 if (GET_CODE (x) == REG)
718 {
719 *base = x;
720 return true;
721 }
722
723 /* We sometimes get these without the CONST wrapper */
724 if (GET_CODE (x) == PLUS
725 && GET_CODE (XEXP (x, 0)) == SYMBOL_REF
726 && GET_CODE (XEXP (x, 1)) == CONST_INT)
727 {
728 *addend = x;
729 return true;
730 }
731
732 if (GET_CODE (x) == PLUS)
733 {
734 *base = XEXP (x, 0);
735 x = XEXP (x, 1);
736
737 if (GET_CODE (*base) != REG
738 && GET_CODE (x) == REG)
739 {
740 rtx tmp = *base;
741 *base = x;
742 x = tmp;
743 }
744
745 if (GET_CODE (*base) != REG)
746 return false;
747
748 if (GET_CODE (x) == ZERO_EXTEND
749 && GET_CODE (XEXP (x, 0)) == REG)
750 {
751 *index = XEXP (x, 0);
752 return false;
753 }
754 }
755
756 switch (GET_CODE (x))
757 {
758 case PLUS:
759 if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
760 && GET_CODE (XEXP (x, 0)) == CONST_INT)
761 {
762 *addend = x;
763 return true;
764 }
765 /* fall through */
766 case MEM:
767 case REG:
768 return false;
769
770 case CONST:
771 case SYMBOL_REF:
772 case CONST_INT:
773 *addend = x;
774 return true;
775
776 default:
777 return false;
778 }
779
780 return false;
781 }
782
783 /* Used by the Whb constraint. Match addresses that use HL+B or HL+C
784 addressing. */
785 bool
786 rl78_hl_b_c_addr_p (rtx op)
787 {
788 rtx hl, bc;
789
790 if (GET_CODE (op) != PLUS)
791 return false;
792 hl = XEXP (op, 0);
793 bc = XEXP (op, 1);
794 if (GET_CODE (hl) == ZERO_EXTEND)
795 {
796 rtx tmp = hl;
797 hl = bc;
798 bc = tmp;
799 }
800 if (GET_CODE (hl) != REG)
801 return false;
802 if (GET_CODE (bc) != ZERO_EXTEND)
803 return false;
804 bc = XEXP (bc, 0);
805 if (GET_CODE (bc) != REG)
806 return false;
807 if (REGNO (hl) != HL_REG)
808 return false;
809 if (REGNO (bc) != B_REG && REGNO (bc) != C_REG)
810 return false;
811
812 return true;
813 }
814
815 #define REG_IS(r, regno) (((r) == (regno)) || ((r) >= FIRST_PSEUDO_REGISTER && !(strict)))
816
817 /* Used in various constraints and predicates to match operands in the
818 "far" address space. */
819 int
820 rl78_far_p (rtx x)
821 {
822 if (! MEM_P (x))
823 return 0;
824 #if DEBUG0
825 fprintf (stderr, "\033[35mrl78_far_p: "); debug_rtx (x);
826 fprintf (stderr, " = %d\033[0m\n", MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR);
827 #endif
828 return MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR;
829 }
830
831 /* Return the appropriate mode for a named address pointer. */
832 #undef TARGET_ADDR_SPACE_POINTER_MODE
833 #define TARGET_ADDR_SPACE_POINTER_MODE rl78_addr_space_pointer_mode
834 static machine_mode
835 rl78_addr_space_pointer_mode (addr_space_t addrspace)
836 {
837 switch (addrspace)
838 {
839 case ADDR_SPACE_GENERIC:
840 return HImode;
841 case ADDR_SPACE_FAR:
842 return SImode;
843 default:
844 gcc_unreachable ();
845 }
846 }
847
848 /* Returns TRUE for valid addresses. */
849 #undef TARGET_VALID_POINTER_MODE
850 #define TARGET_VALID_POINTER_MODE rl78_valid_pointer_mode
851 static bool
852 rl78_valid_pointer_mode (machine_mode m)
853 {
854 return (m == HImode || m == SImode);
855 }
856
857 /* Return the appropriate mode for a named address address. */
858 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
859 #define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode
860 static machine_mode
861 rl78_addr_space_address_mode (addr_space_t addrspace)
862 {
863 switch (addrspace)
864 {
865 case ADDR_SPACE_GENERIC:
866 return HImode;
867 case ADDR_SPACE_FAR:
868 return SImode;
869 default:
870 gcc_unreachable ();
871 }
872 }
873
874 #undef TARGET_LEGITIMATE_CONSTANT_P
875 #define TARGET_LEGITIMATE_CONSTANT_P rl78_is_legitimate_constant
876
877 static bool
878 rl78_is_legitimate_constant (machine_mode mode ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED)
879 {
880 return true;
881 }
882
883 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
884 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P rl78_as_legitimate_address
885
886 bool
887 rl78_as_legitimate_address (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
888 bool strict ATTRIBUTE_UNUSED, addr_space_t as ATTRIBUTE_UNUSED)
889 {
890 rtx base, index, addend;
891 bool is_far_addr = false;
892
893 if (GET_CODE (x) == UNSPEC
894 && XINT (x, 1) == UNS_ES_ADDR)
895 {
896 x = XVECEXP (x, 0, 1);
897 is_far_addr = true;
898 }
899
900 if (as == ADDR_SPACE_GENERIC
901 && (GET_MODE (x) == SImode || is_far_addr))
902 return false;
903
904 if (! characterize_address (x, &base, &index, &addend))
905 return false;
906
907 /* We can't extract the high/low portions of a PLUS address
908 involving a register during devirtualization, so make sure all
909 such __far addresses do not have addends. This forces GCC to do
910 the sum separately. */
911 if (addend && base && as == ADDR_SPACE_FAR)
912 return false;
913
914 if (base && index)
915 {
916 int ir = REGNO (index);
917 int br = REGNO (base);
918
919 #define OK(test, debug) if (test) { /*fprintf(stderr, "%d: OK %s\n", __LINE__, debug);*/ return true; }
920 OK (REG_IS (br, HL_REG) && REG_IS (ir, B_REG), "[hl+b]");
921 OK (REG_IS (br, HL_REG) && REG_IS (ir, C_REG), "[hl+c]");
922 return false;
923 }
924
925 if (strict && base && GET_CODE (base) == REG && REGNO (base) >= FIRST_PSEUDO_REGISTER)
926 return false;
927
928 if (! cfun->machine->virt_insns_ok && base && GET_CODE (base) == REG
929 && REGNO (base) >= 8 && REGNO (base) <= 31)
930 return false;
931
932 return true;
933 }
934
935 /* Determine if one named address space is a subset of another. */
936 #undef TARGET_ADDR_SPACE_SUBSET_P
937 #define TARGET_ADDR_SPACE_SUBSET_P rl78_addr_space_subset_p
938 static bool
939 rl78_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
940 {
941 gcc_assert (subset == ADDR_SPACE_GENERIC || subset == ADDR_SPACE_FAR);
942 gcc_assert (superset == ADDR_SPACE_GENERIC || superset == ADDR_SPACE_FAR);
943
944 if (subset == superset)
945 return true;
946
947 else
948 return (subset == ADDR_SPACE_GENERIC && superset == ADDR_SPACE_FAR);
949 }
950
951 #undef TARGET_ADDR_SPACE_CONVERT
952 #define TARGET_ADDR_SPACE_CONVERT rl78_addr_space_convert
953 /* Convert from one address space to another. */
954 static rtx
955 rl78_addr_space_convert (rtx op, tree from_type, tree to_type)
956 {
957 addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
958 addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
959 rtx result;
960
961 gcc_assert (from_as == ADDR_SPACE_GENERIC || from_as == ADDR_SPACE_FAR);
962 gcc_assert (to_as == ADDR_SPACE_GENERIC || to_as == ADDR_SPACE_FAR);
963
964 if (to_as == ADDR_SPACE_GENERIC && from_as == ADDR_SPACE_FAR)
965 {
966 /* This is unpredictable, as we're truncating off usable address
967 bits. */
968
969 result = gen_reg_rtx (HImode);
970 emit_move_insn (result, simplify_subreg (HImode, op, SImode, 0));
971 return result;
972 }
973 else if (to_as == ADDR_SPACE_FAR && from_as == ADDR_SPACE_GENERIC)
974 {
975 /* This always works. */
976 result = gen_reg_rtx (SImode);
977 emit_move_insn (rl78_subreg (HImode, result, SImode, 0), op);
978 emit_move_insn (rl78_subreg (HImode, result, SImode, 2), const0_rtx);
979 return result;
980 }
981 else
982 gcc_unreachable ();
983 }
984
985 /* Implements REGNO_MODE_CODE_OK_FOR_BASE_P. */
986 bool
987 rl78_regno_mode_code_ok_for_base_p (int regno, machine_mode mode ATTRIBUTE_UNUSED,
988 addr_space_t address_space ATTRIBUTE_UNUSED,
989 int outer_code ATTRIBUTE_UNUSED, int index_code)
990 {
991 if (regno <= SP_REG && regno >= 16)
992 return true;
993 if (index_code == REG)
994 return (regno == HL_REG);
995 if (regno == C_REG || regno == B_REG || regno == E_REG || regno == L_REG)
996 return true;
997 return false;
998 }
999
1000 /* Implements MODE_CODE_BASE_REG_CLASS. */
1001 enum reg_class
1002 rl78_mode_code_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED,
1003 addr_space_t address_space ATTRIBUTE_UNUSED,
1004 int outer_code ATTRIBUTE_UNUSED,
1005 int index_code ATTRIBUTE_UNUSED)
1006 {
1007 return V_REGS;
1008 }
1009
1010 /* Implements INITIAL_ELIMINATION_OFFSET. The frame layout is
1011 described in the machine_Function struct definition, above. */
1012 int
1013 rl78_initial_elimination_offset (int from, int to)
1014 {
1015 int rv = 0; /* as if arg to arg */
1016
1017 rl78_compute_frame_info ();
1018
1019 switch (to)
1020 {
1021 case STACK_POINTER_REGNUM:
1022 rv += cfun->machine->framesize_outgoing;
1023 rv += cfun->machine->framesize_locals;
1024 /* Fall through. */
1025 case FRAME_POINTER_REGNUM:
1026 rv += cfun->machine->framesize_regs;
1027 rv += 4;
1028 break;
1029 default:
1030 gcc_unreachable ();
1031 }
1032
1033 switch (from)
1034 {
1035 case FRAME_POINTER_REGNUM:
1036 rv -= 4;
1037 rv -= cfun->machine->framesize_regs;
1038 case ARG_POINTER_REGNUM:
1039 break;
1040 default:
1041 gcc_unreachable ();
1042 }
1043
1044 return rv;
1045 }
1046
1047 static int
1048 rl78_is_naked_func (void)
1049 {
1050 return (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE);
1051 }
1052
1053 /* Expand the function prologue (from the prologue pattern). */
1054 void
1055 rl78_expand_prologue (void)
1056 {
1057 int i, fs;
1058 rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
1059 int rb = 0;
1060
1061 if (rl78_is_naked_func ())
1062 return;
1063
1064 /* Always re-compute the frame info - the register usage may have changed. */
1065 rl78_compute_frame_info ();
1066
1067 if (flag_stack_usage_info)
1068 current_function_static_stack_size = cfun->machine->framesize;
1069
1070 if (is_interrupt_func (cfun->decl) && !TARGET_G10)
1071 for (i = 0; i < 4; i++)
1072 if (cfun->machine->need_to_push [i])
1073 {
1074 /* Select Bank 0 if we are using any registers from Bank 0. */
1075 emit_insn (gen_sel_rb (GEN_INT (0)));
1076 break;
1077 }
1078
1079 for (i = 0; i < 16; i++)
1080 if (cfun->machine->need_to_push [i])
1081 {
1082 if (TARGET_G10)
1083 {
1084 emit_move_insn (gen_rtx_REG (HImode, 0), gen_rtx_REG (HImode, i*2));
1085 F (emit_insn (gen_push (gen_rtx_REG (HImode, 0))));
1086 }
1087 else
1088 {
1089 int need_bank = i/4;
1090
1091 if (need_bank != rb)
1092 {
1093 emit_insn (gen_sel_rb (GEN_INT (need_bank)));
1094 rb = need_bank;
1095 }
1096 F (emit_insn (gen_push (gen_rtx_REG (HImode, i*2))));
1097 }
1098 }
1099
1100 if (rb != 0)
1101 emit_insn (gen_sel_rb (GEN_INT (0)));
1102
1103 if (frame_pointer_needed)
1104 {
1105 F (emit_move_insn (gen_rtx_REG (HImode, AX_REG),
1106 gen_rtx_REG (HImode, STACK_POINTER_REGNUM)));
1107 F (emit_move_insn (gen_rtx_REG (HImode, FRAME_POINTER_REGNUM),
1108 gen_rtx_REG (HImode, AX_REG)));
1109 }
1110
1111 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1112 while (fs > 0)
1113 {
1114 int fs_byte = (fs > 254) ? 254 : fs;
1115 F (emit_insn (gen_subhi3 (sp, sp, GEN_INT (fs_byte))));
1116 fs -= fs_byte;
1117 }
1118 }
1119
1120 /* Expand the function epilogue (from the epilogue pattern). */
1121 void
1122 rl78_expand_epilogue (void)
1123 {
1124 int i, fs;
1125 rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
1126 int rb = 0;
1127
1128 if (rl78_is_naked_func ())
1129 return;
1130
1131 if (frame_pointer_needed)
1132 {
1133 emit_move_insn (gen_rtx_REG (HImode, AX_REG),
1134 gen_rtx_REG (HImode, FRAME_POINTER_REGNUM));
1135 emit_move_insn (gen_rtx_REG (HImode, STACK_POINTER_REGNUM),
1136 gen_rtx_REG (HImode, AX_REG));
1137 }
1138 else
1139 {
1140 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1141 while (fs > 0)
1142 {
1143 int fs_byte = (fs > 254) ? 254 : fs;
1144
1145 emit_insn (gen_addhi3 (sp, sp, GEN_INT (fs_byte)));
1146 fs -= fs_byte;
1147 }
1148 }
1149
1150 for (i = 15; i >= 0; i--)
1151 if (cfun->machine->need_to_push [i])
1152 {
1153 rtx dest = gen_rtx_REG (HImode, i * 2);
1154
1155 if (TARGET_G10)
1156 {
1157 rtx ax = gen_rtx_REG (HImode, 0);
1158
1159 emit_insn (gen_pop (ax));
1160 if (i != 0)
1161 {
1162 emit_move_insn (dest, ax);
1163 /* Generate a USE of the pop'd register so that DCE will not eliminate the move. */
1164 emit_insn (gen_use (dest));
1165 }
1166 }
1167 else
1168 {
1169 int need_bank = i / 4;
1170
1171 if (need_bank != rb)
1172 {
1173 emit_insn (gen_sel_rb (GEN_INT (need_bank)));
1174 rb = need_bank;
1175 }
1176 emit_insn (gen_pop (dest));
1177 }
1178 }
1179
1180 if (rb != 0)
1181 emit_insn (gen_sel_rb (GEN_INT (0)));
1182
1183 if (cfun->machine->trampolines_used)
1184 emit_insn (gen_trampoline_uninit ());
1185
1186 if (is_brk_interrupt_func (cfun->decl))
1187 emit_jump_insn (gen_brk_interrupt_return ());
1188 else if (is_interrupt_func (cfun->decl))
1189 emit_jump_insn (gen_interrupt_return ());
1190 else
1191 emit_jump_insn (gen_rl78_return ());
1192 }
1193
1194 /* Likewise, for exception handlers. */
1195 void
1196 rl78_expand_eh_epilogue (rtx x ATTRIBUTE_UNUSED)
1197 {
1198 /* FIXME - replace this with an indirect jump with stack adjust. */
1199 emit_jump_insn (gen_rl78_return ());
1200 }
1201
1202 #undef TARGET_ASM_FUNCTION_PROLOGUE
1203 #define TARGET_ASM_FUNCTION_PROLOGUE rl78_start_function
1204
1205 /* We don't use this to actually emit the function prologue. We use
1206 this to insert a comment in the asm file describing the
1207 function. */
1208 static void
1209 rl78_start_function (FILE *file, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED)
1210 {
1211 int i;
1212
1213 if (cfun->machine->framesize == 0)
1214 return;
1215 fprintf (file, "\t; start of function\n");
1216
1217 if (cfun->machine->framesize_regs)
1218 {
1219 fprintf (file, "\t; push %d:", cfun->machine->framesize_regs);
1220 for (i = 0; i < 16; i ++)
1221 if (cfun->machine->need_to_push[i])
1222 fprintf (file, " %s", word_regnames[i*2]);
1223 fprintf (file, "\n");
1224 }
1225
1226 if (frame_pointer_needed)
1227 fprintf (file, "\t; $fp points here (r22)\n");
1228
1229 if (cfun->machine->framesize_locals)
1230 fprintf (file, "\t; locals: %d byte%s\n", cfun->machine->framesize_locals,
1231 cfun->machine->framesize_locals == 1 ? "" : "s");
1232
1233 if (cfun->machine->framesize_outgoing)
1234 fprintf (file, "\t; outgoing: %d byte%s\n", cfun->machine->framesize_outgoing,
1235 cfun->machine->framesize_outgoing == 1 ? "" : "s");
1236 }
1237
1238 /* Return an RTL describing where a function return value of type RET_TYPE
1239 is held. */
1240
1241 #undef TARGET_FUNCTION_VALUE
1242 #define TARGET_FUNCTION_VALUE rl78_function_value
1243
1244 static rtx
1245 rl78_function_value (const_tree ret_type,
1246 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
1247 bool outgoing ATTRIBUTE_UNUSED)
1248 {
1249 machine_mode mode = TYPE_MODE (ret_type);
1250
1251 return gen_rtx_REG (mode, 8);
1252 }
1253
1254 #undef TARGET_PROMOTE_FUNCTION_MODE
1255 #define TARGET_PROMOTE_FUNCTION_MODE rl78_promote_function_mode
1256
1257 static machine_mode
1258 rl78_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
1259 machine_mode mode,
1260 int *punsignedp ATTRIBUTE_UNUSED,
1261 const_tree funtype ATTRIBUTE_UNUSED, int for_return ATTRIBUTE_UNUSED)
1262 {
1263 return mode;
1264 }
1265
1266 /* Return an RTL expression describing the register holding a function
1267 parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
1268 be passed on the stack. CUM describes the previous parameters to the
1269 function and NAMED is false if the parameter is part of a variable
1270 parameter list, or the last named parameter before the start of a
1271 variable parameter list. */
1272
1273 #undef TARGET_FUNCTION_ARG
1274 #define TARGET_FUNCTION_ARG rl78_function_arg
1275
1276 static rtx
1277 rl78_function_arg (cumulative_args_t cum_v ATTRIBUTE_UNUSED,
1278 machine_mode mode ATTRIBUTE_UNUSED,
1279 const_tree type ATTRIBUTE_UNUSED,
1280 bool named ATTRIBUTE_UNUSED)
1281 {
1282 return NULL_RTX;
1283 }
1284
1285 #undef TARGET_FUNCTION_ARG_ADVANCE
1286 #define TARGET_FUNCTION_ARG_ADVANCE rl78_function_arg_advance
1287
1288 static void
1289 rl78_function_arg_advance (cumulative_args_t cum_v, machine_mode mode, const_tree type,
1290 bool named ATTRIBUTE_UNUSED)
1291 {
1292 int rounded_size;
1293 CUMULATIVE_ARGS * cum = get_cumulative_args (cum_v);
1294
1295 rounded_size = ((mode == BLKmode)
1296 ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
1297 if (rounded_size & 1)
1298 rounded_size ++;
1299 (*cum) += rounded_size;
1300 }
1301
1302 #undef TARGET_FUNCTION_ARG_BOUNDARY
1303 #define TARGET_FUNCTION_ARG_BOUNDARY rl78_function_arg_boundary
1304
1305 static unsigned int
1306 rl78_function_arg_boundary (machine_mode mode ATTRIBUTE_UNUSED,
1307 const_tree type ATTRIBUTE_UNUSED)
1308 {
1309 return 16;
1310 }
1311
1312 /* Supported modifier letters:
1313
1314 A - address of a MEM
1315 S - SADDR form of a real register
1316 v - real register corresponding to a virtual register
1317 m - minus - negative of CONST_INT value.
1318 C - inverse of a conditional (NE vs EQ for example)
1319 C - complement of an integer
1320 z - collapsed conditional
1321 s - shift count mod 8
1322 S - shift count mod 16
1323 r - reverse shift count (8-(count mod 8))
1324 B - bit position
1325
1326 h - bottom HI of an SI
1327 H - top HI of an SI
1328 q - bottom QI of an HI
1329 Q - top QI of an HI
1330 e - third QI of an SI (i.e. where the ES register gets values from)
1331 E - fourth QI of an SI (i.e. MSB)
1332
1333 */
1334
1335 /* Implements the bulk of rl78_print_operand, below. We do it this
1336 way because we need to test for a constant at the top level and
1337 insert the '#', but not test for it anywhere else as we recurse
1338 down into the operand. */
1339 static void
1340 rl78_print_operand_1 (FILE * file, rtx op, int letter)
1341 {
1342 int need_paren;
1343
1344 switch (GET_CODE (op))
1345 {
1346 case MEM:
1347 if (letter == 'A')
1348 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1349 else
1350 {
1351 if (rl78_far_p (op))
1352 {
1353 fprintf (file, "es:");
1354 op = gen_rtx_MEM (GET_MODE (op), XVECEXP (XEXP (op, 0), 0, 1));
1355 }
1356 if (letter == 'H')
1357 {
1358 op = adjust_address (op, HImode, 2);
1359 letter = 0;
1360 }
1361 if (letter == 'h')
1362 {
1363 op = adjust_address (op, HImode, 0);
1364 letter = 0;
1365 }
1366 if (letter == 'Q')
1367 {
1368 op = adjust_address (op, QImode, 1);
1369 letter = 0;
1370 }
1371 if (letter == 'q')
1372 {
1373 op = adjust_address (op, QImode, 0);
1374 letter = 0;
1375 }
1376 if (letter == 'e')
1377 {
1378 op = adjust_address (op, QImode, 2);
1379 letter = 0;
1380 }
1381 if (letter == 'E')
1382 {
1383 op = adjust_address (op, QImode, 3);
1384 letter = 0;
1385 }
1386 if (CONSTANT_P (XEXP (op, 0)))
1387 {
1388 fprintf (file, "!");
1389 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1390 }
1391 else if (GET_CODE (XEXP (op, 0)) == PLUS
1392 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF)
1393 {
1394 fprintf (file, "!");
1395 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1396 }
1397 else if (GET_CODE (XEXP (op, 0)) == PLUS
1398 && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
1399 && REGNO (XEXP (XEXP (op, 0), 0)) == 2)
1400 {
1401 rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 1), 'u');
1402 fprintf (file, "[");
1403 rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 0), 0);
1404 fprintf (file, "]");
1405 }
1406 else
1407 {
1408 fprintf (file, "[");
1409 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1410 fprintf (file, "]");
1411 }
1412 }
1413 break;
1414
1415 case REG:
1416 if (letter == 'Q')
1417 fprintf (file, "%s", reg_names [REGNO (op) | 1]);
1418 else if (letter == 'H')
1419 fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1420 else if (letter == 'q')
1421 fprintf (file, "%s", reg_names [REGNO (op) & ~1]);
1422 else if (letter == 'e')
1423 fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1424 else if (letter == 'E')
1425 fprintf (file, "%s", reg_names [REGNO (op) + 3]);
1426 else if (letter == 'S')
1427 fprintf (file, "0x%x", 0xffef8 + REGNO (op));
1428 else if (GET_MODE (op) == HImode
1429 && ! (REGNO (op) & ~0xfe))
1430 {
1431 if (letter == 'v')
1432 fprintf (file, "%s", word_regnames [REGNO (op) % 8]);
1433 else
1434 fprintf (file, "%s", word_regnames [REGNO (op)]);
1435 }
1436 else
1437 fprintf (file, "%s", reg_names [REGNO (op)]);
1438 break;
1439
1440 case CONST_INT:
1441 if (letter == 'Q')
1442 fprintf (file, "%ld", INTVAL (op) >> 8);
1443 else if (letter == 'H')
1444 fprintf (file, "%ld", INTVAL (op) >> 16);
1445 else if (letter == 'q')
1446 fprintf (file, "%ld", INTVAL (op) & 0xff);
1447 else if (letter == 'h')
1448 fprintf (file, "%ld", INTVAL (op) & 0xffff);
1449 else if (letter == 'e')
1450 fprintf (file, "%ld", (INTVAL (op) >> 16) & 0xff);
1451 else if (letter == 'B')
1452 fprintf (file, "%d", exact_log2 (INTVAL (op)));
1453 else if (letter == 'E')
1454 fprintf (file, "%ld", (INTVAL (op) >> 24) & 0xff);
1455 else if (letter == 'm')
1456 fprintf (file, "%ld", - INTVAL (op));
1457 else if (letter == 's')
1458 fprintf (file, "%ld", INTVAL (op) % 8);
1459 else if (letter == 'S')
1460 fprintf (file, "%ld", INTVAL (op) % 16);
1461 else if (letter == 'r')
1462 fprintf (file, "%ld", 8 - (INTVAL (op) % 8));
1463 else if (letter == 'C')
1464 fprintf (file, "%ld", (INTVAL (op) ^ 0x8000) & 0xffff);
1465 else
1466 fprintf (file, "%ld", INTVAL (op));
1467 break;
1468
1469 case CONST:
1470 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1471 break;
1472
1473 case ZERO_EXTRACT:
1474 {
1475 int bits = INTVAL (XEXP (op, 1));
1476 int ofs = INTVAL (XEXP (op, 2));
1477 if (bits == 16 && ofs == 0)
1478 fprintf (file, "%%lo16(");
1479 else if (bits == 16 && ofs == 16)
1480 fprintf (file, "%%hi16(");
1481 else if (bits == 8 && ofs == 16)
1482 fprintf (file, "%%hi8(");
1483 else
1484 gcc_unreachable ();
1485 rl78_print_operand_1 (file, XEXP (op, 0), 0);
1486 fprintf (file, ")");
1487 }
1488 break;
1489
1490 case ZERO_EXTEND:
1491 if (GET_CODE (XEXP (op, 0)) == REG)
1492 fprintf (file, "%s", reg_names [REGNO (XEXP (op, 0))]);
1493 else
1494 print_rtl (file, op);
1495 break;
1496
1497 case PLUS:
1498 need_paren = 0;
1499 if (letter == 'H')
1500 {
1501 fprintf (file, "%%hi16(");
1502 need_paren = 1;
1503 letter = 0;
1504 }
1505 if (letter == 'h')
1506 {
1507 fprintf (file, "%%lo16(");
1508 need_paren = 1;
1509 letter = 0;
1510 }
1511 if (letter == 'e')
1512 {
1513 fprintf (file, "%%hi8(");
1514 need_paren = 1;
1515 letter = 0;
1516 }
1517 if (letter == 'q' || letter == 'Q')
1518 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1519
1520 if (GET_CODE (XEXP (op, 0)) == ZERO_EXTEND)
1521 {
1522 rl78_print_operand_1 (file, XEXP (op, 1), letter);
1523 fprintf (file, "+");
1524 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1525 }
1526 else
1527 {
1528 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1529 fprintf (file, "+");
1530 rl78_print_operand_1 (file, XEXP (op, 1), letter);
1531 }
1532 if (need_paren)
1533 fprintf (file, ")");
1534 break;
1535
1536 case SYMBOL_REF:
1537 need_paren = 0;
1538 if (letter == 'H')
1539 {
1540 fprintf (file, "%%hi16(");
1541 need_paren = 1;
1542 letter = 0;
1543 }
1544 if (letter == 'h')
1545 {
1546 fprintf (file, "%%lo16(");
1547 need_paren = 1;
1548 letter = 0;
1549 }
1550 if (letter == 'e')
1551 {
1552 fprintf (file, "%%hi8(");
1553 need_paren = 1;
1554 letter = 0;
1555 }
1556 if (letter == 'q' || letter == 'Q')
1557 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1558
1559 output_addr_const (file, op);
1560 if (need_paren)
1561 fprintf (file, ")");
1562 break;
1563
1564 case CODE_LABEL:
1565 case LABEL_REF:
1566 output_asm_label (op);
1567 break;
1568
1569 case LTU:
1570 if (letter == 'z')
1571 fprintf (file, "#comparison eliminated");
1572 else
1573 fprintf (file, letter == 'C' ? "nc" : "c");
1574 break;
1575 case LEU:
1576 if (letter == 'z')
1577 fprintf (file, "br");
1578 else
1579 fprintf (file, letter == 'C' ? "h" : "nh");
1580 break;
1581 case GEU:
1582 if (letter == 'z')
1583 fprintf (file, "br");
1584 else
1585 fprintf (file, letter == 'C' ? "c" : "nc");
1586 break;
1587 case GTU:
1588 if (letter == 'z')
1589 fprintf (file, "#comparison eliminated");
1590 else
1591 fprintf (file, letter == 'C' ? "nh" : "h");
1592 break;
1593 case EQ:
1594 if (letter == 'z')
1595 fprintf (file, "br");
1596 else
1597 fprintf (file, letter == 'C' ? "nz" : "z");
1598 break;
1599 case NE:
1600 if (letter == 'z')
1601 fprintf (file, "#comparison eliminated");
1602 else
1603 fprintf (file, letter == 'C' ? "z" : "nz");
1604 break;
1605
1606 /* Note: these assume appropriate adjustments were made so that
1607 unsigned comparisons, which is all this chip has, will
1608 work. */
1609 case LT:
1610 if (letter == 'z')
1611 fprintf (file, "#comparison eliminated");
1612 else
1613 fprintf (file, letter == 'C' ? "nc" : "c");
1614 break;
1615 case LE:
1616 if (letter == 'z')
1617 fprintf (file, "br");
1618 else
1619 fprintf (file, letter == 'C' ? "h" : "nh");
1620 break;
1621 case GE:
1622 if (letter == 'z')
1623 fprintf (file, "br");
1624 else
1625 fprintf (file, letter == 'C' ? "c" : "nc");
1626 break;
1627 case GT:
1628 if (letter == 'z')
1629 fprintf (file, "#comparison eliminated");
1630 else
1631 fprintf (file, letter == 'C' ? "nh" : "h");
1632 break;
1633
1634 default:
1635 fprintf (file, "(%s)", GET_RTX_NAME (GET_CODE (op)));
1636 break;
1637 }
1638 }
1639
1640 #undef TARGET_PRINT_OPERAND
1641 #define TARGET_PRINT_OPERAND rl78_print_operand
1642
1643 static void
1644 rl78_print_operand (FILE * file, rtx op, int letter)
1645 {
1646 if (CONSTANT_P (op) && letter != 'u' && letter != 's' && letter != 'r' && letter != 'S' && letter != 'B')
1647 fprintf (file, "#");
1648 rl78_print_operand_1 (file, op, letter);
1649 }
1650
1651 #undef TARGET_TRAMPOLINE_INIT
1652 #define TARGET_TRAMPOLINE_INIT rl78_trampoline_init
1653
1654 /* Note that the RL78's addressing makes it very difficult to do
1655 trampolines on the stack. So, libgcc has a small pool of
1656 trampolines from which one is allocated to this task. */
1657 static void
1658 rl78_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
1659 {
1660 rtx mov_addr, thunk_addr;
1661 rtx function = XEXP (DECL_RTL (fndecl), 0);
1662
1663 mov_addr = adjust_address (m_tramp, HImode, 0);
1664 thunk_addr = gen_reg_rtx (HImode);
1665
1666 function = force_reg (HImode, function);
1667 static_chain = force_reg (HImode, static_chain);
1668
1669 emit_insn (gen_trampoline_init (thunk_addr, function, static_chain));
1670 emit_move_insn (mov_addr, thunk_addr);
1671
1672 cfun->machine->trampolines_used = 1;
1673 }
1674
1675 #undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
1676 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS rl78_trampoline_adjust_address
1677
1678 static rtx
1679 rl78_trampoline_adjust_address (rtx m_tramp)
1680 {
1681 rtx x = gen_rtx_MEM (HImode, m_tramp);
1682 return x;
1683 }
1684 \f
1685 /* Expander for cbranchqi4 and cbranchhi4. RL78 is missing some of
1686 the "normal" compares, specifically, it only has unsigned compares,
1687 so we must synthesize the missing ones. */
1688 void
1689 rl78_expand_compare (rtx *operands)
1690 {
1691 if (GET_CODE (operands[2]) == MEM)
1692 operands[2] = copy_to_mode_reg (GET_MODE (operands[2]), operands[2]);
1693 }
1694
1695 \f
1696
1697 /* Define this to 1 if you are debugging the peephole optimizers. */
1698 #define DEBUG_PEEP 0
1699
1700 /* Predicate used to enable the peephole2 patterns in rl78-virt.md.
1701 The default "word" size is a byte so we can effectively use all the
1702 registers, but we want to do 16-bit moves whenever possible. This
1703 function determines when such a move is an option. */
1704 bool
1705 rl78_peep_movhi_p (rtx *operands)
1706 {
1707 int i;
1708 rtx m, a;
1709
1710 /* (set (op0) (op1))
1711 (set (op2) (op3)) */
1712
1713 if (! rl78_virt_insns_ok ())
1714 return false;
1715
1716 #if DEBUG_PEEP
1717 fprintf (stderr, "\033[33m");
1718 debug_rtx (operands[0]);
1719 debug_rtx (operands[1]);
1720 debug_rtx (operands[2]);
1721 debug_rtx (operands[3]);
1722 fprintf (stderr, "\033[0m");
1723 #endif
1724
1725 /* You can move a constant to memory as QImode, but not HImode. */
1726 if (GET_CODE (operands[0]) == MEM
1727 && GET_CODE (operands[1]) != REG)
1728 {
1729 #if DEBUG_PEEP
1730 fprintf (stderr, "no peep: move constant to memory\n");
1731 #endif
1732 return false;
1733 }
1734
1735 if (rtx_equal_p (operands[0], operands[3]))
1736 {
1737 #if DEBUG_PEEP
1738 fprintf (stderr, "no peep: overlapping\n");
1739 #endif
1740 return false;
1741 }
1742
1743 for (i = 0; i < 2; i ++)
1744 {
1745 if (GET_CODE (operands[i]) != GET_CODE (operands[i+2]))
1746 {
1747 #if DEBUG_PEEP
1748 fprintf (stderr, "no peep: different codes\n");
1749 #endif
1750 return false;
1751 }
1752 if (GET_MODE (operands[i]) != GET_MODE (operands[i+2]))
1753 {
1754 #if DEBUG_PEEP
1755 fprintf (stderr, "no peep: different modes\n");
1756 #endif
1757 return false;
1758 }
1759
1760 switch (GET_CODE (operands[i]))
1761 {
1762 case REG:
1763 /* LSB MSB */
1764 if (REGNO (operands[i]) + 1 != REGNO (operands[i+2])
1765 || GET_MODE (operands[i]) != QImode)
1766 {
1767 #if DEBUG_PEEP
1768 fprintf (stderr, "no peep: wrong regnos %d %d %d\n",
1769 REGNO (operands[i]), REGNO (operands[i+2]),
1770 i);
1771 #endif
1772 return false;
1773 }
1774 if (! rl78_hard_regno_mode_ok (REGNO (operands[i]), HImode))
1775 {
1776 #if DEBUG_PEEP
1777 fprintf (stderr, "no peep: reg %d not HI\n", REGNO (operands[i]));
1778 #endif
1779 return false;
1780 }
1781 break;
1782
1783 case CONST_INT:
1784 break;
1785
1786 case MEM:
1787 if (GET_MODE (operands[i]) != QImode)
1788 return false;
1789 if (MEM_ALIGN (operands[i]) < 16)
1790 return false;
1791 a = XEXP (operands[i], 0);
1792 if (GET_CODE (a) == CONST)
1793 a = XEXP (a, 0);
1794 if (GET_CODE (a) == PLUS)
1795 a = XEXP (a, 1);
1796 if (GET_CODE (a) == CONST_INT
1797 && INTVAL (a) & 1)
1798 {
1799 #if DEBUG_PEEP
1800 fprintf (stderr, "no peep: misaligned mem %d\n", i);
1801 debug_rtx (operands[i]);
1802 #endif
1803 return false;
1804 }
1805 m = adjust_address (operands[i], QImode, 1);
1806 if (! rtx_equal_p (m, operands[i+2]))
1807 {
1808 #if DEBUG_PEEP
1809 fprintf (stderr, "no peep: wrong mem %d\n", i);
1810 debug_rtx (m);
1811 debug_rtx (operands[i+2]);
1812 #endif
1813 return false;
1814 }
1815 break;
1816
1817 default:
1818 #if DEBUG_PEEP
1819 fprintf (stderr, "no peep: wrong rtx %d\n", i);
1820 #endif
1821 return false;
1822 }
1823 }
1824 #if DEBUG_PEEP
1825 fprintf (stderr, "\033[32mpeep!\033[0m\n");
1826 #endif
1827 return true;
1828 }
1829
1830 /* Likewise, when a peephole is activated, this function helps compute
1831 the new operands. */
1832 void
1833 rl78_setup_peep_movhi (rtx *operands)
1834 {
1835 int i;
1836
1837 for (i = 0; i < 2; i ++)
1838 {
1839 switch (GET_CODE (operands[i]))
1840 {
1841 case REG:
1842 operands[i+4] = gen_rtx_REG (HImode, REGNO (operands[i]));
1843 break;
1844
1845 case CONST_INT:
1846 operands[i+4] = GEN_INT ((INTVAL (operands[i]) & 0xff) + ((char) INTVAL (operands[i+2])) * 256);
1847 break;
1848
1849 case MEM:
1850 operands[i+4] = adjust_address (operands[i], HImode, 0);
1851 break;
1852
1853 default:
1854 break;
1855 }
1856 }
1857 }
1858 \f
1859 /*
1860 How Devirtualization works in the RL78 GCC port
1861
1862 Background
1863
1864 The RL78 is an 8-bit port with some 16-bit operations. It has 32
1865 bytes of register space, in four banks, memory-mapped. One bank is
1866 the "selected" bank and holds the registers used for primary
1867 operations. Since the registers are memory mapped, often you can
1868 still refer to the unselected banks via memory accesses.
1869
1870 Virtual Registers
1871
1872 The GCC port uses bank 0 as the "selected" registers (A, X, BC, etc)
1873 and refers to the other banks via their memory addresses, although
1874 they're treated as regular registers internally. These "virtual"
1875 registers are R8 through R23 (bank3 is reserved for asm-based
1876 interrupt handlers).
1877
1878 There are four machine description files:
1879
1880 rl78.md - common register-independent patterns and definitions
1881 rl78-expand.md - expanders
1882 rl78-virt.md - patterns that match BEFORE devirtualization
1883 rl78-real.md - patterns that match AFTER devirtualization
1884
1885 At least through register allocation and reload, gcc is told that it
1886 can do pretty much anything - but may only use the virtual registers.
1887 GCC cannot properly create the varying addressing modes that the RL78
1888 supports in an efficient way.
1889
1890 Sometime after reload, the RL78 backend "devirtualizes" the RTL. It
1891 uses the "valloc" attribute in rl78-virt.md for determining the rules
1892 by which it will replace virtual registers with real registers (or
1893 not) and how to make up addressing modes. For example, insns tagged
1894 with "ro1" have a single read-only parameter, which may need to be
1895 moved from memory/constant/vreg to a suitable real register. As part
1896 of devirtualization, a flag is toggled, disabling the rl78-virt.md
1897 patterns and enabling the rl78-real.md patterns. The new patterns'
1898 constraints are used to determine the real registers used. NOTE:
1899 patterns in rl78-virt.md essentially ignore the constrains and rely on
1900 predicates, where the rl78-real.md ones essentially ignore the
1901 predicates and rely on the constraints.
1902
1903 The devirtualization pass is scheduled via the pass manager (despite
1904 being called "rl78_reorg") so it can be scheduled prior to var-track
1905 (the idea is to let gdb know about the new registers). Ideally, it
1906 would be scheduled right after pro/epilogue generation, so the
1907 post-reload optimizers could operate on the real registers, but when I
1908 tried that there were some issues building the target libraries.
1909
1910 During devirtualization, a simple register move optimizer is run. It
1911 would be better to run a full CSE/propogation pass on it though, but
1912 that has not yet been attempted.
1913
1914 */
1915 #define DEBUG_ALLOC 0
1916
1917 #define OP(x) (*recog_data.operand_loc[x])
1918
1919 /* This array is used to hold knowledge about the contents of the
1920 real registers (A ... H), the memory-based registers (r8 ... r31)
1921 and the first NUM_STACK_LOCS words on the stack. We use this to
1922 avoid generating redundant move instructions.
1923
1924 A value in the range 0 .. 31 indicates register A .. r31.
1925 A value in the range 32 .. 63 indicates stack slot (value - 32).
1926 A value of NOT_KNOWN indicates that the contents of that location
1927 are not known. */
1928
1929 #define NUM_STACK_LOCS 32
1930 #define NOT_KNOWN 127
1931
1932 static unsigned char content_memory [32 + NUM_STACK_LOCS];
1933
1934 static unsigned char saved_update_index = NOT_KNOWN;
1935 static unsigned char saved_update_value;
1936 static machine_mode saved_update_mode;
1937
1938
1939 static inline void
1940 clear_content_memory (void)
1941 {
1942 memset (content_memory, NOT_KNOWN, sizeof content_memory);
1943 if (dump_file)
1944 fprintf (dump_file, " clear content memory\n");
1945 saved_update_index = NOT_KNOWN;
1946 }
1947
1948 /* Convert LOC into an index into the content_memory array.
1949 If LOC cannot be converted, return NOT_KNOWN. */
1950
1951 static unsigned char
1952 get_content_index (rtx loc)
1953 {
1954 machine_mode mode;
1955
1956 if (loc == NULL_RTX)
1957 return NOT_KNOWN;
1958
1959 if (REG_P (loc))
1960 {
1961 if (REGNO (loc) < 32)
1962 return REGNO (loc);
1963 return NOT_KNOWN;
1964 }
1965
1966 mode = GET_MODE (loc);
1967
1968 if (! rl78_stack_based_mem (loc, mode))
1969 return NOT_KNOWN;
1970
1971 loc = XEXP (loc, 0);
1972
1973 if (REG_P (loc))
1974 /* loc = MEM (SP) */
1975 return 32;
1976
1977 /* loc = MEM (PLUS (SP, INT)). */
1978 loc = XEXP (loc, 1);
1979
1980 if (INTVAL (loc) < NUM_STACK_LOCS)
1981 return 32 + INTVAL (loc);
1982
1983 return NOT_KNOWN;
1984 }
1985
1986 /* Return a string describing content INDEX in mode MODE.
1987 WARNING: Can return a pointer to a static buffer. */
1988 static const char *
1989 get_content_name (unsigned char index, machine_mode mode)
1990 {
1991 static char buffer [128];
1992
1993 if (index == NOT_KNOWN)
1994 return "Unknown";
1995
1996 if (index > 31)
1997 sprintf (buffer, "stack slot %d", index - 32);
1998 else if (mode == HImode)
1999 sprintf (buffer, "%s%s",
2000 reg_names [index + 1], reg_names [index]);
2001 else
2002 return reg_names [index];
2003
2004 return buffer;
2005 }
2006
2007 #if DEBUG_ALLOC
2008
2009 static void
2010 display_content_memory (FILE * file)
2011 {
2012 unsigned int i;
2013
2014 fprintf (file, " Known memory contents:\n");
2015
2016 for (i = 0; i < sizeof content_memory; i++)
2017 if (content_memory[i] != NOT_KNOWN)
2018 {
2019 fprintf (file, " %s contains a copy of ", get_content_name (i, QImode));
2020 fprintf (file, "%s\n", get_content_name (content_memory [i], QImode));
2021 }
2022 }
2023 #endif
2024
2025 static void
2026 update_content (unsigned char index, unsigned char val, machine_mode mode)
2027 {
2028 unsigned int i;
2029
2030 gcc_assert (index < sizeof content_memory);
2031
2032 content_memory [index] = val;
2033 if (val != NOT_KNOWN)
2034 content_memory [val] = index;
2035
2036 /* Make the entry in dump_file *before* VAL is increased below. */
2037 if (dump_file)
2038 {
2039 fprintf (dump_file, " %s now contains ", get_content_name (index, mode));
2040 if (val == NOT_KNOWN)
2041 fprintf (dump_file, "Unknown\n");
2042 else
2043 fprintf (dump_file, "%s and vice versa\n", get_content_name (val, mode));
2044 }
2045
2046 if (mode == HImode)
2047 {
2048 val = val == NOT_KNOWN ? val : val + 1;
2049
2050 content_memory [index + 1] = val;
2051 if (val != NOT_KNOWN)
2052 {
2053 content_memory [val] = index + 1;
2054 -- val;
2055 }
2056 }
2057
2058 /* Any other places that had INDEX recorded as their contents are now invalid. */
2059 for (i = 0; i < sizeof content_memory; i++)
2060 {
2061 if (i == index
2062 || (val != NOT_KNOWN && i == val))
2063 {
2064 if (mode == HImode)
2065 ++ i;
2066 continue;
2067 }
2068
2069 if (content_memory[i] == index
2070 || (val != NOT_KNOWN && content_memory[i] == val))
2071 {
2072 content_memory[i] = NOT_KNOWN;
2073
2074 if (dump_file)
2075 fprintf (dump_file, " %s cleared\n", get_content_name (i, mode));
2076
2077 if (mode == HImode)
2078 content_memory[++ i] = NOT_KNOWN;
2079 }
2080 }
2081 }
2082
2083 /* Record that LOC contains VALUE.
2084 For HImode locations record that LOC+1 contains VALUE+1.
2085 If LOC is not a register or stack slot, do nothing.
2086 If VALUE is not a register or stack slot, clear the recorded content. */
2087
2088 static void
2089 record_content (rtx loc, rtx value)
2090 {
2091 machine_mode mode;
2092 unsigned char index;
2093 unsigned char val;
2094
2095 if ((index = get_content_index (loc)) == NOT_KNOWN)
2096 return;
2097
2098 val = get_content_index (value);
2099
2100 mode = GET_MODE (loc);
2101
2102 if (val == index)
2103 {
2104 if (! optimize)
2105 return;
2106
2107 /* This should not happen when optimizing. */
2108 #if 1
2109 fprintf (stderr, "ASSIGNMENT of location to itself detected! [%s]\n",
2110 get_content_name (val, mode));
2111 return;
2112 #else
2113 gcc_unreachable ();
2114 #endif
2115 }
2116
2117 update_content (index, val, mode);
2118 }
2119
2120 /* Returns TRUE if LOC already contains a copy of VALUE. */
2121
2122 static bool
2123 already_contains (rtx loc, rtx value)
2124 {
2125 unsigned char index;
2126 unsigned char val;
2127
2128 if ((index = get_content_index (loc)) == NOT_KNOWN)
2129 return false;
2130
2131 if ((val = get_content_index (value)) == NOT_KNOWN)
2132 return false;
2133
2134 if (content_memory [index] != val)
2135 return false;
2136
2137 if (GET_MODE (loc) == HImode)
2138 return content_memory [index + 1] == val + 1;
2139
2140 return true;
2141 }
2142
2143 bool
2144 rl78_es_addr (rtx addr)
2145 {
2146 if (GET_CODE (addr) == MEM)
2147 addr = XEXP (addr, 0);
2148 if (GET_CODE (addr) != UNSPEC)
2149 return false;
2150 if (XINT (addr, 1) != UNS_ES_ADDR)
2151 return false;
2152 return true;
2153 }
2154
2155 rtx
2156 rl78_es_base (rtx addr)
2157 {
2158 if (GET_CODE (addr) == MEM)
2159 addr = XEXP (addr, 0);
2160 addr = XVECEXP (addr, 0, 1);
2161 if (GET_CODE (addr) == CONST
2162 && GET_CODE (XEXP (addr, 0)) == ZERO_EXTRACT)
2163 addr = XEXP (XEXP (addr, 0), 0);
2164 /* Mode doesn't matter here. */
2165 return gen_rtx_MEM (HImode, addr);
2166 }
2167
2168 /* Rescans an insn to see if it's recognized again. This is done
2169 carefully to ensure that all the constraint information is accurate
2170 for the newly matched insn. */
2171 static bool
2172 insn_ok_now (rtx_insn *insn)
2173 {
2174 rtx pattern = PATTERN (insn);
2175 int i;
2176
2177 INSN_CODE (insn) = -1;
2178
2179 if (recog (pattern, insn, 0) > -1)
2180 {
2181 extract_insn (insn);
2182 if (constrain_operands (1, get_preferred_alternatives (insn)))
2183 {
2184 #if DEBUG_ALLOC
2185 fprintf (stderr, "\033[32m");
2186 debug_rtx (insn);
2187 fprintf (stderr, "\033[0m");
2188 #endif
2189 if (SET_P (pattern))
2190 record_content (SET_DEST (pattern), SET_SRC (pattern));
2191
2192 /* We need to detect far addresses that haven't been
2193 converted to es/lo16 format. */
2194 for (i=0; i<recog_data.n_operands; i++)
2195 if (GET_CODE (OP (i)) == MEM
2196 && GET_MODE (XEXP (OP (i), 0)) == SImode
2197 && GET_CODE (XEXP (OP (i), 0)) != UNSPEC)
2198 return false;
2199
2200 return true;
2201 }
2202 }
2203 else
2204 {
2205 /* We need to re-recog the insn with virtual registers to get
2206 the operands. */
2207 cfun->machine->virt_insns_ok = 1;
2208 if (recog (pattern, insn, 0) > -1)
2209 {
2210 extract_insn (insn);
2211 if (constrain_operands (0, get_preferred_alternatives (insn)))
2212 {
2213 cfun->machine->virt_insns_ok = 0;
2214 return false;
2215 }
2216 }
2217
2218 #if DEBUG_ALLOC
2219 fprintf (stderr, "\033[41;30m Unrecognized *virtual* insn \033[0m\n");
2220 debug_rtx (insn);
2221 #endif
2222 gcc_unreachable ();
2223 }
2224
2225 #if DEBUG_ALLOC
2226 fprintf (stderr, "\033[31m");
2227 debug_rtx (insn);
2228 fprintf (stderr, "\033[0m");
2229 #endif
2230 return false;
2231 }
2232
2233 #if DEBUG_ALLOC
2234 #define WORKED fprintf (stderr, "\033[48;5;22m Worked at line %d \033[0m\n", __LINE__)
2235 #define FAILEDSOFAR fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__)
2236 #define FAILED fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__), gcc_unreachable()
2237 #define MAYBE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } else { FAILEDSOFAR; }
2238 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } FAILED
2239 #else
2240 #define FAILED gcc_unreachable ()
2241 #define MAYBE_OK(insn) if (insn_ok_now (insn)) return;
2242 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) return; FAILED
2243 #endif
2244
2245 /* Registers into which we move the contents of virtual registers. */
2246 #define X gen_rtx_REG (QImode, X_REG)
2247 #define A gen_rtx_REG (QImode, A_REG)
2248 #define C gen_rtx_REG (QImode, C_REG)
2249 #define B gen_rtx_REG (QImode, B_REG)
2250 #define E gen_rtx_REG (QImode, E_REG)
2251 #define D gen_rtx_REG (QImode, D_REG)
2252 #define L gen_rtx_REG (QImode, L_REG)
2253 #define H gen_rtx_REG (QImode, H_REG)
2254
2255 #define AX gen_rtx_REG (HImode, AX_REG)
2256 #define BC gen_rtx_REG (HImode, BC_REG)
2257 #define DE gen_rtx_REG (HImode, DE_REG)
2258 #define HL gen_rtx_REG (HImode, HL_REG)
2259
2260 /* Returns TRUE if R is a virtual register. */
2261 static inline bool
2262 is_virtual_register (rtx r)
2263 {
2264 return (GET_CODE (r) == REG
2265 && REGNO (r) >= 8
2266 && REGNO (r) < 32);
2267 }
2268
2269 /* In all these alloc routines, we expect the following: the insn
2270 pattern is unshared, the insn was previously recognized and failed
2271 due to predicates or constraints, and the operand data is in
2272 recog_data. */
2273
2274 static int virt_insn_was_frame;
2275
2276 /* Hook for all insns we emit. Re-mark them as FRAME_RELATED if
2277 needed. */
2278 static rtx
2279 EM2 (int line ATTRIBUTE_UNUSED, rtx r)
2280 {
2281 #if DEBUG_ALLOC
2282 fprintf (stderr, "\033[36m%d: ", line);
2283 debug_rtx (r);
2284 fprintf (stderr, "\033[0m");
2285 #endif
2286 /*SCHED_GROUP_P (r) = 1;*/
2287 if (virt_insn_was_frame)
2288 RTX_FRAME_RELATED_P (r) = 1;
2289 return r;
2290 }
2291
2292 #define EM(x) EM2 (__LINE__, x)
2293
2294 /* Return a suitable RTX for the low half of a __far address. */
2295 static rtx
2296 rl78_lo16 (rtx addr)
2297 {
2298 rtx r;
2299
2300 if (GET_CODE (addr) == SYMBOL_REF
2301 || GET_CODE (addr) == CONST)
2302 {
2303 r = gen_rtx_ZERO_EXTRACT (HImode, addr, GEN_INT (16), GEN_INT (0));
2304 r = gen_rtx_CONST (HImode, r);
2305 }
2306 else
2307 r = rl78_subreg (HImode, addr, SImode, 0);
2308
2309 r = gen_es_addr (r);
2310
2311 return r;
2312 }
2313
2314 /* Return a suitable RTX for the high half's lower byte of a __far address. */
2315 static rtx
2316 rl78_hi8 (rtx addr)
2317 {
2318 if (GET_CODE (addr) == SYMBOL_REF
2319 || GET_CODE (addr) == CONST)
2320 {
2321 rtx r = gen_rtx_ZERO_EXTRACT (QImode, addr, GEN_INT (8), GEN_INT (16));
2322 r = gen_rtx_CONST (QImode, r);
2323 return r;
2324 }
2325 return rl78_subreg (QImode, addr, SImode, 2);
2326 }
2327
2328 static void
2329 add_postponed_content_update (rtx to, rtx value)
2330 {
2331 unsigned char index;
2332
2333 if ((index = get_content_index (to)) == NOT_KNOWN)
2334 return;
2335
2336 gcc_assert (saved_update_index == NOT_KNOWN);
2337 saved_update_index = index;
2338 saved_update_value = get_content_index (value);
2339 saved_update_mode = GET_MODE (to);
2340 }
2341
2342 static void
2343 process_postponed_content_update (void)
2344 {
2345 if (saved_update_index != NOT_KNOWN)
2346 {
2347 update_content (saved_update_index, saved_update_value, saved_update_mode);
2348 saved_update_index = NOT_KNOWN;
2349 }
2350 }
2351
2352 /* Generate and emit a move of (register) FROM into TO. if WHERE is not NULL
2353 then if BEFORE is true then emit the insn before WHERE, otherwise emit it
2354 after WHERE. If TO already contains FROM then do nothing. Returns TO if
2355 BEFORE is true, FROM otherwise. */
2356 static rtx
2357 gen_and_emit_move (rtx to, rtx from, rtx where, bool before)
2358 {
2359 machine_mode mode = GET_MODE (to);
2360
2361 if (optimize && before && already_contains (to, from))
2362 {
2363 #if DEBUG_ALLOC
2364 display_content_memory (stderr);
2365 #endif
2366 if (dump_file)
2367 {
2368 fprintf (dump_file, " Omit move of %s into ",
2369 get_content_name (get_content_index (from), mode));
2370 fprintf (dump_file, "%s as it already contains this value\n",
2371 get_content_name (get_content_index (to), mode));
2372 }
2373 }
2374 else
2375 {
2376 rtx move = mode == QImode ? gen_movqi (to, from) : gen_movhi (to, from);
2377
2378 EM (move);
2379
2380 if (where == NULL_RTX)
2381 emit_insn (move);
2382 else if (before)
2383 emit_insn_before (move, where);
2384 else
2385 {
2386 rtx note = find_reg_note (where, REG_EH_REGION, NULL_RTX);
2387
2388 /* If necessary move REG_EH_REGION notes forward.
2389 cf. compiling gcc.dg/pr44545.c. */
2390 if (note != NULL_RTX)
2391 {
2392 add_reg_note (move, REG_EH_REGION, XEXP (note, 0));
2393 remove_note (where, note);
2394 }
2395
2396 emit_insn_after (move, where);
2397 }
2398
2399 if (before)
2400 record_content (to, from);
2401 else
2402 add_postponed_content_update (to, from);
2403 }
2404
2405 return before ? to : from;
2406 }
2407
2408 /* If M is MEM(REG) or MEM(PLUS(REG,INT)) and REG is virtual then
2409 copy it into NEWBASE and return the updated MEM. Otherwise just
2410 return M. Any needed insns are emitted before BEFORE. */
2411 static rtx
2412 transcode_memory_rtx (rtx m, rtx newbase, rtx before)
2413 {
2414 rtx base, index, addendr;
2415 int addend = 0;
2416 int need_es = 0;
2417
2418 if (! MEM_P (m))
2419 return m;
2420
2421 if (GET_MODE (XEXP (m, 0)) == SImode)
2422 {
2423 rtx new_m;
2424 rtx seg = rl78_hi8 (XEXP (m, 0));
2425
2426 #if DEBUG_ALLOC
2427 fprintf (stderr, "setting ES:\n");
2428 debug_rtx(seg);
2429 #endif
2430 emit_insn_before (EM (gen_movqi (A, seg)), before);
2431 emit_insn_before (EM (gen_movqi_es (A)), before);
2432 record_content (A, NULL_RTX);
2433
2434 new_m = gen_rtx_MEM (GET_MODE (m), rl78_lo16 (XEXP (m, 0)));
2435 MEM_COPY_ATTRIBUTES (new_m, m);
2436 m = new_m;
2437 need_es = 1;
2438 }
2439
2440 characterize_address (XEXP (m, 0), & base, & index, & addendr);
2441 gcc_assert (index == NULL_RTX);
2442
2443 #if DEBUG_ALLOC
2444 fprintf (stderr, "\033[33m"); debug_rtx (m); fprintf (stderr, "\033[0m");
2445 debug_rtx (base);
2446 #endif
2447 if (base == NULL_RTX)
2448 return m;
2449
2450 if (addendr && GET_CODE (addendr) == CONST_INT)
2451 addend = INTVAL (addendr);
2452
2453 gcc_assert (REG_P (base));
2454 gcc_assert (REG_P (newbase));
2455
2456 if (REGNO (base) == SP_REG)
2457 {
2458 if (addend >= 0 && addend <= 255)
2459 return m;
2460 }
2461
2462 /* BASE should be a virtual register. We copy it to NEWBASE. If
2463 the addend is out of range for DE/HL, we use AX to compute the full
2464 address. */
2465
2466 if (addend < 0
2467 || (addend > 255 && REGNO (newbase) != 2)
2468 || (addendr && GET_CODE (addendr) != CONST_INT))
2469 {
2470 /* mov ax, vreg
2471 add ax, #imm
2472 mov hl, ax */
2473 EM (emit_insn_before (gen_movhi (AX, base), before));
2474 EM (emit_insn_before (gen_addhi3 (AX, AX, addendr), before));
2475 EM (emit_insn_before (gen_movhi (newbase, AX), before));
2476 record_content (AX, NULL_RTX);
2477 record_content (newbase, NULL_RTX);
2478
2479 base = newbase;
2480 addend = 0;
2481 }
2482 else
2483 {
2484 base = gen_and_emit_move (newbase, base, before, true);
2485 }
2486
2487 if (addend)
2488 {
2489 record_content (base, NULL_RTX);
2490 base = gen_rtx_PLUS (HImode, base, GEN_INT (addend));
2491 }
2492
2493 #if DEBUG_ALLOC
2494 fprintf (stderr, "\033[33m");
2495 debug_rtx (m);
2496 #endif
2497 if (need_es)
2498 m = change_address (m, GET_MODE (m), gen_es_addr (base));
2499 else
2500 m = change_address (m, GET_MODE (m), base);
2501 #if DEBUG_ALLOC
2502 debug_rtx (m);
2503 fprintf (stderr, "\033[0m");
2504 #endif
2505 return m;
2506 }
2507
2508 /* Copy SRC to accumulator (A or AX), placing any generated insns
2509 before BEFORE. Returns accumulator RTX. */
2510 static rtx
2511 move_to_acc (int opno, rtx before)
2512 {
2513 rtx src = OP (opno);
2514 machine_mode mode = GET_MODE (src);
2515
2516 if (REG_P (src) && REGNO (src) < 2)
2517 return src;
2518
2519 if (mode == VOIDmode)
2520 mode = recog_data.operand_mode[opno];
2521
2522 return gen_and_emit_move (mode == QImode ? A : AX, src, before, true);
2523 }
2524
2525 static void
2526 force_into_acc (rtx src, rtx before)
2527 {
2528 machine_mode mode = GET_MODE (src);
2529 rtx move;
2530
2531 if (REG_P (src) && REGNO (src) < 2)
2532 return;
2533
2534 move = mode == QImode ? gen_movqi (A, src) : gen_movhi (AX, src);
2535
2536 EM (move);
2537
2538 emit_insn_before (move, before);
2539 record_content (AX, NULL_RTX);
2540 }
2541
2542 /* Copy accumulator (A or AX) to DEST, placing any generated insns
2543 after AFTER. Returns accumulator RTX. */
2544 static rtx
2545 move_from_acc (unsigned int opno, rtx after)
2546 {
2547 rtx dest = OP (opno);
2548 machine_mode mode = GET_MODE (dest);
2549
2550 if (REG_P (dest) && REGNO (dest) < 2)
2551 return dest;
2552
2553 return gen_and_emit_move (dest, mode == QImode ? A : AX, after, false);
2554 }
2555
2556 /* Copy accumulator (A or AX) to REGNO, placing any generated insns
2557 before BEFORE. Returns reg RTX. */
2558 static rtx
2559 move_acc_to_reg (rtx acc, int regno, rtx before)
2560 {
2561 machine_mode mode = GET_MODE (acc);
2562 rtx reg;
2563
2564 reg = gen_rtx_REG (mode, regno);
2565
2566 return gen_and_emit_move (reg, acc, before, true);
2567 }
2568
2569 /* Copy SRC to X, placing any generated insns before BEFORE.
2570 Returns X RTX. */
2571 static rtx
2572 move_to_x (int opno, rtx before)
2573 {
2574 rtx src = OP (opno);
2575 machine_mode mode = GET_MODE (src);
2576 rtx reg;
2577
2578 if (mode == VOIDmode)
2579 mode = recog_data.operand_mode[opno];
2580 reg = (mode == QImode) ? X : AX;
2581
2582 if (mode == QImode || ! is_virtual_register (OP (opno)))
2583 {
2584 OP (opno) = move_to_acc (opno, before);
2585 OP (opno) = move_acc_to_reg (OP (opno), X_REG, before);
2586 return reg;
2587 }
2588
2589 return gen_and_emit_move (reg, src, before, true);
2590 }
2591
2592 /* Copy OP (opno) to H or HL, placing any generated insns before BEFORE.
2593 Returns H/HL RTX. */
2594 static rtx
2595 move_to_hl (int opno, rtx before)
2596 {
2597 rtx src = OP (opno);
2598 machine_mode mode = GET_MODE (src);
2599 rtx reg;
2600
2601 if (mode == VOIDmode)
2602 mode = recog_data.operand_mode[opno];
2603 reg = (mode == QImode) ? L : HL;
2604
2605 if (mode == QImode || ! is_virtual_register (OP (opno)))
2606 {
2607 OP (opno) = move_to_acc (opno, before);
2608 OP (opno) = move_acc_to_reg (OP (opno), L_REG, before);
2609 return reg;
2610 }
2611
2612 return gen_and_emit_move (reg, src, before, true);
2613 }
2614
2615 /* Copy OP (opno) to E or DE, placing any generated insns before BEFORE.
2616 Returns E/DE RTX. */
2617 static rtx
2618 move_to_de (int opno, rtx before)
2619 {
2620 rtx src = OP (opno);
2621 machine_mode mode = GET_MODE (src);
2622 rtx reg;
2623
2624 if (mode == VOIDmode)
2625 mode = recog_data.operand_mode[opno];
2626
2627 reg = (mode == QImode) ? E : DE;
2628
2629 if (mode == QImode || ! is_virtual_register (OP (opno)))
2630 {
2631 OP (opno) = move_to_acc (opno, before);
2632 OP (opno) = move_acc_to_reg (OP (opno), E_REG, before);
2633 }
2634 else
2635 {
2636 gen_and_emit_move (reg, src, before, true);
2637 }
2638
2639 return reg;
2640 }
2641
2642 /* Devirtualize an insn of the form (SET (op) (unop (op))). */
2643 static void
2644 rl78_alloc_physical_registers_op1 (rtx_insn *insn)
2645 {
2646 /* op[0] = func op[1] */
2647
2648 /* We first try using A as the destination, then copying it
2649 back. */
2650 if (rtx_equal_p (OP (0), OP (1)))
2651 {
2652 OP (0) =
2653 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2654 }
2655 else
2656 {
2657 /* If necessary, load the operands into BC and HL.
2658 Check to see if we already have OP (0) in HL
2659 and if so, swap the order. */
2660 if (MEM_P (OP (0))
2661 && already_contains (HL, XEXP (OP (0), 0)))
2662 {
2663 OP (0) = transcode_memory_rtx (OP (0), HL, insn);
2664 OP (1) = transcode_memory_rtx (OP (1), BC, insn);
2665 }
2666 else
2667 {
2668 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
2669 OP (1) = transcode_memory_rtx (OP (1), HL, insn);
2670 }
2671 }
2672
2673 MAYBE_OK (insn);
2674
2675 OP (0) = move_from_acc (0, insn);
2676
2677 MAYBE_OK (insn);
2678
2679 /* Try copying the src to acc first, then. This is for, for
2680 example, ZERO_EXTEND or NOT. */
2681 OP (1) = move_to_acc (1, insn);
2682
2683 MUST_BE_OK (insn);
2684 }
2685
2686 /* Returns true if operand OPNUM contains a constraint of type CONSTRAINT.
2687 Assumes that the current insn has already been recognised and hence the
2688 constraint data has been filled in. */
2689 static bool
2690 has_constraint (unsigned int opnum, enum constraint_num constraint)
2691 {
2692 const char * p = recog_data.constraints[opnum];
2693
2694 /* No constraints means anything is accepted. */
2695 if (p == NULL || *p == 0 || *p == ',')
2696 return true;
2697
2698 do
2699 {
2700 char c;
2701 unsigned int len;
2702
2703 c = *p;
2704 len = CONSTRAINT_LEN (c, p);
2705 gcc_assert (len > 0);
2706
2707 switch (c)
2708 {
2709 case 0:
2710 case ',':
2711 return false;
2712 default:
2713 if (lookup_constraint (p) == constraint)
2714 return true;
2715 }
2716 p += len;
2717 }
2718 while (1);
2719 }
2720
2721 /* Devirtualize an insn of the form (SET (op) (binop (op) (op))). */
2722 static void
2723 rl78_alloc_physical_registers_op2 (rtx_insn *insn)
2724 {
2725 rtx prev;
2726 rtx first;
2727 bool hl_used;
2728 int tmp_id;
2729 rtx saved_op1;
2730
2731 if (rtx_equal_p (OP (0), OP (1)))
2732 {
2733 OP (0) =
2734 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2735 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2736 }
2737 else if (rtx_equal_p (OP (0), OP (2)))
2738 {
2739 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2740 OP (0) =
2741 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2742 }
2743 else
2744 {
2745 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
2746 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2747 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2748 }
2749
2750 MAYBE_OK (insn);
2751
2752 prev = prev_nonnote_nondebug_insn (insn);
2753 if (recog_data.constraints[1][0] == '%'
2754 && is_virtual_register (OP (1))
2755 && ! is_virtual_register (OP (2))
2756 && ! CONSTANT_P (OP (2)))
2757 {
2758 rtx tmp = OP (1);
2759 OP (1) = OP (2);
2760 OP (2) = tmp;
2761 }
2762
2763 /* Make a note of whether (H)L is being used. It matters
2764 because if OP (2) also needs reloading, then we must take
2765 care not to corrupt HL. */
2766 hl_used = reg_mentioned_p (L, OP (0)) || reg_mentioned_p (L, OP (1));
2767
2768 /* If HL is not currently being used and dest == op1 then there are
2769 some possible optimizations available by reloading one of the
2770 operands into HL, before trying to use the accumulator. */
2771 if (optimize
2772 && ! hl_used
2773 && rtx_equal_p (OP (0), OP (1)))
2774 {
2775 /* If op0 is a Ws1 type memory address then switching the base
2776 address register to HL might allow us to perform an in-memory
2777 operation. (eg for the INCW instruction).
2778
2779 FIXME: Adding the move into HL is costly if this optimization is not
2780 going to work, so for now, make sure that we know that the new insn will
2781 match the requirements of the addhi3_real pattern. Really we ought to
2782 generate a candidate sequence, test that, and then install it if the
2783 results are good. */
2784 if (satisfies_constraint_Ws1 (OP (0))
2785 && has_constraint (0, CONSTRAINT_Wh1)
2786 && (satisfies_constraint_K (OP (2)) || satisfies_constraint_L (OP (2))))
2787 {
2788 rtx base, index, addend, newbase;
2789
2790 characterize_address (XEXP (OP (0), 0), & base, & index, & addend);
2791 gcc_assert (index == NULL_RTX);
2792 gcc_assert (REG_P (base) && REGNO (base) == SP_REG);
2793
2794 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
2795 if (addend != NULL_RTX)
2796 {
2797 newbase = gen_and_emit_move (HL, base, insn, true);
2798 record_content (newbase, NULL_RTX);
2799 newbase = gen_rtx_PLUS (HImode, newbase, addend);
2800
2801 OP (0) = OP (1) = change_address (OP (0), VOIDmode, newbase);
2802
2803 /* We do not want to fail here as this means that
2804 we have inserted useless insns into the stream. */
2805 MUST_BE_OK (insn);
2806 }
2807 }
2808 else if (REG_P (OP (0))
2809 && satisfies_constraint_Ws1 (OP (2))
2810 && has_constraint (2, CONSTRAINT_Wh1))
2811 {
2812 rtx base, index, addend, newbase;
2813
2814 characterize_address (XEXP (OP (2), 0), & base, & index, & addend);
2815 gcc_assert (index == NULL_RTX);
2816 gcc_assert (REG_P (base) && REGNO (base) == SP_REG);
2817
2818 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
2819 if (addend != NULL_RTX)
2820 {
2821 gen_and_emit_move (HL, base, insn, true);
2822
2823 if (REGNO (OP (0)) != X_REG)
2824 {
2825 OP (1) = move_to_acc (1, insn);
2826 OP (0) = move_from_acc (0, insn);
2827 }
2828
2829 record_content (HL, NULL_RTX);
2830 newbase = gen_rtx_PLUS (HImode, HL, addend);
2831
2832 OP (2) = change_address (OP (2), VOIDmode, newbase);
2833
2834 /* We do not want to fail here as this means that
2835 we have inserted useless insns into the stream. */
2836 MUST_BE_OK (insn);
2837 }
2838 }
2839 }
2840
2841 OP (0) = move_from_acc (0, insn);
2842
2843 tmp_id = get_max_insn_count ();
2844 saved_op1 = OP (1);
2845
2846 if (rtx_equal_p (OP (1), OP (2)))
2847 OP (2) = OP (1) = move_to_acc (1, insn);
2848 else
2849 OP (1) = move_to_acc (1, insn);
2850
2851 MAYBE_OK (insn);
2852
2853 /* If we omitted the move of OP1 into the accumulator (because
2854 it was already there from a previous insn), then force the
2855 generation of the move instruction now. We know that we
2856 are about to emit a move into HL (or DE) via AX, and hence
2857 our optimization to remove the load of OP1 is no longer valid. */
2858 if (tmp_id == get_max_insn_count ())
2859 force_into_acc (saved_op1, insn);
2860
2861 /* We have to copy op2 to HL (or DE), but that involves AX, which
2862 already has a live value. Emit it before those insns. */
2863
2864 if (prev)
2865 first = next_nonnote_nondebug_insn (prev);
2866 else
2867 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
2868 ;
2869
2870 OP (2) = hl_used ? move_to_de (2, first) : move_to_hl (2, first);
2871
2872 MUST_BE_OK (insn);
2873 }
2874
2875 /* Devirtualize an insn of the form SET (PC) (MEM/REG). */
2876 static void
2877 rl78_alloc_physical_registers_ro1 (rtx_insn *insn)
2878 {
2879 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
2880
2881 MAYBE_OK (insn);
2882
2883 OP (0) = move_to_acc (0, insn);
2884
2885 MUST_BE_OK (insn);
2886 }
2887
2888 /* Devirtualize a compare insn. */
2889 static void
2890 rl78_alloc_physical_registers_cmp (rtx_insn *insn)
2891 {
2892 int tmp_id;
2893 rtx saved_op1;
2894 rtx prev = prev_nonnote_nondebug_insn (insn);
2895 rtx first;
2896
2897 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2898 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2899
2900 /* HI compares have to have OP (1) in AX, but QI
2901 compares do not, so it is worth checking here. */
2902 MAYBE_OK (insn);
2903
2904 /* For an HImode compare, OP (1) must always be in AX.
2905 But if OP (1) is a REG (and not AX), then we can avoid
2906 a reload of OP (1) if we reload OP (2) into AX and invert
2907 the comparison. */
2908 if (REG_P (OP (1))
2909 && REGNO (OP (1)) != AX_REG
2910 && GET_MODE (OP (1)) == HImode
2911 && MEM_P (OP (2)))
2912 {
2913 rtx cmp = XEXP (SET_SRC (PATTERN (insn)), 0);
2914
2915 OP (2) = move_to_acc (2, insn);
2916
2917 switch (GET_CODE (cmp))
2918 {
2919 case EQ:
2920 case NE:
2921 break;
2922 case LTU: cmp = gen_rtx_GTU (HImode, OP (2), OP (1)); break;
2923 case GTU: cmp = gen_rtx_LTU (HImode, OP (2), OP (1)); break;
2924 case LEU: cmp = gen_rtx_GEU (HImode, OP (2), OP (1)); break;
2925 case GEU: cmp = gen_rtx_LEU (HImode, OP (2), OP (1)); break;
2926
2927 case LT:
2928 case GT:
2929 case LE:
2930 case GE:
2931 #if DEBUG_ALLOC
2932 debug_rtx (insn);
2933 #endif
2934 default:
2935 gcc_unreachable ();
2936 }
2937
2938 if (GET_CODE (cmp) == EQ || GET_CODE (cmp) == NE)
2939 PATTERN (insn) = gen_cbranchhi4_real (cmp, OP (2), OP (1), OP (3));
2940 else
2941 PATTERN (insn) = gen_cbranchhi4_real_inverted (cmp, OP (2), OP (1), OP (3));
2942
2943 MUST_BE_OK (insn);
2944 }
2945
2946 /* Surprisingly, gcc can generate a comparison of a register with itself, but this
2947 should be handled by the second alternative of the cbranchhi_real pattern. */
2948 if (rtx_equal_p (OP (1), OP (2)))
2949 {
2950 OP (1) = OP (2) = BC;
2951 MUST_BE_OK (insn);
2952 }
2953
2954 tmp_id = get_max_insn_count ();
2955 saved_op1 = OP (1);
2956
2957 OP (1) = move_to_acc (1, insn);
2958
2959 MAYBE_OK (insn);
2960
2961 /* If we omitted the move of OP1 into the accumulator (because
2962 it was already there from a previous insn), then force the
2963 generation of the move instruction now. We know that we
2964 are about to emit a move into HL via AX, and hence our
2965 optimization to remove the load of OP1 is no longer valid. */
2966 if (tmp_id == get_max_insn_count ())
2967 force_into_acc (saved_op1, insn);
2968
2969 /* We have to copy op2 to HL, but that involves the acc, which
2970 already has a live value. Emit it before those insns. */
2971 if (prev)
2972 first = next_nonnote_nondebug_insn (prev);
2973 else
2974 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
2975 ;
2976 OP (2) = move_to_hl (2, first);
2977
2978 MUST_BE_OK (insn);
2979 }
2980
2981 /* Like op2, but AX = A * X. */
2982 static void
2983 rl78_alloc_physical_registers_umul (rtx_insn *insn)
2984 {
2985 rtx prev = prev_nonnote_nondebug_insn (insn);
2986 rtx first;
2987 int tmp_id;
2988 rtx saved_op1;
2989
2990 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
2991 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2992 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2993
2994 MAYBE_OK (insn);
2995
2996 if (recog_data.constraints[1][0] == '%'
2997 && is_virtual_register (OP (1))
2998 && !is_virtual_register (OP (2))
2999 && !CONSTANT_P (OP (2)))
3000 {
3001 rtx tmp = OP (1);
3002 OP (1) = OP (2);
3003 OP (2) = tmp;
3004 }
3005
3006 OP (0) = move_from_acc (0, insn);
3007
3008 tmp_id = get_max_insn_count ();
3009 saved_op1 = OP (1);
3010
3011 if (rtx_equal_p (OP (1), OP (2)))
3012 {
3013 gcc_assert (GET_MODE (OP (2)) == QImode);
3014 /* The MULU instruction does not support duplicate arguments
3015 but we know that if we copy OP (2) to X it will do so via
3016 A and thus OP (1) will already be loaded into A. */
3017 OP (2) = move_to_x (2, insn);
3018 OP (1) = A;
3019 }
3020 else
3021 OP (1) = move_to_acc (1, insn);
3022
3023 MAYBE_OK (insn);
3024
3025 /* If we omitted the move of OP1 into the accumulator (because
3026 it was already there from a previous insn), then force the
3027 generation of the move instruction now. We know that we
3028 are about to emit a move into HL (or DE) via AX, and hence
3029 our optimization to remove the load of OP1 is no longer valid. */
3030 if (tmp_id == get_max_insn_count ())
3031 force_into_acc (saved_op1, insn);
3032
3033 /* We have to copy op2 to X, but that involves the acc, which
3034 already has a live value. Emit it before those insns. */
3035
3036 if (prev)
3037 first = next_nonnote_nondebug_insn (prev);
3038 else
3039 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
3040 ;
3041 OP (2) = move_to_x (2, first);
3042
3043 MUST_BE_OK (insn);
3044 }
3045
3046 static void
3047 rl78_alloc_address_registers_macax (rtx_insn *insn)
3048 {
3049 int which, op;
3050 bool replace_in_op0 = false;
3051 bool replace_in_op1 = false;
3052
3053 MAYBE_OK (insn);
3054
3055 /* Two different MEMs are not allowed. */
3056 which = 0;
3057 for (op = 2; op >= 0; op --)
3058 {
3059 if (MEM_P (OP (op)))
3060 {
3061 if (op == 0 && replace_in_op0)
3062 continue;
3063 if (op == 1 && replace_in_op1)
3064 continue;
3065
3066 switch (which)
3067 {
3068 case 0:
3069 /* If we replace a MEM, make sure that we replace it for all
3070 occurrences of the same MEM in the insn. */
3071 replace_in_op0 = (op > 0 && rtx_equal_p (OP (op), OP (0)));
3072 replace_in_op1 = (op > 1 && rtx_equal_p (OP (op), OP (1)));
3073
3074 OP (op) = transcode_memory_rtx (OP (op), HL, insn);
3075 if (op == 2
3076 && MEM_P (OP (op))
3077 && ((GET_CODE (XEXP (OP (op), 0)) == REG
3078 && REGNO (XEXP (OP (op), 0)) == SP_REG)
3079 || (GET_CODE (XEXP (OP (op), 0)) == PLUS
3080 && REGNO (XEXP (XEXP (OP (op), 0), 0)) == SP_REG)))
3081 {
3082 emit_insn_before (gen_movhi (HL, gen_rtx_REG (HImode, SP_REG)), insn);
3083 OP (op) = replace_rtx (OP (op), gen_rtx_REG (HImode, SP_REG), HL);
3084 }
3085 if (replace_in_op0)
3086 OP (0) = OP (op);
3087 if (replace_in_op1)
3088 OP (1) = OP (op);
3089 break;
3090 case 1:
3091 OP (op) = transcode_memory_rtx (OP (op), DE, insn);
3092 break;
3093 case 2:
3094 OP (op) = transcode_memory_rtx (OP (op), BC, insn);
3095 break;
3096 }
3097 which ++;
3098 }
3099 }
3100
3101 MUST_BE_OK (insn);
3102 }
3103
3104 /* Scan all insns and devirtualize them. */
3105 static void
3106 rl78_alloc_physical_registers (void)
3107 {
3108 /* During most of the compile, gcc is dealing with virtual
3109 registers. At this point, we need to assign physical registers
3110 to the vitual ones, and copy in/out as needed. */
3111
3112 rtx_insn *insn, *curr;
3113 enum attr_valloc valloc_method;
3114
3115 for (insn = get_insns (); insn; insn = curr)
3116 {
3117 int i;
3118
3119 curr = next_nonnote_nondebug_insn (insn);
3120
3121 if (INSN_P (insn)
3122 && (GET_CODE (PATTERN (insn)) == SET
3123 || GET_CODE (PATTERN (insn)) == CALL)
3124 && INSN_CODE (insn) == -1)
3125 {
3126 if (GET_CODE (SET_SRC (PATTERN (insn))) == ASM_OPERANDS)
3127 continue;
3128 i = recog (PATTERN (insn), insn, 0);
3129 if (i == -1)
3130 {
3131 debug_rtx (insn);
3132 gcc_unreachable ();
3133 }
3134 INSN_CODE (insn) = i;
3135 }
3136 }
3137
3138 cfun->machine->virt_insns_ok = 0;
3139 cfun->machine->real_insns_ok = 1;
3140
3141 clear_content_memory ();
3142
3143 for (insn = get_insns (); insn; insn = curr)
3144 {
3145 rtx pattern;
3146
3147 curr = insn ? next_nonnote_nondebug_insn (insn) : NULL;
3148
3149 if (!INSN_P (insn))
3150 {
3151 if (LABEL_P (insn))
3152 clear_content_memory ();
3153
3154 continue;
3155 }
3156
3157 if (dump_file)
3158 fprintf (dump_file, "Converting insn %d\n", INSN_UID (insn));
3159
3160 pattern = PATTERN (insn);
3161 if (GET_CODE (pattern) == PARALLEL)
3162 pattern = XVECEXP (pattern, 0, 0);
3163 if (JUMP_P (insn) || CALL_P (insn) || GET_CODE (pattern) == CALL)
3164 clear_content_memory ();
3165 if (GET_CODE (pattern) != SET
3166 && GET_CODE (pattern) != CALL)
3167 continue;
3168 if (GET_CODE (pattern) == SET
3169 && GET_CODE (SET_SRC (pattern)) == ASM_OPERANDS)
3170 continue;
3171
3172 valloc_method = get_attr_valloc (insn);
3173
3174 PATTERN (insn) = copy_rtx_if_shared (PATTERN (insn));
3175
3176 if (valloc_method == VALLOC_MACAX)
3177 {
3178 record_content (AX, NULL_RTX);
3179 record_content (BC, NULL_RTX);
3180 record_content (DE, NULL_RTX);
3181 }
3182
3183 if (insn_ok_now (insn))
3184 continue;
3185
3186 INSN_CODE (insn) = -1;
3187
3188 if (RTX_FRAME_RELATED_P (insn))
3189 virt_insn_was_frame = 1;
3190 else
3191 virt_insn_was_frame = 0;
3192
3193 switch (valloc_method)
3194 {
3195 case VALLOC_OP1:
3196 rl78_alloc_physical_registers_op1 (insn);
3197 break;
3198 case VALLOC_OP2:
3199 rl78_alloc_physical_registers_op2 (insn);
3200 break;
3201 case VALLOC_RO1:
3202 rl78_alloc_physical_registers_ro1 (insn);
3203 break;
3204 case VALLOC_CMP:
3205 rl78_alloc_physical_registers_cmp (insn);
3206 break;
3207 case VALLOC_UMUL:
3208 rl78_alloc_physical_registers_umul (insn);
3209 break;
3210 case VALLOC_MACAX:
3211 /* Macro that clobbers AX. */
3212 rl78_alloc_address_registers_macax (insn);
3213 record_content (AX, NULL_RTX);
3214 record_content (BC, NULL_RTX);
3215 record_content (DE, NULL_RTX);
3216 break;
3217 }
3218
3219 if (JUMP_P (insn) || CALL_P (insn) || GET_CODE (pattern) == CALL)
3220 clear_content_memory ();
3221 else
3222 process_postponed_content_update ();
3223 }
3224
3225 #if DEBUG_ALLOC
3226 fprintf (stderr, "\033[0m");
3227 #endif
3228 }
3229
3230 /* Add REG_DEAD notes using DEAD[reg] for rtx S which is part of INSN.
3231 This function scans for uses of registers; the last use (i.e. first
3232 encounter when scanning backwards) triggers a REG_DEAD note if the
3233 reg was previously in DEAD[]. */
3234 static void
3235 rl78_note_reg_uses (char *dead, rtx s, rtx insn)
3236 {
3237 const char *fmt;
3238 int i, r;
3239 enum rtx_code code;
3240
3241 if (!s)
3242 return;
3243
3244 code = GET_CODE (s);
3245
3246 switch (code)
3247 {
3248 /* Compare registers by number. */
3249 case REG:
3250 r = REGNO (s);
3251 if (dump_file)
3252 {
3253 fprintf (dump_file, "note use reg %d size %d on insn %d\n",
3254 r, GET_MODE_SIZE (GET_MODE (s)), INSN_UID (insn));
3255 print_rtl_single (dump_file, s);
3256 }
3257 if (dead [r])
3258 add_reg_note (insn, REG_DEAD, gen_rtx_REG (GET_MODE (s), r));
3259 for (i = 0; i < GET_MODE_SIZE (GET_MODE (s)); i ++)
3260 dead [r + i] = 0;
3261 return;
3262
3263 /* These codes have no constituent expressions
3264 and are unique. */
3265 case SCRATCH:
3266 case CC0:
3267 case PC:
3268 return;
3269
3270 case CONST_INT:
3271 case CONST_VECTOR:
3272 case CONST_DOUBLE:
3273 case CONST_FIXED:
3274 /* These are kept unique for a given value. */
3275 return;
3276
3277 default:
3278 break;
3279 }
3280
3281 fmt = GET_RTX_FORMAT (code);
3282
3283 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
3284 {
3285 if (fmt[i] == 'E')
3286 {
3287 int j;
3288 for (j = XVECLEN (s, i) - 1; j >= 0; j--)
3289 rl78_note_reg_uses (dead, XVECEXP (s, i, j), insn);
3290 }
3291 else if (fmt[i] == 'e')
3292 rl78_note_reg_uses (dead, XEXP (s, i), insn);
3293 }
3294 }
3295
3296 /* Like the previous function, but scan for SETs instead. */
3297 static void
3298 rl78_note_reg_set (char *dead, rtx d, rtx insn)
3299 {
3300 int r, i;
3301
3302 if (GET_CODE (d) != REG)
3303 return;
3304
3305 r = REGNO (d);
3306 if (dead [r])
3307 add_reg_note (insn, REG_UNUSED, gen_rtx_REG (GET_MODE (d), r));
3308 if (dump_file)
3309 fprintf (dump_file, "note set reg %d size %d\n", r, GET_MODE_SIZE (GET_MODE (d)));
3310 for (i = 0; i < GET_MODE_SIZE (GET_MODE (d)); i ++)
3311 dead [r + i] = 1;
3312 }
3313
3314 /* This is a rather crude register death pass. Death status is reset
3315 at every jump or call insn. */
3316 static void
3317 rl78_calculate_death_notes (void)
3318 {
3319 char dead[FIRST_PSEUDO_REGISTER];
3320 rtx insn, p, s, d;
3321 int i;
3322
3323 memset (dead, 0, sizeof (dead));
3324
3325 for (insn = get_last_insn ();
3326 insn;
3327 insn = prev_nonnote_nondebug_insn (insn))
3328 {
3329 if (dump_file)
3330 {
3331 fprintf (dump_file, "\n--------------------------------------------------");
3332 fprintf (dump_file, "\nDead:");
3333 for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
3334 if (dead[i])
3335 fprintf (dump_file, " %s", reg_names[i]);
3336 fprintf (dump_file, "\n");
3337 print_rtl_single (dump_file, insn);
3338 }
3339
3340 switch (GET_CODE (insn))
3341 {
3342 case INSN:
3343 p = PATTERN (insn);
3344 switch (GET_CODE (p))
3345 {
3346 case SET:
3347 s = SET_SRC (p);
3348 d = SET_DEST (p);
3349 rl78_note_reg_set (dead, d, insn);
3350 rl78_note_reg_uses (dead, s, insn);
3351 break;
3352
3353 case USE:
3354 rl78_note_reg_uses (dead, p, insn);
3355 break;
3356
3357 default:
3358 break;
3359 }
3360 break;
3361
3362 case JUMP_INSN:
3363 if (INSN_CODE (insn) == CODE_FOR_rl78_return)
3364 {
3365 memset (dead, 1, sizeof (dead));
3366 /* We expect a USE just prior to this, which will mark
3367 the actual return registers. The USE will have a
3368 death note, but we aren't going to be modifying it
3369 after this pass. */
3370 break;
3371 }
3372 case CALL_INSN:
3373 memset (dead, 0, sizeof (dead));
3374 break;
3375
3376 default:
3377 break;
3378 }
3379 if (dump_file)
3380 print_rtl_single (dump_file, insn);
3381 }
3382 }
3383
3384 /* Helper function to reset the origins in RP and the age in AGE for
3385 all registers. */
3386 static void
3387 reset_origins (int *rp, int *age)
3388 {
3389 int i;
3390 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3391 {
3392 rp[i] = i;
3393 age[i] = 0;
3394 }
3395 }
3396
3397 /* The idea behind this optimization is to look for cases where we
3398 move data from A to B to C, and instead move from A to B, and A to
3399 C. If B is a virtual register or memory, this is a big win on its
3400 own. If B turns out to be unneeded after this, it's a bigger win.
3401 For each register, we try to determine where it's value originally
3402 came from, if it's propogated purely through moves (and not
3403 computes). The ORIGINS[] array has the regno for the "origin" of
3404 the value in the [regno] it's indexed by. */
3405 static void
3406 rl78_propogate_register_origins (void)
3407 {
3408 int origins[FIRST_PSEUDO_REGISTER];
3409 int age[FIRST_PSEUDO_REGISTER];
3410 int i;
3411 rtx_insn *insn, *ninsn = NULL;
3412 rtx pat;
3413
3414 reset_origins (origins, age);
3415
3416 for (insn = get_insns (); insn; insn = ninsn)
3417 {
3418 ninsn = next_nonnote_nondebug_insn (insn);
3419
3420 if (dump_file)
3421 {
3422 fprintf (dump_file, "\n");
3423 fprintf (dump_file, "Origins:");
3424 for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
3425 if (origins[i] != i)
3426 fprintf (dump_file, " r%d=r%d", i, origins[i]);
3427 fprintf (dump_file, "\n");
3428 print_rtl_single (dump_file, insn);
3429 }
3430
3431 switch (GET_CODE (insn))
3432 {
3433 case CODE_LABEL:
3434 case BARRIER:
3435 case CALL_INSN:
3436 case JUMP_INSN:
3437 reset_origins (origins, age);
3438 break;
3439
3440 default:
3441 break;
3442
3443 case INSN:
3444 pat = PATTERN (insn);
3445
3446 if (GET_CODE (pat) == PARALLEL)
3447 {
3448 rtx clobber = XVECEXP (pat, 0, 1);
3449 pat = XVECEXP (pat, 0, 0);
3450 if (GET_CODE (clobber) == CLOBBER
3451 && GET_CODE (XEXP (clobber, 0)) == REG)
3452 {
3453 int cr = REGNO (XEXP (clobber, 0));
3454 int mb = GET_MODE_SIZE (GET_MODE (XEXP (clobber, 0)));
3455 if (dump_file)
3456 fprintf (dump_file, "reset origins of %d regs at %d\n", mb, cr);
3457 for (i = 0; i < mb; i++)
3458 {
3459 origins[cr + i] = cr + i;
3460 age[cr + i] = 0;
3461 }
3462 }
3463 else
3464 break;
3465 }
3466
3467 if (GET_CODE (pat) == SET)
3468 {
3469 rtx src = SET_SRC (pat);
3470 rtx dest = SET_DEST (pat);
3471 int mb = GET_MODE_SIZE (GET_MODE (dest));
3472
3473 if (GET_CODE (dest) == REG)
3474 {
3475 int dr = REGNO (dest);
3476
3477 if (GET_CODE (src) == REG)
3478 {
3479 int sr = REGNO (src);
3480 int same = 1;
3481 int best_age, best_reg;
3482
3483 /* See if the copy is not needed. */
3484 for (i = 0; i < mb; i ++)
3485 if (origins[dr + i] != origins[sr + i])
3486 same = 0;
3487 if (same)
3488 {
3489 if (dump_file)
3490 fprintf (dump_file, "deleting because dest already has correct value\n");
3491 delete_insn (insn);
3492 break;
3493 }
3494
3495 if (dr < 8 || sr >= 8)
3496 {
3497 int ar;
3498
3499 best_age = -1;
3500 best_reg = -1;
3501 /* See if the copy can be made from another
3502 bank 0 register instead, instead of the
3503 virtual src register. */
3504 for (ar = 0; ar < 8; ar += mb)
3505 {
3506 same = 1;
3507 for (i = 0; i < mb; i ++)
3508 if (origins[ar + i] != origins[sr + i])
3509 same = 0;
3510
3511 /* The chip has some reg-reg move limitations. */
3512 if (mb == 1 && dr > 3)
3513 same = 0;
3514
3515 if (same)
3516 {
3517 if (best_age == -1 || best_age > age[sr + i])
3518 {
3519 best_age = age[sr + i];
3520 best_reg = sr;
3521 }
3522 }
3523 }
3524
3525 if (best_reg != -1)
3526 {
3527 /* FIXME: copy debug info too. */
3528 SET_SRC (pat) = gen_rtx_REG (GET_MODE (src), best_reg);
3529 sr = best_reg;
3530 }
3531 }
3532
3533 for (i = 0; i < mb; i++)
3534 {
3535 origins[dr + i] = origins[sr + i];
3536 age[dr + i] = age[sr + i] + 1;
3537 }
3538 }
3539 else
3540 {
3541 /* The destination is computed, its origin is itself. */
3542 if (dump_file)
3543 fprintf (dump_file, "resetting origin of r%d for %d byte%s\n",
3544 dr, mb, mb == 1 ? "" : "s");
3545 for (i = 0; i < mb; i ++)
3546 {
3547 origins[dr + i] = dr + i;
3548 age[dr + i] = 0;
3549 }
3550 }
3551
3552 /* Any registers marked with that reg as an origin are reset. */
3553 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3554 if (origins[i] >= dr && origins[i] < dr + mb)
3555 {
3556 origins[i] = i;
3557 age[i] = 0;
3558 }
3559 }
3560
3561 /* Special case - our ADDSI3 macro uses AX and sometimes BC. */
3562 if (get_attr_valloc (insn) == VALLOC_MACAX)
3563 {
3564 if (dump_file)
3565 fprintf (dump_file, "Resetting origin of AX/BC for macro.\n");
3566 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3567 if (i <= 3 || origins[i] <= 3)
3568 {
3569 origins[i] = i;
3570 age[i] = 0;
3571 }
3572 }
3573
3574 if (GET_CODE (src) == ASHIFT
3575 || GET_CODE (src) == ASHIFTRT
3576 || GET_CODE (src) == LSHIFTRT)
3577 {
3578 rtx count = XEXP (src, 1);
3579 if (GET_CODE (count) == REG)
3580 {
3581 /* Special case - our pattern clobbers the count register. */
3582 int r = REGNO (count);
3583 if (dump_file)
3584 fprintf (dump_file, "Resetting origin of r%d for shift.\n", r);
3585 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3586 if (i == r || origins[i] == r)
3587 {
3588 origins[i] = i;
3589 age[i] = 0;
3590 }
3591 }
3592 }
3593 }
3594 else if (GET_CODE (pat) == CLOBBER
3595 && GET_CODE (XEXP (pat, 0)) == REG)
3596 {
3597 if (REG_P (XEXP (pat, 0)))
3598 {
3599 unsigned int reg = REGNO (XEXP (pat, 0));
3600
3601 origins[reg] = reg;
3602 age[reg] = 0;
3603 }
3604 }
3605 }
3606 }
3607 }
3608
3609 /* Remove any SETs where the destination is unneeded. */
3610 static void
3611 rl78_remove_unused_sets (void)
3612 {
3613 rtx_insn *insn, *ninsn = NULL;
3614 rtx dest;
3615
3616 for (insn = get_insns (); insn; insn = ninsn)
3617 {
3618 ninsn = next_nonnote_nondebug_insn (insn);
3619
3620 rtx set = single_set (insn);
3621 if (set == NULL)
3622 continue;
3623
3624 dest = SET_DEST (set);
3625
3626 if (GET_CODE (dest) != REG || REGNO (dest) > 23)
3627 continue;
3628
3629 if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
3630 delete_insn (insn);
3631 }
3632 }
3633
3634 /* This is the top of the devritualization pass. */
3635 static void
3636 rl78_reorg (void)
3637 {
3638 /* split2 only happens when optimizing, but we need all movSIs to be
3639 split now. */
3640 if (optimize <= 0)
3641 split_all_insns ();
3642
3643 rl78_alloc_physical_registers ();
3644
3645 if (dump_file)
3646 {
3647 fprintf (dump_file, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n");
3648 print_rtl_with_bb (dump_file, get_insns (), 0);
3649 }
3650
3651 rl78_propogate_register_origins ();
3652 rl78_calculate_death_notes ();
3653
3654 if (dump_file)
3655 {
3656 fprintf (dump_file, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n");
3657 print_rtl_with_bb (dump_file, get_insns (), 0);
3658 fprintf (dump_file, "\n======================================================================\n");
3659 }
3660
3661 rl78_remove_unused_sets ();
3662
3663 /* The code after devirtualizing has changed so much that at this point
3664 we might as well just rescan everything. Note that
3665 df_rescan_all_insns is not going to help here because it does not
3666 touch the artificial uses and defs. */
3667 df_finish_pass (true);
3668 if (optimize > 1)
3669 df_live_add_problem ();
3670 df_scan_alloc (NULL);
3671 df_scan_blocks ();
3672
3673 if (optimize)
3674 df_analyze ();
3675 }
3676
3677 #undef TARGET_RETURN_IN_MEMORY
3678 #define TARGET_RETURN_IN_MEMORY rl78_return_in_memory
3679
3680 static bool
3681 rl78_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
3682 {
3683 const HOST_WIDE_INT size = int_size_in_bytes (type);
3684 return (size == -1 || size > 8);
3685 }
3686
3687 \f
3688 #undef TARGET_RTX_COSTS
3689 #define TARGET_RTX_COSTS rl78_rtx_costs
3690
3691 static bool rl78_rtx_costs (rtx x,
3692 int code,
3693 int outer_code ATTRIBUTE_UNUSED,
3694 int opno ATTRIBUTE_UNUSED,
3695 int * total,
3696 bool speed ATTRIBUTE_UNUSED)
3697 {
3698 if (code == IF_THEN_ELSE)
3699 return COSTS_N_INSNS (10);
3700 if (GET_MODE (x) == SImode)
3701 {
3702 switch (code)
3703 {
3704 case MULT:
3705 if (RL78_MUL_RL78)
3706 *total = COSTS_N_INSNS (14);
3707 else if (RL78_MUL_G13)
3708 *total = COSTS_N_INSNS (29);
3709 else
3710 *total = COSTS_N_INSNS (500);
3711 return true;
3712 case PLUS:
3713 *total = COSTS_N_INSNS (8);
3714 return true;
3715 case ASHIFT:
3716 case ASHIFTRT:
3717 case LSHIFTRT:
3718 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
3719 {
3720 switch (INTVAL (XEXP (x, 1)))
3721 {
3722 case 0: *total = COSTS_N_INSNS (0); break;
3723 case 1: *total = COSTS_N_INSNS (6); break;
3724 case 2: case 3: case 4: case 5: case 6: case 7:
3725 *total = COSTS_N_INSNS (10); break;
3726 case 8: *total = COSTS_N_INSNS (6); break;
3727 case 9: case 10: case 11: case 12: case 13: case 14: case 15:
3728 *total = COSTS_N_INSNS (10); break;
3729 case 16: *total = COSTS_N_INSNS (3); break;
3730 case 17: case 18: case 19: case 20: case 21: case 22: case 23:
3731 *total = COSTS_N_INSNS (4); break;
3732 case 24: *total = COSTS_N_INSNS (4); break;
3733 case 25: case 26: case 27: case 28: case 29: case 30: case 31:
3734 *total = COSTS_N_INSNS (5); break;
3735 }
3736 }
3737 else
3738 *total = COSTS_N_INSNS (10+4*16);
3739 return true;
3740 }
3741 }
3742 return false;
3743 }
3744 \f
3745
3746 #undef TARGET_UNWIND_WORD_MODE
3747 #define TARGET_UNWIND_WORD_MODE rl78_unwind_word_mode
3748
3749 static machine_mode
3750 rl78_unwind_word_mode (void)
3751 {
3752 return HImode;
3753 }
3754
3755 \f
3756 struct gcc_target targetm = TARGET_INITIALIZER;
3757
3758 #include "gt-rl78.h"