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