2018-01-12 Sebastian Perta <sebastian.perta@renesas.com>
[official-gcc.git] / gcc / config / rl78 / rl78.c
blob3e34a88f0b797173ee9d9562251e18c3c1df9167
1 /* Subroutines used for code generation on Renesas RL78 processors.
2 Copyright (C) 2011-2018 Free Software Foundation, Inc.
3 Contributed by Red Hat.
5 This file is part of GCC.
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.
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.
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/>. */
21 #define IN_TARGET_CODE 1
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "backend.h"
27 #include "target.h"
28 #include "rtl.h"
29 #include "tree.h"
30 #include "df.h"
31 #include "memmodel.h"
32 #include "tm_p.h"
33 #include "stringpool.h"
34 #include "attribs.h"
35 #include "optabs.h"
36 #include "emit-rtl.h"
37 #include "recog.h"
38 #include "diagnostic-core.h"
39 #include "varasm.h"
40 #include "stor-layout.h"
41 #include "calls.h"
42 #include "output.h"
43 #include "insn-attr.h"
44 #include "explow.h"
45 #include "expr.h"
46 #include "reload.h"
47 #include "cfgrtl.h"
48 #include "langhooks.h"
49 #include "tree-pass.h"
50 #include "context.h"
51 #include "tm-constrs.h" /* for satisfies_constraint_*(). */
52 #include "builtins.h"
54 /* This file should be included last. */
55 #include "target-def.h"
57 static inline bool is_interrupt_func (const_tree decl);
58 static inline bool is_brk_interrupt_func (const_tree decl);
59 static void rl78_reorg (void);
60 static const char *rl78_strip_name_encoding (const char *);
61 static const char *rl78_strip_nonasm_name_encoding (const char *);
62 static section * rl78_select_section (tree, int, unsigned HOST_WIDE_INT);
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
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[] =
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"
83 /* Structure for G13 MDUC registers. */
84 struct mduc_reg_type
86 unsigned int address;
87 enum machine_mode mode;
90 struct mduc_reg_type mduc_regs[] =
92 {0xf00e8, E_QImode},
93 {0xffff0, E_HImode},
94 {0xffff2, E_HImode},
95 {0xf2224, E_HImode},
96 {0xf00e0, E_HImode},
97 {0xf00e2, E_HImode}
100 struct GTY(()) machine_function
102 /* If set, the rest of the fields have been computed. */
103 int computed;
104 /* Which register pairs need to be pushed in the prologue. */
105 int need_to_push [FIRST_PSEUDO_REGISTER / 2];
107 /* These fields describe the frame layout... */
108 /* arg pointer */
109 /* 4 bytes for saved PC */
110 int framesize_regs;
111 /* frame pointer */
112 int framesize_locals;
113 int framesize_outgoing;
114 /* stack pointer */
115 int framesize;
117 /* If set, recog is allowed to match against the "real" patterns. */
118 int real_insns_ok;
119 /* If set, recog is allowed to match against the "virtual" patterns. */
120 int virt_insns_ok;
121 /* Set if the current function needs to clean up any trampolines. */
122 int trampolines_used;
123 /* True if the ES register is used and hence
124 needs to be saved inside interrupt handlers. */
125 bool uses_es;
128 /* This is our init_machine_status, as set in
129 rl78_option_override. */
130 static struct machine_function *
131 rl78_init_machine_status (void)
133 struct machine_function *m;
135 m = ggc_cleared_alloc<machine_function> ();
136 m->virt_insns_ok = 1;
138 return m;
141 /* This pass converts virtual instructions using virtual registers, to
142 real instructions using real registers. Rather than run it as
143 reorg, we reschedule it before vartrack to help with debugging. */
144 namespace
146 const pass_data pass_data_rl78_devirt =
148 RTL_PASS, /* type */
149 "devirt", /* name */
150 OPTGROUP_NONE, /* optinfo_flags */
151 TV_MACH_DEP, /* tv_id */
152 0, /* properties_required */
153 0, /* properties_provided */
154 0, /* properties_destroyed */
155 0, /* todo_flags_start */
156 0, /* todo_flags_finish */
159 class pass_rl78_devirt : public rtl_opt_pass
161 public:
162 pass_rl78_devirt (gcc::context *ctxt)
163 : rtl_opt_pass (pass_data_rl78_devirt, ctxt)
167 /* opt_pass methods: */
168 virtual unsigned int execute (function *)
170 rl78_reorg ();
171 return 0;
174 } // anon namespace
176 rtl_opt_pass *
177 make_pass_rl78_devirt (gcc::context *ctxt)
179 return new pass_rl78_devirt (ctxt);
182 /* Redundant move elimination pass. Must be run after the basic block
183 reordering pass for the best effect. */
185 static unsigned int
186 move_elim_pass (void)
188 rtx_insn *insn, *ninsn;
189 rtx prev = NULL_RTX;
191 for (insn = get_insns (); insn; insn = ninsn)
193 rtx set;
195 ninsn = next_nonnote_nondebug_insn (insn);
197 if ((set = single_set (insn)) == NULL_RTX)
199 prev = NULL_RTX;
200 continue;
203 /* If we have two SET insns in a row (without anything
204 between them) and the source of the second one is the
205 destination of the first one, and vice versa, then we
206 can eliminate the second SET. */
207 if (prev
208 && rtx_equal_p (SET_DEST (prev), SET_SRC (set))
209 && rtx_equal_p (SET_DEST (set), SET_SRC (prev))
210 /* ... and none of the operands are volatile. */
211 && ! volatile_refs_p (SET_SRC (prev))
212 && ! volatile_refs_p (SET_DEST (prev))
213 && ! volatile_refs_p (SET_SRC (set))
214 && ! volatile_refs_p (SET_DEST (set)))
216 if (dump_file)
217 fprintf (dump_file, " Delete insn %d because it is redundant\n",
218 INSN_UID (insn));
220 delete_insn (insn);
221 prev = NULL_RTX;
223 else
224 prev = set;
227 if (dump_file)
228 print_rtl_with_bb (dump_file, get_insns (), 0);
230 return 0;
233 namespace
235 const pass_data pass_data_rl78_move_elim =
237 RTL_PASS, /* type */
238 "move_elim", /* name */
239 OPTGROUP_NONE, /* optinfo_flags */
240 TV_MACH_DEP, /* tv_id */
241 0, /* properties_required */
242 0, /* properties_provided */
243 0, /* properties_destroyed */
244 0, /* todo_flags_start */
245 0, /* todo_flags_finish */
248 class pass_rl78_move_elim : public rtl_opt_pass
250 public:
251 pass_rl78_move_elim (gcc::context *ctxt)
252 : rtl_opt_pass (pass_data_rl78_move_elim, ctxt)
256 /* opt_pass methods: */
257 virtual unsigned int execute (function *) { return move_elim_pass (); }
259 } // anon namespace
261 rtl_opt_pass *
262 make_pass_rl78_move_elim (gcc::context *ctxt)
264 return new pass_rl78_move_elim (ctxt);
267 #undef TARGET_ASM_FILE_START
268 #define TARGET_ASM_FILE_START rl78_asm_file_start
270 static void
271 rl78_asm_file_start (void)
273 int i;
275 if (TARGET_G10)
277 /* The memory used is 0xffec8 to 0xffedf; real registers are in
278 0xffee0 to 0xffee7. */
279 for (i = 8; i < 32; i++)
280 fprintf (asm_out_file, "r%d\t=\t0x%x\n", i, 0xffec0 + i);
282 else
284 for (i = 0; i < 8; i++)
286 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 8 + i, 0xffef0 + i);
287 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 16 + i, 0xffee8 + i);
288 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 24 + i, 0xffee0 + i);
292 opt_pass *rl78_devirt_pass = make_pass_rl78_devirt (g);
293 struct register_pass_info rl78_devirt_info =
295 rl78_devirt_pass,
296 "pro_and_epilogue",
298 PASS_POS_INSERT_BEFORE
301 opt_pass *rl78_move_elim_pass = make_pass_rl78_move_elim (g);
302 struct register_pass_info rl78_move_elim_info =
304 rl78_move_elim_pass,
305 "bbro",
307 PASS_POS_INSERT_AFTER
310 register_pass (& rl78_devirt_info);
311 register_pass (& rl78_move_elim_info);
314 void
315 rl78_output_symbol_ref (FILE * file, rtx sym)
317 tree type = SYMBOL_REF_DECL (sym);
318 const char *str = XSTR (sym, 0);
320 if (str[0] == '*')
322 fputs (str + 1, file);
324 else
326 str = rl78_strip_nonasm_name_encoding (str);
327 if (type && TREE_CODE (type) == FUNCTION_DECL)
329 fprintf (file, "%%code(");
330 assemble_name (file, str);
331 fprintf (file, ")");
333 else
334 assemble_name (file, str);
338 #undef TARGET_OPTION_OVERRIDE
339 #define TARGET_OPTION_OVERRIDE rl78_option_override
341 #define MUST_SAVE_MDUC_REGISTERS \
342 (TARGET_SAVE_MDUC_REGISTERS \
343 && (is_interrupt_func (NULL_TREE)) && RL78_MUL_G13)
345 static void
346 rl78_option_override (void)
348 flag_omit_frame_pointer = 1;
349 flag_no_function_cse = 1;
350 flag_split_wide_types = 0;
352 init_machine_status = rl78_init_machine_status;
354 if (TARGET_ALLREGS)
356 int i;
358 for (i = 24; i < 32; i++)
359 fixed_regs[i] = 0;
362 if (TARGET_ES0
363 && strcmp (lang_hooks.name, "GNU C")
364 && strcmp (lang_hooks.name, "GNU C11")
365 && strcmp (lang_hooks.name, "GNU C17")
366 && strcmp (lang_hooks.name, "GNU C89")
367 && strcmp (lang_hooks.name, "GNU C99")
368 /* Compiling with -flto results in a language of GNU GIMPLE being used... */
369 && strcmp (lang_hooks.name, "GNU GIMPLE"))
370 /* Address spaces are currently only supported by C. */
371 error ("-mes0 can only be used with C");
373 if (TARGET_SAVE_MDUC_REGISTERS && !(TARGET_G13 || RL78_MUL_G13))
374 warning (0, "mduc registers only saved for G13 target");
376 switch (rl78_cpu_type)
378 case CPU_UNINIT:
379 rl78_cpu_type = CPU_G14;
380 if (rl78_mul_type == MUL_UNINIT)
381 rl78_mul_type = MUL_NONE;
382 break;
384 case CPU_G10:
385 switch (rl78_mul_type)
387 case MUL_UNINIT: rl78_mul_type = MUL_NONE; break;
388 case MUL_NONE: break;
389 case MUL_G13: error ("-mmul=g13 cannot be used with -mcpu=g10"); break;
390 case MUL_G14: error ("-mmul=g14 cannot be used with -mcpu=g10"); break;
392 break;
394 case CPU_G13:
395 switch (rl78_mul_type)
397 case MUL_UNINIT: rl78_mul_type = MUL_G13; break;
398 case MUL_NONE: break;
399 case MUL_G13: break;
400 /* The S2 core does not have mul/div instructions. */
401 case MUL_G14: error ("-mmul=g14 cannot be used with -mcpu=g13"); break;
403 break;
405 case CPU_G14:
406 switch (rl78_mul_type)
408 case MUL_UNINIT: rl78_mul_type = MUL_G14; break;
409 case MUL_NONE: break;
410 case MUL_G14: break;
411 /* The G14 core does not have the hardware multiply peripheral used by the
412 G13 core, hence you cannot use G13 multipliy routines on G14 hardware. */
413 case MUL_G13: error ("-mmul=g13 cannot be used with -mcpu=g14"); break;
415 break;
419 /* Most registers are 8 bits. Some are 16 bits because, for example,
420 gcc doesn't like dealing with $FP as a register pair (the second
421 half of $fp is also 2 to keep reload happy wrt register pairs, but
422 no register class includes it). This table maps register numbers
423 to size in bytes. */
424 static const int register_sizes[] =
426 1, 1, 1, 1, 1, 1, 1, 1,
427 1, 1, 1, 1, 1, 1, 1, 1,
428 1, 1, 1, 1, 1, 1, 2, 2,
429 1, 1, 1, 1, 1, 1, 1, 1,
430 2, 2, 1, 1, 1
433 /* Predicates used in the MD patterns. This one is true when virtual
434 insns may be matched, which typically means before (or during) the
435 devirt pass. */
436 bool
437 rl78_virt_insns_ok (void)
439 if (cfun)
440 return cfun->machine->virt_insns_ok;
441 return true;
444 /* Predicates used in the MD patterns. This one is true when real
445 insns may be matched, which typically means after (or during) the
446 devirt pass. */
447 bool
448 rl78_real_insns_ok (void)
450 if (cfun)
451 return cfun->machine->real_insns_ok;
452 return false;
455 #undef TARGET_HARD_REGNO_NREGS
456 #define TARGET_HARD_REGNO_NREGS rl78_hard_regno_nregs
458 static unsigned int
459 rl78_hard_regno_nregs (unsigned int regno, machine_mode mode)
461 int rs = register_sizes[regno];
462 if (rs < 1)
463 rs = 1;
464 return ((GET_MODE_SIZE (mode) + rs - 1) / rs);
467 #undef TARGET_HARD_REGNO_MODE_OK
468 #define TARGET_HARD_REGNO_MODE_OK rl78_hard_regno_mode_ok
470 static bool
471 rl78_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
473 int s = GET_MODE_SIZE (mode);
475 if (s < 1)
476 return false;
477 /* These are not to be used by gcc. */
478 if (regno == 23 || regno == ES_REG || regno == CS_REG)
479 return false;
480 /* $fp can always be accessed as a 16-bit value. */
481 if (regno == FP_REG && s == 2)
482 return true;
483 if (regno < SP_REG)
485 /* Since a reg-reg move is really a reg-mem move, we must
486 enforce alignment. */
487 if (s > 1 && (regno % 2))
488 return false;
489 return true;
491 if (s == CC_REGNUM)
492 return (mode == BImode);
493 /* All other registers must be accessed in their natural sizes. */
494 if (s == register_sizes [regno])
495 return true;
496 return false;
499 #undef TARGET_MODES_TIEABLE_P
500 #define TARGET_MODES_TIEABLE_P rl78_modes_tieable_p
502 static bool
503 rl78_modes_tieable_p (machine_mode mode1, machine_mode mode2)
505 return ((GET_MODE_CLASS (mode1) == MODE_FLOAT
506 || GET_MODE_CLASS (mode1) == MODE_COMPLEX_FLOAT)
507 == (GET_MODE_CLASS (mode2) == MODE_FLOAT
508 || GET_MODE_CLASS (mode2) == MODE_COMPLEX_FLOAT));
511 /* Simplify_gen_subreg() doesn't handle memory references the way we
512 need it to below, so we use this function for when we must get a
513 valid subreg in a "natural" state. */
514 static rtx
515 rl78_subreg (machine_mode mode, rtx r, machine_mode omode, int byte)
517 if (GET_CODE (r) == MEM)
518 return adjust_address (r, mode, byte);
519 else
520 return simplify_gen_subreg (mode, r, omode, byte);
523 /* Used by movsi. Split SImode moves into two HImode moves, using
524 appropriate patterns for the upper and lower halves of symbols. */
525 void
526 rl78_expand_movsi (rtx *operands)
528 rtx op00, op02, op10, op12;
530 op00 = rl78_subreg (HImode, operands[0], SImode, 0);
531 op02 = rl78_subreg (HImode, operands[0], SImode, 2);
532 if (GET_CODE (operands[1]) == CONST
533 || GET_CODE (operands[1]) == SYMBOL_REF)
535 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
536 op10 = gen_rtx_CONST (HImode, op10);
537 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
538 op12 = gen_rtx_CONST (HImode, op12);
540 else
542 op10 = rl78_subreg (HImode, operands[1], SImode, 0);
543 op12 = rl78_subreg (HImode, operands[1], SImode, 2);
546 if (rtx_equal_p (operands[0], operands[1]))
548 else if (rtx_equal_p (op00, op12))
550 emit_move_insn (op02, op12);
551 emit_move_insn (op00, op10);
553 else
555 emit_move_insn (op00, op10);
556 emit_move_insn (op02, op12);
560 /* Generate code to move an SImode value. */
561 void
562 rl78_split_movsi (rtx *operands, machine_mode omode)
564 rtx op00, op02, op10, op12;
566 op00 = rl78_subreg (HImode, operands[0], omode, 0);
567 op02 = rl78_subreg (HImode, operands[0], omode, 2);
569 if (GET_CODE (operands[1]) == CONST
570 || GET_CODE (operands[1]) == SYMBOL_REF)
572 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
573 op10 = gen_rtx_CONST (HImode, op10);
574 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
575 op12 = gen_rtx_CONST (HImode, op12);
577 else
579 op10 = rl78_subreg (HImode, operands[1], omode, 0);
580 op12 = rl78_subreg (HImode, operands[1], omode, 2);
583 if (rtx_equal_p (operands[0], operands[1]))
585 else if (rtx_equal_p (op00, op12))
587 operands[2] = op02;
588 operands[4] = op12;
589 operands[3] = op00;
590 operands[5] = op10;
592 else
594 operands[2] = op00;
595 operands[4] = op10;
596 operands[3] = op02;
597 operands[5] = op12;
601 /* Used by various two-operand expanders which cannot accept all
602 operands in the "far" namespace. Force some such operands into
603 registers so that each pattern has at most one far operand. */
605 rl78_force_nonfar_2 (rtx *operands, rtx (*gen)(rtx,rtx))
607 int did = 0;
608 rtx temp_reg = NULL;
610 /* FIXME: in the future, be smarter about only doing this if the
611 other operand is also far, assuming the devirtualizer can also
612 handle that. */
613 if (rl78_far_p (operands[0]))
615 temp_reg = operands[0];
616 operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
617 did = 1;
619 if (!did)
620 return 0;
622 emit_insn (gen (operands[0], operands[1]));
623 if (temp_reg)
624 emit_move_insn (temp_reg, operands[0]);
625 return 1;
628 /* Likewise, but for three-operand expanders. */
630 rl78_force_nonfar_3 (rtx *operands, rtx (*gen)(rtx,rtx,rtx))
632 int did = 0;
633 rtx temp_reg = NULL;
635 /* FIXME: Likewise. */
636 if (rl78_far_p (operands[1]))
638 rtx temp_reg = gen_reg_rtx (GET_MODE (operands[1]));
639 emit_move_insn (temp_reg, operands[1]);
640 operands[1] = temp_reg;
641 did = 1;
643 if (rl78_far_p (operands[0]))
645 temp_reg = operands[0];
646 operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
647 did = 1;
649 if (!did)
650 return 0;
652 emit_insn (gen (operands[0], operands[1], operands[2]));
653 if (temp_reg)
654 emit_move_insn (temp_reg, operands[0]);
655 return 1;
659 rl78_one_far_p (rtx *operands, int n)
661 rtx which = NULL;
662 int i, c = 0;
664 for (i = 0; i < n; i ++)
665 if (rl78_far_p (operands[i]))
667 if (which == NULL)
668 which = operands[i];
669 else if (rtx_equal_p (operands[i], which))
670 continue;
671 c ++;
673 return c <= 1;
676 #undef TARGET_CAN_ELIMINATE
677 #define TARGET_CAN_ELIMINATE rl78_can_eliminate
679 static bool
680 rl78_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to ATTRIBUTE_UNUSED)
682 return true;
685 /* Returns true if the given register needs to be saved by the
686 current function. */
687 static bool
688 need_to_save (unsigned int regno)
690 if (is_interrupt_func (cfun->decl))
692 /* We don't know what devirt will need */
693 if (regno < 8)
694 return true;
696 /* We don't need to save registers that have
697 been reserved for interrupt handlers. */
698 if (regno > 23)
699 return false;
701 /* If the handler is a non-leaf function then it may call
702 non-interrupt aware routines which will happily clobber
703 any call_used registers, so we have to preserve them.
704 We do not have to worry about the frame pointer register
705 though, as that is handled below. */
706 if (!crtl->is_leaf && call_used_regs[regno] && regno < 22)
707 return true;
709 /* Otherwise we only have to save a register, call_used
710 or not, if it is used by this handler. */
711 return df_regs_ever_live_p (regno);
714 if (regno == FRAME_POINTER_REGNUM
715 && (frame_pointer_needed || df_regs_ever_live_p (regno)))
716 return true;
717 if (fixed_regs[regno])
718 return false;
719 if (crtl->calls_eh_return)
720 return true;
721 if (df_regs_ever_live_p (regno)
722 && !call_used_regs[regno])
723 return true;
724 return false;
727 /* We use this to wrap all emitted insns in the prologue. */
728 static rtx
729 F (rtx x)
731 RTX_FRAME_RELATED_P (x) = 1;
732 return x;
735 /* Compute all the frame-related fields in our machine_function
736 structure. */
737 static void
738 rl78_compute_frame_info (void)
740 int i;
742 cfun->machine->computed = 1;
743 cfun->machine->framesize_regs = 0;
744 cfun->machine->framesize_locals = get_frame_size ();
745 cfun->machine->framesize_outgoing = crtl->outgoing_args_size;
747 for (i = 0; i < 16; i ++)
748 if (need_to_save (i * 2) || need_to_save (i * 2 + 1))
750 cfun->machine->need_to_push [i] = 1;
751 cfun->machine->framesize_regs += 2;
753 else
754 cfun->machine->need_to_push [i] = 0;
756 if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1)
757 cfun->machine->framesize_locals ++;
759 cfun->machine->framesize = (cfun->machine->framesize_regs
760 + cfun->machine->framesize_locals
761 + cfun->machine->framesize_outgoing);
764 /* Returns true if the provided function has the specified attribute. */
765 static inline bool
766 has_func_attr (const_tree decl, const char * func_attr)
768 if (decl == NULL_TREE)
769 decl = current_function_decl;
771 return lookup_attribute (func_attr, DECL_ATTRIBUTES (decl)) != NULL_TREE;
774 /* Returns true if the provided function has the "interrupt" attribute. */
775 static inline bool
776 is_interrupt_func (const_tree decl)
778 return has_func_attr (decl, "interrupt") || has_func_attr (decl, "brk_interrupt");
781 /* Returns true if the provided function has the "brk_interrupt" attribute. */
782 static inline bool
783 is_brk_interrupt_func (const_tree decl)
785 return has_func_attr (decl, "brk_interrupt");
788 /* Check "interrupt" attributes. */
789 static tree
790 rl78_handle_func_attribute (tree * node,
791 tree name,
792 tree args,
793 int flags ATTRIBUTE_UNUSED,
794 bool * no_add_attrs)
796 gcc_assert (DECL_P (* node));
797 gcc_assert (args == NULL_TREE);
799 if (TREE_CODE (* node) != FUNCTION_DECL)
801 warning (OPT_Wattributes, "%qE attribute only applies to functions",
802 name);
803 * no_add_attrs = true;
806 /* FIXME: We ought to check that the interrupt and exception
807 handler attributes have been applied to void functions. */
808 return NULL_TREE;
811 /* Check "naked" attributes. */
812 static tree
813 rl78_handle_naked_attribute (tree * node,
814 tree name ATTRIBUTE_UNUSED,
815 tree args,
816 int flags ATTRIBUTE_UNUSED,
817 bool * no_add_attrs)
819 gcc_assert (DECL_P (* node));
820 gcc_assert (args == NULL_TREE);
822 if (TREE_CODE (* node) != FUNCTION_DECL)
824 warning (OPT_Wattributes, "naked attribute only applies to functions");
825 * no_add_attrs = true;
828 /* Disable warnings about this function - eg reaching the end without
829 seeing a return statement - because the programmer is doing things
830 that gcc does not know about. */
831 TREE_NO_WARNING (* node) = 1;
833 return NULL_TREE;
836 /* Check "saddr" attributes. */
837 static tree
838 rl78_handle_saddr_attribute (tree * node,
839 tree name,
840 tree args ATTRIBUTE_UNUSED,
841 int flags ATTRIBUTE_UNUSED,
842 bool * no_add_attrs)
844 gcc_assert (DECL_P (* node));
846 if (TREE_CODE (* node) == FUNCTION_DECL)
848 warning (OPT_Wattributes, "%qE attribute doesn't apply to functions",
849 name);
850 * no_add_attrs = true;
853 return NULL_TREE;
856 #undef TARGET_ATTRIBUTE_TABLE
857 #define TARGET_ATTRIBUTE_TABLE rl78_attribute_table
859 /* Table of RL78-specific attributes. */
860 const struct attribute_spec rl78_attribute_table[] =
862 /* Name, min_len, max_len, decl_req, type_req, fn_type_req,
863 affects_type_identity, handler, exclude. */
864 { "interrupt", 0, 0, true, false, false, false,
865 rl78_handle_func_attribute, NULL },
866 { "brk_interrupt", 0, 0, true, false, false, false,
867 rl78_handle_func_attribute, NULL },
868 { "naked", 0, 0, true, false, false, false,
869 rl78_handle_naked_attribute, NULL },
870 { "saddr", 0, 0, true, false, false, false,
871 rl78_handle_saddr_attribute, NULL },
872 { NULL, 0, 0, false, false, false, false, NULL, NULL }
877 /* Break down an address RTX into its component base/index/addend
878 portions and return TRUE if the address is of a valid form, else
879 FALSE. */
880 static bool
881 characterize_address (rtx x, rtx *base, rtx *index, rtx *addend)
883 *base = NULL_RTX;
884 *index = NULL_RTX;
885 *addend = NULL_RTX;
887 if (GET_CODE (x) == UNSPEC
888 && XINT (x, 1) == UNS_ES_ADDR)
889 x = XVECEXP (x, 0, 1);
891 if (GET_CODE (x) == REG)
893 *base = x;
894 return true;
897 /* We sometimes get these without the CONST wrapper */
898 if (GET_CODE (x) == PLUS
899 && GET_CODE (XEXP (x, 0)) == SYMBOL_REF
900 && GET_CODE (XEXP (x, 1)) == CONST_INT)
902 *addend = x;
903 return true;
906 if (GET_CODE (x) == PLUS)
908 *base = XEXP (x, 0);
909 x = XEXP (x, 1);
911 if (GET_CODE (*base) == SUBREG)
913 if (GET_MODE (*base) == HImode
914 && GET_MODE (XEXP (*base, 0)) == SImode
915 && GET_CODE (XEXP (*base, 0)) == REG)
917 /* This is a throw-away rtx just to tell everyone
918 else what effective register we're using. */
919 *base = gen_rtx_REG (HImode, REGNO (XEXP (*base, 0)));
923 if (GET_CODE (*base) != REG
924 && GET_CODE (x) == REG)
926 rtx tmp = *base;
927 *base = x;
928 x = tmp;
931 if (GET_CODE (*base) != REG)
932 return false;
934 if (GET_CODE (x) == ZERO_EXTEND
935 && GET_CODE (XEXP (x, 0)) == REG)
937 *index = XEXP (x, 0);
938 return false;
942 switch (GET_CODE (x))
944 case PLUS:
945 if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
946 && GET_CODE (XEXP (x, 0)) == CONST_INT)
948 *addend = x;
949 return true;
951 /* fall through */
952 case MEM:
953 case REG:
954 return false;
956 case SUBREG:
957 switch (GET_CODE (XEXP (x, 0)))
959 case CONST:
960 case SYMBOL_REF:
961 case CONST_INT:
962 *addend = x;
963 return true;
964 default:
965 return false;
968 case CONST:
969 case SYMBOL_REF:
970 case CONST_INT:
971 *addend = x;
972 return true;
974 default:
975 return false;
978 return false;
981 /* Used by the Whb constraint. Match addresses that use HL+B or HL+C
982 addressing. */
983 bool
984 rl78_hl_b_c_addr_p (rtx op)
986 rtx hl, bc;
988 if (GET_CODE (op) != PLUS)
989 return false;
990 hl = XEXP (op, 0);
991 bc = XEXP (op, 1);
992 if (GET_CODE (hl) == ZERO_EXTEND)
994 rtx tmp = hl;
995 hl = bc;
996 bc = tmp;
998 if (GET_CODE (hl) != REG)
999 return false;
1000 if (GET_CODE (bc) != ZERO_EXTEND)
1001 return false;
1002 bc = XEXP (bc, 0);
1003 if (GET_CODE (bc) != REG)
1004 return false;
1005 if (REGNO (hl) != HL_REG)
1006 return false;
1007 if (REGNO (bc) != B_REG && REGNO (bc) != C_REG)
1008 return false;
1010 return true;
1013 #define REG_IS(r, regno) (((r) == (regno)) || ((r) >= FIRST_PSEUDO_REGISTER && !(strict)))
1015 /* Return the appropriate mode for a named address address. */
1017 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
1018 #define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode
1020 static scalar_int_mode
1021 rl78_addr_space_address_mode (addr_space_t addrspace)
1023 switch (addrspace)
1025 case ADDR_SPACE_GENERIC:
1026 return HImode;
1027 case ADDR_SPACE_NEAR:
1028 return HImode;
1029 case ADDR_SPACE_FAR:
1030 return SImode;
1031 default:
1032 gcc_unreachable ();
1036 /* Used in various constraints and predicates to match operands in the
1037 "far" address space. */
1039 rl78_far_p (rtx x)
1041 if (! MEM_P (x))
1042 return 0;
1043 #if DEBUG0
1044 fprintf (stderr, "\033[35mrl78_far_p: "); debug_rtx (x);
1045 fprintf (stderr, " = %d\033[0m\n", MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR);
1046 #endif
1048 /* Not all far addresses are legitimate, because the devirtualizer
1049 can't handle them. */
1050 if (! rl78_as_legitimate_address (GET_MODE (x), XEXP (x, 0), false, ADDR_SPACE_FAR))
1051 return 0;
1053 return GET_MODE_BITSIZE (rl78_addr_space_address_mode (MEM_ADDR_SPACE (x))) == 32;
1056 /* Return the appropriate mode for a named address pointer. */
1057 #undef TARGET_ADDR_SPACE_POINTER_MODE
1058 #define TARGET_ADDR_SPACE_POINTER_MODE rl78_addr_space_pointer_mode
1060 static scalar_int_mode
1061 rl78_addr_space_pointer_mode (addr_space_t addrspace)
1063 switch (addrspace)
1065 case ADDR_SPACE_GENERIC:
1066 return HImode;
1067 case ADDR_SPACE_NEAR:
1068 return HImode;
1069 case ADDR_SPACE_FAR:
1070 return SImode;
1071 default:
1072 gcc_unreachable ();
1076 /* Returns TRUE for valid addresses. */
1077 #undef TARGET_VALID_POINTER_MODE
1078 #define TARGET_VALID_POINTER_MODE rl78_valid_pointer_mode
1080 static bool
1081 rl78_valid_pointer_mode (scalar_int_mode m)
1083 return (m == HImode || m == SImode);
1086 #undef TARGET_LEGITIMATE_CONSTANT_P
1087 #define TARGET_LEGITIMATE_CONSTANT_P rl78_is_legitimate_constant
1089 static bool
1090 rl78_is_legitimate_constant (machine_mode mode ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED)
1092 return true;
1095 #undef TARGET_LRA_P
1096 #define TARGET_LRA_P hook_bool_void_false
1098 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
1099 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P rl78_as_legitimate_address
1101 bool
1102 rl78_as_legitimate_address (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
1103 bool strict ATTRIBUTE_UNUSED, addr_space_t as ATTRIBUTE_UNUSED)
1105 rtx base, index, addend;
1106 bool is_far_addr = false;
1107 int as_bits;
1109 as_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (as));
1111 if (GET_CODE (x) == UNSPEC
1112 && XINT (x, 1) == UNS_ES_ADDR)
1114 x = XVECEXP (x, 0, 1);
1115 is_far_addr = true;
1118 if (as_bits == 16 && is_far_addr)
1119 return false;
1121 if (! characterize_address (x, &base, &index, &addend))
1122 return false;
1124 /* We can't extract the high/low portions of a PLUS address
1125 involving a register during devirtualization, so make sure all
1126 such __far addresses do not have addends. This forces GCC to do
1127 the sum separately. */
1128 if (addend && base && as_bits == 32 && GET_MODE (base) == SImode)
1129 return false;
1131 if (base && index)
1133 int ir = REGNO (index);
1134 int br = REGNO (base);
1136 #define OK(test, debug) if (test) { /*fprintf(stderr, "%d: OK %s\n", __LINE__, debug);*/ return true; }
1137 OK (REG_IS (br, HL_REG) && REG_IS (ir, B_REG), "[hl+b]");
1138 OK (REG_IS (br, HL_REG) && REG_IS (ir, C_REG), "[hl+c]");
1139 return false;
1142 if (strict && base && GET_CODE (base) == REG && REGNO (base) >= FIRST_PSEUDO_REGISTER)
1143 return false;
1145 if (! cfun->machine->virt_insns_ok && base && GET_CODE (base) == REG
1146 && REGNO (base) >= 8 && REGNO (base) <= 31)
1147 return false;
1149 return true;
1152 /* Determine if one named address space is a subset of another. */
1153 #undef TARGET_ADDR_SPACE_SUBSET_P
1154 #define TARGET_ADDR_SPACE_SUBSET_P rl78_addr_space_subset_p
1156 static bool
1157 rl78_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
1159 int subset_bits;
1160 int superset_bits;
1162 subset_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (subset));
1163 superset_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (superset));
1165 return (subset_bits <= superset_bits);
1168 #undef TARGET_ADDR_SPACE_CONVERT
1169 #define TARGET_ADDR_SPACE_CONVERT rl78_addr_space_convert
1171 /* Convert from one address space to another. */
1172 static rtx
1173 rl78_addr_space_convert (rtx op, tree from_type, tree to_type)
1175 addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
1176 addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
1177 rtx result;
1178 int to_bits;
1179 int from_bits;
1181 to_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (to_as));
1182 from_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (from_as));
1184 if (to_bits < from_bits)
1186 rtx tmp;
1187 /* This is unpredictable, as we're truncating off usable address
1188 bits. */
1190 warning (OPT_Waddress, "converting far pointer to near pointer");
1191 result = gen_reg_rtx (HImode);
1192 if (GET_CODE (op) == SYMBOL_REF
1193 || (GET_CODE (op) == REG && REGNO (op) >= FIRST_PSEUDO_REGISTER))
1194 tmp = gen_rtx_raw_SUBREG (HImode, op, 0);
1195 else
1196 tmp = simplify_subreg (HImode, op, SImode, 0);
1197 gcc_assert (tmp != NULL_RTX);
1198 emit_move_insn (result, tmp);
1199 return result;
1201 else if (to_bits > from_bits)
1203 /* This always works. */
1204 result = gen_reg_rtx (SImode);
1205 emit_move_insn (rl78_subreg (HImode, result, SImode, 0), op);
1206 if (TREE_CODE (from_type) == POINTER_TYPE
1207 && TREE_CODE (TREE_TYPE (from_type)) == FUNCTION_TYPE)
1208 emit_move_insn (rl78_subreg (HImode, result, SImode, 2), const0_rtx);
1209 else
1210 emit_move_insn (rl78_subreg (HImode, result, SImode, 2), GEN_INT (0x0f));
1211 return result;
1213 else
1214 return op;
1215 gcc_unreachable ();
1218 /* Implements REGNO_MODE_CODE_OK_FOR_BASE_P. */
1219 bool
1220 rl78_regno_mode_code_ok_for_base_p (int regno, machine_mode mode ATTRIBUTE_UNUSED,
1221 addr_space_t address_space ATTRIBUTE_UNUSED,
1222 int outer_code ATTRIBUTE_UNUSED, int index_code)
1224 if (regno <= SP_REG && regno >= 16)
1225 return true;
1226 if (index_code == REG)
1227 return (regno == HL_REG);
1228 if (regno == C_REG || regno == B_REG || regno == E_REG || regno == L_REG)
1229 return true;
1230 return false;
1233 /* Implements MODE_CODE_BASE_REG_CLASS. */
1234 enum reg_class
1235 rl78_mode_code_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED,
1236 addr_space_t address_space ATTRIBUTE_UNUSED,
1237 int outer_code ATTRIBUTE_UNUSED,
1238 int index_code ATTRIBUTE_UNUSED)
1240 return V_REGS;
1243 /* Typical stack layout should looks like this after the function's prologue:
1246 -- ^
1247 | | \ |
1248 | | arguments saved | Increasing
1249 | | on the stack | addresses
1250 PARENT arg pointer -> | | /
1251 -------------------------- ---- -------------------
1252 CHILD |ret | return address
1254 | | \
1255 | | call saved
1256 | | registers
1257 frame pointer -> | | /
1259 | | \
1260 | | local
1261 | | variables
1262 | | /
1264 | | \
1265 | | outgoing | Decreasing
1266 | | arguments | addresses
1267 current stack pointer -> | | / |
1268 -------------------------- ---- ------------------ V
1269 | | */
1271 /* Implements INITIAL_ELIMINATION_OFFSET. The frame layout is
1272 described in the machine_Function struct definition, above. */
1274 rl78_initial_elimination_offset (int from, int to)
1276 int rv = 0; /* as if arg to arg */
1278 rl78_compute_frame_info ();
1280 switch (to)
1282 case STACK_POINTER_REGNUM:
1283 rv += cfun->machine->framesize_outgoing;
1284 rv += cfun->machine->framesize_locals;
1285 /* Fall through. */
1286 case FRAME_POINTER_REGNUM:
1287 rv += cfun->machine->framesize_regs;
1288 rv += 4;
1289 break;
1290 default:
1291 gcc_unreachable ();
1294 switch (from)
1296 case FRAME_POINTER_REGNUM:
1297 rv -= 4;
1298 rv -= cfun->machine->framesize_regs;
1299 case ARG_POINTER_REGNUM:
1300 break;
1301 default:
1302 gcc_unreachable ();
1305 return rv;
1308 static bool
1309 rl78_is_naked_func (void)
1311 return (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE);
1314 /* Check if the block uses mul/div insns for G13 target. */
1316 static bool
1317 check_mduc_usage (void)
1319 rtx_insn * insn;
1320 basic_block bb;
1322 FOR_EACH_BB_FN (bb, cfun)
1324 FOR_BB_INSNS (bb, insn)
1326 if (INSN_P (insn)
1327 && (get_attr_is_g13_muldiv_insn (insn) == IS_G13_MULDIV_INSN_YES))
1328 return true;
1331 return false;
1334 /* Expand the function prologue (from the prologue pattern). */
1336 void
1337 rl78_expand_prologue (void)
1339 int i, fs;
1340 rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
1341 rtx ax = gen_rtx_REG (HImode, AX_REG);
1342 int rb = 0;
1344 if (rl78_is_naked_func ())
1345 return;
1347 /* Always re-compute the frame info - the register usage may have changed. */
1348 rl78_compute_frame_info ();
1350 if (MUST_SAVE_MDUC_REGISTERS && (!crtl->is_leaf || check_mduc_usage ()))
1351 cfun->machine->framesize += ARRAY_SIZE (mduc_regs) * 2;
1353 if (flag_stack_usage_info)
1354 current_function_static_stack_size = cfun->machine->framesize;
1356 if (is_interrupt_func (cfun->decl) && !TARGET_G10)
1357 for (i = 0; i < 4; i++)
1358 if (cfun->machine->need_to_push [i])
1360 /* Select Bank 0 if we are using any registers from Bank 0. */
1361 emit_insn (gen_sel_rb (GEN_INT (0)));
1362 break;
1365 for (i = 0; i < 16; i++)
1366 if (cfun->machine->need_to_push [i])
1368 int reg = i * 2;
1370 if (TARGET_G10)
1372 if (reg >= 8)
1374 emit_move_insn (ax, gen_rtx_REG (HImode, reg));
1375 reg = AX_REG;
1378 else
1380 int need_bank = i/4;
1382 if (need_bank != rb)
1384 emit_insn (gen_sel_rb (GEN_INT (need_bank)));
1385 rb = need_bank;
1389 F (emit_insn (gen_push (gen_rtx_REG (HImode, reg))));
1392 if (rb != 0)
1393 emit_insn (gen_sel_rb (GEN_INT (0)));
1395 /* Save ES register inside interrupt functions if it is used. */
1396 if (is_interrupt_func (cfun->decl) && cfun->machine->uses_es)
1398 emit_insn (gen_movqi_from_es (gen_rtx_REG (QImode, A_REG)));
1399 F (emit_insn (gen_push (ax)));
1402 /* Save MDUC registers inside interrupt routine. */
1403 if (MUST_SAVE_MDUC_REGISTERS && (!crtl->is_leaf || check_mduc_usage ()))
1405 for (unsigned i = 0; i < ARRAY_SIZE (mduc_regs); i++)
1407 mduc_reg_type *reg = mduc_regs + i;
1408 rtx mem_mduc = gen_rtx_MEM (reg->mode, GEN_INT (reg->address));
1410 MEM_VOLATILE_P (mem_mduc) = 1;
1411 if (reg->mode == QImode)
1412 emit_insn (gen_movqi (gen_rtx_REG (QImode, A_REG), mem_mduc));
1413 else
1414 emit_insn (gen_movhi (gen_rtx_REG (HImode, AX_REG), mem_mduc));
1416 emit_insn (gen_push (gen_rtx_REG (HImode, AX_REG)));
1420 if (frame_pointer_needed)
1422 F (emit_move_insn (ax, sp));
1423 F (emit_move_insn (gen_rtx_REG (HImode, FRAME_POINTER_REGNUM), ax));
1426 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1427 if (fs > 0)
1429 /* If we need to subtract more than 254*3 then it is faster and
1430 smaller to move SP into AX and perform the subtraction there. */
1431 if (fs > 254 * 3)
1433 rtx insn;
1435 emit_move_insn (ax, sp);
1436 emit_insn (gen_subhi3 (ax, ax, GEN_INT (fs)));
1437 insn = F (emit_move_insn (sp, ax));
1438 add_reg_note (insn, REG_FRAME_RELATED_EXPR,
1439 gen_rtx_SET (sp, gen_rtx_PLUS (HImode, sp,
1440 GEN_INT (-fs))));
1442 else
1444 while (fs > 0)
1446 int fs_byte = (fs > 254) ? 254 : fs;
1448 F (emit_insn (gen_subhi3 (sp, sp, GEN_INT (fs_byte))));
1449 fs -= fs_byte;
1455 /* Expand the function epilogue (from the epilogue pattern). */
1456 void
1457 rl78_expand_epilogue (void)
1459 int i, fs;
1460 rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
1461 rtx ax = gen_rtx_REG (HImode, AX_REG);
1462 int rb = 0;
1464 if (rl78_is_naked_func ())
1465 return;
1467 if (frame_pointer_needed)
1469 emit_move_insn (ax, gen_rtx_REG (HImode, FRAME_POINTER_REGNUM));
1470 emit_move_insn (sp, ax);
1472 else
1474 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1475 if (fs > 254 * 3)
1477 emit_move_insn (ax, sp);
1478 emit_insn (gen_addhi3 (ax, ax, GEN_INT (fs)));
1479 emit_move_insn (sp, ax);
1481 else
1483 while (fs > 0)
1485 int fs_byte = (fs > 254) ? 254 : fs;
1487 emit_insn (gen_addhi3 (sp, sp, GEN_INT (fs_byte)));
1488 fs -= fs_byte;
1493 /* Restore MDUC registers from interrupt routine. */
1494 if (MUST_SAVE_MDUC_REGISTERS && (!crtl->is_leaf || check_mduc_usage ()))
1496 for (int i = ARRAY_SIZE (mduc_regs) - 1; i >= 0; i--)
1498 mduc_reg_type *reg = mduc_regs + i;
1499 rtx mem_mduc = gen_rtx_MEM (reg->mode, GEN_INT (reg->address));
1501 emit_insn (gen_pop (gen_rtx_REG (HImode, AX_REG)));
1502 MEM_VOLATILE_P (mem_mduc) = 1;
1503 if (reg->mode == QImode)
1504 emit_insn (gen_movqi (mem_mduc, gen_rtx_REG (QImode, A_REG)));
1505 else
1506 emit_insn (gen_movhi (mem_mduc, gen_rtx_REG (HImode, AX_REG)));
1510 if (is_interrupt_func (cfun->decl) && cfun->machine->uses_es)
1512 emit_insn (gen_pop (gen_rtx_REG (HImode, AX_REG)));
1513 emit_insn (gen_movqi_to_es (gen_rtx_REG (QImode, A_REG)));
1516 for (i = 15; i >= 0; i--)
1517 if (cfun->machine->need_to_push [i])
1519 rtx dest = gen_rtx_REG (HImode, i * 2);
1521 if (TARGET_G10)
1523 if (i < 8)
1524 emit_insn (gen_pop (dest));
1525 else
1527 emit_insn (gen_pop (ax));
1528 emit_move_insn (dest, ax);
1529 /* Generate a USE of the pop'd register so that DCE will not eliminate the move. */
1530 emit_insn (gen_use (dest));
1533 else
1535 int need_bank = i / 4;
1537 if (need_bank != rb)
1539 emit_insn (gen_sel_rb (GEN_INT (need_bank)));
1540 rb = need_bank;
1542 emit_insn (gen_pop (dest));
1546 if (rb != 0)
1547 emit_insn (gen_sel_rb (GEN_INT (0)));
1549 if (cfun->machine->trampolines_used)
1550 emit_insn (gen_trampoline_uninit ());
1552 if (is_brk_interrupt_func (cfun->decl))
1553 emit_jump_insn (gen_brk_interrupt_return ());
1554 else if (is_interrupt_func (cfun->decl))
1555 emit_jump_insn (gen_interrupt_return ());
1556 else
1557 emit_jump_insn (gen_rl78_return ());
1560 /* Likewise, for exception handlers. */
1561 void
1562 rl78_expand_eh_epilogue (rtx x ATTRIBUTE_UNUSED)
1564 /* FIXME - replace this with an indirect jump with stack adjust. */
1565 emit_jump_insn (gen_rl78_return ());
1568 #undef TARGET_ASM_FUNCTION_PROLOGUE
1569 #define TARGET_ASM_FUNCTION_PROLOGUE rl78_start_function
1571 /* We don't use this to actually emit the function prologue. We use
1572 this to insert a comment in the asm file describing the
1573 function. */
1574 static void
1575 rl78_start_function (FILE *file)
1577 int i;
1579 if (cfun->machine->framesize == 0)
1580 return;
1581 fprintf (file, "\t; start of function\n");
1583 if (cfun->machine->framesize_regs)
1585 fprintf (file, "\t; push %d:", cfun->machine->framesize_regs);
1586 for (i = 0; i < 16; i ++)
1587 if (cfun->machine->need_to_push[i])
1588 fprintf (file, " %s", word_regnames[i*2]);
1589 fprintf (file, "\n");
1592 if (frame_pointer_needed)
1593 fprintf (file, "\t; $fp points here (r22)\n");
1595 if (cfun->machine->framesize_locals)
1596 fprintf (file, "\t; locals: %d byte%s\n", cfun->machine->framesize_locals,
1597 cfun->machine->framesize_locals == 1 ? "" : "s");
1599 if (cfun->machine->framesize_outgoing)
1600 fprintf (file, "\t; outgoing: %d byte%s\n", cfun->machine->framesize_outgoing,
1601 cfun->machine->framesize_outgoing == 1 ? "" : "s");
1603 if (cfun->machine->uses_es)
1604 fprintf (file, "\t; uses ES register\n");
1606 if (MUST_SAVE_MDUC_REGISTERS)
1607 fprintf (file, "\t; preserves MDUC registers\n");
1610 /* Return an RTL describing where a function return value of type RET_TYPE
1611 is held. */
1613 #undef TARGET_FUNCTION_VALUE
1614 #define TARGET_FUNCTION_VALUE rl78_function_value
1616 static rtx
1617 rl78_function_value (const_tree ret_type,
1618 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
1619 bool outgoing ATTRIBUTE_UNUSED)
1621 machine_mode mode = TYPE_MODE (ret_type);
1623 return gen_rtx_REG (mode, 8);
1626 #undef TARGET_PROMOTE_FUNCTION_MODE
1627 #define TARGET_PROMOTE_FUNCTION_MODE rl78_promote_function_mode
1629 static machine_mode
1630 rl78_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
1631 machine_mode mode,
1632 int *punsignedp ATTRIBUTE_UNUSED,
1633 const_tree funtype ATTRIBUTE_UNUSED, int for_return ATTRIBUTE_UNUSED)
1635 return mode;
1638 /* Return an RTL expression describing the register holding a function
1639 parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
1640 be passed on the stack. CUM describes the previous parameters to the
1641 function and NAMED is false if the parameter is part of a variable
1642 parameter list, or the last named parameter before the start of a
1643 variable parameter list. */
1645 #undef TARGET_FUNCTION_ARG
1646 #define TARGET_FUNCTION_ARG rl78_function_arg
1648 static rtx
1649 rl78_function_arg (cumulative_args_t cum_v ATTRIBUTE_UNUSED,
1650 machine_mode mode ATTRIBUTE_UNUSED,
1651 const_tree type ATTRIBUTE_UNUSED,
1652 bool named ATTRIBUTE_UNUSED)
1654 return NULL_RTX;
1657 #undef TARGET_FUNCTION_ARG_ADVANCE
1658 #define TARGET_FUNCTION_ARG_ADVANCE rl78_function_arg_advance
1660 static void
1661 rl78_function_arg_advance (cumulative_args_t cum_v, machine_mode mode, const_tree type,
1662 bool named ATTRIBUTE_UNUSED)
1664 int rounded_size;
1665 CUMULATIVE_ARGS * cum = get_cumulative_args (cum_v);
1667 rounded_size = ((mode == BLKmode)
1668 ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
1669 if (rounded_size & 1)
1670 rounded_size ++;
1671 (*cum) += rounded_size;
1674 #undef TARGET_FUNCTION_ARG_BOUNDARY
1675 #define TARGET_FUNCTION_ARG_BOUNDARY rl78_function_arg_boundary
1677 static unsigned int
1678 rl78_function_arg_boundary (machine_mode mode ATTRIBUTE_UNUSED,
1679 const_tree type ATTRIBUTE_UNUSED)
1681 return 16;
1684 /* Supported modifier letters:
1686 A - address of a MEM
1687 S - SADDR form of a real register
1688 v - real register corresponding to a virtual register
1689 m - minus - negative of CONST_INT value.
1690 C - inverse of a conditional (NE vs EQ for example)
1691 C - complement of an integer
1692 z - collapsed conditional
1693 s - shift count mod 8
1694 S - shift count mod 16
1695 r - reverse shift count (8-(count mod 8))
1696 B - bit position
1698 h - bottom HI of an SI
1699 H - top HI of an SI
1700 q - bottom QI of an HI
1701 Q - top QI of an HI
1702 e - third QI of an SI (i.e. where the ES register gets values from)
1703 E - fourth QI of an SI (i.e. MSB)
1705 p - Add +0 to a zero-indexed HL based address.
1708 /* Implements the bulk of rl78_print_operand, below. We do it this
1709 way because we need to test for a constant at the top level and
1710 insert the '#', but not test for it anywhere else as we recurse
1711 down into the operand. */
1712 static void
1713 rl78_print_operand_1 (FILE * file, rtx op, int letter)
1715 int need_paren;
1717 switch (GET_CODE (op))
1719 case MEM:
1720 if (letter == 'A')
1721 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1722 else
1724 if (rl78_far_p (op))
1726 fprintf (file, "es:");
1727 if (GET_CODE (XEXP (op, 0)) == UNSPEC)
1728 op = gen_rtx_MEM (GET_MODE (op), XVECEXP (XEXP (op, 0), 0, 1));
1730 if (letter == 'H')
1732 op = adjust_address (op, HImode, 2);
1733 letter = 0;
1735 if (letter == 'h')
1737 op = adjust_address (op, HImode, 0);
1738 letter = 0;
1740 if (letter == 'Q')
1742 op = adjust_address (op, QImode, 1);
1743 letter = 0;
1745 if (letter == 'q')
1747 op = adjust_address (op, QImode, 0);
1748 letter = 0;
1750 if (letter == 'e')
1752 op = adjust_address (op, QImode, 2);
1753 letter = 0;
1755 if (letter == 'E')
1757 op = adjust_address (op, QImode, 3);
1758 letter = 0;
1760 if (CONSTANT_P (XEXP (op, 0)))
1762 if (!rl78_saddr_p (op))
1763 fprintf (file, "!");
1764 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1766 else if (GET_CODE (XEXP (op, 0)) == PLUS
1767 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF)
1769 if (!rl78_saddr_p (op))
1770 fprintf (file, "!");
1771 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1773 else if (GET_CODE (XEXP (op, 0)) == PLUS
1774 && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
1775 && REGNO (XEXP (XEXP (op, 0), 0)) == 2)
1777 rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 1), 'u');
1778 fprintf (file, "[");
1779 rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 0), 0);
1780 if (letter == 'p' && GET_CODE (XEXP (op, 0)) == REG)
1781 fprintf (file, "+0");
1782 fprintf (file, "]");
1784 else
1786 op = XEXP (op, 0);
1787 fprintf (file, "[");
1788 rl78_print_operand_1 (file, op, letter);
1789 if (letter == 'p' && REG_P (op) && REGNO (op) == 6)
1790 fprintf (file, "+0");
1791 fprintf (file, "]");
1794 break;
1796 case REG:
1797 if (letter == 'Q')
1798 fprintf (file, "%s", reg_names [REGNO (op) | 1]);
1799 else if (letter == 'H')
1800 fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1801 else if (letter == 'q')
1802 fprintf (file, "%s", reg_names [REGNO (op) & ~1]);
1803 else if (letter == 'e')
1804 fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1805 else if (letter == 'E')
1806 fprintf (file, "%s", reg_names [REGNO (op) + 3]);
1807 else if (letter == 'S')
1808 fprintf (file, "0x%x", 0xffef8 + REGNO (op));
1809 else if (GET_MODE (op) == HImode
1810 && ! (REGNO (op) & ~0xfe))
1812 if (letter == 'v')
1813 fprintf (file, "%s", word_regnames [REGNO (op) % 8]);
1814 else
1815 fprintf (file, "%s", word_regnames [REGNO (op)]);
1817 else
1818 fprintf (file, "%s", reg_names [REGNO (op)]);
1819 break;
1821 case CONST_INT:
1822 if (letter == 'Q')
1823 fprintf (file, "%ld", INTVAL (op) >> 8);
1824 else if (letter == 'H')
1825 fprintf (file, "%ld", INTVAL (op) >> 16);
1826 else if (letter == 'q')
1827 fprintf (file, "%ld", INTVAL (op) & 0xff);
1828 else if (letter == 'h')
1829 fprintf (file, "%ld", INTVAL (op) & 0xffff);
1830 else if (letter == 'e')
1831 fprintf (file, "%ld", (INTVAL (op) >> 16) & 0xff);
1832 else if (letter == 'B')
1834 int ival = INTVAL (op);
1835 if (ival == -128)
1836 ival = 0x80;
1837 if (exact_log2 (ival) >= 0)
1838 fprintf (file, "%d", exact_log2 (ival));
1839 else
1840 fprintf (file, "%d", exact_log2 (~ival & 0xff));
1842 else if (letter == 'E')
1843 fprintf (file, "%ld", (INTVAL (op) >> 24) & 0xff);
1844 else if (letter == 'm')
1845 fprintf (file, "%ld", - INTVAL (op));
1846 else if (letter == 's')
1847 fprintf (file, "%ld", INTVAL (op) % 8);
1848 else if (letter == 'S')
1849 fprintf (file, "%ld", INTVAL (op) % 16);
1850 else if (letter == 'r')
1851 fprintf (file, "%ld", 8 - (INTVAL (op) % 8));
1852 else if (letter == 'C')
1853 fprintf (file, "%ld", (INTVAL (op) ^ 0x8000) & 0xffff);
1854 else
1855 fprintf (file, "%ld", INTVAL (op));
1856 break;
1858 case CONST:
1859 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1860 break;
1862 case ZERO_EXTRACT:
1864 int bits = INTVAL (XEXP (op, 1));
1865 int ofs = INTVAL (XEXP (op, 2));
1866 if (bits == 16 && ofs == 0)
1867 fprintf (file, "%%lo16(");
1868 else if (bits == 16 && ofs == 16)
1869 fprintf (file, "%%hi16(");
1870 else if (bits == 8 && ofs == 16)
1871 fprintf (file, "%%hi8(");
1872 else
1873 gcc_unreachable ();
1874 rl78_print_operand_1 (file, XEXP (op, 0), 0);
1875 fprintf (file, ")");
1877 break;
1879 case ZERO_EXTEND:
1880 if (GET_CODE (XEXP (op, 0)) == REG)
1881 fprintf (file, "%s", reg_names [REGNO (XEXP (op, 0))]);
1882 else
1883 print_rtl (file, op);
1884 break;
1886 case PLUS:
1887 need_paren = 0;
1888 if (letter == 'H')
1890 fprintf (file, "%%hi16(");
1891 need_paren = 1;
1892 letter = 0;
1894 if (letter == 'h')
1896 fprintf (file, "%%lo16(");
1897 need_paren = 1;
1898 letter = 0;
1900 if (letter == 'e')
1902 fprintf (file, "%%hi8(");
1903 need_paren = 1;
1904 letter = 0;
1906 if (letter == 'q' || letter == 'Q')
1907 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1909 if (GET_CODE (XEXP (op, 0)) == ZERO_EXTEND)
1911 if (GET_CODE (XEXP (op, 1)) == SYMBOL_REF
1912 && SYMBOL_REF_DECL (XEXP (op, 1))
1913 && TREE_CODE (SYMBOL_REF_DECL (XEXP (op, 1))) == FUNCTION_DECL)
1915 fprintf (file, "%%code(");
1916 assemble_name (file, rl78_strip_nonasm_name_encoding (XSTR (XEXP (op, 1), 0)));
1917 fprintf (file, "+");
1918 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1919 fprintf (file, ")");
1921 else
1923 rl78_print_operand_1 (file, XEXP (op, 1), letter);
1924 fprintf (file, "+");
1925 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1928 else
1930 if (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
1931 && SYMBOL_REF_DECL (XEXP (op, 0))
1932 && TREE_CODE (SYMBOL_REF_DECL (XEXP (op, 0))) == FUNCTION_DECL)
1934 fprintf (file, "%%code(");
1935 assemble_name (file, rl78_strip_nonasm_name_encoding (XSTR (XEXP (op, 0), 0)));
1936 fprintf (file, "+");
1937 rl78_print_operand_1 (file, XEXP (op, 1), letter);
1938 fprintf (file, ")");
1940 else
1942 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1943 fprintf (file, "+");
1944 rl78_print_operand_1 (file, XEXP (op, 1), letter);
1947 if (need_paren)
1948 fprintf (file, ")");
1949 break;
1951 case SUBREG:
1952 if (GET_MODE (op) == HImode
1953 && SUBREG_BYTE (op) == 0)
1955 fprintf (file, "%%lo16(");
1956 rl78_print_operand_1 (file, SUBREG_REG (op), 0);
1957 fprintf (file, ")");
1959 else if (GET_MODE (op) == HImode
1960 && SUBREG_BYTE (op) == 2)
1962 fprintf (file, "%%hi16(");
1963 rl78_print_operand_1 (file, SUBREG_REG (op), 0);
1964 fprintf (file, ")");
1966 else
1968 fprintf (file, "(%s)", GET_RTX_NAME (GET_CODE (op)));
1970 break;
1972 case SYMBOL_REF:
1973 need_paren = 0;
1974 if (letter == 'H')
1976 fprintf (file, "%%hi16(");
1977 need_paren = 1;
1978 letter = 0;
1980 if (letter == 'h')
1982 fprintf (file, "%%lo16(");
1983 need_paren = 1;
1984 letter = 0;
1986 if (letter == 'e')
1988 fprintf (file, "%%hi8(");
1989 need_paren = 1;
1990 letter = 0;
1992 if (letter == 'q' || letter == 'Q')
1993 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1995 if (SYMBOL_REF_DECL (op) && TREE_CODE (SYMBOL_REF_DECL (op)) == FUNCTION_DECL)
1997 fprintf (file, "%%code(");
1998 assemble_name (file, rl78_strip_nonasm_name_encoding (XSTR (op, 0)));
1999 fprintf (file, ")");
2001 else
2002 assemble_name (file, rl78_strip_nonasm_name_encoding (XSTR (op, 0)));
2003 if (need_paren)
2004 fprintf (file, ")");
2005 break;
2007 case CODE_LABEL:
2008 case LABEL_REF:
2009 output_asm_label (op);
2010 break;
2012 case LTU:
2013 if (letter == 'z')
2014 fprintf (file, "#comparison eliminated");
2015 else
2016 fprintf (file, letter == 'C' ? "nc" : "c");
2017 break;
2018 case LEU:
2019 if (letter == 'z')
2020 fprintf (file, "br");
2021 else
2022 fprintf (file, letter == 'C' ? "h" : "nh");
2023 break;
2024 case GEU:
2025 if (letter == 'z')
2026 fprintf (file, "br");
2027 else
2028 fprintf (file, letter == 'C' ? "c" : "nc");
2029 break;
2030 case GTU:
2031 if (letter == 'z')
2032 fprintf (file, "#comparison eliminated");
2033 else
2034 fprintf (file, letter == 'C' ? "nh" : "h");
2035 break;
2036 case EQ:
2037 if (letter == 'z')
2038 fprintf (file, "br");
2039 else
2040 fprintf (file, letter == 'C' ? "nz" : "z");
2041 break;
2042 case NE:
2043 if (letter == 'z')
2044 fprintf (file, "#comparison eliminated");
2045 else
2046 fprintf (file, letter == 'C' ? "z" : "nz");
2047 break;
2049 /* Note: these assume appropriate adjustments were made so that
2050 unsigned comparisons, which is all this chip has, will
2051 work. */
2052 case LT:
2053 if (letter == 'z')
2054 fprintf (file, "#comparison eliminated");
2055 else
2056 fprintf (file, letter == 'C' ? "nc" : "c");
2057 break;
2058 case LE:
2059 if (letter == 'z')
2060 fprintf (file, "br");
2061 else
2062 fprintf (file, letter == 'C' ? "h" : "nh");
2063 break;
2064 case GE:
2065 if (letter == 'z')
2066 fprintf (file, "br");
2067 else
2068 fprintf (file, letter == 'C' ? "c" : "nc");
2069 break;
2070 case GT:
2071 if (letter == 'z')
2072 fprintf (file, "#comparison eliminated");
2073 else
2074 fprintf (file, letter == 'C' ? "nh" : "h");
2075 break;
2077 default:
2078 fprintf (file, "(%s)", GET_RTX_NAME (GET_CODE (op)));
2079 break;
2083 #undef TARGET_PRINT_OPERAND
2084 #define TARGET_PRINT_OPERAND rl78_print_operand
2086 static void
2087 rl78_print_operand (FILE * file, rtx op, int letter)
2089 if (CONSTANT_P (op) && letter != 'u' && letter != 's' && letter != 'r' && letter != 'S' && letter != 'B')
2090 fprintf (file, "#");
2091 rl78_print_operand_1 (file, op, letter);
2094 #undef TARGET_TRAMPOLINE_INIT
2095 #define TARGET_TRAMPOLINE_INIT rl78_trampoline_init
2097 /* Note that the RL78's addressing makes it very difficult to do
2098 trampolines on the stack. So, libgcc has a small pool of
2099 trampolines from which one is allocated to this task. */
2100 static void
2101 rl78_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
2103 rtx mov_addr, thunk_addr;
2104 rtx function = XEXP (DECL_RTL (fndecl), 0);
2106 mov_addr = adjust_address (m_tramp, HImode, 0);
2107 thunk_addr = gen_reg_rtx (HImode);
2109 function = force_reg (HImode, function);
2110 static_chain = force_reg (HImode, static_chain);
2112 emit_insn (gen_trampoline_init (thunk_addr, function, static_chain));
2113 emit_move_insn (mov_addr, thunk_addr);
2115 cfun->machine->trampolines_used = 1;
2118 #undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
2119 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS rl78_trampoline_adjust_address
2121 static rtx
2122 rl78_trampoline_adjust_address (rtx m_tramp)
2124 rtx x = gen_rtx_MEM (HImode, m_tramp);
2125 return x;
2128 /* Expander for cbranchqi4 and cbranchhi4. RL78 is missing some of
2129 the "normal" compares, specifically, it only has unsigned compares,
2130 so we must synthesize the missing ones. */
2131 void
2132 rl78_expand_compare (rtx *operands)
2134 if (GET_CODE (operands[2]) == MEM)
2135 operands[2] = copy_to_mode_reg (GET_MODE (operands[2]), operands[2]);
2140 /* Define this to 1 if you are debugging the peephole optimizers. */
2141 #define DEBUG_PEEP 0
2143 /* Predicate used to enable the peephole2 patterns in rl78-virt.md.
2144 The default "word" size is a byte so we can effectively use all the
2145 registers, but we want to do 16-bit moves whenever possible. This
2146 function determines when such a move is an option. */
2147 bool
2148 rl78_peep_movhi_p (rtx *operands)
2150 int i;
2151 rtx m, a;
2153 /* (set (op0) (op1))
2154 (set (op2) (op3)) */
2156 if (! rl78_virt_insns_ok ())
2157 return false;
2159 #if DEBUG_PEEP
2160 fprintf (stderr, "\033[33m");
2161 debug_rtx (operands[0]);
2162 debug_rtx (operands[1]);
2163 debug_rtx (operands[2]);
2164 debug_rtx (operands[3]);
2165 fprintf (stderr, "\033[0m");
2166 #endif
2168 /* You can move a constant to memory as QImode, but not HImode. */
2169 if (GET_CODE (operands[0]) == MEM
2170 && GET_CODE (operands[1]) != REG)
2172 #if DEBUG_PEEP
2173 fprintf (stderr, "no peep: move constant to memory\n");
2174 #endif
2175 return false;
2178 if (rtx_equal_p (operands[0], operands[3]))
2180 #if DEBUG_PEEP
2181 fprintf (stderr, "no peep: overlapping\n");
2182 #endif
2183 return false;
2186 for (i = 0; i < 2; i ++)
2188 if (GET_CODE (operands[i]) != GET_CODE (operands[i+2]))
2190 #if DEBUG_PEEP
2191 fprintf (stderr, "no peep: different codes\n");
2192 #endif
2193 return false;
2195 if (GET_MODE (operands[i]) != GET_MODE (operands[i+2]))
2197 #if DEBUG_PEEP
2198 fprintf (stderr, "no peep: different modes\n");
2199 #endif
2200 return false;
2203 switch (GET_CODE (operands[i]))
2205 case REG:
2206 /* LSB MSB */
2207 if (REGNO (operands[i]) + 1 != REGNO (operands[i+2])
2208 || GET_MODE (operands[i]) != QImode)
2210 #if DEBUG_PEEP
2211 fprintf (stderr, "no peep: wrong regnos %d %d %d\n",
2212 REGNO (operands[i]), REGNO (operands[i+2]),
2214 #endif
2215 return false;
2217 if (! rl78_hard_regno_mode_ok (REGNO (operands[i]), HImode))
2219 #if DEBUG_PEEP
2220 fprintf (stderr, "no peep: reg %d not HI\n", REGNO (operands[i]));
2221 #endif
2222 return false;
2224 break;
2226 case CONST_INT:
2227 break;
2229 case MEM:
2230 if (GET_MODE (operands[i]) != QImode)
2231 return false;
2232 if (MEM_ALIGN (operands[i]) < 16)
2233 return false;
2234 a = XEXP (operands[i], 0);
2235 if (GET_CODE (a) == CONST)
2236 a = XEXP (a, 0);
2237 if (GET_CODE (a) == PLUS)
2238 a = XEXP (a, 1);
2239 if (GET_CODE (a) == CONST_INT
2240 && INTVAL (a) & 1)
2242 #if DEBUG_PEEP
2243 fprintf (stderr, "no peep: misaligned mem %d\n", i);
2244 debug_rtx (operands[i]);
2245 #endif
2246 return false;
2248 m = adjust_address (operands[i], QImode, 1);
2249 if (! rtx_equal_p (m, operands[i+2]))
2251 #if DEBUG_PEEP
2252 fprintf (stderr, "no peep: wrong mem %d\n", i);
2253 debug_rtx (m);
2254 debug_rtx (operands[i+2]);
2255 #endif
2256 return false;
2258 break;
2260 default:
2261 #if DEBUG_PEEP
2262 fprintf (stderr, "no peep: wrong rtx %d\n", i);
2263 #endif
2264 return false;
2267 #if DEBUG_PEEP
2268 fprintf (stderr, "\033[32mpeep!\033[0m\n");
2269 #endif
2270 return true;
2273 /* Likewise, when a peephole is activated, this function helps compute
2274 the new operands. */
2275 void
2276 rl78_setup_peep_movhi (rtx *operands)
2278 int i;
2280 for (i = 0; i < 2; i ++)
2282 switch (GET_CODE (operands[i]))
2284 case REG:
2285 operands[i+4] = gen_rtx_REG (HImode, REGNO (operands[i]));
2286 break;
2288 case CONST_INT:
2289 operands[i+4] = GEN_INT ((INTVAL (operands[i]) & 0xff) + ((char) INTVAL (operands[i+2])) * 256);
2290 break;
2292 case MEM:
2293 operands[i+4] = adjust_address (operands[i], HImode, 0);
2294 break;
2296 default:
2297 break;
2303 How Devirtualization works in the RL78 GCC port
2305 Background
2307 The RL78 is an 8-bit port with some 16-bit operations. It has 32
2308 bytes of register space, in four banks, memory-mapped. One bank is
2309 the "selected" bank and holds the registers used for primary
2310 operations. Since the registers are memory mapped, often you can
2311 still refer to the unselected banks via memory accesses.
2313 Virtual Registers
2315 The GCC port uses bank 0 as the "selected" registers (A, X, BC, etc)
2316 and refers to the other banks via their memory addresses, although
2317 they're treated as regular registers internally. These "virtual"
2318 registers are R8 through R23 (bank3 is reserved for asm-based
2319 interrupt handlers).
2321 There are four machine description files:
2323 rl78.md - common register-independent patterns and definitions
2324 rl78-expand.md - expanders
2325 rl78-virt.md - patterns that match BEFORE devirtualization
2326 rl78-real.md - patterns that match AFTER devirtualization
2328 At least through register allocation and reload, gcc is told that it
2329 can do pretty much anything - but may only use the virtual registers.
2330 GCC cannot properly create the varying addressing modes that the RL78
2331 supports in an efficient way.
2333 Sometime after reload, the RL78 backend "devirtualizes" the RTL. It
2334 uses the "valloc" attribute in rl78-virt.md for determining the rules
2335 by which it will replace virtual registers with real registers (or
2336 not) and how to make up addressing modes. For example, insns tagged
2337 with "ro1" have a single read-only parameter, which may need to be
2338 moved from memory/constant/vreg to a suitable real register. As part
2339 of devirtualization, a flag is toggled, disabling the rl78-virt.md
2340 patterns and enabling the rl78-real.md patterns. The new patterns'
2341 constraints are used to determine the real registers used. NOTE:
2342 patterns in rl78-virt.md essentially ignore the constrains and rely on
2343 predicates, where the rl78-real.md ones essentially ignore the
2344 predicates and rely on the constraints.
2346 The devirtualization pass is scheduled via the pass manager (despite
2347 being called "rl78_reorg") so it can be scheduled prior to var-track
2348 (the idea is to let gdb know about the new registers). Ideally, it
2349 would be scheduled right after pro/epilogue generation, so the
2350 post-reload optimizers could operate on the real registers, but when I
2351 tried that there were some issues building the target libraries.
2353 During devirtualization, a simple register move optimizer is run. It
2354 would be better to run a full CSE/propogation pass on it though, but
2355 that has not yet been attempted.
2358 #define DEBUG_ALLOC 0
2360 #define OP(x) (*recog_data.operand_loc[x])
2362 /* This array is used to hold knowledge about the contents of the
2363 real registers (A ... H), the memory-based registers (r8 ... r31)
2364 and the first NUM_STACK_LOCS words on the stack. We use this to
2365 avoid generating redundant move instructions.
2367 A value in the range 0 .. 31 indicates register A .. r31.
2368 A value in the range 32 .. 63 indicates stack slot (value - 32).
2369 A value of NOT_KNOWN indicates that the contents of that location
2370 are not known. */
2372 #define NUM_STACK_LOCS 32
2373 #define NOT_KNOWN 127
2375 static unsigned char content_memory [32 + NUM_STACK_LOCS];
2377 static unsigned char saved_update_index = NOT_KNOWN;
2378 static unsigned char saved_update_value;
2379 static machine_mode saved_update_mode;
2382 static inline void
2383 clear_content_memory (void)
2385 memset (content_memory, NOT_KNOWN, sizeof content_memory);
2386 if (dump_file)
2387 fprintf (dump_file, " clear content memory\n");
2388 saved_update_index = NOT_KNOWN;
2391 /* Convert LOC into an index into the content_memory array.
2392 If LOC cannot be converted, return NOT_KNOWN. */
2394 static unsigned char
2395 get_content_index (rtx loc)
2397 machine_mode mode;
2399 if (loc == NULL_RTX)
2400 return NOT_KNOWN;
2402 if (REG_P (loc))
2404 if (REGNO (loc) < 32)
2405 return REGNO (loc);
2406 return NOT_KNOWN;
2409 mode = GET_MODE (loc);
2411 if (! rl78_stack_based_mem (loc, mode))
2412 return NOT_KNOWN;
2414 loc = XEXP (loc, 0);
2416 if (REG_P (loc))
2417 /* loc = MEM (SP) */
2418 return 32;
2420 /* loc = MEM (PLUS (SP, INT)). */
2421 loc = XEXP (loc, 1);
2423 if (INTVAL (loc) < NUM_STACK_LOCS)
2424 return 32 + INTVAL (loc);
2426 return NOT_KNOWN;
2429 /* Return a string describing content INDEX in mode MODE.
2430 WARNING: Can return a pointer to a static buffer. */
2431 static const char *
2432 get_content_name (unsigned char index, machine_mode mode)
2434 static char buffer [128];
2436 if (index == NOT_KNOWN)
2437 return "Unknown";
2439 if (index > 31)
2440 sprintf (buffer, "stack slot %d", index - 32);
2441 else if (mode == HImode)
2442 sprintf (buffer, "%s%s",
2443 reg_names [index + 1], reg_names [index]);
2444 else
2445 return reg_names [index];
2447 return buffer;
2450 #if DEBUG_ALLOC
2452 static void
2453 display_content_memory (FILE * file)
2455 unsigned int i;
2457 fprintf (file, " Known memory contents:\n");
2459 for (i = 0; i < sizeof content_memory; i++)
2460 if (content_memory[i] != NOT_KNOWN)
2462 fprintf (file, " %s contains a copy of ", get_content_name (i, QImode));
2463 fprintf (file, "%s\n", get_content_name (content_memory [i], QImode));
2466 #endif
2468 static void
2469 update_content (unsigned char index, unsigned char val, machine_mode mode)
2471 unsigned int i;
2473 gcc_assert (index < sizeof content_memory);
2475 content_memory [index] = val;
2476 if (val != NOT_KNOWN)
2477 content_memory [val] = index;
2479 /* Make the entry in dump_file *before* VAL is increased below. */
2480 if (dump_file)
2482 fprintf (dump_file, " %s now contains ", get_content_name (index, mode));
2483 if (val == NOT_KNOWN)
2484 fprintf (dump_file, "Unknown\n");
2485 else
2486 fprintf (dump_file, "%s and vice versa\n", get_content_name (val, mode));
2489 if (mode == HImode)
2491 val = val == NOT_KNOWN ? val : val + 1;
2493 content_memory [index + 1] = val;
2494 if (val != NOT_KNOWN)
2496 content_memory [val] = index + 1;
2497 -- val;
2501 /* Any other places that had INDEX recorded as their contents are now invalid. */
2502 for (i = 0; i < sizeof content_memory; i++)
2504 if (i == index
2505 || (val != NOT_KNOWN && i == val))
2507 if (mode == HImode)
2508 ++ i;
2509 continue;
2512 if (content_memory[i] == index
2513 || (val != NOT_KNOWN && content_memory[i] == val))
2515 content_memory[i] = NOT_KNOWN;
2517 if (dump_file)
2518 fprintf (dump_file, " %s cleared\n", get_content_name (i, mode));
2520 if (mode == HImode)
2521 content_memory[++ i] = NOT_KNOWN;
2526 /* Record that LOC contains VALUE.
2527 For HImode locations record that LOC+1 contains VALUE+1.
2528 If LOC is not a register or stack slot, do nothing.
2529 If VALUE is not a register or stack slot, clear the recorded content. */
2531 static void
2532 record_content (rtx loc, rtx value)
2534 machine_mode mode;
2535 unsigned char index;
2536 unsigned char val;
2538 if ((index = get_content_index (loc)) == NOT_KNOWN)
2539 return;
2541 val = get_content_index (value);
2543 mode = GET_MODE (loc);
2545 if (val == index)
2547 if (! optimize)
2548 return;
2550 /* This should not happen when optimizing. */
2551 #if 1
2552 fprintf (stderr, "ASSIGNMENT of location to itself detected! [%s]\n",
2553 get_content_name (val, mode));
2554 return;
2555 #else
2556 gcc_unreachable ();
2557 #endif
2560 update_content (index, val, mode);
2563 /* Returns TRUE if LOC already contains a copy of VALUE. */
2565 static bool
2566 already_contains (rtx loc, rtx value)
2568 unsigned char index;
2569 unsigned char val;
2571 if ((index = get_content_index (loc)) == NOT_KNOWN)
2572 return false;
2574 if ((val = get_content_index (value)) == NOT_KNOWN)
2575 return false;
2577 if (content_memory [index] != val)
2578 return false;
2580 if (GET_MODE (loc) == HImode)
2581 return content_memory [index + 1] == val + 1;
2583 return true;
2586 bool
2587 rl78_es_addr (rtx addr)
2589 if (GET_CODE (addr) == MEM)
2590 addr = XEXP (addr, 0);
2591 if (GET_CODE (addr) != UNSPEC)
2592 return false;
2593 if (XINT (addr, 1) != UNS_ES_ADDR)
2594 return false;
2595 return true;
2599 rl78_es_base (rtx addr)
2601 if (GET_CODE (addr) == MEM)
2602 addr = XEXP (addr, 0);
2603 addr = XVECEXP (addr, 0, 1);
2604 if (GET_CODE (addr) == CONST
2605 && GET_CODE (XEXP (addr, 0)) == ZERO_EXTRACT)
2606 addr = XEXP (XEXP (addr, 0), 0);
2607 /* Mode doesn't matter here. */
2608 return gen_rtx_MEM (HImode, addr);
2611 /* Rescans an insn to see if it's recognized again. This is done
2612 carefully to ensure that all the constraint information is accurate
2613 for the newly matched insn. */
2614 static bool
2615 insn_ok_now (rtx_insn * insn)
2617 rtx pattern = PATTERN (insn);
2618 int i;
2620 INSN_CODE (insn) = -1;
2622 if (recog (pattern, insn, 0) > -1)
2624 extract_insn (insn);
2625 if (constrain_operands (1, get_preferred_alternatives (insn)))
2627 #if DEBUG_ALLOC
2628 fprintf (stderr, "\033[32m");
2629 debug_rtx (insn);
2630 fprintf (stderr, "\033[0m");
2631 #endif
2632 if (SET_P (pattern))
2633 record_content (SET_DEST (pattern), SET_SRC (pattern));
2635 /* We need to detect far addresses that haven't been
2636 converted to es/lo16 format. */
2637 for (i=0; i<recog_data.n_operands; i++)
2638 if (GET_CODE (OP (i)) == MEM
2639 && GET_MODE (XEXP (OP (i), 0)) == SImode
2640 && GET_CODE (XEXP (OP (i), 0)) != UNSPEC)
2641 return false;
2643 return true;
2646 else
2648 /* We need to re-recog the insn with virtual registers to get
2649 the operands. */
2650 cfun->machine->virt_insns_ok = 1;
2651 if (recog (pattern, insn, 0) > -1)
2653 extract_insn (insn);
2654 if (constrain_operands (0, get_preferred_alternatives (insn)))
2656 cfun->machine->virt_insns_ok = 0;
2657 return false;
2661 #if DEBUG_ALLOC
2662 fprintf (stderr, "\033[41;30m Unrecognized *virtual* insn \033[0m\n");
2663 debug_rtx (insn);
2664 #endif
2665 gcc_unreachable ();
2668 #if DEBUG_ALLOC
2669 fprintf (stderr, "\033[31m");
2670 debug_rtx (insn);
2671 fprintf (stderr, "\033[0m");
2672 #endif
2673 return false;
2676 #if DEBUG_ALLOC
2677 #define WORKED fprintf (stderr, "\033[48;5;22m Worked at line %d \033[0m\n", __LINE__)
2678 #define FAILEDSOFAR fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__)
2679 #define FAILED fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__), gcc_unreachable ()
2680 #define MAYBE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } else { FAILEDSOFAR; }
2681 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } FAILED
2682 #else
2683 #define FAILED gcc_unreachable ()
2684 #define MAYBE_OK(insn) if (insn_ok_now (insn)) return;
2685 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) return; FAILED
2686 #endif
2688 /* Registers into which we move the contents of virtual registers. */
2689 #define X gen_rtx_REG (QImode, X_REG)
2690 #define A gen_rtx_REG (QImode, A_REG)
2691 #define C gen_rtx_REG (QImode, C_REG)
2692 #define B gen_rtx_REG (QImode, B_REG)
2693 #define E gen_rtx_REG (QImode, E_REG)
2694 #define D gen_rtx_REG (QImode, D_REG)
2695 #define L gen_rtx_REG (QImode, L_REG)
2696 #define H gen_rtx_REG (QImode, H_REG)
2698 #define AX gen_rtx_REG (HImode, AX_REG)
2699 #define BC gen_rtx_REG (HImode, BC_REG)
2700 #define DE gen_rtx_REG (HImode, DE_REG)
2701 #define HL gen_rtx_REG (HImode, HL_REG)
2703 /* Returns TRUE if R is a virtual register. */
2704 static inline bool
2705 is_virtual_register (rtx r)
2707 return (GET_CODE (r) == REG
2708 && REGNO (r) >= 8
2709 && REGNO (r) < 32);
2712 /* In all these alloc routines, we expect the following: the insn
2713 pattern is unshared, the insn was previously recognized and failed
2714 due to predicates or constraints, and the operand data is in
2715 recog_data. */
2717 static int virt_insn_was_frame;
2719 /* Hook for all insns we emit. Re-mark them as FRAME_RELATED if
2720 needed. */
2721 static rtx
2722 EM2 (int line ATTRIBUTE_UNUSED, rtx r)
2724 #if DEBUG_ALLOC
2725 fprintf (stderr, "\033[36m%d: ", line);
2726 debug_rtx (r);
2727 fprintf (stderr, "\033[0m");
2728 #endif
2729 /*SCHED_GROUP_P (r) = 1;*/
2730 if (virt_insn_was_frame)
2731 RTX_FRAME_RELATED_P (r) = 1;
2732 return r;
2735 #define EM(x) EM2 (__LINE__, x)
2737 /* Return a suitable RTX for the low half of a __far address. */
2738 static rtx
2739 rl78_lo16 (rtx addr)
2741 rtx r;
2743 if (GET_CODE (addr) == SYMBOL_REF
2744 || GET_CODE (addr) == CONST)
2746 r = gen_rtx_ZERO_EXTRACT (HImode, addr, GEN_INT (16), GEN_INT (0));
2747 r = gen_rtx_CONST (HImode, r);
2749 else
2750 r = rl78_subreg (HImode, addr, SImode, 0);
2752 r = gen_es_addr (r);
2753 cfun->machine->uses_es = true;
2755 return r;
2758 /* Return a suitable RTX for the high half's lower byte of a __far address. */
2759 static rtx
2760 rl78_hi8 (rtx addr)
2762 if (GET_CODE (addr) == SYMBOL_REF
2763 || GET_CODE (addr) == CONST)
2765 rtx r = gen_rtx_ZERO_EXTRACT (QImode, addr, GEN_INT (8), GEN_INT (16));
2766 r = gen_rtx_CONST (QImode, r);
2767 return r;
2769 return rl78_subreg (QImode, addr, SImode, 2);
2772 static void
2773 add_postponed_content_update (rtx to, rtx value)
2775 unsigned char index;
2777 if ((index = get_content_index (to)) == NOT_KNOWN)
2778 return;
2780 gcc_assert (saved_update_index == NOT_KNOWN);
2781 saved_update_index = index;
2782 saved_update_value = get_content_index (value);
2783 saved_update_mode = GET_MODE (to);
2786 static void
2787 process_postponed_content_update (void)
2789 if (saved_update_index != NOT_KNOWN)
2791 update_content (saved_update_index, saved_update_value, saved_update_mode);
2792 saved_update_index = NOT_KNOWN;
2796 /* Generate and emit a move of (register) FROM into TO. if WHERE is not NULL
2797 then if BEFORE is true then emit the insn before WHERE, otherwise emit it
2798 after WHERE. If TO already contains FROM then do nothing. Returns TO if
2799 BEFORE is true, FROM otherwise. */
2800 static rtx
2801 gen_and_emit_move (rtx to, rtx from, rtx_insn *where, bool before)
2803 machine_mode mode = GET_MODE (to);
2805 if (optimize && before && already_contains (to, from))
2807 #if DEBUG_ALLOC
2808 display_content_memory (stderr);
2809 #endif
2810 if (dump_file)
2812 fprintf (dump_file, " Omit move of %s into ",
2813 get_content_name (get_content_index (from), mode));
2814 fprintf (dump_file, "%s as it already contains this value\n",
2815 get_content_name (get_content_index (to), mode));
2818 else
2820 rtx move = mode == QImode ? gen_movqi (to, from) : gen_movhi (to, from);
2822 EM (move);
2824 if (where == NULL_RTX)
2825 emit_insn (move);
2826 else if (before)
2827 emit_insn_before (move, where);
2828 else
2830 rtx note = find_reg_note (where, REG_EH_REGION, NULL_RTX);
2832 /* If necessary move REG_EH_REGION notes forward.
2833 cf. compiling gcc.dg/pr44545.c. */
2834 if (note != NULL_RTX)
2836 add_reg_note (move, REG_EH_REGION, XEXP (note, 0));
2837 remove_note (where, note);
2840 emit_insn_after (move, where);
2843 if (before)
2844 record_content (to, from);
2845 else
2846 add_postponed_content_update (to, from);
2849 return before ? to : from;
2852 /* If M is MEM(REG) or MEM(PLUS(REG,INT)) and REG is virtual then
2853 copy it into NEWBASE and return the updated MEM. Otherwise just
2854 return M. Any needed insns are emitted before BEFORE. */
2855 static rtx
2856 transcode_memory_rtx (rtx m, rtx newbase, rtx_insn *before)
2858 rtx base, index, addendr;
2859 int addend = 0;
2860 int need_es = 0;
2862 if (! MEM_P (m))
2863 return m;
2865 if (GET_MODE (XEXP (m, 0)) == SImode)
2867 rtx new_m;
2868 rtx seg = rl78_hi8 (XEXP (m, 0));
2870 if (!TARGET_ES0)
2872 emit_insn_before (EM (gen_movqi (A, seg)), before);
2873 emit_insn_before (EM (gen_movqi_to_es (A)), before);
2876 record_content (A, NULL_RTX);
2878 new_m = gen_rtx_MEM (GET_MODE (m), rl78_lo16 (XEXP (m, 0)));
2879 MEM_COPY_ATTRIBUTES (new_m, m);
2880 m = new_m;
2881 need_es = 1;
2884 characterize_address (XEXP (m, 0), & base, & index, & addendr);
2885 gcc_assert (index == NULL_RTX);
2887 if (base == NULL_RTX)
2888 return m;
2890 if (addendr && GET_CODE (addendr) == CONST_INT)
2891 addend = INTVAL (addendr);
2893 gcc_assert (REG_P (base));
2894 gcc_assert (REG_P (newbase));
2896 int limit = 256 - GET_MODE_SIZE (GET_MODE (m));
2898 if (REGNO (base) == SP_REG)
2900 if (addend >= 0 && addend <= limit)
2901 return m;
2904 /* BASE should be a virtual register. We copy it to NEWBASE. If
2905 the addend is out of range for DE/HL, we use AX to compute the full
2906 address. */
2908 if (addend < 0
2909 || (addend > limit && REGNO (newbase) != BC_REG)
2910 || (addendr
2911 && (GET_CODE (addendr) != CONST_INT)
2912 && ((REGNO (newbase) != BC_REG))
2915 /* mov ax, vreg
2916 add ax, #imm
2917 mov hl, ax */
2918 EM (emit_insn_before (gen_movhi (AX, base), before));
2919 EM (emit_insn_before (gen_addhi3 (AX, AX, addendr), before));
2920 EM (emit_insn_before (gen_movhi (newbase, AX), before));
2921 record_content (AX, NULL_RTX);
2922 record_content (newbase, NULL_RTX);
2924 base = newbase;
2925 addend = 0;
2926 addendr = 0;
2928 else
2930 base = gen_and_emit_move (newbase, base, before, true);
2933 if (addend)
2935 record_content (base, NULL_RTX);
2936 base = gen_rtx_PLUS (HImode, base, GEN_INT (addend));
2938 else if (addendr)
2940 record_content (base, NULL_RTX);
2941 base = gen_rtx_PLUS (HImode, base, addendr);
2944 if (need_es)
2946 m = change_address (m, GET_MODE (m), gen_es_addr (base));
2947 cfun->machine->uses_es = true;
2949 else
2950 m = change_address (m, GET_MODE (m), base);
2951 return m;
2954 /* Copy SRC to accumulator (A or AX), placing any generated insns
2955 before BEFORE. Returns accumulator RTX. */
2956 static rtx
2957 move_to_acc (int opno, rtx_insn *before)
2959 rtx src = OP (opno);
2960 machine_mode mode = GET_MODE (src);
2962 if (REG_P (src) && REGNO (src) < 2)
2963 return src;
2965 if (mode == VOIDmode)
2966 mode = recog_data.operand_mode[opno];
2968 return gen_and_emit_move (mode == QImode ? A : AX, src, before, true);
2971 static void
2972 force_into_acc (rtx src, rtx_insn *before)
2974 machine_mode mode = GET_MODE (src);
2975 rtx move;
2977 if (REG_P (src) && REGNO (src) < 2)
2978 return;
2980 move = mode == QImode ? gen_movqi (A, src) : gen_movhi (AX, src);
2982 EM (move);
2984 emit_insn_before (move, before);
2985 record_content (AX, NULL_RTX);
2988 /* Copy accumulator (A or AX) to DEST, placing any generated insns
2989 after AFTER. Returns accumulator RTX. */
2990 static rtx
2991 move_from_acc (unsigned int opno, rtx_insn *after)
2993 rtx dest = OP (opno);
2994 machine_mode mode = GET_MODE (dest);
2996 if (REG_P (dest) && REGNO (dest) < 2)
2997 return dest;
2999 return gen_and_emit_move (dest, mode == QImode ? A : AX, after, false);
3002 /* Copy accumulator (A or AX) to REGNO, placing any generated insns
3003 before BEFORE. Returns reg RTX. */
3004 static rtx
3005 move_acc_to_reg (rtx acc, int regno, rtx_insn *before)
3007 machine_mode mode = GET_MODE (acc);
3008 rtx reg;
3010 reg = gen_rtx_REG (mode, regno);
3012 return gen_and_emit_move (reg, acc, before, true);
3015 /* Copy SRC to X, placing any generated insns before BEFORE.
3016 Returns X RTX. */
3017 static rtx
3018 move_to_x (int opno, rtx_insn *before)
3020 rtx src = OP (opno);
3021 machine_mode mode = GET_MODE (src);
3022 rtx reg;
3024 if (mode == VOIDmode)
3025 mode = recog_data.operand_mode[opno];
3026 reg = (mode == QImode) ? X : AX;
3028 if (mode == QImode || ! is_virtual_register (OP (opno)))
3030 OP (opno) = move_to_acc (opno, before);
3031 OP (opno) = move_acc_to_reg (OP (opno), X_REG, before);
3032 return reg;
3035 return gen_and_emit_move (reg, src, before, true);
3038 /* Copy OP (opno) to H or HL, placing any generated insns before BEFORE.
3039 Returns H/HL RTX. */
3040 static rtx
3041 move_to_hl (int opno, rtx_insn *before)
3043 rtx src = OP (opno);
3044 machine_mode mode = GET_MODE (src);
3045 rtx reg;
3047 if (mode == VOIDmode)
3048 mode = recog_data.operand_mode[opno];
3049 reg = (mode == QImode) ? L : HL;
3051 if (mode == QImode || ! is_virtual_register (OP (opno)))
3053 OP (opno) = move_to_acc (opno, before);
3054 OP (opno) = move_acc_to_reg (OP (opno), L_REG, before);
3055 return reg;
3058 return gen_and_emit_move (reg, src, before, true);
3061 /* Copy OP (opno) to E or DE, placing any generated insns before BEFORE.
3062 Returns E/DE RTX. */
3063 static rtx
3064 move_to_de (int opno, rtx_insn *before)
3066 rtx src = OP (opno);
3067 machine_mode mode = GET_MODE (src);
3068 rtx reg;
3070 if (mode == VOIDmode)
3071 mode = recog_data.operand_mode[opno];
3073 reg = (mode == QImode) ? E : DE;
3075 if (mode == QImode || ! is_virtual_register (OP (opno)))
3077 OP (opno) = move_to_acc (opno, before);
3078 OP (opno) = move_acc_to_reg (OP (opno), E_REG, before);
3080 else
3082 gen_and_emit_move (reg, src, before, true);
3085 return reg;
3088 /* Devirtualize an insn of the form (SET (op) (unop (op))). */
3089 static void
3090 rl78_alloc_physical_registers_op1 (rtx_insn * insn)
3092 /* op[0] = func op[1] */
3094 /* We first try using A as the destination, then copying it
3095 back. */
3096 if (rtx_equal_p (OP (0), OP (1)))
3098 OP (0) =
3099 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3101 else
3103 /* If necessary, load the operands into BC and HL.
3104 Check to see if we already have OP (0) in HL
3105 and if so, swap the order.
3107 It is tempting to perform this optimization when OP(0) does
3108 not hold a MEM, but this leads to bigger code in general.
3109 The problem is that if OP(1) holds a MEM then swapping it
3110 into BC means a BC-relative load is used and these are 3
3111 bytes long vs 1 byte for an HL load. */
3112 if (MEM_P (OP (0))
3113 && already_contains (HL, XEXP (OP (0), 0)))
3115 OP (0) = transcode_memory_rtx (OP (0), HL, insn);
3116 OP (1) = transcode_memory_rtx (OP (1), BC, insn);
3118 else
3120 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
3121 OP (1) = transcode_memory_rtx (OP (1), HL, insn);
3125 MAYBE_OK (insn);
3127 OP (0) = move_from_acc (0, insn);
3129 MAYBE_OK (insn);
3131 /* Try copying the src to acc first, then. This is for, for
3132 example, ZERO_EXTEND or NOT. */
3133 OP (1) = move_to_acc (1, insn);
3135 MUST_BE_OK (insn);
3138 /* Returns true if operand OPNUM contains a constraint of type CONSTRAINT.
3139 Assumes that the current insn has already been recognised and hence the
3140 constraint data has been filled in. */
3141 static bool
3142 has_constraint (unsigned int opnum, enum constraint_num constraint)
3144 const char * p = recog_data.constraints[opnum];
3146 /* No constraints means anything is accepted. */
3147 if (p == NULL || *p == 0 || *p == ',')
3148 return true;
3152 char c;
3153 unsigned int len;
3155 c = *p;
3156 len = CONSTRAINT_LEN (c, p);
3157 gcc_assert (len > 0);
3159 switch (c)
3161 case 0:
3162 case ',':
3163 return false;
3164 default:
3165 if (lookup_constraint (p) == constraint)
3166 return true;
3168 p += len;
3170 while (1);
3173 /* Devirtualize an insn of the form (SET (op) (binop (op) (op))). */
3174 static void
3175 rl78_alloc_physical_registers_op2 (rtx_insn * insn)
3177 rtx_insn *prev;
3178 rtx_insn *first;
3179 bool hl_used;
3180 int tmp_id;
3181 rtx saved_op1;
3183 if (rtx_equal_p (OP (0), OP (1)))
3185 if (MEM_P (OP (2)))
3187 OP (0) =
3188 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3189 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
3191 else
3193 OP (0) =
3194 OP (1) = transcode_memory_rtx (OP (1), HL, insn);
3195 OP (2) = transcode_memory_rtx (OP (2), DE, insn);
3198 else if (rtx_equal_p (OP (0), OP (2)))
3200 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3201 OP (0) =
3202 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
3204 else
3206 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
3207 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3208 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
3211 MAYBE_OK (insn);
3213 prev = prev_nonnote_nondebug_insn (insn);
3214 if (recog_data.constraints[1][0] == '%'
3215 && is_virtual_register (OP (1))
3216 && ! is_virtual_register (OP (2))
3217 && ! CONSTANT_P (OP (2)))
3219 rtx tmp = OP (1);
3220 OP (1) = OP (2);
3221 OP (2) = tmp;
3224 /* Make a note of whether (H)L is being used. It matters
3225 because if OP (2) also needs reloading, then we must take
3226 care not to corrupt HL. */
3227 hl_used = reg_mentioned_p (L, OP (0)) || reg_mentioned_p (L, OP (1));
3229 /* If HL is not currently being used and dest == op1 then there are
3230 some possible optimizations available by reloading one of the
3231 operands into HL, before trying to use the accumulator. */
3232 if (optimize
3233 && ! hl_used
3234 && rtx_equal_p (OP (0), OP (1)))
3236 /* If op0 is a Ws1 type memory address then switching the base
3237 address register to HL might allow us to perform an in-memory
3238 operation. (eg for the INCW instruction).
3240 FIXME: Adding the move into HL is costly if this optimization is not
3241 going to work, so for now, make sure that we know that the new insn will
3242 match the requirements of the addhi3_real pattern. Really we ought to
3243 generate a candidate sequence, test that, and then install it if the
3244 results are good. */
3245 if (satisfies_constraint_Ws1 (OP (0))
3246 && has_constraint (0, CONSTRAINT_Wh1)
3247 && (satisfies_constraint_K (OP (2)) || satisfies_constraint_L (OP (2))))
3249 rtx base, index, addend, newbase;
3251 characterize_address (XEXP (OP (0), 0), & base, & index, & addend);
3252 gcc_assert (index == NULL_RTX);
3253 gcc_assert (REG_P (base) && REGNO (base) == SP_REG);
3255 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
3256 if (addend != NULL_RTX)
3258 newbase = gen_and_emit_move (HL, base, insn, true);
3259 record_content (newbase, NULL_RTX);
3260 newbase = gen_rtx_PLUS (HImode, newbase, addend);
3262 OP (0) = OP (1) = change_address (OP (0), VOIDmode, newbase);
3264 /* We do not want to fail here as this means that
3265 we have inserted useless insns into the stream. */
3266 MUST_BE_OK (insn);
3269 else if (REG_P (OP (0))
3270 && satisfies_constraint_Ws1 (OP (2))
3271 && has_constraint (2, CONSTRAINT_Wh1))
3273 rtx base, index, addend, newbase;
3275 characterize_address (XEXP (OP (2), 0), & base, & index, & addend);
3276 gcc_assert (index == NULL_RTX);
3277 gcc_assert (REG_P (base) && REGNO (base) == SP_REG);
3279 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
3280 if (addend != NULL_RTX)
3282 gen_and_emit_move (HL, base, insn, true);
3284 if (REGNO (OP (0)) != X_REG)
3286 OP (1) = move_to_acc (1, insn);
3287 OP (0) = move_from_acc (0, insn);
3290 record_content (HL, NULL_RTX);
3291 newbase = gen_rtx_PLUS (HImode, HL, addend);
3293 OP (2) = change_address (OP (2), VOIDmode, newbase);
3295 /* We do not want to fail here as this means that
3296 we have inserted useless insns into the stream. */
3297 MUST_BE_OK (insn);
3302 OP (0) = move_from_acc (0, insn);
3304 tmp_id = get_max_insn_count ();
3305 saved_op1 = OP (1);
3307 if (rtx_equal_p (OP (1), OP (2)))
3308 OP (2) = OP (1) = move_to_acc (1, insn);
3309 else
3310 OP (1) = move_to_acc (1, insn);
3312 MAYBE_OK (insn);
3314 /* If we omitted the move of OP1 into the accumulator (because
3315 it was already there from a previous insn), then force the
3316 generation of the move instruction now. We know that we
3317 are about to emit a move into HL (or DE) via AX, and hence
3318 our optimization to remove the load of OP1 is no longer valid. */
3319 if (tmp_id == get_max_insn_count ())
3320 force_into_acc (saved_op1, insn);
3322 /* We have to copy op2 to HL (or DE), but that involves AX, which
3323 already has a live value. Emit it before those insns. */
3325 if (prev)
3326 first = next_nonnote_nondebug_insn (prev);
3327 else
3328 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
3331 OP (2) = hl_used ? move_to_de (2, first) : move_to_hl (2, first);
3333 MUST_BE_OK (insn);
3336 /* Devirtualize an insn of the form SET (PC) (MEM/REG). */
3337 static void
3338 rl78_alloc_physical_registers_ro1 (rtx_insn * insn)
3340 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
3342 MAYBE_OK (insn);
3344 OP (0) = move_to_acc (0, insn);
3346 MUST_BE_OK (insn);
3349 /* Devirtualize a compare insn. */
3350 static void
3351 rl78_alloc_physical_registers_cmp (rtx_insn * insn)
3353 int tmp_id;
3354 rtx saved_op1;
3355 rtx_insn *prev = prev_nonnote_nondebug_insn (insn);
3356 rtx_insn *first;
3358 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3359 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
3361 /* HI compares have to have OP (1) in AX, but QI
3362 compares do not, so it is worth checking here. */
3363 MAYBE_OK (insn);
3365 /* For an HImode compare, OP (1) must always be in AX.
3366 But if OP (1) is a REG (and not AX), then we can avoid
3367 a reload of OP (1) if we reload OP (2) into AX and invert
3368 the comparison. */
3369 if (REG_P (OP (1))
3370 && REGNO (OP (1)) != AX_REG
3371 && GET_MODE (OP (1)) == HImode
3372 && MEM_P (OP (2)))
3374 rtx cmp = XEXP (SET_SRC (PATTERN (insn)), 0);
3376 OP (2) = move_to_acc (2, insn);
3378 switch (GET_CODE (cmp))
3380 case EQ:
3381 case NE:
3382 break;
3383 case LTU: cmp = gen_rtx_GTU (HImode, OP (2), OP (1)); break;
3384 case GTU: cmp = gen_rtx_LTU (HImode, OP (2), OP (1)); break;
3385 case LEU: cmp = gen_rtx_GEU (HImode, OP (2), OP (1)); break;
3386 case GEU: cmp = gen_rtx_LEU (HImode, OP (2), OP (1)); break;
3388 case LT:
3389 case GT:
3390 case LE:
3391 case GE:
3392 #if DEBUG_ALLOC
3393 debug_rtx (insn);
3394 #endif
3395 default:
3396 gcc_unreachable ();
3399 if (GET_CODE (cmp) == EQ || GET_CODE (cmp) == NE)
3400 PATTERN (insn) = gen_cbranchhi4_real (cmp, OP (2), OP (1), OP (3));
3401 else
3402 PATTERN (insn) = gen_cbranchhi4_real_inverted (cmp, OP (2), OP (1), OP (3));
3404 MUST_BE_OK (insn);
3407 /* Surprisingly, gcc can generate a comparison of a register with itself, but this
3408 should be handled by the second alternative of the cbranchhi_real pattern. */
3409 if (rtx_equal_p (OP (1), OP (2)))
3411 OP (1) = OP (2) = BC;
3412 MUST_BE_OK (insn);
3415 tmp_id = get_max_insn_count ();
3416 saved_op1 = OP (1);
3418 OP (1) = move_to_acc (1, insn);
3420 MAYBE_OK (insn);
3422 /* If we omitted the move of OP1 into the accumulator (because
3423 it was already there from a previous insn), then force the
3424 generation of the move instruction now. We know that we
3425 are about to emit a move into HL via AX, and hence our
3426 optimization to remove the load of OP1 is no longer valid. */
3427 if (tmp_id == get_max_insn_count ())
3428 force_into_acc (saved_op1, insn);
3430 /* We have to copy op2 to HL, but that involves the acc, which
3431 already has a live value. Emit it before those insns. */
3432 if (prev)
3433 first = next_nonnote_nondebug_insn (prev);
3434 else
3435 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
3437 OP (2) = move_to_hl (2, first);
3439 MUST_BE_OK (insn);
3442 /* Like op2, but AX = A * X. */
3443 static void
3444 rl78_alloc_physical_registers_umul (rtx_insn * insn)
3446 rtx_insn *prev = prev_nonnote_nondebug_insn (insn);
3447 rtx_insn *first;
3448 int tmp_id;
3449 rtx saved_op1;
3451 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
3452 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3453 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
3455 MAYBE_OK (insn);
3457 if (recog_data.constraints[1][0] == '%'
3458 && is_virtual_register (OP (1))
3459 && !is_virtual_register (OP (2))
3460 && !CONSTANT_P (OP (2)))
3462 rtx tmp = OP (1);
3463 OP (1) = OP (2);
3464 OP (2) = tmp;
3467 OP (0) = move_from_acc (0, insn);
3469 tmp_id = get_max_insn_count ();
3470 saved_op1 = OP (1);
3472 if (rtx_equal_p (OP (1), OP (2)))
3474 gcc_assert (GET_MODE (OP (2)) == QImode);
3475 /* The MULU instruction does not support duplicate arguments
3476 but we know that if we copy OP (2) to X it will do so via
3477 A and thus OP (1) will already be loaded into A. */
3478 OP (2) = move_to_x (2, insn);
3479 OP (1) = A;
3481 else
3482 OP (1) = move_to_acc (1, insn);
3484 MAYBE_OK (insn);
3486 /* If we omitted the move of OP1 into the accumulator (because
3487 it was already there from a previous insn), then force the
3488 generation of the move instruction now. We know that we
3489 are about to emit a move into HL (or DE) via AX, and hence
3490 our optimization to remove the load of OP1 is no longer valid. */
3491 if (tmp_id == get_max_insn_count ())
3492 force_into_acc (saved_op1, insn);
3494 /* We have to copy op2 to X, but that involves the acc, which
3495 already has a live value. Emit it before those insns. */
3497 if (prev)
3498 first = next_nonnote_nondebug_insn (prev);
3499 else
3500 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
3502 OP (2) = move_to_x (2, first);
3504 MUST_BE_OK (insn);
3507 static void
3508 rl78_alloc_address_registers_macax (rtx_insn * insn)
3510 int which, op;
3511 bool replace_in_op0 = false;
3512 bool replace_in_op1 = false;
3514 MAYBE_OK (insn);
3516 /* Two different MEMs are not allowed. */
3517 which = 0;
3518 for (op = 2; op >= 0; op --)
3520 if (MEM_P (OP (op)))
3522 if (op == 0 && replace_in_op0)
3523 continue;
3524 if (op == 1 && replace_in_op1)
3525 continue;
3527 switch (which)
3529 case 0:
3530 /* If we replace a MEM, make sure that we replace it for all
3531 occurrences of the same MEM in the insn. */
3532 replace_in_op0 = (op > 0 && rtx_equal_p (OP (op), OP (0)));
3533 replace_in_op1 = (op > 1 && rtx_equal_p (OP (op), OP (1)));
3535 OP (op) = transcode_memory_rtx (OP (op), HL, insn);
3536 if (op == 2
3537 && MEM_P (OP (op))
3538 && ((GET_CODE (XEXP (OP (op), 0)) == REG
3539 && REGNO (XEXP (OP (op), 0)) == SP_REG)
3540 || (GET_CODE (XEXP (OP (op), 0)) == PLUS
3541 && REGNO (XEXP (XEXP (OP (op), 0), 0)) == SP_REG)))
3543 emit_insn_before (gen_movhi (HL, gen_rtx_REG (HImode, SP_REG)), insn);
3544 OP (op) = replace_rtx (OP (op), gen_rtx_REG (HImode, SP_REG), HL);
3546 if (replace_in_op0)
3547 OP (0) = OP (op);
3548 if (replace_in_op1)
3549 OP (1) = OP (op);
3550 break;
3551 case 1:
3552 OP (op) = transcode_memory_rtx (OP (op), DE, insn);
3553 break;
3554 case 2:
3555 OP (op) = transcode_memory_rtx (OP (op), BC, insn);
3556 break;
3558 which ++;
3562 MUST_BE_OK (insn);
3565 static void
3566 rl78_alloc_address_registers_div (rtx_insn * insn)
3568 MUST_BE_OK (insn);
3571 /* Scan all insns and devirtualize them. */
3572 static void
3573 rl78_alloc_physical_registers (void)
3575 /* During most of the compile, gcc is dealing with virtual
3576 registers. At this point, we need to assign physical registers
3577 to the vitual ones, and copy in/out as needed. */
3579 rtx_insn *insn, *curr;
3580 enum attr_valloc valloc_method;
3582 for (insn = get_insns (); insn; insn = curr)
3584 int i;
3586 curr = next_nonnote_nondebug_insn (insn);
3588 if (INSN_P (insn)
3589 && (GET_CODE (PATTERN (insn)) == SET
3590 || GET_CODE (PATTERN (insn)) == CALL)
3591 && INSN_CODE (insn) == -1)
3593 if (GET_CODE (SET_SRC (PATTERN (insn))) == ASM_OPERANDS)
3594 continue;
3595 i = recog (PATTERN (insn), insn, 0);
3596 if (i == -1)
3598 debug_rtx (insn);
3599 gcc_unreachable ();
3601 INSN_CODE (insn) = i;
3605 cfun->machine->virt_insns_ok = 0;
3606 cfun->machine->real_insns_ok = 1;
3608 clear_content_memory ();
3610 for (insn = get_insns (); insn; insn = curr)
3612 rtx pattern;
3614 curr = insn ? next_nonnote_nondebug_insn (insn) : NULL;
3616 if (!INSN_P (insn))
3618 if (LABEL_P (insn))
3619 clear_content_memory ();
3621 continue;
3624 if (dump_file)
3625 fprintf (dump_file, "Converting insn %d\n", INSN_UID (insn));
3627 pattern = PATTERN (insn);
3628 if (GET_CODE (pattern) == PARALLEL)
3629 pattern = XVECEXP (pattern, 0, 0);
3630 if (JUMP_P (insn) || CALL_P (insn) || GET_CODE (pattern) == CALL)
3631 clear_content_memory ();
3632 if (GET_CODE (pattern) != SET
3633 && GET_CODE (pattern) != CALL)
3634 continue;
3635 if (GET_CODE (pattern) == SET
3636 && GET_CODE (SET_SRC (pattern)) == ASM_OPERANDS)
3637 continue;
3639 valloc_method = get_attr_valloc (insn);
3641 PATTERN (insn) = copy_rtx_if_shared (PATTERN (insn));
3643 if (valloc_method == VALLOC_MACAX)
3645 record_content (AX, NULL_RTX);
3646 record_content (BC, NULL_RTX);
3647 record_content (DE, NULL_RTX);
3649 else if (valloc_method == VALLOC_DIVHI)
3651 record_content (AX, NULL_RTX);
3652 record_content (BC, NULL_RTX);
3654 else if (valloc_method == VALLOC_DIVSI)
3656 record_content (AX, NULL_RTX);
3657 record_content (BC, NULL_RTX);
3658 record_content (DE, NULL_RTX);
3659 record_content (HL, NULL_RTX);
3662 if (insn_ok_now (insn))
3663 continue;
3665 INSN_CODE (insn) = -1;
3667 if (RTX_FRAME_RELATED_P (insn))
3668 virt_insn_was_frame = 1;
3669 else
3670 virt_insn_was_frame = 0;
3672 switch (valloc_method)
3674 case VALLOC_OP1:
3675 rl78_alloc_physical_registers_op1 (insn);
3676 break;
3677 case VALLOC_OP2:
3678 rl78_alloc_physical_registers_op2 (insn);
3679 break;
3680 case VALLOC_RO1:
3681 rl78_alloc_physical_registers_ro1 (insn);
3682 break;
3683 case VALLOC_CMP:
3684 rl78_alloc_physical_registers_cmp (insn);
3685 break;
3686 case VALLOC_UMUL:
3687 rl78_alloc_physical_registers_umul (insn);
3688 record_content (AX, NULL_RTX);
3689 break;
3690 case VALLOC_MACAX:
3691 /* Macro that clobbers AX. */
3692 rl78_alloc_address_registers_macax (insn);
3693 record_content (AX, NULL_RTX);
3694 record_content (BC, NULL_RTX);
3695 record_content (DE, NULL_RTX);
3696 break;
3697 case VALLOC_DIVSI:
3698 rl78_alloc_address_registers_div (insn);
3699 record_content (AX, NULL_RTX);
3700 record_content (BC, NULL_RTX);
3701 record_content (DE, NULL_RTX);
3702 record_content (HL, NULL_RTX);
3703 break;
3704 case VALLOC_DIVHI:
3705 rl78_alloc_address_registers_div (insn);
3706 record_content (AX, NULL_RTX);
3707 record_content (BC, NULL_RTX);
3708 break;
3709 default:
3710 gcc_unreachable ();
3713 if (JUMP_P (insn) || CALL_P (insn) || GET_CODE (pattern) == CALL)
3714 clear_content_memory ();
3715 else
3716 process_postponed_content_update ();
3719 #if DEBUG_ALLOC
3720 fprintf (stderr, "\033[0m");
3721 #endif
3724 /* Add REG_DEAD notes using DEAD[reg] for rtx S which is part of INSN.
3725 This function scans for uses of registers; the last use (i.e. first
3726 encounter when scanning backwards) triggers a REG_DEAD note if the
3727 reg was previously in DEAD[]. */
3728 static void
3729 rl78_note_reg_uses (char *dead, rtx s, rtx insn)
3731 const char *fmt;
3732 int i, r;
3733 enum rtx_code code;
3735 if (!s)
3736 return;
3738 code = GET_CODE (s);
3740 switch (code)
3742 /* Compare registers by number. */
3743 case REG:
3744 r = REGNO (s);
3745 if (dump_file)
3747 fprintf (dump_file, "note use reg %d size %d on insn %d\n",
3748 r, GET_MODE_SIZE (GET_MODE (s)), INSN_UID (insn));
3749 print_rtl_single (dump_file, s);
3751 if (dead [r])
3752 add_reg_note (insn, REG_DEAD, gen_rtx_REG (GET_MODE (s), r));
3753 for (i = 0; i < GET_MODE_SIZE (GET_MODE (s)); i ++)
3754 dead [r + i] = 0;
3755 return;
3757 /* These codes have no constituent expressions
3758 and are unique. */
3759 case SCRATCH:
3760 case CC0:
3761 case PC:
3762 return;
3764 case CONST_INT:
3765 case CONST_VECTOR:
3766 case CONST_DOUBLE:
3767 case CONST_FIXED:
3768 /* These are kept unique for a given value. */
3769 return;
3771 default:
3772 break;
3775 fmt = GET_RTX_FORMAT (code);
3777 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
3779 if (fmt[i] == 'E')
3781 int j;
3782 for (j = XVECLEN (s, i) - 1; j >= 0; j--)
3783 rl78_note_reg_uses (dead, XVECEXP (s, i, j), insn);
3785 else if (fmt[i] == 'e')
3786 rl78_note_reg_uses (dead, XEXP (s, i), insn);
3790 /* Like the previous function, but scan for SETs instead. */
3791 static void
3792 rl78_note_reg_set (char *dead, rtx d, rtx insn)
3794 int r, i;
3795 bool is_dead;
3796 if (GET_CODE (d) == MEM)
3797 rl78_note_reg_uses (dead, XEXP (d, 0), insn);
3799 if (GET_CODE (d) != REG)
3800 return;
3802 /* Do not mark the reg unused unless all QImode parts of it are dead. */
3803 r = REGNO (d);
3804 is_dead = true;
3805 for (i = 0; i < GET_MODE_SIZE (GET_MODE (d)); i ++)
3806 if (!dead [r + i])
3807 is_dead = false;
3808 if(is_dead)
3809 add_reg_note (insn, REG_UNUSED, gen_rtx_REG (GET_MODE (d), r));
3810 if (dump_file)
3811 fprintf (dump_file, "note set reg %d size %d\n", r, GET_MODE_SIZE (GET_MODE (d)));
3812 for (i = 0; i < GET_MODE_SIZE (GET_MODE (d)); i ++)
3813 dead [r + i] = 1;
3816 /* This is a rather crude register death pass. Death status is reset
3817 at every jump or call insn. */
3818 static void
3819 rl78_calculate_death_notes (void)
3821 char dead[FIRST_PSEUDO_REGISTER];
3822 rtx p, s, d;
3823 rtx_insn *insn;
3824 int i;
3826 memset (dead, 0, sizeof (dead));
3828 for (insn = get_last_insn ();
3829 insn;
3830 insn = prev_nonnote_nondebug_insn (insn))
3832 if (dump_file)
3834 fprintf (dump_file, "\n--------------------------------------------------");
3835 fprintf (dump_file, "\nDead:");
3836 for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
3837 if (dead[i])
3838 fprintf (dump_file, " %s", reg_names[i]);
3839 fprintf (dump_file, "\n");
3840 print_rtl_single (dump_file, insn);
3843 switch (GET_CODE (insn))
3845 case INSN:
3846 p = PATTERN (insn);
3847 if (GET_CODE (p) == PARALLEL)
3849 rtx q = XVECEXP (p, 0 ,1);
3851 /* This happens with the DIV patterns. */
3852 if (GET_CODE (q) == SET)
3854 s = SET_SRC (q);
3855 d = SET_DEST (q);
3856 rl78_note_reg_set (dead, d, insn);
3857 rl78_note_reg_uses (dead, s, insn);
3860 p = XVECEXP (p, 0, 0);
3863 switch (GET_CODE (p))
3865 case SET:
3866 s = SET_SRC (p);
3867 d = SET_DEST (p);
3868 rl78_note_reg_set (dead, d, insn);
3869 rl78_note_reg_uses (dead, s, insn);
3870 break;
3872 case USE:
3873 rl78_note_reg_uses (dead, p, insn);
3874 break;
3876 default:
3877 break;
3879 break;
3881 case JUMP_INSN:
3882 if (INSN_CODE (insn) == CODE_FOR_rl78_return)
3884 memset (dead, 1, sizeof (dead));
3885 /* We expect a USE just prior to this, which will mark
3886 the actual return registers. The USE will have a
3887 death note, but we aren't going to be modifying it
3888 after this pass. */
3889 break;
3891 /* FALLTHRU */
3892 case CALL_INSN:
3893 memset (dead, 0, sizeof (dead));
3894 break;
3896 default:
3897 break;
3899 if (dump_file)
3900 print_rtl_single (dump_file, insn);
3904 /* Helper function to reset the origins in RP and the age in AGE for
3905 all registers. */
3906 static void
3907 reset_origins (int *rp, int *age)
3909 int i;
3910 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3912 rp[i] = i;
3913 age[i] = 0;
3917 static void
3918 set_origin (rtx pat, rtx_insn * insn, int * origins, int * age)
3920 rtx src = SET_SRC (pat);
3921 rtx dest = SET_DEST (pat);
3922 int mb = GET_MODE_SIZE (GET_MODE (dest));
3923 int i;
3925 if (GET_CODE (dest) == REG)
3927 int dr = REGNO (dest);
3929 if (GET_CODE (src) == REG)
3931 int sr = REGNO (src);
3932 bool same = true;
3933 int best_age, best_reg;
3935 /* See if the copy is not needed. */
3936 for (i = 0; i < mb; i ++)
3937 if (origins[dr + i] != origins[sr + i])
3938 same = false;
3940 if (same)
3942 if (dump_file)
3943 fprintf (dump_file, "deleting because dest already has correct value\n");
3944 delete_insn (insn);
3945 return;
3948 if (dr < 8 || sr >= 8)
3950 int ar;
3952 best_age = -1;
3953 best_reg = -1;
3955 /* See if the copy can be made from another
3956 bank 0 register instead, instead of the
3957 virtual src register. */
3958 for (ar = 0; ar < 8; ar += mb)
3960 same = true;
3962 for (i = 0; i < mb; i ++)
3963 if (origins[ar + i] != origins[sr + i])
3964 same = false;
3966 /* The chip has some reg-reg move limitations. */
3967 if (mb == 1 && dr > 3)
3968 same = false;
3970 if (same)
3972 if (best_age == -1 || best_age > age[sr + i])
3974 best_age = age[sr + i];
3975 best_reg = sr;
3980 if (best_reg != -1)
3982 /* FIXME: copy debug info too. */
3983 SET_SRC (pat) = gen_rtx_REG (GET_MODE (src), best_reg);
3984 sr = best_reg;
3988 for (i = 0; i < mb; i++)
3990 origins[dr + i] = origins[sr + i];
3991 age[dr + i] = age[sr + i] + 1;
3994 else
3996 /* The destination is computed, its origin is itself. */
3997 if (dump_file)
3998 fprintf (dump_file, "resetting origin of r%d for %d byte%s\n",
3999 dr, mb, mb == 1 ? "" : "s");
4001 for (i = 0; i < mb; i ++)
4003 origins[dr + i] = dr + i;
4004 age[dr + i] = 0;
4008 /* Any registers marked with that reg as an origin are reset. */
4009 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4010 if (origins[i] >= dr && origins[i] < dr + mb)
4012 origins[i] = i;
4013 age[i] = 0;
4017 /* Special case - our MUL patterns uses AX and sometimes BC. */
4018 if (get_attr_valloc (insn) == VALLOC_MACAX)
4020 if (dump_file)
4021 fprintf (dump_file, "Resetting origin of AX/BC for MUL pattern.\n");
4023 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4024 if (i <= 3 || origins[i] <= 3)
4026 origins[i] = i;
4027 age[i] = 0;
4030 else if (get_attr_valloc (insn) == VALLOC_DIVHI)
4032 if (dump_file)
4033 fprintf (dump_file, "Resetting origin of AX/DE for DIVHI pattern.\n");
4035 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4036 if (i == A_REG
4037 || i == X_REG
4038 || i == D_REG
4039 || i == E_REG
4040 || origins[i] == A_REG
4041 || origins[i] == X_REG
4042 || origins[i] == D_REG
4043 || origins[i] == E_REG)
4045 origins[i] = i;
4046 age[i] = 0;
4049 else if (get_attr_valloc (insn) == VALLOC_DIVSI)
4051 if (dump_file)
4052 fprintf (dump_file, "Resetting origin of AX/BC/DE/HL for DIVSI pattern.\n");
4054 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4055 if (i <= 7 || origins[i] <= 7)
4057 origins[i] = i;
4058 age[i] = 0;
4062 if (GET_CODE (src) == ASHIFT
4063 || GET_CODE (src) == ASHIFTRT
4064 || GET_CODE (src) == LSHIFTRT)
4066 rtx count = XEXP (src, 1);
4068 if (GET_CODE (count) == REG)
4070 /* Special case - our pattern clobbers the count register. */
4071 int r = REGNO (count);
4073 if (dump_file)
4074 fprintf (dump_file, "Resetting origin of r%d for shift.\n", r);
4076 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4077 if (i == r || origins[i] == r)
4079 origins[i] = i;
4080 age[i] = 0;
4086 /* The idea behind this optimization is to look for cases where we
4087 move data from A to B to C, and instead move from A to B, and A to
4088 C. If B is a virtual register or memory, this is a big win on its
4089 own. If B turns out to be unneeded after this, it's a bigger win.
4090 For each register, we try to determine where it's value originally
4091 came from, if it's propogated purely through moves (and not
4092 computes). The ORIGINS[] array has the regno for the "origin" of
4093 the value in the [regno] it's indexed by. */
4094 static void
4095 rl78_propogate_register_origins (void)
4097 int origins[FIRST_PSEUDO_REGISTER];
4098 int age[FIRST_PSEUDO_REGISTER];
4099 int i;
4100 rtx_insn *insn, *ninsn = NULL;
4101 rtx pat;
4103 reset_origins (origins, age);
4105 for (insn = get_insns (); insn; insn = ninsn)
4107 ninsn = next_nonnote_nondebug_insn (insn);
4109 if (dump_file)
4111 fprintf (dump_file, "\n");
4112 fprintf (dump_file, "Origins:");
4113 for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
4114 if (origins[i] != i)
4115 fprintf (dump_file, " r%d=r%d", i, origins[i]);
4116 fprintf (dump_file, "\n");
4117 print_rtl_single (dump_file, insn);
4120 switch (GET_CODE (insn))
4122 case CODE_LABEL:
4123 case BARRIER:
4124 case CALL_INSN:
4125 case JUMP_INSN:
4126 reset_origins (origins, age);
4127 break;
4129 default:
4130 break;
4132 case INSN:
4133 pat = PATTERN (insn);
4135 if (GET_CODE (pat) == PARALLEL)
4137 rtx clobber = XVECEXP (pat, 0, 1);
4138 pat = XVECEXP (pat, 0, 0);
4139 if (GET_CODE (clobber) == CLOBBER
4140 && GET_CODE (XEXP (clobber, 0)) == REG)
4142 int cr = REGNO (XEXP (clobber, 0));
4143 int mb = GET_MODE_SIZE (GET_MODE (XEXP (clobber, 0)));
4144 if (dump_file)
4145 fprintf (dump_file, "reset origins of %d regs at %d\n", mb, cr);
4146 for (i = 0; i < mb; i++)
4148 origins[cr + i] = cr + i;
4149 age[cr + i] = 0;
4152 /* This happens with the DIV patterns. */
4153 else if (GET_CODE (clobber) == SET)
4155 set_origin (clobber, insn, origins, age);
4157 else
4158 break;
4161 if (GET_CODE (pat) == SET)
4163 set_origin (pat, insn, origins, age);
4165 else if (GET_CODE (pat) == CLOBBER
4166 && GET_CODE (XEXP (pat, 0)) == REG)
4168 if (REG_P (XEXP (pat, 0)))
4170 unsigned int reg = REGNO (XEXP (pat, 0));
4172 origins[reg] = reg;
4173 age[reg] = 0;
4180 /* Remove any SETs where the destination is unneeded. */
4181 static void
4182 rl78_remove_unused_sets (void)
4184 rtx_insn *insn, *ninsn = NULL;
4185 rtx dest;
4187 for (insn = get_insns (); insn; insn = ninsn)
4189 ninsn = next_nonnote_nondebug_insn (insn);
4191 rtx set = single_set (insn);
4192 if (set == NULL)
4193 continue;
4195 dest = SET_DEST (set);
4197 if (GET_CODE (dest) != REG || REGNO (dest) > 23)
4198 continue;
4200 if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
4202 if (dump_file)
4203 fprintf (dump_file, "deleting because the set register is never used.\n");
4204 delete_insn (insn);
4209 /* This is the top of the devritualization pass. */
4210 static void
4211 rl78_reorg (void)
4213 /* split2 only happens when optimizing, but we need all movSIs to be
4214 split now. */
4215 if (optimize <= 0)
4216 split_all_insns ();
4218 rl78_alloc_physical_registers ();
4220 if (dump_file)
4222 fprintf (dump_file, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n");
4223 print_rtl_with_bb (dump_file, get_insns (), 0);
4226 rl78_propogate_register_origins ();
4227 rl78_calculate_death_notes ();
4229 if (dump_file)
4231 fprintf (dump_file, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n");
4232 print_rtl_with_bb (dump_file, get_insns (), 0);
4233 fprintf (dump_file, "\n======================================================================\n");
4236 rl78_remove_unused_sets ();
4238 /* The code after devirtualizing has changed so much that at this point
4239 we might as well just rescan everything. Note that
4240 df_rescan_all_insns is not going to help here because it does not
4241 touch the artificial uses and defs. */
4242 df_finish_pass (true);
4243 if (optimize > 1)
4244 df_live_add_problem ();
4245 df_scan_alloc (NULL);
4246 df_scan_blocks ();
4248 if (optimize)
4249 df_analyze ();
4252 #undef TARGET_RETURN_IN_MEMORY
4253 #define TARGET_RETURN_IN_MEMORY rl78_return_in_memory
4255 static bool
4256 rl78_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
4258 const HOST_WIDE_INT size = int_size_in_bytes (type);
4259 return (size == -1 || size > 8);
4263 #undef TARGET_RTX_COSTS
4264 #define TARGET_RTX_COSTS rl78_rtx_costs
4266 static bool
4267 rl78_rtx_costs (rtx x,
4268 machine_mode mode,
4269 int outer_code ATTRIBUTE_UNUSED,
4270 int opno ATTRIBUTE_UNUSED,
4271 int * total,
4272 bool speed ATTRIBUTE_UNUSED)
4274 int code = GET_CODE (x);
4276 if (code == IF_THEN_ELSE)
4278 *total = COSTS_N_INSNS (10);
4279 return true;
4282 if (mode == HImode)
4284 if (code == MULT && ! speed)
4286 * total = COSTS_N_INSNS (8);
4287 return true;
4289 return false;
4292 if (mode == SImode)
4294 switch (code)
4296 case MULT:
4297 if (! speed)
4298 /* If we are compiling for space then we do not want to use the
4299 inline SImode multiplication patterns or shift sequences.
4300 The cost is not set to 1 or 5 however as we have to allow for
4301 the possibility that we might be converting a leaf function
4302 into a non-leaf function. (There is no way to tell here).
4303 A value of 13 seems to be a reasonable compromise for the
4304 moment. */
4305 * total = COSTS_N_INSNS (13);
4306 else if (RL78_MUL_G14)
4307 *total = COSTS_N_INSNS (14);
4308 else if (RL78_MUL_G13)
4309 *total = COSTS_N_INSNS (29);
4310 else
4311 *total = COSTS_N_INSNS (500);
4312 return true;
4314 case PLUS:
4315 *total = COSTS_N_INSNS (8);
4316 return true;
4318 case ASHIFT:
4319 case ASHIFTRT:
4320 case LSHIFTRT:
4321 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
4323 switch (INTVAL (XEXP (x, 1)))
4325 case 0: *total = COSTS_N_INSNS (0); break;
4326 case 1: *total = COSTS_N_INSNS (6); break;
4327 case 2: case 3: case 4: case 5: case 6: case 7:
4328 *total = COSTS_N_INSNS (10); break;
4329 case 8: *total = COSTS_N_INSNS (6); break;
4330 case 9: case 10: case 11: case 12: case 13: case 14: case 15:
4331 *total = COSTS_N_INSNS (10); break;
4332 case 16: *total = COSTS_N_INSNS (3); break;
4333 case 17: case 18: case 19: case 20: case 21: case 22: case 23:
4334 *total = COSTS_N_INSNS (4); break;
4335 case 24: *total = COSTS_N_INSNS (4); break;
4336 case 25: case 26: case 27: case 28: case 29: case 30: case 31:
4337 *total = COSTS_N_INSNS (5); break;
4340 else
4341 *total = COSTS_N_INSNS (10+4*16);
4342 return true;
4344 default:
4345 break;
4348 return false;
4352 static GTY(()) section * saddr_section;
4353 static GTY(()) section * frodata_section;
4356 rl78_saddr_p (rtx x)
4358 const char * c;
4360 if (MEM_P (x))
4361 x = XEXP (x, 0);
4362 if (GET_CODE (x) == PLUS)
4363 x = XEXP (x, 0);
4364 if (GET_CODE (x) != SYMBOL_REF)
4365 return 0;
4367 c = XSTR (x, 0);
4368 if (memcmp (c, "@s.", 3) == 0)
4369 return 1;
4371 return 0;
4375 rl78_sfr_p (rtx x)
4377 if (MEM_P (x))
4378 x = XEXP (x, 0);
4379 if (GET_CODE (x) != CONST_INT)
4380 return 0;
4382 if ((INTVAL (x) & 0xFF00) != 0xFF00)
4383 return 0;
4385 return 1;
4388 #undef TARGET_STRIP_NAME_ENCODING
4389 #define TARGET_STRIP_NAME_ENCODING rl78_strip_name_encoding
4391 static const char *
4392 rl78_strip_name_encoding (const char * sym)
4394 while (1)
4396 if (*sym == '*')
4397 sym++;
4398 else if (*sym == '@' && sym[2] == '.')
4399 sym += 3;
4400 else
4401 return sym;
4405 /* Like rl78_strip_name_encoding, but does not strip leading asterisks. This
4406 is important if the stripped name is going to be passed to assemble_name()
4407 as that handles asterisk prefixed names in a special manner. */
4409 static const char *
4410 rl78_strip_nonasm_name_encoding (const char * sym)
4412 while (1)
4414 if (*sym == '@' && sym[2] == '.')
4415 sym += 3;
4416 else
4417 return sym;
4422 static int
4423 rl78_attrlist_to_encoding (tree list, tree decl ATTRIBUTE_UNUSED)
4425 while (list)
4427 if (is_attribute_p ("saddr", TREE_PURPOSE (list)))
4428 return 's';
4429 list = TREE_CHAIN (list);
4432 return 0;
4435 #define RL78_ATTRIBUTES(decl) \
4436 (TYPE_P (decl)) ? TYPE_ATTRIBUTES (decl) \
4437 : DECL_ATTRIBUTES (decl) \
4438 ? (DECL_ATTRIBUTES (decl)) \
4439 : TYPE_ATTRIBUTES (TREE_TYPE (decl))
4441 #undef TARGET_ENCODE_SECTION_INFO
4442 #define TARGET_ENCODE_SECTION_INFO rl78_encode_section_info
4444 static void
4445 rl78_encode_section_info (tree decl, rtx rtl, int first)
4447 rtx rtlname;
4448 const char * oldname;
4449 char encoding;
4450 char * newname;
4451 tree idp;
4452 tree type;
4453 tree rl78_attributes;
4455 if (!first)
4456 return;
4458 rtlname = XEXP (rtl, 0);
4460 if (GET_CODE (rtlname) == SYMBOL_REF)
4461 oldname = XSTR (rtlname, 0);
4462 else if (GET_CODE (rtlname) == MEM
4463 && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
4464 oldname = XSTR (XEXP (rtlname, 0), 0);
4465 else
4466 gcc_unreachable ();
4468 type = TREE_TYPE (decl);
4469 if (type == error_mark_node)
4470 return;
4471 if (! DECL_P (decl))
4472 return;
4473 rl78_attributes = RL78_ATTRIBUTES (decl);
4475 encoding = rl78_attrlist_to_encoding (rl78_attributes, decl);
4477 if (encoding)
4479 newname = (char *) alloca (strlen (oldname) + 4);
4480 sprintf (newname, "@%c.%s", encoding, oldname);
4481 idp = get_identifier (newname);
4482 XEXP (rtl, 0) =
4483 gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
4484 SYMBOL_REF_WEAK (XEXP (rtl, 0)) = DECL_WEAK (decl);
4485 SET_SYMBOL_REF_DECL (XEXP (rtl, 0), decl);
4489 #undef TARGET_ASM_INIT_SECTIONS
4490 #define TARGET_ASM_INIT_SECTIONS rl78_asm_init_sections
4492 static void
4493 rl78_asm_init_sections (void)
4495 saddr_section
4496 = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
4497 "\t.section .saddr,\"aw\",@progbits");
4498 frodata_section
4499 = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
4500 "\t.section .frodata,\"aw\",@progbits");
4503 #undef TARGET_ASM_SELECT_SECTION
4504 #define TARGET_ASM_SELECT_SECTION rl78_select_section
4506 static section *
4507 rl78_select_section (tree decl,
4508 int reloc,
4509 unsigned HOST_WIDE_INT align)
4511 int readonly = 1;
4513 switch (TREE_CODE (decl))
4515 case VAR_DECL:
4516 if (!TREE_READONLY (decl)
4517 || TREE_SIDE_EFFECTS (decl)
4518 || !DECL_INITIAL (decl)
4519 || (DECL_INITIAL (decl) != error_mark_node
4520 && !TREE_CONSTANT (DECL_INITIAL (decl))))
4521 readonly = 0;
4522 break;
4523 case CONSTRUCTOR:
4524 if (! TREE_CONSTANT (decl))
4525 readonly = 0;
4526 break;
4528 default:
4529 break;
4532 if (TREE_CODE (decl) == VAR_DECL)
4534 const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
4536 if (name[0] == '@' && name[2] == '.')
4537 switch (name[1])
4539 case 's':
4540 return saddr_section;
4543 if (TYPE_ADDR_SPACE (TREE_TYPE (decl)) == ADDR_SPACE_FAR
4544 && readonly)
4546 return frodata_section;
4550 if (readonly)
4551 return TARGET_ES0 ? frodata_section : readonly_data_section;
4553 switch (categorize_decl_for_section (decl, reloc))
4555 case SECCAT_TEXT: return text_section;
4556 case SECCAT_DATA: return data_section;
4557 case SECCAT_BSS: return bss_section;
4558 case SECCAT_RODATA: return TARGET_ES0 ? frodata_section : readonly_data_section;
4559 default:
4560 return default_select_section (decl, reloc, align);
4564 void
4565 rl78_output_labelref (FILE *file, const char *str)
4567 const char *str2;
4569 str2 = targetm.strip_name_encoding (str);
4570 if (str2[0] != '.')
4571 fputs (user_label_prefix, file);
4572 fputs (str2, file);
4575 void
4576 rl78_output_aligned_common (FILE *stream,
4577 tree decl ATTRIBUTE_UNUSED,
4578 const char *name,
4579 int size, int align, int global)
4581 /* We intentionally don't use rl78_section_tag() here. */
4582 if (name[0] == '@' && name[2] == '.')
4584 const char *sec = 0;
4585 switch (name[1])
4587 case 's':
4588 switch_to_section (saddr_section);
4589 sec = ".saddr";
4590 break;
4592 if (sec)
4594 const char *name2;
4595 int p2align = 0;
4597 while (align > BITS_PER_UNIT)
4599 align /= 2;
4600 p2align ++;
4602 name2 = targetm.strip_name_encoding (name);
4603 if (global)
4604 fprintf (stream, "\t.global\t_%s\n", name2);
4605 fprintf (stream, "\t.p2align %d\n", p2align);
4606 fprintf (stream, "\t.type\t_%s,@object\n", name2);
4607 fprintf (stream, "\t.size\t_%s,%d\n", name2, size);
4608 fprintf (stream, "_%s:\n\t.zero\t%d\n", name2, size);
4609 return;
4613 if (!global)
4615 fprintf (stream, "\t.local\t");
4616 assemble_name (stream, name);
4617 fprintf (stream, "\n");
4619 fprintf (stream, "\t.comm\t");
4620 assemble_name (stream, name);
4621 fprintf (stream, ",%u,%u\n", size, align / BITS_PER_UNIT);
4624 #undef TARGET_INSERT_ATTRIBUTES
4625 #define TARGET_INSERT_ATTRIBUTES rl78_insert_attributes
4627 static void
4628 rl78_insert_attributes (tree decl, tree *attributes ATTRIBUTE_UNUSED)
4630 if (TARGET_ES0
4631 && TREE_CODE (decl) == VAR_DECL
4632 && TREE_READONLY (decl)
4633 && TREE_ADDRESSABLE (decl)
4634 && TYPE_ADDR_SPACE (TREE_TYPE (decl)) == ADDR_SPACE_GENERIC)
4636 tree type = TREE_TYPE (decl);
4637 tree attr = TYPE_ATTRIBUTES (type);
4638 int q = TYPE_QUALS_NO_ADDR_SPACE (type) | ENCODE_QUAL_ADDR_SPACE (ADDR_SPACE_FAR);
4640 TREE_TYPE (decl) = build_type_attribute_qual_variant (type, attr, q);
4644 #undef TARGET_ASM_INTEGER
4645 #define TARGET_ASM_INTEGER rl78_asm_out_integer
4647 static bool
4648 rl78_asm_out_integer (rtx x, unsigned int size, int aligned_p)
4650 if (default_assemble_integer (x, size, aligned_p))
4651 return true;
4653 if (size == 4)
4655 assemble_integer_with_op (".long\t", x);
4656 return true;
4659 return false;
4662 #undef TARGET_UNWIND_WORD_MODE
4663 #define TARGET_UNWIND_WORD_MODE rl78_unwind_word_mode
4665 static scalar_int_mode
4666 rl78_unwind_word_mode (void)
4668 return HImode;
4671 #ifndef USE_COLLECT2
4672 #undef TARGET_ASM_CONSTRUCTOR
4673 #define TARGET_ASM_CONSTRUCTOR rl78_asm_constructor
4674 #undef TARGET_ASM_DESTRUCTOR
4675 #define TARGET_ASM_DESTRUCTOR rl78_asm_destructor
4677 static void
4678 rl78_asm_ctor_dtor (rtx symbol, int priority, bool is_ctor)
4680 section *sec;
4682 if (priority != DEFAULT_INIT_PRIORITY)
4684 /* This section of the function is based upon code copied
4685 from: gcc/varasm.c:get_cdtor_priority_section(). */
4686 char buf[18];
4688 sprintf (buf, "%s.%.5u", is_ctor ? ".ctors" : ".dtors",
4689 MAX_INIT_PRIORITY - priority);
4690 sec = get_section (buf, 0, NULL);
4692 else
4693 sec = is_ctor ? ctors_section : dtors_section;
4695 assemble_addr_to_section (symbol, sec);
4698 static void
4699 rl78_asm_constructor (rtx symbol, int priority)
4701 rl78_asm_ctor_dtor (symbol, priority, true);
4704 static void
4705 rl78_asm_destructor (rtx symbol, int priority)
4707 rl78_asm_ctor_dtor (symbol, priority, false);
4709 #endif /* ! USE_COLLECT2 */
4711 /* Scan backwards through the insn chain looking to see if the flags
4712 have been set for a comparison of OP against OPERAND. Start with
4713 the insn *before* the current insn. */
4715 bool
4716 rl78_flags_already_set (rtx op, rtx operand)
4718 /* We only track the Z flag. */
4719 if (GET_CODE (op) != EQ && GET_CODE (op) != NE)
4720 return false;
4722 /* This should not happen, but let's be paranoid. */
4723 if (current_output_insn == NULL_RTX)
4724 return false;
4726 rtx_insn *insn;
4727 bool res = false;
4729 for (insn = prev_nonnote_nondebug_insn (current_output_insn);
4730 insn != NULL_RTX;
4731 insn = prev_nonnote_nondebug_insn (insn))
4733 if (LABEL_P (insn))
4734 break;
4736 if (! INSN_P (insn))
4737 continue;
4739 /* Make sure that the insn can be recognized. */
4740 if (recog_memoized (insn) == -1)
4741 continue;
4743 enum attr_update_Z updated = get_attr_update_Z (insn);
4745 rtx set = single_set (insn);
4746 bool must_break = (set != NULL_RTX && rtx_equal_p (operand, SET_DEST (set)));
4748 switch (updated)
4750 case UPDATE_Z_NO:
4751 break;
4752 case UPDATE_Z_CLOBBER:
4753 must_break = true;
4754 break;
4755 case UPDATE_Z_UPDATE_Z:
4756 res = must_break;
4757 must_break = true;
4758 break;
4759 default:
4760 gcc_unreachable ();
4763 if (must_break)
4764 break;
4767 /* We have to re-recognize the current insn as the call(s) to
4768 get_attr_update_Z() above will have overwritten the recog_data cache. */
4769 recog_memoized (current_output_insn);
4770 cleanup_subreg_operands (current_output_insn);
4771 constrain_operands_cached (current_output_insn, 1);
4773 return res;
4776 const char *
4777 rl78_addsi3_internal (rtx * operands, unsigned int alternative)
4779 /* If we are adding in a constant symbolic address when -mes0
4780 is active then we know that the address must be <64K and
4781 that it is invalid to access anything above 64K relative to
4782 this address. So we can skip adding in the high bytes. */
4783 if (TARGET_ES0
4784 && GET_CODE (operands[2]) == SYMBOL_REF
4785 && TREE_CODE (SYMBOL_REF_DECL (operands[2])) == VAR_DECL
4786 && TREE_READONLY (SYMBOL_REF_DECL (operands[2]))
4787 && ! TREE_SIDE_EFFECTS (SYMBOL_REF_DECL (operands[2])))
4788 return "movw ax, %h1\n\taddw ax, %h2\n\tmovw %h0, ax";
4790 switch (alternative)
4792 case 0:
4793 case 1:
4794 return "movw ax, %h1\n\taddw ax, %h2\n\tmovw %h0, ax\n\tmovw ax, %H1\n\tsknc\n\tincw ax\n\taddw ax, %H2\n\tmovw %H0, ax";
4795 case 2:
4796 return "movw ax, %h1\n\taddw ax,%h2\n\tmovw bc, ax\n\tmovw ax, %H1\n\tsknc\n\tincw ax\n\taddw ax, %H2\n\tmovw %H0, ax\n\tmovw ax, bc\n\tmovw %h0, ax";
4797 default:
4798 gcc_unreachable ();
4803 rl78_emit_libcall (const char *name, enum rtx_code code,
4804 enum machine_mode dmode, enum machine_mode smode,
4805 int noperands, rtx *operands)
4807 rtx ret;
4808 rtx_insn *insns;
4809 rtx libcall;
4810 rtx equiv;
4812 start_sequence ();
4813 libcall = gen_rtx_SYMBOL_REF (Pmode, name);
4815 switch (noperands)
4817 case 2:
4818 ret = emit_library_call_value (libcall, NULL_RTX, LCT_CONST,
4819 dmode, operands[1], smode);
4820 equiv = gen_rtx_fmt_e (code, dmode, operands[1]);
4821 break;
4823 case 3:
4824 ret = emit_library_call_value (libcall, NULL_RTX,
4825 LCT_CONST, dmode,
4826 operands[1], smode, operands[2],
4827 smode);
4828 equiv = gen_rtx_fmt_ee (code, dmode, operands[1], operands[2]);
4829 break;
4831 default:
4832 gcc_unreachable ();
4835 insns = get_insns ();
4836 end_sequence ();
4837 emit_libcall_block (insns, operands[0], ret, equiv);
4838 return ret;
4842 #undef TARGET_PREFERRED_RELOAD_CLASS
4843 #define TARGET_PREFERRED_RELOAD_CLASS rl78_preferred_reload_class
4845 static reg_class_t
4846 rl78_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, reg_class_t rclass)
4848 if (rclass == NO_REGS)
4849 rclass = V_REGS;
4851 return rclass;
4855 struct gcc_target targetm = TARGET_INITIALIZER;
4857 #include "gt-rl78.h"