Fix version check for ATTRIBUTE_GCC_DUMP_PRINTF
[official-gcc.git] / gcc / config / rl78 / rl78.c
blob03c78fc7549f2e712b0bc79d4a94497a5051f9b8
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 /* used by rl78_addsi3_internal for formatting insns output */
84 static char fmt_buffer[1024];
86 /* Structure for G13 MDUC registers. */
87 struct mduc_reg_type
89 unsigned int address;
90 enum machine_mode mode;
93 struct mduc_reg_type mduc_regs[] =
95 {0xf00e8, E_QImode},
96 {0xffff0, E_HImode},
97 {0xffff2, E_HImode},
98 {0xf2224, E_HImode},
99 {0xf00e0, E_HImode},
100 {0xf00e2, E_HImode}
103 struct GTY(()) machine_function
105 /* If set, the rest of the fields have been computed. */
106 int computed;
107 /* Which register pairs need to be pushed in the prologue. */
108 int need_to_push [FIRST_PSEUDO_REGISTER / 2];
110 /* These fields describe the frame layout... */
111 /* arg pointer */
112 /* 4 bytes for saved PC */
113 int framesize_regs;
114 /* frame pointer */
115 int framesize_locals;
116 int framesize_outgoing;
117 /* stack pointer */
118 int framesize;
120 /* If set, recog is allowed to match against the "real" patterns. */
121 int real_insns_ok;
122 /* If set, recog is allowed to match against the "virtual" patterns. */
123 int virt_insns_ok;
124 /* Set if the current function needs to clean up any trampolines. */
125 int trampolines_used;
126 /* True if the ES register is used and hence
127 needs to be saved inside interrupt handlers. */
128 bool uses_es;
131 /* This is our init_machine_status, as set in
132 rl78_option_override. */
133 static struct machine_function *
134 rl78_init_machine_status (void)
136 struct machine_function *m;
138 m = ggc_cleared_alloc<machine_function> ();
139 m->virt_insns_ok = 1;
141 return m;
144 /* This pass converts virtual instructions using virtual registers, to
145 real instructions using real registers. Rather than run it as
146 reorg, we reschedule it before vartrack to help with debugging. */
147 namespace
149 const pass_data pass_data_rl78_devirt =
151 RTL_PASS, /* type */
152 "devirt", /* name */
153 OPTGROUP_NONE, /* optinfo_flags */
154 TV_MACH_DEP, /* tv_id */
155 0, /* properties_required */
156 0, /* properties_provided */
157 0, /* properties_destroyed */
158 0, /* todo_flags_start */
159 0, /* todo_flags_finish */
162 class pass_rl78_devirt : public rtl_opt_pass
164 public:
165 pass_rl78_devirt (gcc::context *ctxt)
166 : rtl_opt_pass (pass_data_rl78_devirt, ctxt)
170 /* opt_pass methods: */
171 virtual unsigned int execute (function *)
173 rl78_reorg ();
174 return 0;
177 } // anon namespace
179 rtl_opt_pass *
180 make_pass_rl78_devirt (gcc::context *ctxt)
182 return new pass_rl78_devirt (ctxt);
185 /* Redundant move elimination pass. Must be run after the basic block
186 reordering pass for the best effect. */
188 static unsigned int
189 move_elim_pass (void)
191 rtx_insn *insn, *ninsn;
192 rtx prev = NULL_RTX;
194 for (insn = get_insns (); insn; insn = ninsn)
196 rtx set;
198 ninsn = next_nonnote_nondebug_insn (insn);
200 if ((set = single_set (insn)) == NULL_RTX)
202 prev = NULL_RTX;
203 continue;
206 /* If we have two SET insns in a row (without anything
207 between them) and the source of the second one is the
208 destination of the first one, and vice versa, then we
209 can eliminate the second SET. */
210 if (prev
211 && rtx_equal_p (SET_DEST (prev), SET_SRC (set))
212 && rtx_equal_p (SET_DEST (set), SET_SRC (prev))
213 /* ... and none of the operands are volatile. */
214 && ! volatile_refs_p (SET_SRC (prev))
215 && ! volatile_refs_p (SET_DEST (prev))
216 && ! volatile_refs_p (SET_SRC (set))
217 && ! volatile_refs_p (SET_DEST (set)))
219 if (dump_file)
220 fprintf (dump_file, " Delete insn %d because it is redundant\n",
221 INSN_UID (insn));
223 delete_insn (insn);
224 prev = NULL_RTX;
226 else
227 prev = set;
230 if (dump_file)
231 print_rtl_with_bb (dump_file, get_insns (), TDF_NONE);
233 return 0;
236 namespace
238 const pass_data pass_data_rl78_move_elim =
240 RTL_PASS, /* type */
241 "move_elim", /* name */
242 OPTGROUP_NONE, /* optinfo_flags */
243 TV_MACH_DEP, /* tv_id */
244 0, /* properties_required */
245 0, /* properties_provided */
246 0, /* properties_destroyed */
247 0, /* todo_flags_start */
248 0, /* todo_flags_finish */
251 class pass_rl78_move_elim : public rtl_opt_pass
253 public:
254 pass_rl78_move_elim (gcc::context *ctxt)
255 : rtl_opt_pass (pass_data_rl78_move_elim, ctxt)
259 /* opt_pass methods: */
260 virtual unsigned int execute (function *) { return move_elim_pass (); }
262 } // anon namespace
264 rtl_opt_pass *
265 make_pass_rl78_move_elim (gcc::context *ctxt)
267 return new pass_rl78_move_elim (ctxt);
270 #undef TARGET_ASM_FILE_START
271 #define TARGET_ASM_FILE_START rl78_asm_file_start
273 static void
274 rl78_asm_file_start (void)
276 int i;
278 if (TARGET_G10)
280 /* The memory used is 0xffec8 to 0xffedf; real registers are in
281 0xffee0 to 0xffee7. */
282 for (i = 8; i < 32; i++)
283 fprintf (asm_out_file, "r%d\t=\t0x%x\n", i, 0xffec0 + i);
285 else
287 for (i = 0; i < 8; i++)
289 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 8 + i, 0xffef0 + i);
290 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 16 + i, 0xffee8 + i);
291 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 24 + i, 0xffee0 + i);
295 opt_pass *rl78_devirt_pass = make_pass_rl78_devirt (g);
296 struct register_pass_info rl78_devirt_info =
298 rl78_devirt_pass,
299 "pro_and_epilogue",
301 PASS_POS_INSERT_BEFORE
304 opt_pass *rl78_move_elim_pass = make_pass_rl78_move_elim (g);
305 struct register_pass_info rl78_move_elim_info =
307 rl78_move_elim_pass,
308 "bbro",
310 PASS_POS_INSERT_AFTER
313 register_pass (& rl78_devirt_info);
314 register_pass (& rl78_move_elim_info);
317 void
318 rl78_output_symbol_ref (FILE * file, rtx sym)
320 tree type = SYMBOL_REF_DECL (sym);
321 const char *str = XSTR (sym, 0);
323 if (str[0] == '*')
325 fputs (str + 1, file);
327 else
329 str = rl78_strip_nonasm_name_encoding (str);
330 if (type && TREE_CODE (type) == FUNCTION_DECL)
332 fprintf (file, "%%code(");
333 assemble_name (file, str);
334 fprintf (file, ")");
336 else
337 assemble_name (file, str);
341 #undef TARGET_OPTION_OVERRIDE
342 #define TARGET_OPTION_OVERRIDE rl78_option_override
344 #define MUST_SAVE_MDUC_REGISTERS \
345 (TARGET_SAVE_MDUC_REGISTERS \
346 && (is_interrupt_func (NULL_TREE)) && RL78_MUL_G13)
348 static void
349 rl78_option_override (void)
351 flag_omit_frame_pointer = 1;
352 flag_no_function_cse = 1;
353 flag_split_wide_types = 0;
355 init_machine_status = rl78_init_machine_status;
357 if (TARGET_ALLREGS)
359 int i;
361 for (i = 24; i < 32; i++)
362 fixed_regs[i] = 0;
365 if (TARGET_ES0
366 && strcmp (lang_hooks.name, "GNU C")
367 && strcmp (lang_hooks.name, "GNU C11")
368 && strcmp (lang_hooks.name, "GNU C17")
369 && strcmp (lang_hooks.name, "GNU C89")
370 && strcmp (lang_hooks.name, "GNU C99")
371 /* Compiling with -flto results in a language of GNU GIMPLE being used... */
372 && strcmp (lang_hooks.name, "GNU GIMPLE"))
373 /* Address spaces are currently only supported by C. */
374 error ("-mes0 can only be used with C");
376 if (TARGET_SAVE_MDUC_REGISTERS && !(TARGET_G13 || RL78_MUL_G13))
377 warning (0, "mduc registers only saved for G13 target");
379 switch (rl78_cpu_type)
381 case CPU_UNINIT:
382 rl78_cpu_type = CPU_G14;
383 if (rl78_mul_type == MUL_UNINIT)
384 rl78_mul_type = MUL_NONE;
385 break;
387 case CPU_G10:
388 switch (rl78_mul_type)
390 case MUL_UNINIT: rl78_mul_type = MUL_NONE; break;
391 case MUL_NONE: break;
392 case MUL_G13: error ("-mmul=g13 cannot be used with -mcpu=g10"); break;
393 case MUL_G14: error ("-mmul=g14 cannot be used with -mcpu=g10"); break;
395 break;
397 case CPU_G13:
398 switch (rl78_mul_type)
400 case MUL_UNINIT: rl78_mul_type = MUL_G13; break;
401 case MUL_NONE: break;
402 case MUL_G13: break;
403 /* The S2 core does not have mul/div instructions. */
404 case MUL_G14: error ("-mmul=g14 cannot be used with -mcpu=g13"); break;
406 break;
408 case CPU_G14:
409 switch (rl78_mul_type)
411 case MUL_UNINIT: rl78_mul_type = MUL_G14; break;
412 case MUL_NONE: break;
413 case MUL_G14: break;
414 /* The G14 core does not have the hardware multiply peripheral used by the
415 G13 core, hence you cannot use G13 multipliy routines on G14 hardware. */
416 case MUL_G13: error ("-mmul=g13 cannot be used with -mcpu=g14"); break;
418 break;
422 /* Most registers are 8 bits. Some are 16 bits because, for example,
423 gcc doesn't like dealing with $FP as a register pair (the second
424 half of $fp is also 2 to keep reload happy wrt register pairs, but
425 no register class includes it). This table maps register numbers
426 to size in bytes. */
427 static const int register_sizes[] =
429 1, 1, 1, 1, 1, 1, 1, 1,
430 1, 1, 1, 1, 1, 1, 1, 1,
431 1, 1, 1, 1, 1, 1, 2, 2,
432 1, 1, 1, 1, 1, 1, 1, 1,
433 2, 2, 1, 1, 1
436 /* Predicates used in the MD patterns. This one is true when virtual
437 insns may be matched, which typically means before (or during) the
438 devirt pass. */
439 bool
440 rl78_virt_insns_ok (void)
442 if (cfun)
443 return cfun->machine->virt_insns_ok;
444 return true;
447 /* Predicates used in the MD patterns. This one is true when real
448 insns may be matched, which typically means after (or during) the
449 devirt pass. */
450 bool
451 rl78_real_insns_ok (void)
453 if (cfun)
454 return cfun->machine->real_insns_ok;
455 return false;
458 #undef TARGET_HARD_REGNO_NREGS
459 #define TARGET_HARD_REGNO_NREGS rl78_hard_regno_nregs
461 static unsigned int
462 rl78_hard_regno_nregs (unsigned int regno, machine_mode mode)
464 int rs = register_sizes[regno];
465 if (rs < 1)
466 rs = 1;
467 return ((GET_MODE_SIZE (mode) + rs - 1) / rs);
470 #undef TARGET_HARD_REGNO_MODE_OK
471 #define TARGET_HARD_REGNO_MODE_OK rl78_hard_regno_mode_ok
473 static bool
474 rl78_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
476 int s = GET_MODE_SIZE (mode);
478 if (s < 1)
479 return false;
480 /* These are not to be used by gcc. */
481 if (regno == 23 || regno == ES_REG || regno == CS_REG)
482 return false;
483 /* $fp can always be accessed as a 16-bit value. */
484 if (regno == FP_REG && s == 2)
485 return true;
486 if (regno < SP_REG)
488 /* Since a reg-reg move is really a reg-mem move, we must
489 enforce alignment. */
490 if (s > 1 && (regno % 2))
491 return false;
492 return true;
494 if (s == CC_REGNUM)
495 return (mode == BImode);
496 /* All other registers must be accessed in their natural sizes. */
497 if (s == register_sizes [regno])
498 return true;
499 return false;
502 #undef TARGET_MODES_TIEABLE_P
503 #define TARGET_MODES_TIEABLE_P rl78_modes_tieable_p
505 static bool
506 rl78_modes_tieable_p (machine_mode mode1, machine_mode mode2)
508 return ((GET_MODE_CLASS (mode1) == MODE_FLOAT
509 || GET_MODE_CLASS (mode1) == MODE_COMPLEX_FLOAT)
510 == (GET_MODE_CLASS (mode2) == MODE_FLOAT
511 || GET_MODE_CLASS (mode2) == MODE_COMPLEX_FLOAT));
514 /* Simplify_gen_subreg() doesn't handle memory references the way we
515 need it to below, so we use this function for when we must get a
516 valid subreg in a "natural" state. */
517 static rtx
518 rl78_subreg (machine_mode mode, rtx r, machine_mode omode, int byte)
520 if (GET_CODE (r) == MEM)
521 return adjust_address (r, mode, byte);
522 else
523 return simplify_gen_subreg (mode, r, omode, byte);
526 /* Used by movsi. Split SImode moves into two HImode moves, using
527 appropriate patterns for the upper and lower halves of symbols. */
528 void
529 rl78_expand_movsi (rtx *operands)
531 rtx op00, op02, op10, op12;
533 op00 = rl78_subreg (HImode, operands[0], SImode, 0);
534 op02 = rl78_subreg (HImode, operands[0], SImode, 2);
535 if (GET_CODE (operands[1]) == CONST
536 || GET_CODE (operands[1]) == SYMBOL_REF)
538 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
539 op10 = gen_rtx_CONST (HImode, op10);
540 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
541 op12 = gen_rtx_CONST (HImode, op12);
543 else
545 op10 = rl78_subreg (HImode, operands[1], SImode, 0);
546 op12 = rl78_subreg (HImode, operands[1], SImode, 2);
549 if (rtx_equal_p (operands[0], operands[1]))
551 else if (rtx_equal_p (op00, op12))
553 emit_move_insn (op02, op12);
554 emit_move_insn (op00, op10);
556 else
558 emit_move_insn (op00, op10);
559 emit_move_insn (op02, op12);
563 /* Generate code to move an SImode value. */
564 void
565 rl78_split_movsi (rtx *operands, machine_mode omode)
567 rtx op00, op02, op10, op12;
569 op00 = rl78_subreg (HImode, operands[0], omode, 0);
570 op02 = rl78_subreg (HImode, operands[0], omode, 2);
572 if (GET_CODE (operands[1]) == CONST
573 || GET_CODE (operands[1]) == SYMBOL_REF)
575 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
576 op10 = gen_rtx_CONST (HImode, op10);
577 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
578 op12 = gen_rtx_CONST (HImode, op12);
580 else
582 op10 = rl78_subreg (HImode, operands[1], omode, 0);
583 op12 = rl78_subreg (HImode, operands[1], omode, 2);
586 if (rtx_equal_p (operands[0], operands[1]))
588 else if (rtx_equal_p (op00, op12))
590 operands[2] = op02;
591 operands[4] = op12;
592 operands[3] = op00;
593 operands[5] = op10;
595 else
597 operands[2] = op00;
598 operands[4] = op10;
599 operands[3] = op02;
600 operands[5] = op12;
604 void
605 rl78_split_movdi (rtx *operands, enum machine_mode omode)
607 rtx op00, op04, op10, op14;
608 op00 = rl78_subreg (SImode, operands[0], omode, 0);
609 op04 = rl78_subreg (SImode, operands[0], omode, 4);
610 op10 = rl78_subreg (SImode, operands[1], omode, 0);
611 op14 = rl78_subreg (SImode, operands[1], omode, 4);
612 emit_insn (gen_movsi (op00, op10));
613 emit_insn (gen_movsi (op04, op14));
616 /* Used by various two-operand expanders which cannot accept all
617 operands in the "far" namespace. Force some such operands into
618 registers so that each pattern has at most one far operand. */
620 rl78_force_nonfar_2 (rtx *operands, rtx (*gen)(rtx,rtx))
622 int did = 0;
623 rtx temp_reg = NULL;
625 /* FIXME: in the future, be smarter about only doing this if the
626 other operand is also far, assuming the devirtualizer can also
627 handle that. */
628 if (rl78_far_p (operands[0]))
630 temp_reg = operands[0];
631 operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
632 did = 1;
634 if (!did)
635 return 0;
637 emit_insn (gen (operands[0], operands[1]));
638 if (temp_reg)
639 emit_move_insn (temp_reg, operands[0]);
640 return 1;
643 /* Likewise, but for three-operand expanders. */
645 rl78_force_nonfar_3 (rtx *operands, rtx (*gen)(rtx,rtx,rtx))
647 int did = 0;
648 rtx temp_reg = NULL;
650 /* FIXME: Likewise. */
651 if (rl78_far_p (operands[1]))
653 rtx temp_reg = gen_reg_rtx (GET_MODE (operands[1]));
654 emit_move_insn (temp_reg, operands[1]);
655 operands[1] = temp_reg;
656 did = 1;
658 if (rl78_far_p (operands[0]))
660 temp_reg = operands[0];
661 operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
662 did = 1;
664 if (!did)
665 return 0;
667 emit_insn (gen (operands[0], operands[1], operands[2]));
668 if (temp_reg)
669 emit_move_insn (temp_reg, operands[0]);
670 return 1;
674 rl78_one_far_p (rtx *operands, int n)
676 rtx which = NULL;
677 int i, c = 0;
679 for (i = 0; i < n; i ++)
680 if (rl78_far_p (operands[i]))
682 if (which == NULL)
683 which = operands[i];
684 else if (rtx_equal_p (operands[i], which))
685 continue;
686 c ++;
688 return c <= 1;
691 #undef TARGET_CAN_ELIMINATE
692 #define TARGET_CAN_ELIMINATE rl78_can_eliminate
694 static bool
695 rl78_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to ATTRIBUTE_UNUSED)
697 return true;
700 /* Returns true if the given register needs to be saved by the
701 current function. */
702 static bool
703 need_to_save (unsigned int regno)
705 if (is_interrupt_func (cfun->decl))
707 /* We don't know what devirt will need */
708 if (regno < 8)
709 return true;
711 /* We don't need to save registers that have
712 been reserved for interrupt handlers. */
713 if (regno > 23)
714 return false;
716 /* If the handler is a non-leaf function then it may call
717 non-interrupt aware routines which will happily clobber
718 any call_used registers, so we have to preserve them.
719 We do not have to worry about the frame pointer register
720 though, as that is handled below. */
721 if (!crtl->is_leaf && call_used_regs[regno] && regno < 22)
722 return true;
724 /* Otherwise we only have to save a register, call_used
725 or not, if it is used by this handler. */
726 return df_regs_ever_live_p (regno);
729 if (regno == FRAME_POINTER_REGNUM
730 && (frame_pointer_needed || df_regs_ever_live_p (regno)))
731 return true;
732 if (fixed_regs[regno])
733 return false;
734 if (crtl->calls_eh_return)
735 return true;
736 if (df_regs_ever_live_p (regno)
737 && !call_used_regs[regno])
738 return true;
739 return false;
742 /* We use this to wrap all emitted insns in the prologue. */
743 static rtx
744 F (rtx x)
746 RTX_FRAME_RELATED_P (x) = 1;
747 return x;
750 /* Compute all the frame-related fields in our machine_function
751 structure. */
752 static void
753 rl78_compute_frame_info (void)
755 int i;
757 cfun->machine->computed = 1;
758 cfun->machine->framesize_regs = 0;
759 cfun->machine->framesize_locals = get_frame_size ();
760 cfun->machine->framesize_outgoing = crtl->outgoing_args_size;
762 for (i = 0; i < 16; i ++)
763 if (need_to_save (i * 2) || need_to_save (i * 2 + 1))
765 cfun->machine->need_to_push [i] = 1;
766 cfun->machine->framesize_regs += 2;
768 else
769 cfun->machine->need_to_push [i] = 0;
771 if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1)
772 cfun->machine->framesize_locals ++;
774 cfun->machine->framesize = (cfun->machine->framesize_regs
775 + cfun->machine->framesize_locals
776 + cfun->machine->framesize_outgoing);
779 /* Returns true if the provided function has the specified attribute. */
780 static inline bool
781 has_func_attr (const_tree decl, const char * func_attr)
783 if (decl == NULL_TREE)
784 decl = current_function_decl;
786 return lookup_attribute (func_attr, DECL_ATTRIBUTES (decl)) != NULL_TREE;
789 /* Returns true if the provided function has the "interrupt" attribute. */
790 static inline bool
791 is_interrupt_func (const_tree decl)
793 return has_func_attr (decl, "interrupt") || has_func_attr (decl, "brk_interrupt");
796 /* Returns true if the provided function has the "brk_interrupt" attribute. */
797 static inline bool
798 is_brk_interrupt_func (const_tree decl)
800 return has_func_attr (decl, "brk_interrupt");
803 /* Check "interrupt" attributes. */
804 static tree
805 rl78_handle_func_attribute (tree * node,
806 tree name,
807 tree args ATTRIBUTE_UNUSED,
808 int flags ATTRIBUTE_UNUSED,
809 bool * no_add_attrs)
811 gcc_assert (DECL_P (* node));
813 if (TREE_CODE (* node) != FUNCTION_DECL)
815 warning (OPT_Wattributes, "%qE attribute only applies to functions",
816 name);
817 * no_add_attrs = true;
820 /* FIXME: We ought to check that the interrupt and exception
821 handler attributes have been applied to void functions. */
822 return NULL_TREE;
825 /* Check "naked" attributes. */
826 static tree
827 rl78_handle_naked_attribute (tree * node,
828 tree name ATTRIBUTE_UNUSED,
829 tree args,
830 int flags ATTRIBUTE_UNUSED,
831 bool * no_add_attrs)
833 gcc_assert (DECL_P (* node));
834 gcc_assert (args == NULL_TREE);
836 if (TREE_CODE (* node) != FUNCTION_DECL)
838 warning (OPT_Wattributes, "naked attribute only applies to functions");
839 * no_add_attrs = true;
842 /* Disable warnings about this function - eg reaching the end without
843 seeing a return statement - because the programmer is doing things
844 that gcc does not know about. */
845 TREE_NO_WARNING (* node) = 1;
847 return NULL_TREE;
850 /* Check "saddr" attributes. */
851 static tree
852 rl78_handle_saddr_attribute (tree * node,
853 tree name,
854 tree args ATTRIBUTE_UNUSED,
855 int flags ATTRIBUTE_UNUSED,
856 bool * no_add_attrs)
858 gcc_assert (DECL_P (* node));
860 if (TREE_CODE (* node) == FUNCTION_DECL)
862 warning (OPT_Wattributes, "%qE attribute doesn't apply to functions",
863 name);
864 * no_add_attrs = true;
867 return NULL_TREE;
870 /* Check "vector" attribute. */
872 static tree
873 rl78_handle_vector_attribute (tree * node,
874 tree name,
875 tree args,
876 int flags ATTRIBUTE_UNUSED,
877 bool * no_add_attrs)
879 gcc_assert (DECL_P (* node));
880 gcc_assert (args != NULL_TREE);
882 if (TREE_CODE (* node) != FUNCTION_DECL)
884 warning (OPT_Wattributes, "%qE attribute only applies to functions",
885 name);
886 * no_add_attrs = true;
889 return NULL_TREE;
892 #undef TARGET_ATTRIBUTE_TABLE
893 #define TARGET_ATTRIBUTE_TABLE rl78_attribute_table
895 /* Table of RL78-specific attributes. */
896 const struct attribute_spec rl78_attribute_table[] =
898 /* Name, min_len, max_len, decl_req, type_req, fn_type_req,
899 affects_type_identity, handler, exclude. */
900 { "interrupt", 0, -1, true, false, false, false,
901 rl78_handle_func_attribute, NULL },
902 { "brk_interrupt", 0, 0, true, false, false, false,
903 rl78_handle_func_attribute, NULL },
904 { "naked", 0, 0, true, false, false, false,
905 rl78_handle_naked_attribute, NULL },
906 { "saddr", 0, 0, true, false, false, false,
907 rl78_handle_saddr_attribute, NULL },
908 { "vector", 1, -1, true, false, false, false,
909 rl78_handle_vector_attribute, NULL },
910 { NULL, 0, 0, false, false, false, false, NULL, NULL }
915 /* Break down an address RTX into its component base/index/addend
916 portions and return TRUE if the address is of a valid form, else
917 FALSE. */
918 static bool
919 characterize_address (rtx x, rtx *base, rtx *index, rtx *addend)
921 *base = NULL_RTX;
922 *index = NULL_RTX;
923 *addend = NULL_RTX;
925 if (GET_CODE (x) == UNSPEC
926 && XINT (x, 1) == UNS_ES_ADDR)
927 x = XVECEXP (x, 0, 1);
929 if (GET_CODE (x) == REG)
931 *base = x;
932 return true;
935 /* We sometimes get these without the CONST wrapper */
936 if (GET_CODE (x) == PLUS
937 && GET_CODE (XEXP (x, 0)) == SYMBOL_REF
938 && GET_CODE (XEXP (x, 1)) == CONST_INT)
940 *addend = x;
941 return true;
944 if (GET_CODE (x) == PLUS)
946 *base = XEXP (x, 0);
947 x = XEXP (x, 1);
949 if (GET_CODE (*base) == SUBREG)
951 if (GET_MODE (*base) == HImode
952 && GET_MODE (XEXP (*base, 0)) == SImode
953 && GET_CODE (XEXP (*base, 0)) == REG)
955 /* This is a throw-away rtx just to tell everyone
956 else what effective register we're using. */
957 *base = gen_rtx_REG (HImode, REGNO (XEXP (*base, 0)));
961 if (GET_CODE (*base) != REG
962 && GET_CODE (x) == REG)
964 rtx tmp = *base;
965 *base = x;
966 x = tmp;
969 if (GET_CODE (*base) != REG)
970 return false;
972 if (GET_CODE (x) == ZERO_EXTEND
973 && GET_CODE (XEXP (x, 0)) == REG)
975 *index = XEXP (x, 0);
976 return false;
980 switch (GET_CODE (x))
982 case PLUS:
983 if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
984 && GET_CODE (XEXP (x, 0)) == CONST_INT)
986 *addend = x;
987 return true;
989 /* fall through */
990 case MEM:
991 case REG:
992 return false;
994 case SUBREG:
995 switch (GET_CODE (XEXP (x, 0)))
997 case CONST:
998 case SYMBOL_REF:
999 case CONST_INT:
1000 *addend = x;
1001 return true;
1002 default:
1003 return false;
1006 case CONST:
1007 case SYMBOL_REF:
1008 case CONST_INT:
1009 *addend = x;
1010 return true;
1012 default:
1013 return false;
1016 return false;
1019 /* Used by the Whb constraint. Match addresses that use HL+B or HL+C
1020 addressing. */
1021 bool
1022 rl78_hl_b_c_addr_p (rtx op)
1024 rtx hl, bc;
1026 if (GET_CODE (op) != PLUS)
1027 return false;
1028 hl = XEXP (op, 0);
1029 bc = XEXP (op, 1);
1030 if (GET_CODE (hl) == ZERO_EXTEND)
1032 rtx tmp = hl;
1033 hl = bc;
1034 bc = tmp;
1036 if (GET_CODE (hl) != REG)
1037 return false;
1038 if (GET_CODE (bc) != ZERO_EXTEND)
1039 return false;
1040 bc = XEXP (bc, 0);
1041 if (GET_CODE (bc) != REG)
1042 return false;
1043 if (REGNO (hl) != HL_REG)
1044 return false;
1045 if (REGNO (bc) != B_REG && REGNO (bc) != C_REG)
1046 return false;
1048 return true;
1051 #define REG_IS(r, regno) (((r) == (regno)) || ((r) >= FIRST_PSEUDO_REGISTER && !(strict)))
1053 /* Return the appropriate mode for a named address address. */
1055 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
1056 #define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode
1058 static scalar_int_mode
1059 rl78_addr_space_address_mode (addr_space_t addrspace)
1061 switch (addrspace)
1063 case ADDR_SPACE_GENERIC:
1064 return HImode;
1065 case ADDR_SPACE_NEAR:
1066 return HImode;
1067 case ADDR_SPACE_FAR:
1068 return SImode;
1069 default:
1070 gcc_unreachable ();
1074 /* Used in various constraints and predicates to match operands in the
1075 "far" address space. */
1077 rl78_far_p (rtx x)
1079 if (! MEM_P (x))
1080 return 0;
1081 #if DEBUG0
1082 fprintf (stderr, "\033[35mrl78_far_p: "); debug_rtx (x);
1083 fprintf (stderr, " = %d\033[0m\n", MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR);
1084 #endif
1086 /* Not all far addresses are legitimate, because the devirtualizer
1087 can't handle them. */
1088 if (! rl78_as_legitimate_address (GET_MODE (x), XEXP (x, 0), false, ADDR_SPACE_FAR))
1089 return 0;
1091 return GET_MODE_BITSIZE (rl78_addr_space_address_mode (MEM_ADDR_SPACE (x))) == 32;
1094 /* Return the appropriate mode for a named address pointer. */
1095 #undef TARGET_ADDR_SPACE_POINTER_MODE
1096 #define TARGET_ADDR_SPACE_POINTER_MODE rl78_addr_space_pointer_mode
1098 static scalar_int_mode
1099 rl78_addr_space_pointer_mode (addr_space_t addrspace)
1101 switch (addrspace)
1103 case ADDR_SPACE_GENERIC:
1104 return HImode;
1105 case ADDR_SPACE_NEAR:
1106 return HImode;
1107 case ADDR_SPACE_FAR:
1108 return SImode;
1109 default:
1110 gcc_unreachable ();
1114 /* Returns TRUE for valid addresses. */
1115 #undef TARGET_VALID_POINTER_MODE
1116 #define TARGET_VALID_POINTER_MODE rl78_valid_pointer_mode
1118 static bool
1119 rl78_valid_pointer_mode (scalar_int_mode m)
1121 return (m == HImode || m == SImode);
1124 #undef TARGET_LEGITIMATE_CONSTANT_P
1125 #define TARGET_LEGITIMATE_CONSTANT_P rl78_is_legitimate_constant
1127 static bool
1128 rl78_is_legitimate_constant (machine_mode mode ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED)
1130 return true;
1133 #undef TARGET_LRA_P
1134 #define TARGET_LRA_P hook_bool_void_false
1136 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
1137 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P rl78_as_legitimate_address
1139 bool
1140 rl78_as_legitimate_address (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
1141 bool strict ATTRIBUTE_UNUSED, addr_space_t as ATTRIBUTE_UNUSED)
1143 rtx base, index, addend;
1144 bool is_far_addr = false;
1145 int as_bits;
1147 as_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (as));
1149 if (GET_CODE (x) == UNSPEC
1150 && XINT (x, 1) == UNS_ES_ADDR)
1152 x = XVECEXP (x, 0, 1);
1153 is_far_addr = true;
1156 if (as_bits == 16 && is_far_addr)
1157 return false;
1159 if (! characterize_address (x, &base, &index, &addend))
1160 return false;
1162 /* We can't extract the high/low portions of a PLUS address
1163 involving a register during devirtualization, so make sure all
1164 such __far addresses do not have addends. This forces GCC to do
1165 the sum separately. */
1166 if (addend && base && as_bits == 32 && GET_MODE (base) == SImode)
1167 return false;
1169 if (base && index)
1171 int ir = REGNO (index);
1172 int br = REGNO (base);
1174 #define OK(test, debug) if (test) { /*fprintf(stderr, "%d: OK %s\n", __LINE__, debug);*/ return true; }
1175 OK (REG_IS (br, HL_REG) && REG_IS (ir, B_REG), "[hl+b]");
1176 OK (REG_IS (br, HL_REG) && REG_IS (ir, C_REG), "[hl+c]");
1177 return false;
1180 if (strict && base && GET_CODE (base) == REG && REGNO (base) >= FIRST_PSEUDO_REGISTER)
1181 return false;
1183 if (! cfun->machine->virt_insns_ok && base && GET_CODE (base) == REG
1184 && REGNO (base) >= 8 && REGNO (base) <= 31)
1185 return false;
1187 return true;
1190 /* Determine if one named address space is a subset of another. */
1191 #undef TARGET_ADDR_SPACE_SUBSET_P
1192 #define TARGET_ADDR_SPACE_SUBSET_P rl78_addr_space_subset_p
1194 static bool
1195 rl78_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
1197 int subset_bits;
1198 int superset_bits;
1200 subset_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (subset));
1201 superset_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (superset));
1203 return (subset_bits <= superset_bits);
1206 #undef TARGET_ADDR_SPACE_CONVERT
1207 #define TARGET_ADDR_SPACE_CONVERT rl78_addr_space_convert
1209 /* Convert from one address space to another. */
1210 static rtx
1211 rl78_addr_space_convert (rtx op, tree from_type, tree to_type)
1213 addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
1214 addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
1215 rtx result;
1216 int to_bits;
1217 int from_bits;
1219 to_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (to_as));
1220 from_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (from_as));
1222 if (to_bits < from_bits)
1224 rtx tmp;
1225 /* This is unpredictable, as we're truncating off usable address
1226 bits. */
1228 warning (OPT_Waddress, "converting far pointer to near pointer");
1229 result = gen_reg_rtx (HImode);
1230 if (GET_CODE (op) == SYMBOL_REF
1231 || (GET_CODE (op) == REG && REGNO (op) >= FIRST_PSEUDO_REGISTER))
1232 tmp = gen_rtx_raw_SUBREG (HImode, op, 0);
1233 else
1234 tmp = simplify_subreg (HImode, op, SImode, 0);
1235 gcc_assert (tmp != NULL_RTX);
1236 emit_move_insn (result, tmp);
1237 return result;
1239 else if (to_bits > from_bits)
1241 /* This always works. */
1242 result = gen_reg_rtx (SImode);
1243 emit_move_insn (rl78_subreg (HImode, result, SImode, 0), op);
1244 if (TREE_CODE (from_type) == POINTER_TYPE
1245 && TREE_CODE (TREE_TYPE (from_type)) == FUNCTION_TYPE)
1246 emit_move_insn (rl78_subreg (HImode, result, SImode, 2), const0_rtx);
1247 else
1248 emit_move_insn (rl78_subreg (HImode, result, SImode, 2), GEN_INT (0x0f));
1249 return result;
1251 else
1252 return op;
1253 gcc_unreachable ();
1256 /* Implements REGNO_MODE_CODE_OK_FOR_BASE_P. */
1257 bool
1258 rl78_regno_mode_code_ok_for_base_p (int regno, machine_mode mode ATTRIBUTE_UNUSED,
1259 addr_space_t address_space ATTRIBUTE_UNUSED,
1260 int outer_code ATTRIBUTE_UNUSED, int index_code)
1262 if (regno <= SP_REG && regno >= 16)
1263 return true;
1264 if (index_code == REG)
1265 return (regno == HL_REG);
1266 if (regno == C_REG || regno == B_REG || regno == E_REG || regno == L_REG)
1267 return true;
1268 return false;
1271 /* Implements MODE_CODE_BASE_REG_CLASS. */
1272 enum reg_class
1273 rl78_mode_code_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED,
1274 addr_space_t address_space ATTRIBUTE_UNUSED,
1275 int outer_code ATTRIBUTE_UNUSED,
1276 int index_code ATTRIBUTE_UNUSED)
1278 return V_REGS;
1281 /* Typical stack layout should looks like this after the function's prologue:
1284 -- ^
1285 | | \ |
1286 | | arguments saved | Increasing
1287 | | on the stack | addresses
1288 PARENT arg pointer -> | | /
1289 -------------------------- ---- -------------------
1290 CHILD |ret | return address
1292 | | \
1293 | | call saved
1294 | | registers
1295 frame pointer -> | | /
1297 | | \
1298 | | local
1299 | | variables
1300 | | /
1302 | | \
1303 | | outgoing | Decreasing
1304 | | arguments | addresses
1305 current stack pointer -> | | / |
1306 -------------------------- ---- ------------------ V
1307 | | */
1309 /* Implements INITIAL_ELIMINATION_OFFSET. The frame layout is
1310 described in the machine_Function struct definition, above. */
1312 rl78_initial_elimination_offset (int from, int to)
1314 int rv = 0; /* as if arg to arg */
1316 rl78_compute_frame_info ();
1318 switch (to)
1320 case STACK_POINTER_REGNUM:
1321 rv += cfun->machine->framesize_outgoing;
1322 rv += cfun->machine->framesize_locals;
1323 /* Fall through. */
1324 case FRAME_POINTER_REGNUM:
1325 rv += cfun->machine->framesize_regs;
1326 rv += 4;
1327 break;
1328 default:
1329 gcc_unreachable ();
1332 switch (from)
1334 case FRAME_POINTER_REGNUM:
1335 rv -= 4;
1336 rv -= cfun->machine->framesize_regs;
1337 case ARG_POINTER_REGNUM:
1338 break;
1339 default:
1340 gcc_unreachable ();
1343 return rv;
1346 static bool
1347 rl78_is_naked_func (void)
1349 return (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE);
1352 /* Check if the block uses mul/div insns for G13 target. */
1354 static bool
1355 check_mduc_usage (void)
1357 rtx_insn * insn;
1358 basic_block bb;
1360 FOR_EACH_BB_FN (bb, cfun)
1362 FOR_BB_INSNS (bb, insn)
1364 if (INSN_P (insn)
1365 && (get_attr_is_g13_muldiv_insn (insn) == IS_G13_MULDIV_INSN_YES))
1366 return true;
1369 return false;
1372 /* Expand the function prologue (from the prologue pattern). */
1374 void
1375 rl78_expand_prologue (void)
1377 int i, fs;
1378 rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
1379 rtx ax = gen_rtx_REG (HImode, AX_REG);
1380 int rb = 0;
1382 if (rl78_is_naked_func ())
1383 return;
1385 /* Always re-compute the frame info - the register usage may have changed. */
1386 rl78_compute_frame_info ();
1388 if (MUST_SAVE_MDUC_REGISTERS && (!crtl->is_leaf || check_mduc_usage ()))
1389 cfun->machine->framesize += ARRAY_SIZE (mduc_regs) * 2;
1391 if (flag_stack_usage_info)
1392 current_function_static_stack_size = cfun->machine->framesize;
1394 if (is_interrupt_func (cfun->decl) && !TARGET_G10)
1395 for (i = 0; i < 4; i++)
1396 if (cfun->machine->need_to_push [i])
1398 /* Select Bank 0 if we are using any registers from Bank 0. */
1399 emit_insn (gen_sel_rb (GEN_INT (0)));
1400 break;
1403 for (i = 0; i < 16; i++)
1404 if (cfun->machine->need_to_push [i])
1406 int reg = i * 2;
1408 if (TARGET_G10)
1410 if (reg >= 8)
1412 emit_move_insn (ax, gen_rtx_REG (HImode, reg));
1413 reg = AX_REG;
1416 else
1418 int need_bank = i/4;
1420 if (need_bank != rb)
1422 emit_insn (gen_sel_rb (GEN_INT (need_bank)));
1423 rb = need_bank;
1427 F (emit_insn (gen_push (gen_rtx_REG (HImode, reg))));
1430 if (rb != 0)
1431 emit_insn (gen_sel_rb (GEN_INT (0)));
1433 /* Save ES register inside interrupt functions if it is used. */
1434 if (is_interrupt_func (cfun->decl) && cfun->machine->uses_es)
1436 emit_insn (gen_movqi_from_es (gen_rtx_REG (QImode, A_REG)));
1437 F (emit_insn (gen_push (ax)));
1440 /* Save MDUC registers inside interrupt routine. */
1441 if (MUST_SAVE_MDUC_REGISTERS && (!crtl->is_leaf || check_mduc_usage ()))
1443 for (unsigned i = 0; i < ARRAY_SIZE (mduc_regs); i++)
1445 mduc_reg_type *reg = mduc_regs + i;
1446 rtx mem_mduc = gen_rtx_MEM (reg->mode, GEN_INT (reg->address));
1448 MEM_VOLATILE_P (mem_mduc) = 1;
1449 if (reg->mode == QImode)
1450 emit_insn (gen_movqi (gen_rtx_REG (QImode, A_REG), mem_mduc));
1451 else
1452 emit_insn (gen_movhi (gen_rtx_REG (HImode, AX_REG), mem_mduc));
1454 emit_insn (gen_push (gen_rtx_REG (HImode, AX_REG)));
1458 if (frame_pointer_needed)
1460 F (emit_move_insn (ax, sp));
1461 F (emit_move_insn (gen_rtx_REG (HImode, FRAME_POINTER_REGNUM), ax));
1464 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1465 if (fs > 0)
1467 /* If we need to subtract more than 254*3 then it is faster and
1468 smaller to move SP into AX and perform the subtraction there. */
1469 if (fs > 254 * 3)
1471 rtx insn;
1473 emit_move_insn (ax, sp);
1474 emit_insn (gen_subhi3 (ax, ax, GEN_INT (fs)));
1475 insn = F (emit_move_insn (sp, ax));
1476 add_reg_note (insn, REG_FRAME_RELATED_EXPR,
1477 gen_rtx_SET (sp, gen_rtx_PLUS (HImode, sp,
1478 GEN_INT (-fs))));
1480 else
1482 while (fs > 0)
1484 int fs_byte = (fs > 254) ? 254 : fs;
1486 F (emit_insn (gen_subhi3 (sp, sp, GEN_INT (fs_byte))));
1487 fs -= fs_byte;
1493 /* Expand the function epilogue (from the epilogue pattern). */
1494 void
1495 rl78_expand_epilogue (void)
1497 int i, fs;
1498 rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
1499 rtx ax = gen_rtx_REG (HImode, AX_REG);
1500 int rb = 0;
1502 if (rl78_is_naked_func ())
1503 return;
1505 if (frame_pointer_needed)
1507 emit_move_insn (ax, gen_rtx_REG (HImode, FRAME_POINTER_REGNUM));
1508 emit_move_insn (sp, ax);
1510 else
1512 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1513 if (fs > 254 * 3)
1515 emit_move_insn (ax, sp);
1516 emit_insn (gen_addhi3 (ax, ax, GEN_INT (fs)));
1517 emit_move_insn (sp, ax);
1519 else
1521 while (fs > 0)
1523 int fs_byte = (fs > 254) ? 254 : fs;
1525 emit_insn (gen_addhi3 (sp, sp, GEN_INT (fs_byte)));
1526 fs -= fs_byte;
1531 /* Restore MDUC registers from interrupt routine. */
1532 if (MUST_SAVE_MDUC_REGISTERS && (!crtl->is_leaf || check_mduc_usage ()))
1534 for (int i = ARRAY_SIZE (mduc_regs) - 1; i >= 0; i--)
1536 mduc_reg_type *reg = mduc_regs + i;
1537 rtx mem_mduc = gen_rtx_MEM (reg->mode, GEN_INT (reg->address));
1539 emit_insn (gen_pop (gen_rtx_REG (HImode, AX_REG)));
1540 MEM_VOLATILE_P (mem_mduc) = 1;
1541 if (reg->mode == QImode)
1542 emit_insn (gen_movqi (mem_mduc, gen_rtx_REG (QImode, A_REG)));
1543 else
1544 emit_insn (gen_movhi (mem_mduc, gen_rtx_REG (HImode, AX_REG)));
1548 if (is_interrupt_func (cfun->decl) && cfun->machine->uses_es)
1550 emit_insn (gen_pop (gen_rtx_REG (HImode, AX_REG)));
1551 emit_insn (gen_movqi_to_es (gen_rtx_REG (QImode, A_REG)));
1554 for (i = 15; i >= 0; i--)
1555 if (cfun->machine->need_to_push [i])
1557 rtx dest = gen_rtx_REG (HImode, i * 2);
1559 if (TARGET_G10)
1561 if (i < 8)
1562 emit_insn (gen_pop (dest));
1563 else
1565 emit_insn (gen_pop (ax));
1566 emit_move_insn (dest, ax);
1567 /* Generate a USE of the pop'd register so that DCE will not eliminate the move. */
1568 emit_insn (gen_use (dest));
1571 else
1573 int need_bank = i / 4;
1575 if (need_bank != rb)
1577 emit_insn (gen_sel_rb (GEN_INT (need_bank)));
1578 rb = need_bank;
1580 emit_insn (gen_pop (dest));
1584 if (rb != 0)
1585 emit_insn (gen_sel_rb (GEN_INT (0)));
1587 if (cfun->machine->trampolines_used)
1588 emit_insn (gen_trampoline_uninit ());
1590 if (is_brk_interrupt_func (cfun->decl))
1591 emit_jump_insn (gen_brk_interrupt_return ());
1592 else if (is_interrupt_func (cfun->decl))
1593 emit_jump_insn (gen_interrupt_return ());
1594 else
1595 emit_jump_insn (gen_rl78_return ());
1598 /* Likewise, for exception handlers. */
1599 void
1600 rl78_expand_eh_epilogue (rtx x ATTRIBUTE_UNUSED)
1602 /* FIXME - replace this with an indirect jump with stack adjust. */
1603 emit_jump_insn (gen_rl78_return ());
1606 #undef TARGET_ASM_FUNCTION_PROLOGUE
1607 #define TARGET_ASM_FUNCTION_PROLOGUE rl78_start_function
1609 static void
1610 add_vector_labels (FILE *file, const char *aname)
1612 tree vec_attr;
1613 tree val_attr;
1614 const char *vname = "vect";
1615 const char *s;
1616 int vnum;
1618 /* This node is for the vector/interrupt tag itself */
1619 vec_attr = lookup_attribute (aname, DECL_ATTRIBUTES (current_function_decl));
1620 if (!vec_attr)
1621 return;
1623 /* Now point it at the first argument */
1624 vec_attr = TREE_VALUE (vec_attr);
1626 /* Iterate through the arguments. */
1627 while (vec_attr)
1629 val_attr = TREE_VALUE (vec_attr);
1630 switch (TREE_CODE (val_attr))
1632 case STRING_CST:
1633 s = TREE_STRING_POINTER (val_attr);
1634 goto string_id_common;
1636 case IDENTIFIER_NODE:
1637 s = IDENTIFIER_POINTER (val_attr);
1639 string_id_common:
1640 if (strcmp (s, "$default") == 0)
1642 fprintf (file, "\t.global\t$tableentry$default$%s\n", vname);
1643 fprintf (file, "$tableentry$default$%s:\n", vname);
1645 else
1646 vname = s;
1647 break;
1649 case INTEGER_CST:
1650 vnum = TREE_INT_CST_LOW (val_attr);
1652 fprintf (file, "\t.global\t$tableentry$%d$%s\n", vnum, vname);
1653 fprintf (file, "$tableentry$%d$%s:\n", vnum, vname);
1654 break;
1656 default:
1660 vec_attr = TREE_CHAIN (vec_attr);
1665 /* We don't use this to actually emit the function prologue. We use
1666 this to insert a comment in the asm file describing the
1667 function. */
1668 static void
1669 rl78_start_function (FILE *file)
1671 int i;
1673 add_vector_labels (file, "interrupt");
1674 add_vector_labels (file, "vector");
1676 if (cfun->machine->framesize == 0)
1677 return;
1678 fprintf (file, "\t; start of function\n");
1680 if (cfun->machine->framesize_regs)
1682 fprintf (file, "\t; push %d:", cfun->machine->framesize_regs);
1683 for (i = 0; i < 16; i ++)
1684 if (cfun->machine->need_to_push[i])
1685 fprintf (file, " %s", word_regnames[i*2]);
1686 fprintf (file, "\n");
1689 if (frame_pointer_needed)
1690 fprintf (file, "\t; $fp points here (r22)\n");
1692 if (cfun->machine->framesize_locals)
1693 fprintf (file, "\t; locals: %d byte%s\n", cfun->machine->framesize_locals,
1694 cfun->machine->framesize_locals == 1 ? "" : "s");
1696 if (cfun->machine->framesize_outgoing)
1697 fprintf (file, "\t; outgoing: %d byte%s\n", cfun->machine->framesize_outgoing,
1698 cfun->machine->framesize_outgoing == 1 ? "" : "s");
1700 if (cfun->machine->uses_es)
1701 fprintf (file, "\t; uses ES register\n");
1703 if (MUST_SAVE_MDUC_REGISTERS)
1704 fprintf (file, "\t; preserves MDUC registers\n");
1707 /* Return an RTL describing where a function return value of type RET_TYPE
1708 is held. */
1710 #undef TARGET_FUNCTION_VALUE
1711 #define TARGET_FUNCTION_VALUE rl78_function_value
1713 static rtx
1714 rl78_function_value (const_tree ret_type,
1715 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
1716 bool outgoing ATTRIBUTE_UNUSED)
1718 machine_mode mode = TYPE_MODE (ret_type);
1720 return gen_rtx_REG (mode, 8);
1723 #undef TARGET_PROMOTE_FUNCTION_MODE
1724 #define TARGET_PROMOTE_FUNCTION_MODE rl78_promote_function_mode
1726 static machine_mode
1727 rl78_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
1728 machine_mode mode,
1729 int *punsignedp ATTRIBUTE_UNUSED,
1730 const_tree funtype ATTRIBUTE_UNUSED, int for_return ATTRIBUTE_UNUSED)
1732 return mode;
1735 /* Return an RTL expression describing the register holding a function
1736 parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
1737 be passed on the stack. CUM describes the previous parameters to the
1738 function and NAMED is false if the parameter is part of a variable
1739 parameter list, or the last named parameter before the start of a
1740 variable parameter list. */
1742 #undef TARGET_FUNCTION_ARG
1743 #define TARGET_FUNCTION_ARG rl78_function_arg
1745 static rtx
1746 rl78_function_arg (cumulative_args_t cum_v ATTRIBUTE_UNUSED,
1747 machine_mode mode ATTRIBUTE_UNUSED,
1748 const_tree type ATTRIBUTE_UNUSED,
1749 bool named ATTRIBUTE_UNUSED)
1751 return NULL_RTX;
1754 #undef TARGET_FUNCTION_ARG_ADVANCE
1755 #define TARGET_FUNCTION_ARG_ADVANCE rl78_function_arg_advance
1757 static void
1758 rl78_function_arg_advance (cumulative_args_t cum_v, machine_mode mode, const_tree type,
1759 bool named ATTRIBUTE_UNUSED)
1761 int rounded_size;
1762 CUMULATIVE_ARGS * cum = get_cumulative_args (cum_v);
1764 rounded_size = ((mode == BLKmode)
1765 ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
1766 if (rounded_size & 1)
1767 rounded_size ++;
1768 (*cum) += rounded_size;
1771 #undef TARGET_FUNCTION_ARG_BOUNDARY
1772 #define TARGET_FUNCTION_ARG_BOUNDARY rl78_function_arg_boundary
1774 static unsigned int
1775 rl78_function_arg_boundary (machine_mode mode ATTRIBUTE_UNUSED,
1776 const_tree type ATTRIBUTE_UNUSED)
1778 return 16;
1781 /* Supported modifier letters:
1783 A - address of a MEM
1784 S - SADDR form of a real register
1785 v - real register corresponding to a virtual register
1786 m - minus - negative of CONST_INT value.
1787 C - inverse of a conditional (NE vs EQ for example)
1788 C - complement of an integer
1789 z - collapsed conditional
1790 s - shift count mod 8
1791 S - shift count mod 16
1792 r - reverse shift count (8-(count mod 8))
1793 B - bit position
1795 h - bottom HI of an SI
1796 H - top HI of an SI
1797 q - bottom QI of an HI
1798 Q - top QI of an HI
1799 e - third QI of an SI (i.e. where the ES register gets values from)
1800 E - fourth QI of an SI (i.e. MSB)
1802 p - Add +0 to a zero-indexed HL based address.
1805 /* Implements the bulk of rl78_print_operand, below. We do it this
1806 way because we need to test for a constant at the top level and
1807 insert the '#', but not test for it anywhere else as we recurse
1808 down into the operand. */
1809 static void
1810 rl78_print_operand_1 (FILE * file, rtx op, int letter)
1812 int need_paren;
1814 switch (GET_CODE (op))
1816 case MEM:
1817 if (letter == 'A')
1818 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1819 else
1821 if (rl78_far_p (op))
1823 fprintf (file, "es:");
1824 if (GET_CODE (XEXP (op, 0)) == UNSPEC)
1825 op = gen_rtx_MEM (GET_MODE (op), XVECEXP (XEXP (op, 0), 0, 1));
1827 if (letter == 'H')
1829 op = adjust_address (op, HImode, 2);
1830 letter = 0;
1832 if (letter == 'h')
1834 op = adjust_address (op, HImode, 0);
1835 letter = 0;
1837 if (letter == 'Q')
1839 op = adjust_address (op, QImode, 1);
1840 letter = 0;
1842 if (letter == 'q')
1844 op = adjust_address (op, QImode, 0);
1845 letter = 0;
1847 if (letter == 'e')
1849 op = adjust_address (op, QImode, 2);
1850 letter = 0;
1852 if (letter == 'E')
1854 op = adjust_address (op, QImode, 3);
1855 letter = 0;
1857 if (CONSTANT_P (XEXP (op, 0)))
1859 if (!rl78_saddr_p (op))
1860 fprintf (file, "!");
1861 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1863 else if (GET_CODE (XEXP (op, 0)) == PLUS
1864 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF)
1866 if (!rl78_saddr_p (op))
1867 fprintf (file, "!");
1868 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1870 else if (GET_CODE (XEXP (op, 0)) == PLUS
1871 && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
1872 && REGNO (XEXP (XEXP (op, 0), 0)) == 2)
1874 rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 1), 'u');
1875 fprintf (file, "[");
1876 rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 0), 0);
1877 if (letter == 'p' && GET_CODE (XEXP (op, 0)) == REG)
1878 fprintf (file, "+0");
1879 fprintf (file, "]");
1881 else
1883 op = XEXP (op, 0);
1884 fprintf (file, "[");
1885 rl78_print_operand_1 (file, op, letter);
1886 if (letter == 'p' && REG_P (op) && REGNO (op) == 6)
1887 fprintf (file, "+0");
1888 fprintf (file, "]");
1891 break;
1893 case REG:
1894 if (letter == 'Q')
1895 fprintf (file, "%s", reg_names [REGNO (op) | 1]);
1896 else if (letter == 'H')
1897 fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1898 else if (letter == 'q')
1899 fprintf (file, "%s", reg_names [REGNO (op) & ~1]);
1900 else if (letter == 'e')
1901 fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1902 else if (letter == 'E')
1903 fprintf (file, "%s", reg_names [REGNO (op) + 3]);
1904 else if (letter == 'S')
1905 fprintf (file, "0x%x", 0xffef8 + REGNO (op));
1906 else if (GET_MODE (op) == HImode
1907 && ! (REGNO (op) & ~0xfe))
1909 if (letter == 'v')
1910 fprintf (file, "%s", word_regnames [REGNO (op) % 8]);
1911 else
1912 fprintf (file, "%s", word_regnames [REGNO (op)]);
1914 else
1915 fprintf (file, "%s", reg_names [REGNO (op)]);
1916 break;
1918 case CONST_INT:
1919 if (letter == 'Q')
1920 fprintf (file, "%ld", INTVAL (op) >> 8);
1921 else if (letter == 'H')
1922 fprintf (file, "%ld", INTVAL (op) >> 16);
1923 else if (letter == 'q')
1924 fprintf (file, "%ld", INTVAL (op) & 0xff);
1925 else if (letter == 'h')
1926 fprintf (file, "%ld", INTVAL (op) & 0xffff);
1927 else if (letter == 'e')
1928 fprintf (file, "%ld", (INTVAL (op) >> 16) & 0xff);
1929 else if (letter == 'B')
1931 int ival = INTVAL (op);
1932 if (ival == -128)
1933 ival = 0x80;
1934 if (exact_log2 (ival) >= 0)
1935 fprintf (file, "%d", exact_log2 (ival));
1936 else
1937 fprintf (file, "%d", exact_log2 (~ival & 0xff));
1939 else if (letter == 'E')
1940 fprintf (file, "%ld", (INTVAL (op) >> 24) & 0xff);
1941 else if (letter == 'm')
1942 fprintf (file, "%ld", - INTVAL (op));
1943 else if (letter == 's')
1944 fprintf (file, "%ld", INTVAL (op) % 8);
1945 else if (letter == 'S')
1946 fprintf (file, "%ld", INTVAL (op) % 16);
1947 else if (letter == 'r')
1948 fprintf (file, "%ld", 8 - (INTVAL (op) % 8));
1949 else if (letter == 'C')
1950 fprintf (file, "%ld", (INTVAL (op) ^ 0x8000) & 0xffff);
1951 else
1952 fprintf (file, "%ld", INTVAL (op));
1953 break;
1955 case CONST:
1956 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1957 break;
1959 case ZERO_EXTRACT:
1961 int bits = INTVAL (XEXP (op, 1));
1962 int ofs = INTVAL (XEXP (op, 2));
1963 if (bits == 16 && ofs == 0)
1964 fprintf (file, "%%lo16(");
1965 else if (bits == 16 && ofs == 16)
1966 fprintf (file, "%%hi16(");
1967 else if (bits == 8 && ofs == 16)
1968 fprintf (file, "%%hi8(");
1969 else
1970 gcc_unreachable ();
1971 rl78_print_operand_1 (file, XEXP (op, 0), 0);
1972 fprintf (file, ")");
1974 break;
1976 case ZERO_EXTEND:
1977 if (GET_CODE (XEXP (op, 0)) == REG)
1978 fprintf (file, "%s", reg_names [REGNO (XEXP (op, 0))]);
1979 else
1980 print_rtl (file, op);
1981 break;
1983 case PLUS:
1984 need_paren = 0;
1985 if (letter == 'H')
1987 fprintf (file, "%%hi16(");
1988 need_paren = 1;
1989 letter = 0;
1991 if (letter == 'h')
1993 fprintf (file, "%%lo16(");
1994 need_paren = 1;
1995 letter = 0;
1997 if (letter == 'e')
1999 fprintf (file, "%%hi8(");
2000 need_paren = 1;
2001 letter = 0;
2003 if (letter == 'q' || letter == 'Q')
2004 output_operand_lossage ("q/Q modifiers invalid for symbol references");
2006 if (GET_CODE (XEXP (op, 0)) == ZERO_EXTEND)
2008 if (GET_CODE (XEXP (op, 1)) == SYMBOL_REF
2009 && SYMBOL_REF_DECL (XEXP (op, 1))
2010 && TREE_CODE (SYMBOL_REF_DECL (XEXP (op, 1))) == FUNCTION_DECL)
2012 fprintf (file, "%%code(");
2013 assemble_name (file, rl78_strip_nonasm_name_encoding (XSTR (XEXP (op, 1), 0)));
2014 fprintf (file, "+");
2015 rl78_print_operand_1 (file, XEXP (op, 0), letter);
2016 fprintf (file, ")");
2018 else
2020 rl78_print_operand_1 (file, XEXP (op, 1), letter);
2021 fprintf (file, "+");
2022 rl78_print_operand_1 (file, XEXP (op, 0), letter);
2025 else
2027 if (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
2028 && SYMBOL_REF_DECL (XEXP (op, 0))
2029 && TREE_CODE (SYMBOL_REF_DECL (XEXP (op, 0))) == FUNCTION_DECL)
2031 fprintf (file, "%%code(");
2032 assemble_name (file, rl78_strip_nonasm_name_encoding (XSTR (XEXP (op, 0), 0)));
2033 fprintf (file, "+");
2034 rl78_print_operand_1 (file, XEXP (op, 1), letter);
2035 fprintf (file, ")");
2037 else
2039 rl78_print_operand_1 (file, XEXP (op, 0), letter);
2040 fprintf (file, "+");
2041 rl78_print_operand_1 (file, XEXP (op, 1), letter);
2044 if (need_paren)
2045 fprintf (file, ")");
2046 break;
2048 case SUBREG:
2049 if (GET_MODE (op) == HImode
2050 && SUBREG_BYTE (op) == 0)
2052 fprintf (file, "%%lo16(");
2053 rl78_print_operand_1 (file, SUBREG_REG (op), 0);
2054 fprintf (file, ")");
2056 else if (GET_MODE (op) == HImode
2057 && SUBREG_BYTE (op) == 2)
2059 fprintf (file, "%%hi16(");
2060 rl78_print_operand_1 (file, SUBREG_REG (op), 0);
2061 fprintf (file, ")");
2063 else
2065 fprintf (file, "(%s)", GET_RTX_NAME (GET_CODE (op)));
2067 break;
2069 case SYMBOL_REF:
2070 need_paren = 0;
2071 if (letter == 'H')
2073 fprintf (file, "%%hi16(");
2074 need_paren = 1;
2075 letter = 0;
2077 if (letter == 'h')
2079 fprintf (file, "%%lo16(");
2080 need_paren = 1;
2081 letter = 0;
2083 if (letter == 'e')
2085 fprintf (file, "%%hi8(");
2086 need_paren = 1;
2087 letter = 0;
2089 if (letter == 'q' || letter == 'Q')
2090 output_operand_lossage ("q/Q modifiers invalid for symbol references");
2092 if (SYMBOL_REF_DECL (op) && TREE_CODE (SYMBOL_REF_DECL (op)) == FUNCTION_DECL)
2094 fprintf (file, "%%code(");
2095 assemble_name (file, rl78_strip_nonasm_name_encoding (XSTR (op, 0)));
2096 fprintf (file, ")");
2098 else
2099 assemble_name (file, rl78_strip_nonasm_name_encoding (XSTR (op, 0)));
2100 if (need_paren)
2101 fprintf (file, ")");
2102 break;
2104 case CODE_LABEL:
2105 case LABEL_REF:
2106 output_asm_label (op);
2107 break;
2109 case LTU:
2110 if (letter == 'z')
2111 fprintf (file, "#comparison eliminated");
2112 else
2113 fprintf (file, letter == 'C' ? "nc" : "c");
2114 break;
2115 case LEU:
2116 if (letter == 'z')
2117 fprintf (file, "br");
2118 else
2119 fprintf (file, letter == 'C' ? "h" : "nh");
2120 break;
2121 case GEU:
2122 if (letter == 'z')
2123 fprintf (file, "br");
2124 else
2125 fprintf (file, letter == 'C' ? "c" : "nc");
2126 break;
2127 case GTU:
2128 if (letter == 'z')
2129 fprintf (file, "#comparison eliminated");
2130 else
2131 fprintf (file, letter == 'C' ? "nh" : "h");
2132 break;
2133 case EQ:
2134 if (letter == 'z')
2135 fprintf (file, "br");
2136 else
2137 fprintf (file, letter == 'C' ? "nz" : "z");
2138 break;
2139 case NE:
2140 if (letter == 'z')
2141 fprintf (file, "#comparison eliminated");
2142 else
2143 fprintf (file, letter == 'C' ? "z" : "nz");
2144 break;
2146 /* Note: these assume appropriate adjustments were made so that
2147 unsigned comparisons, which is all this chip has, will
2148 work. */
2149 case LT:
2150 if (letter == 'z')
2151 fprintf (file, "#comparison eliminated");
2152 else
2153 fprintf (file, letter == 'C' ? "nc" : "c");
2154 break;
2155 case LE:
2156 if (letter == 'z')
2157 fprintf (file, "br");
2158 else
2159 fprintf (file, letter == 'C' ? "h" : "nh");
2160 break;
2161 case GE:
2162 if (letter == 'z')
2163 fprintf (file, "br");
2164 else
2165 fprintf (file, letter == 'C' ? "c" : "nc");
2166 break;
2167 case GT:
2168 if (letter == 'z')
2169 fprintf (file, "#comparison eliminated");
2170 else
2171 fprintf (file, letter == 'C' ? "nh" : "h");
2172 break;
2174 default:
2175 fprintf (file, "(%s)", GET_RTX_NAME (GET_CODE (op)));
2176 break;
2180 #undef TARGET_PRINT_OPERAND
2181 #define TARGET_PRINT_OPERAND rl78_print_operand
2183 static void
2184 rl78_print_operand (FILE * file, rtx op, int letter)
2186 if (CONSTANT_P (op) && letter != 'u' && letter != 's' && letter != 'r' && letter != 'S' && letter != 'B')
2187 fprintf (file, "#");
2188 rl78_print_operand_1 (file, op, letter);
2191 #undef TARGET_TRAMPOLINE_INIT
2192 #define TARGET_TRAMPOLINE_INIT rl78_trampoline_init
2194 /* Note that the RL78's addressing makes it very difficult to do
2195 trampolines on the stack. So, libgcc has a small pool of
2196 trampolines from which one is allocated to this task. */
2197 static void
2198 rl78_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
2200 rtx mov_addr, thunk_addr;
2201 rtx function = XEXP (DECL_RTL (fndecl), 0);
2203 mov_addr = adjust_address (m_tramp, HImode, 0);
2204 thunk_addr = gen_reg_rtx (HImode);
2206 function = force_reg (HImode, function);
2207 static_chain = force_reg (HImode, static_chain);
2209 emit_insn (gen_trampoline_init (thunk_addr, function, static_chain));
2210 emit_move_insn (mov_addr, thunk_addr);
2212 cfun->machine->trampolines_used = 1;
2215 #undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
2216 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS rl78_trampoline_adjust_address
2218 static rtx
2219 rl78_trampoline_adjust_address (rtx m_tramp)
2221 rtx x = gen_rtx_MEM (HImode, m_tramp);
2222 return x;
2225 /* Expander for cbranchqi4 and cbranchhi4. RL78 is missing some of
2226 the "normal" compares, specifically, it only has unsigned compares,
2227 so we must synthesize the missing ones. */
2228 void
2229 rl78_expand_compare (rtx *operands)
2231 if (GET_CODE (operands[2]) == MEM)
2232 operands[2] = copy_to_mode_reg (GET_MODE (operands[2]), operands[2]);
2237 /* Define this to 1 if you are debugging the peephole optimizers. */
2238 #define DEBUG_PEEP 0
2240 /* Predicate used to enable the peephole2 patterns in rl78-virt.md.
2241 The default "word" size is a byte so we can effectively use all the
2242 registers, but we want to do 16-bit moves whenever possible. This
2243 function determines when such a move is an option. */
2244 bool
2245 rl78_peep_movhi_p (rtx *operands)
2247 int i;
2248 rtx m, a;
2250 /* (set (op0) (op1))
2251 (set (op2) (op3)) */
2253 if (! rl78_virt_insns_ok ())
2254 return false;
2256 #if DEBUG_PEEP
2257 fprintf (stderr, "\033[33m");
2258 debug_rtx (operands[0]);
2259 debug_rtx (operands[1]);
2260 debug_rtx (operands[2]);
2261 debug_rtx (operands[3]);
2262 fprintf (stderr, "\033[0m");
2263 #endif
2265 /* You can move a constant to memory as QImode, but not HImode. */
2266 if (GET_CODE (operands[0]) == MEM
2267 && GET_CODE (operands[1]) != REG)
2269 #if DEBUG_PEEP
2270 fprintf (stderr, "no peep: move constant to memory\n");
2271 #endif
2272 return false;
2275 if (rtx_equal_p (operands[0], operands[3]))
2277 #if DEBUG_PEEP
2278 fprintf (stderr, "no peep: overlapping\n");
2279 #endif
2280 return false;
2283 for (i = 0; i < 2; i ++)
2285 if (GET_CODE (operands[i]) != GET_CODE (operands[i+2]))
2287 #if DEBUG_PEEP
2288 fprintf (stderr, "no peep: different codes\n");
2289 #endif
2290 return false;
2292 if (GET_MODE (operands[i]) != GET_MODE (operands[i+2]))
2294 #if DEBUG_PEEP
2295 fprintf (stderr, "no peep: different modes\n");
2296 #endif
2297 return false;
2300 switch (GET_CODE (operands[i]))
2302 case REG:
2303 /* LSB MSB */
2304 if (REGNO (operands[i]) + 1 != REGNO (operands[i+2])
2305 || GET_MODE (operands[i]) != QImode)
2307 #if DEBUG_PEEP
2308 fprintf (stderr, "no peep: wrong regnos %d %d %d\n",
2309 REGNO (operands[i]), REGNO (operands[i+2]),
2311 #endif
2312 return false;
2314 if (! rl78_hard_regno_mode_ok (REGNO (operands[i]), HImode))
2316 #if DEBUG_PEEP
2317 fprintf (stderr, "no peep: reg %d not HI\n", REGNO (operands[i]));
2318 #endif
2319 return false;
2321 break;
2323 case CONST_INT:
2324 break;
2326 case MEM:
2327 if (GET_MODE (operands[i]) != QImode)
2328 return false;
2329 if (MEM_ALIGN (operands[i]) < 16)
2330 return false;
2331 a = XEXP (operands[i], 0);
2332 if (GET_CODE (a) == CONST)
2333 a = XEXP (a, 0);
2334 if (GET_CODE (a) == PLUS)
2335 a = XEXP (a, 1);
2336 if (GET_CODE (a) == CONST_INT
2337 && INTVAL (a) & 1)
2339 #if DEBUG_PEEP
2340 fprintf (stderr, "no peep: misaligned mem %d\n", i);
2341 debug_rtx (operands[i]);
2342 #endif
2343 return false;
2345 m = adjust_address (operands[i], QImode, 1);
2346 if (! rtx_equal_p (m, operands[i+2]))
2348 #if DEBUG_PEEP
2349 fprintf (stderr, "no peep: wrong mem %d\n", i);
2350 debug_rtx (m);
2351 debug_rtx (operands[i+2]);
2352 #endif
2353 return false;
2355 break;
2357 default:
2358 #if DEBUG_PEEP
2359 fprintf (stderr, "no peep: wrong rtx %d\n", i);
2360 #endif
2361 return false;
2364 #if DEBUG_PEEP
2365 fprintf (stderr, "\033[32mpeep!\033[0m\n");
2366 #endif
2367 return true;
2370 /* Likewise, when a peephole is activated, this function helps compute
2371 the new operands. */
2372 void
2373 rl78_setup_peep_movhi (rtx *operands)
2375 int i;
2377 for (i = 0; i < 2; i ++)
2379 switch (GET_CODE (operands[i]))
2381 case REG:
2382 operands[i+4] = gen_rtx_REG (HImode, REGNO (operands[i]));
2383 break;
2385 case CONST_INT:
2386 operands[i+4] = GEN_INT ((INTVAL (operands[i]) & 0xff) + ((char) INTVAL (operands[i+2])) * 256);
2387 break;
2389 case MEM:
2390 operands[i+4] = adjust_address (operands[i], HImode, 0);
2391 break;
2393 default:
2394 break;
2400 How Devirtualization works in the RL78 GCC port
2402 Background
2404 The RL78 is an 8-bit port with some 16-bit operations. It has 32
2405 bytes of register space, in four banks, memory-mapped. One bank is
2406 the "selected" bank and holds the registers used for primary
2407 operations. Since the registers are memory mapped, often you can
2408 still refer to the unselected banks via memory accesses.
2410 Virtual Registers
2412 The GCC port uses bank 0 as the "selected" registers (A, X, BC, etc)
2413 and refers to the other banks via their memory addresses, although
2414 they're treated as regular registers internally. These "virtual"
2415 registers are R8 through R23 (bank3 is reserved for asm-based
2416 interrupt handlers).
2418 There are four machine description files:
2420 rl78.md - common register-independent patterns and definitions
2421 rl78-expand.md - expanders
2422 rl78-virt.md - patterns that match BEFORE devirtualization
2423 rl78-real.md - patterns that match AFTER devirtualization
2425 At least through register allocation and reload, gcc is told that it
2426 can do pretty much anything - but may only use the virtual registers.
2427 GCC cannot properly create the varying addressing modes that the RL78
2428 supports in an efficient way.
2430 Sometime after reload, the RL78 backend "devirtualizes" the RTL. It
2431 uses the "valloc" attribute in rl78-virt.md for determining the rules
2432 by which it will replace virtual registers with real registers (or
2433 not) and how to make up addressing modes. For example, insns tagged
2434 with "ro1" have a single read-only parameter, which may need to be
2435 moved from memory/constant/vreg to a suitable real register. As part
2436 of devirtualization, a flag is toggled, disabling the rl78-virt.md
2437 patterns and enabling the rl78-real.md patterns. The new patterns'
2438 constraints are used to determine the real registers used. NOTE:
2439 patterns in rl78-virt.md essentially ignore the constrains and rely on
2440 predicates, where the rl78-real.md ones essentially ignore the
2441 predicates and rely on the constraints.
2443 The devirtualization pass is scheduled via the pass manager (despite
2444 being called "rl78_reorg") so it can be scheduled prior to var-track
2445 (the idea is to let gdb know about the new registers). Ideally, it
2446 would be scheduled right after pro/epilogue generation, so the
2447 post-reload optimizers could operate on the real registers, but when I
2448 tried that there were some issues building the target libraries.
2450 During devirtualization, a simple register move optimizer is run. It
2451 would be better to run a full CSE/propogation pass on it though, but
2452 that has not yet been attempted.
2455 #define DEBUG_ALLOC 0
2457 #define OP(x) (*recog_data.operand_loc[x])
2459 /* This array is used to hold knowledge about the contents of the
2460 real registers (A ... H), the memory-based registers (r8 ... r31)
2461 and the first NUM_STACK_LOCS words on the stack. We use this to
2462 avoid generating redundant move instructions.
2464 A value in the range 0 .. 31 indicates register A .. r31.
2465 A value in the range 32 .. 63 indicates stack slot (value - 32).
2466 A value of NOT_KNOWN indicates that the contents of that location
2467 are not known. */
2469 #define NUM_STACK_LOCS 32
2470 #define NOT_KNOWN 127
2472 static unsigned char content_memory [32 + NUM_STACK_LOCS];
2474 static unsigned char saved_update_index = NOT_KNOWN;
2475 static unsigned char saved_update_value;
2476 static machine_mode saved_update_mode;
2479 static inline void
2480 clear_content_memory (void)
2482 memset (content_memory, NOT_KNOWN, sizeof content_memory);
2483 if (dump_file)
2484 fprintf (dump_file, " clear content memory\n");
2485 saved_update_index = NOT_KNOWN;
2488 /* Convert LOC into an index into the content_memory array.
2489 If LOC cannot be converted, return NOT_KNOWN. */
2491 static unsigned char
2492 get_content_index (rtx loc)
2494 machine_mode mode;
2496 if (loc == NULL_RTX)
2497 return NOT_KNOWN;
2499 if (REG_P (loc))
2501 if (REGNO (loc) < 32)
2502 return REGNO (loc);
2503 return NOT_KNOWN;
2506 mode = GET_MODE (loc);
2508 if (! rl78_stack_based_mem (loc, mode))
2509 return NOT_KNOWN;
2511 loc = XEXP (loc, 0);
2513 if (REG_P (loc))
2514 /* loc = MEM (SP) */
2515 return 32;
2517 /* loc = MEM (PLUS (SP, INT)). */
2518 loc = XEXP (loc, 1);
2520 if (INTVAL (loc) < NUM_STACK_LOCS)
2521 return 32 + INTVAL (loc);
2523 return NOT_KNOWN;
2526 /* Return a string describing content INDEX in mode MODE.
2527 WARNING: Can return a pointer to a static buffer. */
2528 static const char *
2529 get_content_name (unsigned char index, machine_mode mode)
2531 static char buffer [128];
2533 if (index == NOT_KNOWN)
2534 return "Unknown";
2536 if (index > 31)
2537 sprintf (buffer, "stack slot %d", index - 32);
2538 else if (mode == HImode)
2539 sprintf (buffer, "%s%s",
2540 reg_names [index + 1], reg_names [index]);
2541 else
2542 return reg_names [index];
2544 return buffer;
2547 #if DEBUG_ALLOC
2549 static void
2550 display_content_memory (FILE * file)
2552 unsigned int i;
2554 fprintf (file, " Known memory contents:\n");
2556 for (i = 0; i < sizeof content_memory; i++)
2557 if (content_memory[i] != NOT_KNOWN)
2559 fprintf (file, " %s contains a copy of ", get_content_name (i, QImode));
2560 fprintf (file, "%s\n", get_content_name (content_memory [i], QImode));
2563 #endif
2565 static void
2566 update_content (unsigned char index, unsigned char val, machine_mode mode)
2568 unsigned int i;
2570 gcc_assert (index < sizeof content_memory);
2572 content_memory [index] = val;
2573 if (val != NOT_KNOWN)
2574 content_memory [val] = index;
2576 /* Make the entry in dump_file *before* VAL is increased below. */
2577 if (dump_file)
2579 fprintf (dump_file, " %s now contains ", get_content_name (index, mode));
2580 if (val == NOT_KNOWN)
2581 fprintf (dump_file, "Unknown\n");
2582 else
2583 fprintf (dump_file, "%s and vice versa\n", get_content_name (val, mode));
2586 if (mode == HImode)
2588 val = val == NOT_KNOWN ? val : val + 1;
2590 content_memory [index + 1] = val;
2591 if (val != NOT_KNOWN)
2593 content_memory [val] = index + 1;
2594 -- val;
2598 /* Any other places that had INDEX recorded as their contents are now invalid. */
2599 for (i = 0; i < sizeof content_memory; i++)
2601 if (i == index
2602 || (val != NOT_KNOWN && i == val))
2604 if (mode == HImode)
2605 ++ i;
2606 continue;
2609 if (content_memory[i] == index
2610 || (val != NOT_KNOWN && content_memory[i] == val))
2612 content_memory[i] = NOT_KNOWN;
2614 if (dump_file)
2615 fprintf (dump_file, " %s cleared\n", get_content_name (i, mode));
2617 if (mode == HImode)
2618 content_memory[++ i] = NOT_KNOWN;
2623 /* Record that LOC contains VALUE.
2624 For HImode locations record that LOC+1 contains VALUE+1.
2625 If LOC is not a register or stack slot, do nothing.
2626 If VALUE is not a register or stack slot, clear the recorded content. */
2628 static void
2629 record_content (rtx loc, rtx value)
2631 machine_mode mode;
2632 unsigned char index;
2633 unsigned char val;
2635 if ((index = get_content_index (loc)) == NOT_KNOWN)
2636 return;
2638 val = get_content_index (value);
2640 mode = GET_MODE (loc);
2642 if (val == index)
2644 if (! optimize)
2645 return;
2647 /* This should not happen when optimizing. */
2648 #if 1
2649 fprintf (stderr, "ASSIGNMENT of location to itself detected! [%s]\n",
2650 get_content_name (val, mode));
2651 return;
2652 #else
2653 gcc_unreachable ();
2654 #endif
2657 update_content (index, val, mode);
2660 /* Returns TRUE if LOC already contains a copy of VALUE. */
2662 static bool
2663 already_contains (rtx loc, rtx value)
2665 unsigned char index;
2666 unsigned char val;
2668 if ((index = get_content_index (loc)) == NOT_KNOWN)
2669 return false;
2671 if ((val = get_content_index (value)) == NOT_KNOWN)
2672 return false;
2674 if (content_memory [index] != val)
2675 return false;
2677 if (GET_MODE (loc) == HImode)
2678 return content_memory [index + 1] == val + 1;
2680 return true;
2683 bool
2684 rl78_es_addr (rtx addr)
2686 if (GET_CODE (addr) == MEM)
2687 addr = XEXP (addr, 0);
2688 if (GET_CODE (addr) != UNSPEC)
2689 return false;
2690 if (XINT (addr, 1) != UNS_ES_ADDR)
2691 return false;
2692 return true;
2696 rl78_es_base (rtx addr)
2698 if (GET_CODE (addr) == MEM)
2699 addr = XEXP (addr, 0);
2700 addr = XVECEXP (addr, 0, 1);
2701 if (GET_CODE (addr) == CONST
2702 && GET_CODE (XEXP (addr, 0)) == ZERO_EXTRACT)
2703 addr = XEXP (XEXP (addr, 0), 0);
2704 /* Mode doesn't matter here. */
2705 return gen_rtx_MEM (HImode, addr);
2708 /* Rescans an insn to see if it's recognized again. This is done
2709 carefully to ensure that all the constraint information is accurate
2710 for the newly matched insn. */
2711 static bool
2712 insn_ok_now (rtx_insn * insn)
2714 rtx pattern = PATTERN (insn);
2715 int i;
2717 INSN_CODE (insn) = -1;
2719 if (recog (pattern, insn, 0) > -1)
2721 extract_insn (insn);
2722 if (constrain_operands (1, get_preferred_alternatives (insn)))
2724 #if DEBUG_ALLOC
2725 fprintf (stderr, "\033[32m");
2726 debug_rtx (insn);
2727 fprintf (stderr, "\033[0m");
2728 #endif
2729 if (SET_P (pattern))
2730 record_content (SET_DEST (pattern), SET_SRC (pattern));
2732 /* We need to detect far addresses that haven't been
2733 converted to es/lo16 format. */
2734 for (i=0; i<recog_data.n_operands; i++)
2735 if (GET_CODE (OP (i)) == MEM
2736 && GET_MODE (XEXP (OP (i), 0)) == SImode
2737 && GET_CODE (XEXP (OP (i), 0)) != UNSPEC)
2738 return false;
2740 return true;
2743 else
2745 /* We need to re-recog the insn with virtual registers to get
2746 the operands. */
2747 cfun->machine->virt_insns_ok = 1;
2748 if (recog (pattern, insn, 0) > -1)
2750 extract_insn (insn);
2751 if (constrain_operands (0, get_preferred_alternatives (insn)))
2753 cfun->machine->virt_insns_ok = 0;
2754 return false;
2758 #if DEBUG_ALLOC
2759 fprintf (stderr, "\033[41;30m Unrecognized *virtual* insn \033[0m\n");
2760 debug_rtx (insn);
2761 #endif
2762 gcc_unreachable ();
2765 #if DEBUG_ALLOC
2766 fprintf (stderr, "\033[31m");
2767 debug_rtx (insn);
2768 fprintf (stderr, "\033[0m");
2769 #endif
2770 return false;
2773 #if DEBUG_ALLOC
2774 #define WORKED fprintf (stderr, "\033[48;5;22m Worked at line %d \033[0m\n", __LINE__)
2775 #define FAILEDSOFAR fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__)
2776 #define FAILED fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__), gcc_unreachable ()
2777 #define MAYBE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } else { FAILEDSOFAR; }
2778 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } FAILED
2779 #else
2780 #define FAILED gcc_unreachable ()
2781 #define MAYBE_OK(insn) if (insn_ok_now (insn)) return;
2782 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) return; FAILED
2783 #endif
2785 /* Registers into which we move the contents of virtual registers. */
2786 #define X gen_rtx_REG (QImode, X_REG)
2787 #define A gen_rtx_REG (QImode, A_REG)
2788 #define C gen_rtx_REG (QImode, C_REG)
2789 #define B gen_rtx_REG (QImode, B_REG)
2790 #define E gen_rtx_REG (QImode, E_REG)
2791 #define D gen_rtx_REG (QImode, D_REG)
2792 #define L gen_rtx_REG (QImode, L_REG)
2793 #define H gen_rtx_REG (QImode, H_REG)
2795 #define AX gen_rtx_REG (HImode, AX_REG)
2796 #define BC gen_rtx_REG (HImode, BC_REG)
2797 #define DE gen_rtx_REG (HImode, DE_REG)
2798 #define HL gen_rtx_REG (HImode, HL_REG)
2800 /* Returns TRUE if R is a virtual register. */
2801 static inline bool
2802 is_virtual_register (rtx r)
2804 return (GET_CODE (r) == REG
2805 && REGNO (r) >= 8
2806 && REGNO (r) < 32);
2809 /* In all these alloc routines, we expect the following: the insn
2810 pattern is unshared, the insn was previously recognized and failed
2811 due to predicates or constraints, and the operand data is in
2812 recog_data. */
2814 static int virt_insn_was_frame;
2816 /* Hook for all insns we emit. Re-mark them as FRAME_RELATED if
2817 needed. */
2818 static rtx
2819 EM2 (int line ATTRIBUTE_UNUSED, rtx r)
2821 #if DEBUG_ALLOC
2822 fprintf (stderr, "\033[36m%d: ", line);
2823 debug_rtx (r);
2824 fprintf (stderr, "\033[0m");
2825 #endif
2826 /*SCHED_GROUP_P (r) = 1;*/
2827 if (virt_insn_was_frame)
2828 RTX_FRAME_RELATED_P (r) = 1;
2829 return r;
2832 #define EM(x) EM2 (__LINE__, x)
2834 /* Return a suitable RTX for the low half of a __far address. */
2835 static rtx
2836 rl78_lo16 (rtx addr)
2838 rtx r;
2840 if (GET_CODE (addr) == SYMBOL_REF
2841 || GET_CODE (addr) == CONST)
2843 r = gen_rtx_ZERO_EXTRACT (HImode, addr, GEN_INT (16), GEN_INT (0));
2844 r = gen_rtx_CONST (HImode, r);
2846 else
2847 r = rl78_subreg (HImode, addr, SImode, 0);
2849 r = gen_es_addr (r);
2850 cfun->machine->uses_es = true;
2852 return r;
2855 /* Return a suitable RTX for the high half's lower byte of a __far address. */
2856 static rtx
2857 rl78_hi8 (rtx addr)
2859 if (GET_CODE (addr) == SYMBOL_REF
2860 || GET_CODE (addr) == CONST)
2862 rtx r = gen_rtx_ZERO_EXTRACT (QImode, addr, GEN_INT (8), GEN_INT (16));
2863 r = gen_rtx_CONST (QImode, r);
2864 return r;
2866 return rl78_subreg (QImode, addr, SImode, 2);
2869 static void
2870 add_postponed_content_update (rtx to, rtx value)
2872 unsigned char index;
2874 if ((index = get_content_index (to)) == NOT_KNOWN)
2875 return;
2877 gcc_assert (saved_update_index == NOT_KNOWN);
2878 saved_update_index = index;
2879 saved_update_value = get_content_index (value);
2880 saved_update_mode = GET_MODE (to);
2883 static void
2884 process_postponed_content_update (void)
2886 if (saved_update_index != NOT_KNOWN)
2888 update_content (saved_update_index, saved_update_value, saved_update_mode);
2889 saved_update_index = NOT_KNOWN;
2893 /* Generate and emit a move of (register) FROM into TO. if WHERE is not NULL
2894 then if BEFORE is true then emit the insn before WHERE, otherwise emit it
2895 after WHERE. If TO already contains FROM then do nothing. Returns TO if
2896 BEFORE is true, FROM otherwise. */
2897 static rtx
2898 gen_and_emit_move (rtx to, rtx from, rtx_insn *where, bool before)
2900 machine_mode mode = GET_MODE (to);
2902 if (optimize && before && already_contains (to, from))
2904 #if DEBUG_ALLOC
2905 display_content_memory (stderr);
2906 #endif
2907 if (dump_file)
2909 fprintf (dump_file, " Omit move of %s into ",
2910 get_content_name (get_content_index (from), mode));
2911 fprintf (dump_file, "%s as it already contains this value\n",
2912 get_content_name (get_content_index (to), mode));
2915 else
2917 rtx move = mode == QImode ? gen_movqi (to, from) : gen_movhi (to, from);
2919 EM (move);
2921 if (where == NULL_RTX)
2922 emit_insn (move);
2923 else if (before)
2924 emit_insn_before (move, where);
2925 else
2927 rtx note = find_reg_note (where, REG_EH_REGION, NULL_RTX);
2929 /* If necessary move REG_EH_REGION notes forward.
2930 cf. compiling gcc.dg/pr44545.c. */
2931 if (note != NULL_RTX)
2933 add_reg_note (move, REG_EH_REGION, XEXP (note, 0));
2934 remove_note (where, note);
2937 emit_insn_after (move, where);
2940 if (before)
2941 record_content (to, from);
2942 else
2943 add_postponed_content_update (to, from);
2946 return before ? to : from;
2949 /* If M is MEM(REG) or MEM(PLUS(REG,INT)) and REG is virtual then
2950 copy it into NEWBASE and return the updated MEM. Otherwise just
2951 return M. Any needed insns are emitted before BEFORE. */
2952 static rtx
2953 transcode_memory_rtx (rtx m, rtx newbase, rtx_insn *before)
2955 rtx base, index, addendr;
2956 int addend = 0;
2957 int need_es = 0;
2959 if (! MEM_P (m))
2960 return m;
2962 if (GET_MODE (XEXP (m, 0)) == SImode)
2964 rtx new_m;
2965 rtx seg = rl78_hi8 (XEXP (m, 0));
2967 if (!TARGET_ES0)
2969 emit_insn_before (EM (gen_movqi (A, seg)), before);
2970 emit_insn_before (EM (gen_movqi_to_es (A)), before);
2973 record_content (A, NULL_RTX);
2975 new_m = gen_rtx_MEM (GET_MODE (m), rl78_lo16 (XEXP (m, 0)));
2976 MEM_COPY_ATTRIBUTES (new_m, m);
2977 m = new_m;
2978 need_es = 1;
2981 characterize_address (XEXP (m, 0), & base, & index, & addendr);
2982 gcc_assert (index == NULL_RTX);
2984 if (base == NULL_RTX)
2985 return m;
2987 if (addendr && GET_CODE (addendr) == CONST_INT)
2988 addend = INTVAL (addendr);
2990 gcc_assert (REG_P (base));
2991 gcc_assert (REG_P (newbase));
2993 int limit = 256 - GET_MODE_SIZE (GET_MODE (m));
2995 if (REGNO (base) == SP_REG)
2997 if (addend >= 0 && addend <= limit)
2998 return m;
3001 /* BASE should be a virtual register. We copy it to NEWBASE. If
3002 the addend is out of range for DE/HL, we use AX to compute the full
3003 address. */
3005 if (addend < 0
3006 || (addend > limit && REGNO (newbase) != BC_REG)
3007 || (addendr
3008 && (GET_CODE (addendr) != CONST_INT)
3009 && ((REGNO (newbase) != BC_REG))
3012 /* mov ax, vreg
3013 add ax, #imm
3014 mov hl, ax */
3015 EM (emit_insn_before (gen_movhi (AX, base), before));
3016 EM (emit_insn_before (gen_addhi3 (AX, AX, addendr), before));
3017 EM (emit_insn_before (gen_movhi (newbase, AX), before));
3018 record_content (AX, NULL_RTX);
3019 record_content (newbase, NULL_RTX);
3021 base = newbase;
3022 addend = 0;
3023 addendr = 0;
3025 else
3027 base = gen_and_emit_move (newbase, base, before, true);
3030 if (addend)
3032 record_content (base, NULL_RTX);
3033 base = gen_rtx_PLUS (HImode, base, GEN_INT (addend));
3035 else if (addendr)
3037 record_content (base, NULL_RTX);
3038 base = gen_rtx_PLUS (HImode, base, addendr);
3041 if (need_es)
3043 m = change_address (m, GET_MODE (m), gen_es_addr (base));
3044 cfun->machine->uses_es = true;
3046 else
3047 m = change_address (m, GET_MODE (m), base);
3048 return m;
3051 /* Copy SRC to accumulator (A or AX), placing any generated insns
3052 before BEFORE. Returns accumulator RTX. */
3053 static rtx
3054 move_to_acc (int opno, rtx_insn *before)
3056 rtx src = OP (opno);
3057 machine_mode mode = GET_MODE (src);
3059 if (REG_P (src) && REGNO (src) < 2)
3060 return src;
3062 if (mode == VOIDmode)
3063 mode = recog_data.operand_mode[opno];
3065 return gen_and_emit_move (mode == QImode ? A : AX, src, before, true);
3068 static void
3069 force_into_acc (rtx src, rtx_insn *before)
3071 machine_mode mode = GET_MODE (src);
3072 rtx move;
3074 if (REG_P (src) && REGNO (src) < 2)
3075 return;
3077 move = mode == QImode ? gen_movqi (A, src) : gen_movhi (AX, src);
3079 EM (move);
3081 emit_insn_before (move, before);
3082 record_content (AX, NULL_RTX);
3085 /* Copy accumulator (A or AX) to DEST, placing any generated insns
3086 after AFTER. Returns accumulator RTX. */
3087 static rtx
3088 move_from_acc (unsigned int opno, rtx_insn *after)
3090 rtx dest = OP (opno);
3091 machine_mode mode = GET_MODE (dest);
3093 if (REG_P (dest) && REGNO (dest) < 2)
3094 return dest;
3096 return gen_and_emit_move (dest, mode == QImode ? A : AX, after, false);
3099 /* Copy accumulator (A or AX) to REGNO, placing any generated insns
3100 before BEFORE. Returns reg RTX. */
3101 static rtx
3102 move_acc_to_reg (rtx acc, int regno, rtx_insn *before)
3104 machine_mode mode = GET_MODE (acc);
3105 rtx reg;
3107 reg = gen_rtx_REG (mode, regno);
3109 return gen_and_emit_move (reg, acc, before, true);
3112 /* Copy SRC to X, placing any generated insns before BEFORE.
3113 Returns X RTX. */
3114 static rtx
3115 move_to_x (int opno, rtx_insn *before)
3117 rtx src = OP (opno);
3118 machine_mode mode = GET_MODE (src);
3119 rtx reg;
3121 if (mode == VOIDmode)
3122 mode = recog_data.operand_mode[opno];
3123 reg = (mode == QImode) ? X : AX;
3125 if (mode == QImode || ! is_virtual_register (OP (opno)))
3127 OP (opno) = move_to_acc (opno, before);
3128 OP (opno) = move_acc_to_reg (OP (opno), X_REG, before);
3129 return reg;
3132 return gen_and_emit_move (reg, src, before, true);
3135 /* Copy OP (opno) to H or HL, placing any generated insns before BEFORE.
3136 Returns H/HL RTX. */
3137 static rtx
3138 move_to_hl (int opno, rtx_insn *before)
3140 rtx src = OP (opno);
3141 machine_mode mode = GET_MODE (src);
3142 rtx reg;
3144 if (mode == VOIDmode)
3145 mode = recog_data.operand_mode[opno];
3146 reg = (mode == QImode) ? L : HL;
3148 if (mode == QImode || ! is_virtual_register (OP (opno)))
3150 OP (opno) = move_to_acc (opno, before);
3151 OP (opno) = move_acc_to_reg (OP (opno), L_REG, before);
3152 return reg;
3155 return gen_and_emit_move (reg, src, before, true);
3158 /* Copy OP (opno) to E or DE, placing any generated insns before BEFORE.
3159 Returns E/DE RTX. */
3160 static rtx
3161 move_to_de (int opno, rtx_insn *before)
3163 rtx src = OP (opno);
3164 machine_mode mode = GET_MODE (src);
3165 rtx reg;
3167 if (mode == VOIDmode)
3168 mode = recog_data.operand_mode[opno];
3170 reg = (mode == QImode) ? E : DE;
3172 if (mode == QImode || ! is_virtual_register (OP (opno)))
3174 OP (opno) = move_to_acc (opno, before);
3175 OP (opno) = move_acc_to_reg (OP (opno), E_REG, before);
3177 else
3179 gen_and_emit_move (reg, src, before, true);
3182 return reg;
3185 /* Devirtualize an insn of the form (SET (op) (unop (op))). */
3186 static void
3187 rl78_alloc_physical_registers_op1 (rtx_insn * insn)
3189 /* op[0] = func op[1] */
3191 /* We first try using A as the destination, then copying it
3192 back. */
3193 if (rtx_equal_p (OP (0), OP (1)))
3195 OP (0) =
3196 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3198 else
3200 /* If necessary, load the operands into BC and HL.
3201 Check to see if we already have OP (0) in HL
3202 and if so, swap the order.
3204 It is tempting to perform this optimization when OP(0) does
3205 not hold a MEM, but this leads to bigger code in general.
3206 The problem is that if OP(1) holds a MEM then swapping it
3207 into BC means a BC-relative load is used and these are 3
3208 bytes long vs 1 byte for an HL load. */
3209 if (MEM_P (OP (0))
3210 && already_contains (HL, XEXP (OP (0), 0)))
3212 OP (0) = transcode_memory_rtx (OP (0), HL, insn);
3213 OP (1) = transcode_memory_rtx (OP (1), BC, insn);
3215 else
3217 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
3218 OP (1) = transcode_memory_rtx (OP (1), HL, insn);
3222 MAYBE_OK (insn);
3224 OP (0) = move_from_acc (0, insn);
3226 MAYBE_OK (insn);
3228 /* Try copying the src to acc first, then. This is for, for
3229 example, ZERO_EXTEND or NOT. */
3230 OP (1) = move_to_acc (1, insn);
3232 MUST_BE_OK (insn);
3235 /* Returns true if operand OPNUM contains a constraint of type CONSTRAINT.
3236 Assumes that the current insn has already been recognised and hence the
3237 constraint data has been filled in. */
3238 static bool
3239 has_constraint (unsigned int opnum, enum constraint_num constraint)
3241 const char * p = recog_data.constraints[opnum];
3243 /* No constraints means anything is accepted. */
3244 if (p == NULL || *p == 0 || *p == ',')
3245 return true;
3249 char c;
3250 unsigned int len;
3252 c = *p;
3253 len = CONSTRAINT_LEN (c, p);
3254 gcc_assert (len > 0);
3256 switch (c)
3258 case 0:
3259 case ',':
3260 return false;
3261 default:
3262 if (lookup_constraint (p) == constraint)
3263 return true;
3265 p += len;
3267 while (1);
3270 /* Devirtualize an insn of the form (SET (op) (binop (op) (op))). */
3271 static void
3272 rl78_alloc_physical_registers_op2 (rtx_insn * insn)
3274 rtx_insn *prev;
3275 rtx_insn *first;
3276 bool hl_used;
3277 int tmp_id;
3278 rtx saved_op1;
3280 if (rtx_equal_p (OP (0), OP (1)))
3282 if (MEM_P (OP (2)))
3284 OP (0) =
3285 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3286 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
3288 else
3290 OP (0) =
3291 OP (1) = transcode_memory_rtx (OP (1), HL, insn);
3292 OP (2) = transcode_memory_rtx (OP (2), DE, insn);
3295 else if (rtx_equal_p (OP (0), OP (2)))
3297 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3298 OP (0) =
3299 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
3301 else
3303 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
3304 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3305 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
3308 MAYBE_OK (insn);
3310 prev = prev_nonnote_nondebug_insn (insn);
3311 if (recog_data.constraints[1][0] == '%'
3312 && is_virtual_register (OP (1))
3313 && ! is_virtual_register (OP (2))
3314 && ! CONSTANT_P (OP (2)))
3316 rtx tmp = OP (1);
3317 OP (1) = OP (2);
3318 OP (2) = tmp;
3321 /* Make a note of whether (H)L is being used. It matters
3322 because if OP (2) also needs reloading, then we must take
3323 care not to corrupt HL. */
3324 hl_used = reg_mentioned_p (L, OP (0)) || reg_mentioned_p (L, OP (1));
3326 /* If HL is not currently being used and dest == op1 then there are
3327 some possible optimizations available by reloading one of the
3328 operands into HL, before trying to use the accumulator. */
3329 if (optimize
3330 && ! hl_used
3331 && rtx_equal_p (OP (0), OP (1)))
3333 /* If op0 is a Ws1 type memory address then switching the base
3334 address register to HL might allow us to perform an in-memory
3335 operation. (eg for the INCW instruction).
3337 FIXME: Adding the move into HL is costly if this optimization is not
3338 going to work, so for now, make sure that we know that the new insn will
3339 match the requirements of the addhi3_real pattern. Really we ought to
3340 generate a candidate sequence, test that, and then install it if the
3341 results are good. */
3342 if (satisfies_constraint_Ws1 (OP (0))
3343 && has_constraint (0, CONSTRAINT_Wh1)
3344 && (satisfies_constraint_K (OP (2)) || satisfies_constraint_L (OP (2))))
3346 rtx base, index, addend, newbase;
3348 characterize_address (XEXP (OP (0), 0), & base, & index, & addend);
3349 gcc_assert (index == NULL_RTX);
3350 gcc_assert (REG_P (base) && REGNO (base) == SP_REG);
3352 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
3353 if (addend != NULL_RTX)
3355 newbase = gen_and_emit_move (HL, base, insn, true);
3356 record_content (newbase, NULL_RTX);
3357 newbase = gen_rtx_PLUS (HImode, newbase, addend);
3359 OP (0) = OP (1) = change_address (OP (0), VOIDmode, newbase);
3361 /* We do not want to fail here as this means that
3362 we have inserted useless insns into the stream. */
3363 MUST_BE_OK (insn);
3366 else if (REG_P (OP (0))
3367 && satisfies_constraint_Ws1 (OP (2))
3368 && has_constraint (2, CONSTRAINT_Wh1))
3370 rtx base, index, addend, newbase;
3372 characterize_address (XEXP (OP (2), 0), & base, & index, & addend);
3373 gcc_assert (index == NULL_RTX);
3374 gcc_assert (REG_P (base) && REGNO (base) == SP_REG);
3376 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
3377 if (addend != NULL_RTX)
3379 gen_and_emit_move (HL, base, insn, true);
3381 if (REGNO (OP (0)) != X_REG)
3383 OP (1) = move_to_acc (1, insn);
3384 OP (0) = move_from_acc (0, insn);
3387 record_content (HL, NULL_RTX);
3388 newbase = gen_rtx_PLUS (HImode, HL, addend);
3390 OP (2) = change_address (OP (2), VOIDmode, newbase);
3392 /* We do not want to fail here as this means that
3393 we have inserted useless insns into the stream. */
3394 MUST_BE_OK (insn);
3399 OP (0) = move_from_acc (0, insn);
3401 tmp_id = get_max_insn_count ();
3402 saved_op1 = OP (1);
3404 if (rtx_equal_p (OP (1), OP (2)))
3405 OP (2) = OP (1) = move_to_acc (1, insn);
3406 else
3407 OP (1) = move_to_acc (1, insn);
3409 MAYBE_OK (insn);
3411 /* If we omitted the move of OP1 into the accumulator (because
3412 it was already there from a previous insn), then force the
3413 generation of the move instruction now. We know that we
3414 are about to emit a move into HL (or DE) via AX, and hence
3415 our optimization to remove the load of OP1 is no longer valid. */
3416 if (tmp_id == get_max_insn_count ())
3417 force_into_acc (saved_op1, insn);
3419 /* We have to copy op2 to HL (or DE), but that involves AX, which
3420 already has a live value. Emit it before those insns. */
3422 if (prev)
3423 first = next_nonnote_nondebug_insn (prev);
3424 else
3425 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
3428 OP (2) = hl_used ? move_to_de (2, first) : move_to_hl (2, first);
3430 MUST_BE_OK (insn);
3433 /* Devirtualize an insn of the form SET (PC) (MEM/REG). */
3434 static void
3435 rl78_alloc_physical_registers_ro1 (rtx_insn * insn)
3437 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
3439 MAYBE_OK (insn);
3441 OP (0) = move_to_acc (0, insn);
3443 MUST_BE_OK (insn);
3446 /* Devirtualize a compare insn. */
3447 static void
3448 rl78_alloc_physical_registers_cmp (rtx_insn * insn)
3450 int tmp_id;
3451 rtx saved_op1;
3452 rtx_insn *prev = prev_nonnote_nondebug_insn (insn);
3453 rtx_insn *first;
3455 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3456 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
3458 /* HI compares have to have OP (1) in AX, but QI
3459 compares do not, so it is worth checking here. */
3460 MAYBE_OK (insn);
3462 /* For an HImode compare, OP (1) must always be in AX.
3463 But if OP (1) is a REG (and not AX), then we can avoid
3464 a reload of OP (1) if we reload OP (2) into AX and invert
3465 the comparison. */
3466 if (REG_P (OP (1))
3467 && REGNO (OP (1)) != AX_REG
3468 && GET_MODE (OP (1)) == HImode
3469 && MEM_P (OP (2)))
3471 rtx cmp = XEXP (SET_SRC (PATTERN (insn)), 0);
3473 OP (2) = move_to_acc (2, insn);
3475 switch (GET_CODE (cmp))
3477 case EQ:
3478 case NE:
3479 break;
3480 case LTU: cmp = gen_rtx_GTU (HImode, OP (2), OP (1)); break;
3481 case GTU: cmp = gen_rtx_LTU (HImode, OP (2), OP (1)); break;
3482 case LEU: cmp = gen_rtx_GEU (HImode, OP (2), OP (1)); break;
3483 case GEU: cmp = gen_rtx_LEU (HImode, OP (2), OP (1)); break;
3485 case LT:
3486 case GT:
3487 case LE:
3488 case GE:
3489 #if DEBUG_ALLOC
3490 debug_rtx (insn);
3491 #endif
3492 default:
3493 gcc_unreachable ();
3496 if (GET_CODE (cmp) == EQ || GET_CODE (cmp) == NE)
3497 PATTERN (insn) = gen_cbranchhi4_real (cmp, OP (2), OP (1), OP (3));
3498 else
3499 PATTERN (insn) = gen_cbranchhi4_real_inverted (cmp, OP (2), OP (1), OP (3));
3501 MUST_BE_OK (insn);
3504 /* Surprisingly, gcc can generate a comparison of a register with itself, but this
3505 should be handled by the second alternative of the cbranchhi_real pattern. */
3506 if (rtx_equal_p (OP (1), OP (2)))
3508 OP (1) = OP (2) = BC;
3509 MUST_BE_OK (insn);
3512 tmp_id = get_max_insn_count ();
3513 saved_op1 = OP (1);
3515 OP (1) = move_to_acc (1, insn);
3517 MAYBE_OK (insn);
3519 /* If we omitted the move of OP1 into the accumulator (because
3520 it was already there from a previous insn), then force the
3521 generation of the move instruction now. We know that we
3522 are about to emit a move into HL via AX, and hence our
3523 optimization to remove the load of OP1 is no longer valid. */
3524 if (tmp_id == get_max_insn_count ())
3525 force_into_acc (saved_op1, insn);
3527 /* We have to copy op2 to HL, but that involves the acc, which
3528 already has a live value. Emit it before those insns. */
3529 if (prev)
3530 first = next_nonnote_nondebug_insn (prev);
3531 else
3532 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
3534 OP (2) = move_to_hl (2, first);
3536 MUST_BE_OK (insn);
3539 /* Like op2, but AX = A * X. */
3540 static void
3541 rl78_alloc_physical_registers_umul (rtx_insn * insn)
3543 rtx_insn *prev = prev_nonnote_nondebug_insn (insn);
3544 rtx_insn *first;
3545 int tmp_id;
3546 rtx saved_op1;
3548 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
3549 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3550 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
3552 MAYBE_OK (insn);
3554 if (recog_data.constraints[1][0] == '%'
3555 && is_virtual_register (OP (1))
3556 && !is_virtual_register (OP (2))
3557 && !CONSTANT_P (OP (2)))
3559 rtx tmp = OP (1);
3560 OP (1) = OP (2);
3561 OP (2) = tmp;
3564 OP (0) = move_from_acc (0, insn);
3566 tmp_id = get_max_insn_count ();
3567 saved_op1 = OP (1);
3569 if (rtx_equal_p (OP (1), OP (2)))
3571 gcc_assert (GET_MODE (OP (2)) == QImode);
3572 /* The MULU instruction does not support duplicate arguments
3573 but we know that if we copy OP (2) to X it will do so via
3574 A and thus OP (1) will already be loaded into A. */
3575 OP (2) = move_to_x (2, insn);
3576 OP (1) = A;
3578 else
3579 OP (1) = move_to_acc (1, insn);
3581 MAYBE_OK (insn);
3583 /* If we omitted the move of OP1 into the accumulator (because
3584 it was already there from a previous insn), then force the
3585 generation of the move instruction now. We know that we
3586 are about to emit a move into HL (or DE) via AX, and hence
3587 our optimization to remove the load of OP1 is no longer valid. */
3588 if (tmp_id == get_max_insn_count ())
3589 force_into_acc (saved_op1, insn);
3591 /* We have to copy op2 to X, but that involves the acc, which
3592 already has a live value. Emit it before those insns. */
3594 if (prev)
3595 first = next_nonnote_nondebug_insn (prev);
3596 else
3597 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
3599 OP (2) = move_to_x (2, first);
3601 MUST_BE_OK (insn);
3604 static void
3605 rl78_alloc_address_registers_macax (rtx_insn * insn)
3607 int which, op;
3608 bool replace_in_op0 = false;
3609 bool replace_in_op1 = false;
3611 MAYBE_OK (insn);
3613 /* Two different MEMs are not allowed. */
3614 which = 0;
3615 for (op = 2; op >= 0; op --)
3617 if (MEM_P (OP (op)))
3619 if (op == 0 && replace_in_op0)
3620 continue;
3621 if (op == 1 && replace_in_op1)
3622 continue;
3624 switch (which)
3626 case 0:
3627 /* If we replace a MEM, make sure that we replace it for all
3628 occurrences of the same MEM in the insn. */
3629 replace_in_op0 = (op > 0 && rtx_equal_p (OP (op), OP (0)));
3630 replace_in_op1 = (op > 1 && rtx_equal_p (OP (op), OP (1)));
3632 OP (op) = transcode_memory_rtx (OP (op), HL, insn);
3633 if (op == 2
3634 && MEM_P (OP (op))
3635 && ((GET_CODE (XEXP (OP (op), 0)) == REG
3636 && REGNO (XEXP (OP (op), 0)) == SP_REG)
3637 || (GET_CODE (XEXP (OP (op), 0)) == PLUS
3638 && REGNO (XEXP (XEXP (OP (op), 0), 0)) == SP_REG)))
3640 emit_insn_before (gen_movhi (HL, gen_rtx_REG (HImode, SP_REG)), insn);
3641 OP (op) = replace_rtx (OP (op), gen_rtx_REG (HImode, SP_REG), HL);
3643 if (replace_in_op0)
3644 OP (0) = OP (op);
3645 if (replace_in_op1)
3646 OP (1) = OP (op);
3647 break;
3648 case 1:
3649 OP (op) = transcode_memory_rtx (OP (op), DE, insn);
3650 break;
3651 case 2:
3652 OP (op) = transcode_memory_rtx (OP (op), BC, insn);
3653 break;
3655 which ++;
3659 MUST_BE_OK (insn);
3662 static void
3663 rl78_alloc_address_registers_div (rtx_insn * insn)
3665 MUST_BE_OK (insn);
3668 /* Scan all insns and devirtualize them. */
3669 static void
3670 rl78_alloc_physical_registers (void)
3672 /* During most of the compile, gcc is dealing with virtual
3673 registers. At this point, we need to assign physical registers
3674 to the vitual ones, and copy in/out as needed. */
3676 rtx_insn *insn, *curr;
3677 enum attr_valloc valloc_method;
3679 for (insn = get_insns (); insn; insn = curr)
3681 int i;
3683 curr = next_nonnote_nondebug_insn (insn);
3685 if (INSN_P (insn)
3686 && (GET_CODE (PATTERN (insn)) == SET
3687 || GET_CODE (PATTERN (insn)) == CALL)
3688 && INSN_CODE (insn) == -1)
3690 if (GET_CODE (SET_SRC (PATTERN (insn))) == ASM_OPERANDS)
3691 continue;
3692 i = recog (PATTERN (insn), insn, 0);
3693 if (i == -1)
3695 debug_rtx (insn);
3696 gcc_unreachable ();
3698 INSN_CODE (insn) = i;
3702 cfun->machine->virt_insns_ok = 0;
3703 cfun->machine->real_insns_ok = 1;
3705 clear_content_memory ();
3707 for (insn = get_insns (); insn; insn = curr)
3709 rtx pattern;
3711 curr = insn ? next_nonnote_nondebug_insn (insn) : NULL;
3713 if (!INSN_P (insn))
3715 if (LABEL_P (insn))
3716 clear_content_memory ();
3718 continue;
3721 if (dump_file)
3722 fprintf (dump_file, "Converting insn %d\n", INSN_UID (insn));
3724 pattern = PATTERN (insn);
3725 if (GET_CODE (pattern) == PARALLEL)
3726 pattern = XVECEXP (pattern, 0, 0);
3727 if (JUMP_P (insn) || CALL_P (insn) || GET_CODE (pattern) == CALL)
3728 clear_content_memory ();
3729 if (GET_CODE (pattern) != SET
3730 && GET_CODE (pattern) != CALL)
3731 continue;
3732 if (GET_CODE (pattern) == SET
3733 && GET_CODE (SET_SRC (pattern)) == ASM_OPERANDS)
3734 continue;
3736 valloc_method = get_attr_valloc (insn);
3738 PATTERN (insn) = copy_rtx_if_shared (PATTERN (insn));
3740 if (valloc_method == VALLOC_MACAX)
3742 record_content (AX, NULL_RTX);
3743 record_content (BC, NULL_RTX);
3744 record_content (DE, NULL_RTX);
3746 else if (valloc_method == VALLOC_DIVHI)
3748 record_content (AX, NULL_RTX);
3749 record_content (BC, NULL_RTX);
3751 else if (valloc_method == VALLOC_DIVSI)
3753 record_content (AX, NULL_RTX);
3754 record_content (BC, NULL_RTX);
3755 record_content (DE, NULL_RTX);
3756 record_content (HL, NULL_RTX);
3759 if (insn_ok_now (insn))
3760 continue;
3762 INSN_CODE (insn) = -1;
3764 if (RTX_FRAME_RELATED_P (insn))
3765 virt_insn_was_frame = 1;
3766 else
3767 virt_insn_was_frame = 0;
3769 switch (valloc_method)
3771 case VALLOC_OP1:
3772 rl78_alloc_physical_registers_op1 (insn);
3773 break;
3774 case VALLOC_OP2:
3775 rl78_alloc_physical_registers_op2 (insn);
3776 break;
3777 case VALLOC_RO1:
3778 rl78_alloc_physical_registers_ro1 (insn);
3779 break;
3780 case VALLOC_CMP:
3781 rl78_alloc_physical_registers_cmp (insn);
3782 break;
3783 case VALLOC_UMUL:
3784 rl78_alloc_physical_registers_umul (insn);
3785 record_content (AX, NULL_RTX);
3786 break;
3787 case VALLOC_MACAX:
3788 /* Macro that clobbers AX. */
3789 rl78_alloc_address_registers_macax (insn);
3790 record_content (AX, NULL_RTX);
3791 record_content (BC, NULL_RTX);
3792 record_content (DE, NULL_RTX);
3793 break;
3794 case VALLOC_DIVSI:
3795 rl78_alloc_address_registers_div (insn);
3796 record_content (AX, NULL_RTX);
3797 record_content (BC, NULL_RTX);
3798 record_content (DE, NULL_RTX);
3799 record_content (HL, NULL_RTX);
3800 break;
3801 case VALLOC_DIVHI:
3802 rl78_alloc_address_registers_div (insn);
3803 record_content (AX, NULL_RTX);
3804 record_content (BC, NULL_RTX);
3805 break;
3806 default:
3807 gcc_unreachable ();
3810 if (JUMP_P (insn) || CALL_P (insn) || GET_CODE (pattern) == CALL)
3811 clear_content_memory ();
3812 else
3813 process_postponed_content_update ();
3816 #if DEBUG_ALLOC
3817 fprintf (stderr, "\033[0m");
3818 #endif
3821 /* Add REG_DEAD notes using DEAD[reg] for rtx S which is part of INSN.
3822 This function scans for uses of registers; the last use (i.e. first
3823 encounter when scanning backwards) triggers a REG_DEAD note if the
3824 reg was previously in DEAD[]. */
3825 static void
3826 rl78_note_reg_uses (char *dead, rtx s, rtx insn)
3828 const char *fmt;
3829 int i, r;
3830 enum rtx_code code;
3832 if (!s)
3833 return;
3835 code = GET_CODE (s);
3837 switch (code)
3839 /* Compare registers by number. */
3840 case REG:
3841 r = REGNO (s);
3842 if (dump_file)
3844 fprintf (dump_file, "note use reg %d size %d on insn %d\n",
3845 r, GET_MODE_SIZE (GET_MODE (s)), INSN_UID (insn));
3846 print_rtl_single (dump_file, s);
3848 if (dead [r])
3849 add_reg_note (insn, REG_DEAD, gen_rtx_REG (GET_MODE (s), r));
3850 for (i = 0; i < GET_MODE_SIZE (GET_MODE (s)); i ++)
3851 dead [r + i] = 0;
3852 return;
3854 /* These codes have no constituent expressions
3855 and are unique. */
3856 case SCRATCH:
3857 case CC0:
3858 case PC:
3859 return;
3861 case CONST_INT:
3862 case CONST_VECTOR:
3863 case CONST_DOUBLE:
3864 case CONST_FIXED:
3865 /* These are kept unique for a given value. */
3866 return;
3868 default:
3869 break;
3872 fmt = GET_RTX_FORMAT (code);
3874 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
3876 if (fmt[i] == 'E')
3878 int j;
3879 for (j = XVECLEN (s, i) - 1; j >= 0; j--)
3880 rl78_note_reg_uses (dead, XVECEXP (s, i, j), insn);
3882 else if (fmt[i] == 'e')
3883 rl78_note_reg_uses (dead, XEXP (s, i), insn);
3887 /* Like the previous function, but scan for SETs instead. */
3888 static void
3889 rl78_note_reg_set (char *dead, rtx d, rtx insn)
3891 int r, i;
3892 bool is_dead;
3893 if (GET_CODE (d) == MEM)
3894 rl78_note_reg_uses (dead, XEXP (d, 0), insn);
3896 if (GET_CODE (d) != REG)
3897 return;
3899 /* Do not mark the reg unused unless all QImode parts of it are dead. */
3900 r = REGNO (d);
3901 is_dead = true;
3902 for (i = 0; i < GET_MODE_SIZE (GET_MODE (d)); i ++)
3903 if (!dead [r + i])
3904 is_dead = false;
3905 if(is_dead)
3906 add_reg_note (insn, REG_UNUSED, gen_rtx_REG (GET_MODE (d), r));
3907 if (dump_file)
3908 fprintf (dump_file, "note set reg %d size %d\n", r, GET_MODE_SIZE (GET_MODE (d)));
3909 for (i = 0; i < GET_MODE_SIZE (GET_MODE (d)); i ++)
3910 dead [r + i] = 1;
3913 /* This is a rather crude register death pass. Death status is reset
3914 at every jump or call insn. */
3915 static void
3916 rl78_calculate_death_notes (void)
3918 char dead[FIRST_PSEUDO_REGISTER];
3919 rtx p, s, d;
3920 rtx_insn *insn;
3921 int i;
3923 memset (dead, 0, sizeof (dead));
3925 for (insn = get_last_insn ();
3926 insn;
3927 insn = prev_nonnote_nondebug_insn (insn))
3929 if (dump_file)
3931 fprintf (dump_file, "\n--------------------------------------------------");
3932 fprintf (dump_file, "\nDead:");
3933 for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
3934 if (dead[i])
3935 fprintf (dump_file, " %s", reg_names[i]);
3936 fprintf (dump_file, "\n");
3937 print_rtl_single (dump_file, insn);
3940 switch (GET_CODE (insn))
3942 case INSN:
3943 p = PATTERN (insn);
3944 if (GET_CODE (p) == PARALLEL)
3946 rtx q = XVECEXP (p, 0 ,1);
3948 /* This happens with the DIV patterns. */
3949 if (GET_CODE (q) == SET)
3951 s = SET_SRC (q);
3952 d = SET_DEST (q);
3953 rl78_note_reg_set (dead, d, insn);
3954 rl78_note_reg_uses (dead, s, insn);
3957 p = XVECEXP (p, 0, 0);
3960 switch (GET_CODE (p))
3962 case SET:
3963 s = SET_SRC (p);
3964 d = SET_DEST (p);
3965 rl78_note_reg_set (dead, d, insn);
3966 rl78_note_reg_uses (dead, s, insn);
3967 break;
3969 case USE:
3970 rl78_note_reg_uses (dead, p, insn);
3971 break;
3973 default:
3974 break;
3976 break;
3978 case JUMP_INSN:
3979 if (INSN_CODE (insn) == CODE_FOR_rl78_return)
3981 memset (dead, 1, sizeof (dead));
3982 /* We expect a USE just prior to this, which will mark
3983 the actual return registers. The USE will have a
3984 death note, but we aren't going to be modifying it
3985 after this pass. */
3986 break;
3988 /* FALLTHRU */
3989 case CALL_INSN:
3990 memset (dead, 0, sizeof (dead));
3991 break;
3993 default:
3994 break;
3996 if (dump_file)
3997 print_rtl_single (dump_file, insn);
4001 /* Helper function to reset the origins in RP and the age in AGE for
4002 all registers. */
4003 static void
4004 reset_origins (int *rp, int *age)
4006 int i;
4007 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4009 rp[i] = i;
4010 age[i] = 0;
4014 static void
4015 set_origin (rtx pat, rtx_insn * insn, int * origins, int * age)
4017 rtx src = SET_SRC (pat);
4018 rtx dest = SET_DEST (pat);
4019 int mb = GET_MODE_SIZE (GET_MODE (dest));
4020 int i;
4022 if (GET_CODE (dest) == REG)
4024 int dr = REGNO (dest);
4026 if (GET_CODE (src) == REG)
4028 int sr = REGNO (src);
4029 bool same = true;
4030 int best_age, best_reg;
4032 /* See if the copy is not needed. */
4033 for (i = 0; i < mb; i ++)
4034 if (origins[dr + i] != origins[sr + i])
4035 same = false;
4037 if (same)
4039 if (dump_file)
4040 fprintf (dump_file, "deleting because dest already has correct value\n");
4041 delete_insn (insn);
4042 return;
4045 if (dr < 8 || sr >= 8)
4047 int ar;
4049 best_age = -1;
4050 best_reg = -1;
4052 /* See if the copy can be made from another
4053 bank 0 register instead, instead of the
4054 virtual src register. */
4055 for (ar = 0; ar < 8; ar += mb)
4057 same = true;
4059 for (i = 0; i < mb; i ++)
4060 if (origins[ar + i] != origins[sr + i])
4061 same = false;
4063 /* The chip has some reg-reg move limitations. */
4064 if (mb == 1 && dr > 3)
4065 same = false;
4067 if (same)
4069 if (best_age == -1 || best_age > age[sr + i])
4071 best_age = age[sr + i];
4072 best_reg = sr;
4077 if (best_reg != -1)
4079 /* FIXME: copy debug info too. */
4080 SET_SRC (pat) = gen_rtx_REG (GET_MODE (src), best_reg);
4081 sr = best_reg;
4085 for (i = 0; i < mb; i++)
4087 origins[dr + i] = origins[sr + i];
4088 age[dr + i] = age[sr + i] + 1;
4091 else
4093 /* The destination is computed, its origin is itself. */
4094 if (dump_file)
4095 fprintf (dump_file, "resetting origin of r%d for %d byte%s\n",
4096 dr, mb, mb == 1 ? "" : "s");
4098 for (i = 0; i < mb; i ++)
4100 origins[dr + i] = dr + i;
4101 age[dr + i] = 0;
4105 /* Any registers marked with that reg as an origin are reset. */
4106 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4107 if (origins[i] >= dr && origins[i] < dr + mb)
4109 origins[i] = i;
4110 age[i] = 0;
4114 /* Special case - our MUL patterns uses AX and sometimes BC. */
4115 if (get_attr_valloc (insn) == VALLOC_MACAX)
4117 if (dump_file)
4118 fprintf (dump_file, "Resetting origin of AX/BC for MUL pattern.\n");
4120 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4121 if (i <= 3 || origins[i] <= 3)
4123 origins[i] = i;
4124 age[i] = 0;
4127 else if (get_attr_valloc (insn) == VALLOC_DIVHI)
4129 if (dump_file)
4130 fprintf (dump_file, "Resetting origin of AX/DE for DIVHI pattern.\n");
4132 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4133 if (i == A_REG
4134 || i == X_REG
4135 || i == D_REG
4136 || i == E_REG
4137 || origins[i] == A_REG
4138 || origins[i] == X_REG
4139 || origins[i] == D_REG
4140 || origins[i] == E_REG)
4142 origins[i] = i;
4143 age[i] = 0;
4146 else if (get_attr_valloc (insn) == VALLOC_DIVSI)
4148 if (dump_file)
4149 fprintf (dump_file, "Resetting origin of AX/BC/DE/HL for DIVSI pattern.\n");
4151 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4152 if (i <= 7 || origins[i] <= 7)
4154 origins[i] = i;
4155 age[i] = 0;
4159 if (GET_CODE (src) == ASHIFT
4160 || GET_CODE (src) == ASHIFTRT
4161 || GET_CODE (src) == LSHIFTRT)
4163 rtx count = XEXP (src, 1);
4165 if (GET_CODE (count) == REG)
4167 /* Special case - our pattern clobbers the count register. */
4168 int r = REGNO (count);
4170 if (dump_file)
4171 fprintf (dump_file, "Resetting origin of r%d for shift.\n", r);
4173 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4174 if (i == r || origins[i] == r)
4176 origins[i] = i;
4177 age[i] = 0;
4183 /* The idea behind this optimization is to look for cases where we
4184 move data from A to B to C, and instead move from A to B, and A to
4185 C. If B is a virtual register or memory, this is a big win on its
4186 own. If B turns out to be unneeded after this, it's a bigger win.
4187 For each register, we try to determine where it's value originally
4188 came from, if it's propogated purely through moves (and not
4189 computes). The ORIGINS[] array has the regno for the "origin" of
4190 the value in the [regno] it's indexed by. */
4191 static void
4192 rl78_propogate_register_origins (void)
4194 int origins[FIRST_PSEUDO_REGISTER];
4195 int age[FIRST_PSEUDO_REGISTER];
4196 int i;
4197 rtx_insn *insn, *ninsn = NULL;
4198 rtx pat;
4200 reset_origins (origins, age);
4202 for (insn = get_insns (); insn; insn = ninsn)
4204 ninsn = next_nonnote_nondebug_insn (insn);
4206 if (dump_file)
4208 fprintf (dump_file, "\n");
4209 fprintf (dump_file, "Origins:");
4210 for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
4211 if (origins[i] != i)
4212 fprintf (dump_file, " r%d=r%d", i, origins[i]);
4213 fprintf (dump_file, "\n");
4214 print_rtl_single (dump_file, insn);
4217 switch (GET_CODE (insn))
4219 case CODE_LABEL:
4220 case BARRIER:
4221 case CALL_INSN:
4222 case JUMP_INSN:
4223 reset_origins (origins, age);
4224 break;
4226 default:
4227 break;
4229 case INSN:
4230 pat = PATTERN (insn);
4232 if (GET_CODE (pat) == PARALLEL)
4234 rtx clobber = XVECEXP (pat, 0, 1);
4235 pat = XVECEXP (pat, 0, 0);
4236 if (GET_CODE (clobber) == CLOBBER
4237 && GET_CODE (XEXP (clobber, 0)) == REG)
4239 int cr = REGNO (XEXP (clobber, 0));
4240 int mb = GET_MODE_SIZE (GET_MODE (XEXP (clobber, 0)));
4241 if (dump_file)
4242 fprintf (dump_file, "reset origins of %d regs at %d\n", mb, cr);
4243 for (i = 0; i < mb; i++)
4245 origins[cr + i] = cr + i;
4246 age[cr + i] = 0;
4249 /* This happens with the DIV patterns. */
4250 else if (GET_CODE (clobber) == SET)
4252 set_origin (clobber, insn, origins, age);
4254 else
4255 break;
4258 if (GET_CODE (pat) == SET)
4260 set_origin (pat, insn, origins, age);
4262 else if (GET_CODE (pat) == CLOBBER
4263 && GET_CODE (XEXP (pat, 0)) == REG)
4265 if (REG_P (XEXP (pat, 0)))
4267 unsigned int reg = REGNO (XEXP (pat, 0));
4269 origins[reg] = reg;
4270 age[reg] = 0;
4277 /* Remove any SETs where the destination is unneeded. */
4278 static void
4279 rl78_remove_unused_sets (void)
4281 rtx_insn *insn, *ninsn = NULL;
4282 rtx dest;
4284 for (insn = get_insns (); insn; insn = ninsn)
4286 ninsn = next_nonnote_nondebug_insn (insn);
4288 rtx set = single_set (insn);
4289 if (set == NULL)
4290 continue;
4292 dest = SET_DEST (set);
4294 if (GET_CODE (dest) != REG || REGNO (dest) > 23)
4295 continue;
4297 if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
4299 if (dump_file)
4300 fprintf (dump_file, "deleting because the set register is never used.\n");
4301 delete_insn (insn);
4306 /* This is the top of the devritualization pass. */
4307 static void
4308 rl78_reorg (void)
4310 /* split2 only happens when optimizing, but we need all movSIs to be
4311 split now. */
4312 if (optimize <= 0)
4313 split_all_insns ();
4315 rl78_alloc_physical_registers ();
4317 if (dump_file)
4319 fprintf (dump_file, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n");
4320 print_rtl_with_bb (dump_file, get_insns (), TDF_NONE);
4323 rl78_propogate_register_origins ();
4324 rl78_calculate_death_notes ();
4326 if (dump_file)
4328 fprintf (dump_file, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n");
4329 print_rtl_with_bb (dump_file, get_insns (), TDF_NONE);
4330 fprintf (dump_file, "\n======================================================================\n");
4333 rl78_remove_unused_sets ();
4335 /* The code after devirtualizing has changed so much that at this point
4336 we might as well just rescan everything. Note that
4337 df_rescan_all_insns is not going to help here because it does not
4338 touch the artificial uses and defs. */
4339 df_finish_pass (true);
4340 if (optimize > 1)
4341 df_live_add_problem ();
4342 df_scan_alloc (NULL);
4343 df_scan_blocks ();
4345 if (optimize)
4346 df_analyze ();
4349 #undef TARGET_RETURN_IN_MEMORY
4350 #define TARGET_RETURN_IN_MEMORY rl78_return_in_memory
4352 static bool
4353 rl78_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
4355 const HOST_WIDE_INT size = int_size_in_bytes (type);
4356 return (size == -1 || size > 8);
4360 #undef TARGET_RTX_COSTS
4361 #define TARGET_RTX_COSTS rl78_rtx_costs
4363 static bool
4364 rl78_rtx_costs (rtx x,
4365 machine_mode mode,
4366 int outer_code ATTRIBUTE_UNUSED,
4367 int opno ATTRIBUTE_UNUSED,
4368 int * total,
4369 bool speed ATTRIBUTE_UNUSED)
4371 int code = GET_CODE (x);
4373 if (code == IF_THEN_ELSE)
4375 *total = COSTS_N_INSNS (10);
4376 return true;
4379 if (mode == HImode)
4381 if (code == MULT && ! speed)
4383 * total = COSTS_N_INSNS (8);
4384 return true;
4386 return false;
4389 if (mode == SImode)
4391 switch (code)
4393 case MULT:
4394 if (! speed)
4395 /* If we are compiling for space then we do not want to use the
4396 inline SImode multiplication patterns or shift sequences.
4397 The cost is not set to 1 or 5 however as we have to allow for
4398 the possibility that we might be converting a leaf function
4399 into a non-leaf function. (There is no way to tell here).
4400 A value of 13 seems to be a reasonable compromise for the
4401 moment. */
4402 * total = COSTS_N_INSNS (13);
4403 else if (RL78_MUL_G14)
4404 *total = COSTS_N_INSNS (14);
4405 else if (RL78_MUL_G13)
4406 *total = COSTS_N_INSNS (29);
4407 else
4408 *total = COSTS_N_INSNS (500);
4409 return true;
4411 case PLUS:
4412 *total = COSTS_N_INSNS (8);
4413 return true;
4415 case ASHIFT:
4416 case ASHIFTRT:
4417 case LSHIFTRT:
4418 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
4420 switch (INTVAL (XEXP (x, 1)))
4422 case 0: *total = COSTS_N_INSNS (0); break;
4423 case 1: *total = COSTS_N_INSNS (6); break;
4424 case 2: case 3: case 4: case 5: case 6: case 7:
4425 *total = COSTS_N_INSNS (10); break;
4426 case 8: *total = COSTS_N_INSNS (6); break;
4427 case 9: case 10: case 11: case 12: case 13: case 14: case 15:
4428 *total = COSTS_N_INSNS (10); break;
4429 case 16: *total = COSTS_N_INSNS (3); break;
4430 case 17: case 18: case 19: case 20: case 21: case 22: case 23:
4431 *total = COSTS_N_INSNS (4); break;
4432 case 24: *total = COSTS_N_INSNS (4); break;
4433 case 25: case 26: case 27: case 28: case 29: case 30: case 31:
4434 *total = COSTS_N_INSNS (5); break;
4437 else
4438 *total = COSTS_N_INSNS (10+4*16);
4439 return true;
4441 default:
4442 break;
4445 return false;
4449 static GTY(()) section * saddr_section;
4450 static GTY(()) section * frodata_section;
4453 rl78_saddr_p (rtx x)
4455 const char * c;
4457 if (MEM_P (x))
4458 x = XEXP (x, 0);
4459 if (GET_CODE (x) == PLUS)
4460 x = XEXP (x, 0);
4461 if (GET_CODE (x) != SYMBOL_REF)
4462 return 0;
4464 c = XSTR (x, 0);
4465 if (memcmp (c, "@s.", 3) == 0)
4466 return 1;
4468 return 0;
4472 rl78_sfr_p (rtx x)
4474 if (MEM_P (x))
4475 x = XEXP (x, 0);
4476 if (GET_CODE (x) != CONST_INT)
4477 return 0;
4479 if ((INTVAL (x) & 0xFF00) != 0xFF00)
4480 return 0;
4482 return 1;
4485 #undef TARGET_STRIP_NAME_ENCODING
4486 #define TARGET_STRIP_NAME_ENCODING rl78_strip_name_encoding
4488 static const char *
4489 rl78_strip_name_encoding (const char * sym)
4491 while (1)
4493 if (*sym == '*')
4494 sym++;
4495 else if (*sym == '@' && sym[2] == '.')
4496 sym += 3;
4497 else
4498 return sym;
4502 /* Like rl78_strip_name_encoding, but does not strip leading asterisks. This
4503 is important if the stripped name is going to be passed to assemble_name()
4504 as that handles asterisk prefixed names in a special manner. */
4506 static const char *
4507 rl78_strip_nonasm_name_encoding (const char * sym)
4509 while (1)
4511 if (*sym == '@' && sym[2] == '.')
4512 sym += 3;
4513 else
4514 return sym;
4519 static int
4520 rl78_attrlist_to_encoding (tree list, tree decl ATTRIBUTE_UNUSED)
4522 while (list)
4524 if (is_attribute_p ("saddr", TREE_PURPOSE (list)))
4525 return 's';
4526 list = TREE_CHAIN (list);
4529 return 0;
4532 #define RL78_ATTRIBUTES(decl) \
4533 (TYPE_P (decl)) ? TYPE_ATTRIBUTES (decl) \
4534 : DECL_ATTRIBUTES (decl) \
4535 ? (DECL_ATTRIBUTES (decl)) \
4536 : TYPE_ATTRIBUTES (TREE_TYPE (decl))
4538 #undef TARGET_ENCODE_SECTION_INFO
4539 #define TARGET_ENCODE_SECTION_INFO rl78_encode_section_info
4541 static void
4542 rl78_encode_section_info (tree decl, rtx rtl, int first)
4544 rtx rtlname;
4545 const char * oldname;
4546 char encoding;
4547 char * newname;
4548 tree idp;
4549 tree type;
4550 tree rl78_attributes;
4552 if (!first)
4553 return;
4555 rtlname = XEXP (rtl, 0);
4557 if (GET_CODE (rtlname) == SYMBOL_REF)
4558 oldname = XSTR (rtlname, 0);
4559 else if (GET_CODE (rtlname) == MEM
4560 && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
4561 oldname = XSTR (XEXP (rtlname, 0), 0);
4562 else
4563 gcc_unreachable ();
4565 type = TREE_TYPE (decl);
4566 if (type == error_mark_node)
4567 return;
4568 if (! DECL_P (decl))
4569 return;
4570 rl78_attributes = RL78_ATTRIBUTES (decl);
4572 encoding = rl78_attrlist_to_encoding (rl78_attributes, decl);
4574 if (encoding)
4576 newname = (char *) alloca (strlen (oldname) + 4);
4577 sprintf (newname, "@%c.%s", encoding, oldname);
4578 idp = get_identifier (newname);
4579 XEXP (rtl, 0) =
4580 gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
4581 SYMBOL_REF_WEAK (XEXP (rtl, 0)) = DECL_WEAK (decl);
4582 SET_SYMBOL_REF_DECL (XEXP (rtl, 0), decl);
4586 #undef TARGET_ASM_INIT_SECTIONS
4587 #define TARGET_ASM_INIT_SECTIONS rl78_asm_init_sections
4589 static void
4590 rl78_asm_init_sections (void)
4592 saddr_section
4593 = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
4594 "\t.section .saddr,\"aw\",@progbits");
4595 frodata_section
4596 = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
4597 "\t.section .frodata,\"aw\",@progbits");
4600 #undef TARGET_ASM_SELECT_SECTION
4601 #define TARGET_ASM_SELECT_SECTION rl78_select_section
4603 static section *
4604 rl78_select_section (tree decl,
4605 int reloc,
4606 unsigned HOST_WIDE_INT align)
4608 int readonly = 1;
4610 switch (TREE_CODE (decl))
4612 case VAR_DECL:
4613 if (!TREE_READONLY (decl)
4614 || TREE_SIDE_EFFECTS (decl)
4615 || !DECL_INITIAL (decl)
4616 || (DECL_INITIAL (decl) != error_mark_node
4617 && !TREE_CONSTANT (DECL_INITIAL (decl))))
4618 readonly = 0;
4619 break;
4620 case CONSTRUCTOR:
4621 if (! TREE_CONSTANT (decl))
4622 readonly = 0;
4623 break;
4625 default:
4626 break;
4629 if (TREE_CODE (decl) == VAR_DECL)
4631 const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
4633 if (name[0] == '@' && name[2] == '.')
4634 switch (name[1])
4636 case 's':
4637 return saddr_section;
4640 if (TYPE_ADDR_SPACE (TREE_TYPE (decl)) == ADDR_SPACE_FAR
4641 && readonly)
4643 return frodata_section;
4647 if (readonly)
4648 return TARGET_ES0 ? frodata_section : readonly_data_section;
4650 switch (categorize_decl_for_section (decl, reloc))
4652 case SECCAT_TEXT: return text_section;
4653 case SECCAT_DATA: return data_section;
4654 case SECCAT_BSS: return bss_section;
4655 case SECCAT_RODATA: return TARGET_ES0 ? frodata_section : readonly_data_section;
4656 default:
4657 return default_select_section (decl, reloc, align);
4661 void
4662 rl78_output_labelref (FILE *file, const char *str)
4664 const char *str2;
4666 str2 = targetm.strip_name_encoding (str);
4667 if (str2[0] != '.')
4668 fputs (user_label_prefix, file);
4669 fputs (str2, file);
4672 void
4673 rl78_output_aligned_common (FILE *stream,
4674 tree decl ATTRIBUTE_UNUSED,
4675 const char *name,
4676 int size, int align, int global)
4678 /* We intentionally don't use rl78_section_tag() here. */
4679 if (name[0] == '@' && name[2] == '.')
4681 const char *sec = 0;
4682 switch (name[1])
4684 case 's':
4685 switch_to_section (saddr_section);
4686 sec = ".saddr";
4687 break;
4689 if (sec)
4691 const char *name2;
4692 int p2align = 0;
4694 while (align > BITS_PER_UNIT)
4696 align /= 2;
4697 p2align ++;
4699 name2 = targetm.strip_name_encoding (name);
4700 if (global)
4701 fprintf (stream, "\t.global\t_%s\n", name2);
4702 fprintf (stream, "\t.p2align %d\n", p2align);
4703 fprintf (stream, "\t.type\t_%s,@object\n", name2);
4704 fprintf (stream, "\t.size\t_%s,%d\n", name2, size);
4705 fprintf (stream, "_%s:\n\t.zero\t%d\n", name2, size);
4706 return;
4710 if (!global)
4712 fprintf (stream, "\t.local\t");
4713 assemble_name (stream, name);
4714 fprintf (stream, "\n");
4716 fprintf (stream, "\t.comm\t");
4717 assemble_name (stream, name);
4718 fprintf (stream, ",%u,%u\n", size, align / BITS_PER_UNIT);
4721 #undef TARGET_INSERT_ATTRIBUTES
4722 #define TARGET_INSERT_ATTRIBUTES rl78_insert_attributes
4724 static void
4725 rl78_insert_attributes (tree decl, tree *attributes ATTRIBUTE_UNUSED)
4727 if (TARGET_ES0
4728 && TREE_CODE (decl) == VAR_DECL
4729 && TREE_READONLY (decl)
4730 && TREE_ADDRESSABLE (decl)
4731 && TYPE_ADDR_SPACE (TREE_TYPE (decl)) == ADDR_SPACE_GENERIC)
4733 tree type = TREE_TYPE (decl);
4734 tree attr = TYPE_ATTRIBUTES (type);
4735 int q = TYPE_QUALS_NO_ADDR_SPACE (type) | ENCODE_QUAL_ADDR_SPACE (ADDR_SPACE_FAR);
4737 TREE_TYPE (decl) = build_type_attribute_qual_variant (type, attr, q);
4741 #undef TARGET_ASM_INTEGER
4742 #define TARGET_ASM_INTEGER rl78_asm_out_integer
4744 static bool
4745 rl78_asm_out_integer (rtx x, unsigned int size, int aligned_p)
4747 if (default_assemble_integer (x, size, aligned_p))
4748 return true;
4750 if (size == 4)
4752 assemble_integer_with_op (".long\t", x);
4753 return true;
4756 return false;
4759 #undef TARGET_UNWIND_WORD_MODE
4760 #define TARGET_UNWIND_WORD_MODE rl78_unwind_word_mode
4762 static scalar_int_mode
4763 rl78_unwind_word_mode (void)
4765 return HImode;
4768 #ifndef USE_COLLECT2
4769 #undef TARGET_ASM_CONSTRUCTOR
4770 #define TARGET_ASM_CONSTRUCTOR rl78_asm_constructor
4771 #undef TARGET_ASM_DESTRUCTOR
4772 #define TARGET_ASM_DESTRUCTOR rl78_asm_destructor
4774 static void
4775 rl78_asm_ctor_dtor (rtx symbol, int priority, bool is_ctor)
4777 section *sec;
4779 if (priority != DEFAULT_INIT_PRIORITY)
4781 /* This section of the function is based upon code copied
4782 from: gcc/varasm.c:get_cdtor_priority_section(). */
4783 char buf[18];
4785 sprintf (buf, "%s.%.5u", is_ctor ? ".ctors" : ".dtors",
4786 MAX_INIT_PRIORITY - priority);
4787 sec = get_section (buf, 0, NULL);
4789 else
4790 sec = is_ctor ? ctors_section : dtors_section;
4792 assemble_addr_to_section (symbol, sec);
4795 static void
4796 rl78_asm_constructor (rtx symbol, int priority)
4798 rl78_asm_ctor_dtor (symbol, priority, true);
4801 static void
4802 rl78_asm_destructor (rtx symbol, int priority)
4804 rl78_asm_ctor_dtor (symbol, priority, false);
4806 #endif /* ! USE_COLLECT2 */
4808 /* Scan backwards through the insn chain looking to see if the flags
4809 have been set for a comparison of OP against OPERAND. Start with
4810 the insn *before* the current insn. */
4812 bool
4813 rl78_flags_already_set (rtx op, rtx operand)
4815 /* We only track the Z flag. */
4816 if (GET_CODE (op) != EQ && GET_CODE (op) != NE)
4817 return false;
4819 /* This should not happen, but let's be paranoid. */
4820 if (current_output_insn == NULL_RTX)
4821 return false;
4823 rtx_insn *insn;
4824 bool res = false;
4826 for (insn = prev_nonnote_nondebug_insn (current_output_insn);
4827 insn != NULL_RTX;
4828 insn = prev_nonnote_nondebug_insn (insn))
4830 if (LABEL_P (insn))
4831 break;
4833 if (! INSN_P (insn))
4834 continue;
4836 /* Make sure that the insn can be recognized. */
4837 if (recog_memoized (insn) == -1)
4838 continue;
4840 enum attr_update_Z updated = get_attr_update_Z (insn);
4842 rtx set = single_set (insn);
4843 bool must_break = (set != NULL_RTX && rtx_equal_p (operand, SET_DEST (set)));
4845 switch (updated)
4847 case UPDATE_Z_NO:
4848 break;
4849 case UPDATE_Z_CLOBBER:
4850 must_break = true;
4851 break;
4852 case UPDATE_Z_UPDATE_Z:
4853 res = must_break;
4854 must_break = true;
4855 break;
4856 default:
4857 gcc_unreachable ();
4860 if (must_break)
4861 break;
4864 /* We have to re-recognize the current insn as the call(s) to
4865 get_attr_update_Z() above will have overwritten the recog_data cache. */
4866 recog_memoized (current_output_insn);
4867 cleanup_subreg_operands (current_output_insn);
4868 constrain_operands_cached (current_output_insn, 1);
4870 return res;
4873 const char *
4874 rl78_addsi3_internal (rtx * operands, unsigned int alternative)
4876 const char *addH2 = "addw ax, %H2\n\t";
4878 /* If we are adding in a constant symbolic address when -mes0
4879 is active then we know that the address must be <64K and
4880 that it is invalid to access anything above 64K relative to
4881 this address. So we can skip adding in the high bytes. */
4882 if (TARGET_ES0
4883 && GET_CODE (operands[2]) == SYMBOL_REF
4884 && TREE_CODE (SYMBOL_REF_DECL (operands[2])) == VAR_DECL
4885 && TREE_READONLY (SYMBOL_REF_DECL (operands[2]))
4886 && ! TREE_SIDE_EFFECTS (SYMBOL_REF_DECL (operands[2])))
4887 return "movw ax, %h1\n\taddw ax, %h2\n\tmovw %h0, ax";
4889 if(CONST_INT_P(operands[2]))
4891 if((INTVAL(operands[2]) & 0xFFFF0000) == 0)
4893 addH2 = "";
4895 else if((INTVAL(operands[2]) & 0xFFFF0000) == 0x00010000)
4897 addH2 = "incw ax\n\t";
4899 else if((INTVAL(operands[2]) & 0xFFFF0000) == 0xFFFF0000)
4901 addH2 = "decw ax\n\t";
4905 switch (alternative)
4907 case 0:
4908 case 1:
4909 snprintf(fmt_buffer, sizeof(fmt_buffer),
4910 "movw ax, %%h1\n\taddw ax, %%h2\n\tmovw %%h0, ax\n\tmovw ax, %%H1\n\tsknc\n\tincw ax\n\t%smovw %%H0,ax", addH2);
4911 break;
4912 case 2:
4913 snprintf(fmt_buffer, sizeof(fmt_buffer),
4914 "movw ax, %%h1\n\taddw ax, %%h2\n\tmovw bc, ax\n\tmovw ax, %%H1\n\tsknc\n\tincw ax\n\t%smovw %%H0, ax\n\tmovw ax, bc\n\tmovw %%h0, ax", addH2);
4915 break;
4916 default:
4917 gcc_unreachable ();
4920 return fmt_buffer;
4924 rl78_emit_libcall (const char *name, enum rtx_code code,
4925 enum machine_mode dmode, enum machine_mode smode,
4926 int noperands, rtx *operands)
4928 rtx ret;
4929 rtx_insn *insns;
4930 rtx libcall;
4931 rtx equiv;
4933 start_sequence ();
4934 libcall = gen_rtx_SYMBOL_REF (Pmode, name);
4936 switch (noperands)
4938 case 2:
4939 ret = emit_library_call_value (libcall, NULL_RTX, LCT_CONST,
4940 dmode, operands[1], smode);
4941 equiv = gen_rtx_fmt_e (code, dmode, operands[1]);
4942 break;
4944 case 3:
4945 ret = emit_library_call_value (libcall, NULL_RTX,
4946 LCT_CONST, dmode,
4947 operands[1], smode, operands[2],
4948 smode);
4949 equiv = gen_rtx_fmt_ee (code, dmode, operands[1], operands[2]);
4950 break;
4952 default:
4953 gcc_unreachable ();
4956 insns = get_insns ();
4957 end_sequence ();
4958 emit_libcall_block (insns, operands[0], ret, equiv);
4959 return ret;
4963 #undef TARGET_PREFERRED_RELOAD_CLASS
4964 #define TARGET_PREFERRED_RELOAD_CLASS rl78_preferred_reload_class
4966 static reg_class_t
4967 rl78_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, reg_class_t rclass)
4969 if (rclass == NO_REGS)
4970 rclass = V_REGS;
4972 return rclass;
4976 struct gcc_target targetm = TARGET_INITIALIZER;
4978 #include "gt-rl78.h"