Implement #pragma GCC warning/error
[official-gcc.git] / gcc / config / rl78 / rl78.c
blob990c1bb813922b9acc7626c15d76d9f53af2caa0
1 /* Subroutines used for code generation on Renesas RL78 processors.
2 Copyright (C) 2011, 2012 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 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "tree.h"
26 #include "rtl.h"
27 #include "regs.h"
28 #include "hard-reg-set.h"
29 #include "insn-config.h"
30 #include "conditions.h"
31 #include "output.h"
32 #include "insn-attr.h"
33 #include "flags.h"
34 #include "function.h"
35 #include "expr.h"
36 #include "optabs.h"
37 #include "libfuncs.h"
38 #include "recog.h"
39 #include "diagnostic-core.h"
40 #include "toplev.h"
41 #include "reload.h"
42 #include "df.h"
43 #include "ggc.h"
44 #include "tm_p.h"
45 #include "debug.h"
46 #include "target.h"
47 #include "target-def.h"
48 #include "langhooks.h"
49 #include "rl78-protos.h"
50 #include "dumpfile.h"
51 #include "tree-pass.h"
53 static inline bool is_interrupt_func (const_tree decl);
54 static inline bool is_brk_interrupt_func (const_tree decl);
55 static void rl78_reorg (void);
58 /* Debugging statements are tagged with DEBUG0 only so that they can
59 be easily enabled individually, by replacing the '0' with '1' as
60 needed. */
61 #define DEBUG0 0
62 #define DEBUG1 1
64 /* REGISTER_NAMES has the names for individual 8-bit registers, but
65 these have the names we need to use when referring to 16-bit
66 register pairs. */
67 static const char * const word_regnames[] =
69 "ax", "AX", "bc", "BC", "de", "DE", "hl", "HL",
70 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
71 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
72 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
73 "sp", "ap", "psw", "es", "cs"
76 struct GTY(()) machine_function
78 /* If set, the rest of the fields have been computed. */
79 int computed;
80 /* Which register pairs need to be pushed in the prologue. */
81 int need_to_push [FIRST_PSEUDO_REGISTER / 2];
83 /* These fields describe the frame layout... */
84 /* arg pointer */
85 /* 4 bytes for saved PC */
86 int framesize_regs;
87 /* frame pointer */
88 int framesize_locals;
89 int framesize_outgoing;
90 /* stack pointer */
91 int framesize;
93 /* If set, recog is allowed to match against the "real" patterns. */
94 int real_insns_ok;
95 /* If set, recog is allowed to match against the "virtual" patterns. */
96 int virt_insns_ok;
97 /* Set if the current function needs to clean up any trampolines. */
98 int trampolines_used;
101 /* This is our init_machine_status, as set in
102 rl78_option_override. */
103 static struct machine_function *
104 rl78_init_machine_status (void)
106 struct machine_function *m;
108 m = ggc_alloc_cleared_machine_function ();
109 m->virt_insns_ok = 1;
111 return m;
114 /* Returns whether to run the devirtualization pass. */
115 static bool
116 devirt_gate (void)
118 return true;
121 /* Runs the devirtualization pass. */
122 static unsigned int
123 devirt_pass (void)
125 rl78_reorg ();
126 return 0;
129 /* This pass converts virtual instructions using virtual registers, to
130 real instructions using real registers. Rather than run it as
131 reorg, we reschedule it before vartrack to help with debugging. */
132 static struct opt_pass rl78_devirt_pass =
134 RTL_PASS,
135 "devirt",
136 devirt_gate,
137 devirt_pass,
138 NULL,
139 NULL,
140 212,
141 TV_MACH_DEP,
142 0, 0, 0,
147 static struct register_pass_info rl78_devirt_info =
149 & rl78_devirt_pass,
150 "vartrack",
152 PASS_POS_INSERT_BEFORE
155 #undef TARGET_ASM_FILE_START
156 #define TARGET_ASM_FILE_START rl78_asm_file_start
158 static void
159 rl78_asm_file_start (void)
161 int i;
163 for (i = 0; i < 8; i++)
165 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 8 + i, 0xffef0 + i);
166 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 16 + i, 0xffee8 + i);
169 register_pass (& rl78_devirt_info);
173 #undef TARGET_OPTION_OVERRIDE
174 #define TARGET_OPTION_OVERRIDE rl78_option_override
176 static void
177 rl78_option_override (void)
179 flag_omit_frame_pointer = 1;
180 flag_no_function_cse = 1;
181 flag_split_wide_types = 0;
183 init_machine_status = rl78_init_machine_status;
186 /* Most registers are 8 bits. Some are 16 bits because, for example,
187 gcc doesn't like dealing with $FP as a register pair. This table
188 maps register numbers to size in bytes. */
189 static const int register_sizes[] =
191 1, 1, 1, 1, 1, 1, 1, 1,
192 1, 1, 1, 1, 1, 1, 1, 1,
193 1, 1, 1, 1, 1, 1, 2, 1,
194 1, 1, 1, 1, 1, 1, 1, 1,
195 2, 2, 1, 1, 1
198 /* Predicates used in the MD patterns. This one is true when virtual
199 insns may be matched, which typically means before (or during) the
200 devirt pass. */
201 bool
202 rl78_virt_insns_ok (void)
204 if (cfun)
205 return cfun->machine->virt_insns_ok;
206 return true;
209 /* Predicates used in the MD patterns. This one is true when real
210 insns may be matched, which typically means after (or during) the
211 devirt pass. */
212 bool
213 rl78_real_insns_ok (void)
215 if (cfun)
216 return cfun->machine->real_insns_ok;
217 return false;
220 /* Implements HARD_REGNO_NREGS. */
222 rl78_hard_regno_nregs (int regno, enum machine_mode mode)
224 int rs = register_sizes[regno];
225 if (rs < 1)
226 rs = 1;
227 return ((GET_MODE_SIZE (mode) + rs - 1) / rs);
230 /* Implements HARD_REGNO_MODE_OK. */
232 rl78_hard_regno_mode_ok (int regno, enum machine_mode mode)
234 int s = GET_MODE_SIZE (mode);
236 if (s < 1)
237 return 0;
238 /* These are not to be used by gcc. */
239 if (regno == 23 || regno == ES_REG || regno == CS_REG)
240 return 0;
241 /* $fp can alway sbe accessed as a 16-bit value. */
242 if (regno == FP_REG && s == 2)
243 return 1;
244 if (regno < SP_REG)
246 /* Since a reg-reg move is really a reg-mem move, we must
247 enforce alignment. */
248 if (s > 1 && (regno % 2))
249 return 0;
250 return 1;
252 if (s == CC_REGNUM)
253 return (mode == BImode);
254 /* All other registers must be accessed in their natural sizes. */
255 if (s == register_sizes [regno])
256 return 1;
257 return 0;
260 /* Simplify_gen_subreg() doesn't handle memory references the way we
261 need it to below, so we use this function for when we must get a
262 valid subreg in a "natural" state. */
263 static rtx
264 rl78_subreg (enum machine_mode mode, rtx r, enum machine_mode omode, int byte)
266 if (GET_CODE (r) == MEM)
267 return adjust_address (r, mode, byte);
268 else
269 return simplify_gen_subreg (mode, r, omode, byte);
272 /* Used by movsi. Split SImode moves into two HImode moves, using
273 appropriate patterns for the upper and lower halves of symbols. */
274 void
275 rl78_expand_movsi (rtx *operands)
277 rtx op00, op02, op10, op12;
279 op00 = rl78_subreg (HImode, operands[0], SImode, 0);
280 op02 = rl78_subreg (HImode, operands[0], SImode, 2);
281 if (GET_CODE (operands[1]) == CONST
282 || GET_CODE (operands[1]) == SYMBOL_REF)
284 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
285 op10 = gen_rtx_CONST (HImode, op10);
286 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
287 op12 = gen_rtx_CONST (HImode, op12);
289 else
291 op10 = rl78_subreg (HImode, operands[1], SImode, 0);
292 op12 = rl78_subreg (HImode, operands[1], SImode, 2);
295 if (rtx_equal_p (operands[0], operands[1]))
297 else if (rtx_equal_p (op00, op12))
299 emit_move_insn (op02, op12);
300 emit_move_insn (op00, op10);
302 else
304 emit_move_insn (op00, op10);
305 emit_move_insn (op02, op12);
309 /* Used by various two-operand expanders which cannot accept all
310 operands in the "far" namespace. Force some such operands into
311 registers so that each pattern has at most one far operand. */
313 rl78_force_nonfar_2 (rtx *operands, rtx (*gen)(rtx,rtx))
315 int did = 0;
316 rtx temp_reg = NULL;
318 /* FIXME: in the future, be smarter about only doing this if the
319 other operand is also far, assuming the devirtualizer can also
320 handle that. */
321 if (rl78_far_p (operands[0]))
323 temp_reg = operands[0];
324 operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
325 did = 1;
327 if (!did)
328 return 0;
330 emit_insn (gen (operands[0], operands[1]));
331 if (temp_reg)
332 emit_move_insn (temp_reg, operands[0]);
333 return 1;
336 /* Likewise, but for three-operand expanders. */
338 rl78_force_nonfar_3 (rtx *operands, rtx (*gen)(rtx,rtx,rtx))
340 int did = 0;
341 rtx temp_reg = NULL;
343 /* FIXME: Likewise. */
344 if (rl78_far_p (operands[1]))
346 rtx temp_reg = gen_reg_rtx (GET_MODE (operands[1]));
347 emit_move_insn (temp_reg, operands[1]);
348 operands[1] = temp_reg;
349 did = 1;
351 if (rl78_far_p (operands[0]))
353 temp_reg = operands[0];
354 operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
355 did = 1;
357 if (!did)
358 return 0;
360 emit_insn (gen (operands[0], operands[1], operands[2]));
361 if (temp_reg)
362 emit_move_insn (temp_reg, operands[0]);
363 return 1;
366 #undef TARGET_CAN_ELIMINATE
367 #define TARGET_CAN_ELIMINATE rl78_can_eliminate
369 static bool
370 rl78_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to ATTRIBUTE_UNUSED)
372 return true;
375 /* Returns nonzero if the given register needs to be saved by the
376 current function. */
377 static int
378 need_to_save (int regno)
380 if (is_interrupt_func (cfun->decl))
382 if (regno < 8)
383 return 1; /* don't know what devirt will need */
384 if (regno > 23)
385 return 0; /* don't need to save interrupt registers */
386 if (crtl->is_leaf)
388 return df_regs_ever_live_p (regno);
390 else
391 return 1;
393 if (regno == FRAME_POINTER_REGNUM && frame_pointer_needed)
394 return 1;
395 if (fixed_regs[regno])
396 return 0;
397 if (crtl->calls_eh_return)
398 return 1;
399 if (df_regs_ever_live_p (regno)
400 && !call_used_regs[regno])
401 return 1;
402 return 0;
405 /* We use this to wrap all emitted insns in the prologue. */
406 static rtx
407 F (rtx x)
409 RTX_FRAME_RELATED_P (x) = 1;
410 return x;
413 /* Compute all the frame-related fields in our machine_function
414 structure. */
415 static void
416 rl78_compute_frame_info (void)
418 int i;
420 cfun->machine->computed = 1;
421 cfun->machine->framesize_regs = 0;
422 cfun->machine->framesize_locals = get_frame_size ();
423 cfun->machine->framesize_outgoing = crtl->outgoing_args_size;
425 for (i = 0; i < 16; i ++)
426 if (need_to_save (i * 2) || need_to_save (i * 2 + 1))
428 cfun->machine->need_to_push [i] = 1;
429 cfun->machine->framesize_regs += 2;
431 else
432 cfun->machine->need_to_push [i] = 0;
434 if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1)
435 cfun->machine->framesize_locals ++;
437 cfun->machine->framesize = (cfun->machine->framesize_regs
438 + cfun->machine->framesize_locals
439 + cfun->machine->framesize_outgoing);
442 /* Returns true if the provided function has the specified attribute. */
443 static inline bool
444 has_func_attr (const_tree decl, const char * func_attr)
446 if (decl == NULL_TREE)
447 decl = current_function_decl;
449 return lookup_attribute (func_attr, DECL_ATTRIBUTES (decl)) != NULL_TREE;
452 /* Returns true if the provided function has the "interrupt" attribute. */
453 static inline bool
454 is_interrupt_func (const_tree decl)
456 return has_func_attr (decl, "interrupt") || has_func_attr (decl, "brk_interrupt");
459 /* Returns true if the provided function has the "brk_interrupt" attribute. */
460 static inline bool
461 is_brk_interrupt_func (const_tree decl)
463 return has_func_attr (decl, "brk_interrupt");
466 /* Check "interrupt" attributes. */
467 static tree
468 rl78_handle_func_attribute (tree * node,
469 tree name,
470 tree args,
471 int flags ATTRIBUTE_UNUSED,
472 bool * no_add_attrs)
474 gcc_assert (DECL_P (* node));
475 gcc_assert (args == NULL_TREE);
477 if (TREE_CODE (* node) != FUNCTION_DECL)
479 warning (OPT_Wattributes, "%qE attribute only applies to functions",
480 name);
481 * no_add_attrs = true;
484 /* FIXME: We ought to check that the interrupt and exception
485 handler attributes have been applied to void functions. */
486 return NULL_TREE;
489 #undef TARGET_ATTRIBUTE_TABLE
490 #define TARGET_ATTRIBUTE_TABLE rl78_attribute_table
492 /* Table of RL78-specific attributes. */
493 const struct attribute_spec rl78_attribute_table[] =
495 /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
496 affects_type_identity. */
497 { "interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
498 false },
499 { "brk_interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
500 false },
501 { NULL, 0, 0, false, false, false, NULL, false }
506 /* Break down an address RTX into its component base/index/addend
507 portions and return TRUE if the address is of a valid form, else
508 FALSE. */
509 static bool
510 characterize_address (rtx x, rtx *base, rtx *index, rtx *addend)
512 *base = NULL_RTX;
513 *index = NULL_RTX;
514 *addend = NULL_RTX;
516 if (GET_CODE (x) == REG)
518 *base = x;
519 return true;
522 /* We sometimes get these without the CONST wrapper */
523 if (GET_CODE (x) == PLUS
524 && GET_CODE (XEXP (x, 0)) == SYMBOL_REF
525 && GET_CODE (XEXP (x, 1)) == CONST_INT)
527 *addend = x;
528 return true;
531 if (GET_CODE (x) == PLUS)
533 *base = XEXP (x, 0);
534 x = XEXP (x, 1);
536 if (GET_CODE (*base) != REG
537 && GET_CODE (x) == REG)
539 rtx tmp = *base;
540 *base = x;
541 x = tmp;
544 if (GET_CODE (*base) != REG)
545 return false;
547 if (GET_CODE (x) == ZERO_EXTEND
548 && GET_CODE (XEXP (x, 0)) == REG)
550 *index = XEXP (x, 0);
551 return false;
555 switch (GET_CODE (x))
557 case PLUS:
558 if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
559 && GET_CODE (XEXP (x, 0)) == CONST_INT)
561 *addend = x;
562 return true;
564 /* fall through */
565 case MEM:
566 case REG:
567 return false;
569 case CONST:
570 case SYMBOL_REF:
571 case CONST_INT:
572 *addend = x;
573 return true;
575 default:
576 return false;
579 return false;
582 /* Used by the Whb constraint. Match addresses that use HL+B or HL+C
583 addressing. */
584 bool
585 rl78_hl_b_c_addr_p (rtx op)
587 rtx hl, bc;
589 if (GET_CODE (op) != PLUS)
590 return false;
591 hl = XEXP (op, 0);
592 bc = XEXP (op, 1);
593 if (GET_CODE (hl) == ZERO_EXTEND)
595 rtx tmp = hl;
596 hl = bc;
597 bc = tmp;
599 if (GET_CODE (hl) != REG)
600 return false;
601 if (GET_CODE (bc) != ZERO_EXTEND)
602 return false;
603 bc = XEXP (bc, 0);
604 if (GET_CODE (bc) != REG)
605 return false;
606 if (REGNO (hl) != HL_REG)
607 return false;
608 if (REGNO (bc) != B_REG && REGNO (bc) != C_REG)
609 return false;
611 return true;
614 #define REG_IS(r, regno) (((r) == (regno)) || ((r) >= FIRST_PSEUDO_REGISTER && !(strict)))
616 /* Used in various constraints and predicates to match operands in the
617 "far" address space. */
619 rl78_far_p (rtx x)
621 if (GET_CODE (x) != MEM)
622 return 0;
623 #if DEBUG0
624 fprintf(stderr, "\033[35mrl78_far_p: "); debug_rtx(x);
625 fprintf(stderr, " = %d\033[0m\n", MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR);
626 #endif
627 return MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR;
630 /* Return the appropriate mode for a named address pointer. */
631 #undef TARGET_ADDR_SPACE_POINTER_MODE
632 #define TARGET_ADDR_SPACE_POINTER_MODE rl78_addr_space_pointer_mode
633 static enum machine_mode
634 rl78_addr_space_pointer_mode (addr_space_t addrspace)
636 switch (addrspace)
638 case ADDR_SPACE_GENERIC:
639 return HImode;
640 case ADDR_SPACE_FAR:
641 return SImode;
642 default:
643 gcc_unreachable ();
647 /* Return the appropriate mode for a named address address. */
648 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
649 #define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode
650 static enum machine_mode
651 rl78_addr_space_address_mode (addr_space_t addrspace)
653 switch (addrspace)
655 case ADDR_SPACE_GENERIC:
656 return HImode;
657 case ADDR_SPACE_FAR:
658 return SImode;
659 default:
660 gcc_unreachable ();
664 #undef TARGET_LEGITIMATE_CONSTANT_P
665 #define TARGET_LEGITIMATE_CONSTANT_P rl78_is_legitimate_constant
667 static bool
668 rl78_is_legitimate_constant (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED)
670 return true;
673 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
674 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P rl78_as_legitimate_address
676 bool
677 rl78_as_legitimate_address (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x,
678 bool strict ATTRIBUTE_UNUSED, addr_space_t as ATTRIBUTE_UNUSED)
680 rtx base, index, addend;
682 if (as == ADDR_SPACE_GENERIC
683 && GET_MODE (x) == SImode)
684 return false;
686 if (! characterize_address (x, &base, &index, &addend))
687 return false;
689 if (base && index)
691 int ir = REGNO (index);
692 int br = REGNO (base);
694 #define OK(test, debug) if (test) { /*fprintf(stderr, "%d: OK %s\n", __LINE__, debug);*/ return true; }
695 OK (REG_IS (br, HL_REG) && REG_IS (ir, B_REG), "[hl+b]");
696 OK (REG_IS (br, HL_REG) && REG_IS (ir, C_REG), "[hl+c]");
697 return false;
700 if (strict && base && GET_CODE (base) == REG && REGNO (base) >= FIRST_PSEUDO_REGISTER)
701 return false;
703 return true;
706 /* Determine if one named address space is a subset of another. */
707 #undef TARGET_ADDR_SPACE_SUBSET_P
708 #define TARGET_ADDR_SPACE_SUBSET_P rl78_addr_space_subset_p
709 static bool
710 rl78_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
712 gcc_assert (subset == ADDR_SPACE_GENERIC || subset == ADDR_SPACE_FAR);
713 gcc_assert (superset == ADDR_SPACE_GENERIC || superset == ADDR_SPACE_FAR);
715 if (subset == superset)
716 return true;
718 else
719 return (subset == ADDR_SPACE_GENERIC && superset == ADDR_SPACE_FAR);
722 #undef TARGET_ADDR_SPACE_CONVERT
723 #define TARGET_ADDR_SPACE_CONVERT rl78_addr_space_convert
724 /* Convert from one address space to another. */
725 static rtx
726 rl78_addr_space_convert (rtx op, tree from_type, tree to_type)
728 addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
729 addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
730 rtx result;
732 gcc_assert (from_as == ADDR_SPACE_GENERIC || from_as == ADDR_SPACE_FAR);
733 gcc_assert (to_as == ADDR_SPACE_GENERIC || to_as == ADDR_SPACE_FAR);
735 if (to_as == ADDR_SPACE_GENERIC && from_as == ADDR_SPACE_FAR)
737 /* This is unpredictable, as we're truncating off usable address
738 bits. */
740 result = gen_reg_rtx (HImode);
741 emit_move_insn (result, simplify_subreg (HImode, op, SImode, 0));
742 return result;
744 else if (to_as == ADDR_SPACE_FAR && from_as == ADDR_SPACE_GENERIC)
746 /* This always works. */
747 result = gen_reg_rtx (SImode);
748 debug_rtx(result);
749 debug_rtx(op);
750 emit_move_insn (rl78_subreg (HImode, result, SImode, 0), op);
751 emit_move_insn (rl78_subreg (HImode, result, SImode, 2), const0_rtx);
752 return result;
754 else
755 gcc_unreachable ();
758 /* Implements REGNO_MODE_CODE_OK_FOR_BASE_P. */
759 bool
760 rl78_regno_mode_code_ok_for_base_p (int regno, enum machine_mode mode ATTRIBUTE_UNUSED,
761 addr_space_t address_space ATTRIBUTE_UNUSED,
762 int outer_code ATTRIBUTE_UNUSED, int index_code)
764 if (regno < 24 && regno >= 16)
765 return true;
766 if (index_code == REG)
767 return (regno == HL_REG);
768 if (regno == C_REG || regno == B_REG || regno == E_REG || regno == L_REG)
769 return true;
770 return false;
773 /* Implements MODE_CODE_BASE_REG_CLASS. */
774 enum reg_class
775 rl78_mode_code_base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED,
776 addr_space_t address_space ATTRIBUTE_UNUSED,
777 int outer_code ATTRIBUTE_UNUSED,
778 int index_code ATTRIBUTE_UNUSED)
780 return V_REGS;
783 /* Implements INITIAL_ELIMINATION_OFFSET. The frame layout is
784 described in the machine_Function struct definition, above. */
786 rl78_initial_elimination_offset (int from, int to)
788 int rv = 0; /* as if arg to arg */
790 rl78_compute_frame_info ();
792 switch (to)
794 case STACK_POINTER_REGNUM:
795 rv += cfun->machine->framesize_outgoing;
796 rv += cfun->machine->framesize_locals;
797 /* Fall through. */
798 case FRAME_POINTER_REGNUM:
799 rv += cfun->machine->framesize_regs;
800 rv += 4;
801 break;
802 default:
803 gcc_unreachable ();
806 switch (from)
808 case FRAME_POINTER_REGNUM:
809 rv -= 4;
810 rv -= cfun->machine->framesize_regs;
811 case ARG_POINTER_REGNUM:
812 break;
813 default:
814 gcc_unreachable ();
817 return rv;
820 /* Expand the function prologue (from the prologue pattern). */
821 void
822 rl78_expand_prologue (void)
824 int i, fs;
825 rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
826 int rb = 0;
828 if (!cfun->machine->computed)
829 rl78_compute_frame_info ();
831 if (flag_stack_usage_info)
832 current_function_static_stack_size = cfun->machine->framesize;
834 for (i = 0; i < 16; i++)
835 if (cfun->machine->need_to_push [i])
837 int need_bank = i/4;
838 if (need_bank != rb)
840 emit_insn (gen_sel_rb (GEN_INT (need_bank)));
841 rb = need_bank;
843 F (emit_insn (gen_push (gen_rtx_REG (HImode, i*2))));
845 if (rb != 0)
846 emit_insn (gen_sel_rb (GEN_INT (0)));
848 if (frame_pointer_needed)
849 F (emit_move_insn (gen_rtx_REG (HImode, FRAME_POINTER_REGNUM),
850 gen_rtx_REG (HImode, STACK_POINTER_REGNUM)));
852 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
853 while (fs > 0)
855 int fs_byte = (fs > 254) ? 254 : fs;
856 F (emit_insn (gen_subhi3 (sp, sp, GEN_INT (fs_byte))));
857 fs -= fs_byte;
861 /* Expand the function epilogue (from the epilogue pattern). */
862 void
863 rl78_expand_epilogue (void)
865 int i, fs;
866 rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
867 int rb = 0;
869 if (frame_pointer_needed)
871 emit_move_insn (gen_rtx_REG (HImode, STACK_POINTER_REGNUM),
872 gen_rtx_REG (HImode, FRAME_POINTER_REGNUM));
874 else
876 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
877 while (fs > 0)
879 int fs_byte = (fs > 254) ? 254 : fs;
881 emit_insn (gen_addhi3 (sp, sp, GEN_INT (fs_byte)));
882 fs -= fs_byte;
886 for (i = 15; i >= 0; i--)
887 if (cfun->machine->need_to_push [i])
889 int need_bank = i / 4;
891 if (need_bank != rb)
893 emit_insn (gen_sel_rb (GEN_INT (need_bank)));
894 rb = need_bank;
896 emit_insn (gen_pop (gen_rtx_REG (HImode, i * 2)));
899 if (rb != 0)
900 emit_insn (gen_sel_rb (GEN_INT (0)));
902 if (cfun->machine->trampolines_used)
903 emit_insn (gen_trampoline_uninit ());
905 if (is_brk_interrupt_func (cfun->decl))
906 emit_jump_insn (gen_brk_interrupt_return ());
907 else if (is_interrupt_func (cfun->decl))
908 emit_jump_insn (gen_interrupt_return ());
909 else
910 emit_jump_insn (gen_rl78_return ());
913 /* Likewise, for exception handlers. */
914 void
915 rl78_expand_eh_epilogue (rtx x ATTRIBUTE_UNUSED)
917 /* FIXME - replace this with an indirect jump with stack adjust. */
918 emit_jump_insn (gen_rl78_return ());
921 #undef TARGET_ASM_FUNCTION_PROLOGUE
922 #define TARGET_ASM_FUNCTION_PROLOGUE rl78_start_function
924 /* We don't use this to actually emit the function prologue. We use
925 this to insert a comment in the asm file describing the
926 function. */
927 static void
928 rl78_start_function (FILE *file, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED)
930 int i;
932 if (cfun->machine->framesize == 0)
933 return;
934 fprintf (file, "\t; start of function\n");
936 if (cfun->machine->framesize_regs)
938 fprintf (file, "\t; push %d:", cfun->machine->framesize_regs);
939 for (i = 0; i < 16; i ++)
940 if (cfun->machine->need_to_push[i])
941 fprintf (file, " %s", word_regnames[i*2]);
942 fprintf(file, "\n");
945 if (frame_pointer_needed)
946 fprintf (file, "\t; $fp points here (r22)\n");
948 if (cfun->machine->framesize_locals)
949 fprintf (file, "\t; locals: %d byte%s\n", cfun->machine->framesize_locals,
950 cfun->machine->framesize_locals == 1 ? "" : "s");
952 if (cfun->machine->framesize_outgoing)
953 fprintf (file, "\t; outgoing: %d byte%s\n", cfun->machine->framesize_outgoing,
954 cfun->machine->framesize_outgoing == 1 ? "" : "s");
957 /* Return an RTL describing where a function return value of type RET_TYPE
958 is held. */
960 #undef TARGET_FUNCTION_VALUE
961 #define TARGET_FUNCTION_VALUE rl78_function_value
963 static rtx
964 rl78_function_value (const_tree ret_type,
965 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
966 bool outgoing ATTRIBUTE_UNUSED)
968 enum machine_mode mode = TYPE_MODE (ret_type);
970 return gen_rtx_REG (mode, 8);
973 #undef TARGET_PROMOTE_FUNCTION_MODE
974 #define TARGET_PROMOTE_FUNCTION_MODE rl78_promote_function_mode
976 static enum machine_mode
977 rl78_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
978 enum machine_mode mode,
979 int *punsignedp ATTRIBUTE_UNUSED,
980 const_tree funtype ATTRIBUTE_UNUSED, int for_return ATTRIBUTE_UNUSED)
982 return mode;
985 /* Return an RTL expression describing the register holding a function
986 parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
987 be passed on the stack. CUM describes the previous parameters to the
988 function and NAMED is false if the parameter is part of a variable
989 parameter list, or the last named parameter before the start of a
990 variable parameter list. */
992 #undef TARGET_FUNCTION_ARG
993 #define TARGET_FUNCTION_ARG rl78_function_arg
995 static rtx
996 rl78_function_arg (cumulative_args_t cum_v ATTRIBUTE_UNUSED,
997 enum machine_mode mode ATTRIBUTE_UNUSED,
998 const_tree type ATTRIBUTE_UNUSED,
999 bool named ATTRIBUTE_UNUSED)
1001 return NULL_RTX;
1004 #undef TARGET_FUNCTION_ARG_ADVANCE
1005 #define TARGET_FUNCTION_ARG_ADVANCE rl78_function_arg_advance
1007 static void
1008 rl78_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode, const_tree type,
1009 bool named ATTRIBUTE_UNUSED)
1011 int rounded_size;
1012 CUMULATIVE_ARGS * cum = get_cumulative_args (cum_v);
1014 rounded_size = ((mode == BLKmode)
1015 ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
1016 if (rounded_size & 1)
1017 rounded_size ++;
1018 (*cum) += rounded_size;
1021 #undef TARGET_FUNCTION_ARG_BOUNDARY
1022 #define TARGET_FUNCTION_ARG_BOUNDARY rl78_function_arg_boundary
1024 static unsigned int
1025 rl78_function_arg_boundary (enum machine_mode mode ATTRIBUTE_UNUSED,
1026 const_tree type ATTRIBUTE_UNUSED)
1028 return 16;
1031 /* Supported modifier letters:
1033 A - address of a MEM
1034 S - SADDR form of a real register
1035 v - real register corresponding to a virtual register
1036 m - minus - negative of CONST_INT value.
1037 c - inverse of a conditional (NE vs EQ for example)
1039 h - bottom HI of an SI
1040 H - top HI of an SI
1041 q - bottom QI of an HI
1042 Q - top QI of an HI
1043 e - third QI of an SI (i.e. where the ES register gets values from)
1047 /* Implements the bulk of rl78_print_operand, below. We do it this
1048 way because we need to test for a constant at the top level and
1049 insert the '#', but not test for it anywhere else as we recurse
1050 down into the operand. */
1051 static void
1052 rl78_print_operand_1 (FILE * file, rtx op, int letter)
1054 int need_paren;
1056 switch (GET_CODE (op))
1058 case MEM:
1059 if (letter == 'A')
1060 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1061 else
1063 if (rl78_far_p (op))
1064 fprintf(file, "es:");
1065 if (letter == 'H')
1067 op = adjust_address (op, HImode, 2);
1068 letter = 0;
1070 if (letter == 'h')
1072 op = adjust_address (op, HImode, 0);
1073 letter = 0;
1075 if (letter == 'Q')
1077 op = adjust_address (op, QImode, 1);
1078 letter = 0;
1080 if (letter == 'q')
1082 op = adjust_address (op, QImode, 0);
1083 letter = 0;
1085 if (letter == 'e')
1087 op = adjust_address (op, QImode, 2);
1088 letter = 0;
1090 if (CONSTANT_P (XEXP (op, 0)))
1092 fprintf(file, "!");
1093 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1095 else if (GET_CODE (XEXP (op, 0)) == PLUS
1096 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF)
1098 fprintf(file, "!");
1099 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1101 else if (GET_CODE (XEXP (op, 0)) == PLUS
1102 && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
1103 && REGNO (XEXP (XEXP (op, 0), 0)) == 2)
1105 rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 1), 'u');
1106 fprintf(file, "[");
1107 rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 0), 0);
1108 fprintf(file, "]");
1110 else
1112 fprintf(file, "[");
1113 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1114 fprintf(file, "]");
1117 break;
1119 case REG:
1120 if (letter == 'Q')
1121 fprintf (file, "%s", reg_names [REGNO (op) | 1]);
1122 else if (letter == 'H')
1123 fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1124 else if (letter == 'q')
1125 fprintf (file, "%s", reg_names [REGNO (op) & ~1]);
1126 else if (letter == 'e')
1127 fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1128 else if (letter == 'S')
1129 fprintf (file, "0x%x", 0xffef8 + REGNO (op));
1130 else if (GET_MODE (op) == HImode
1131 && ! (REGNO (op) & ~0xfe))
1133 if (letter == 'v')
1134 fprintf (file, "%s", word_regnames [REGNO (op) % 8]);
1135 else
1136 fprintf (file, "%s", word_regnames [REGNO (op)]);
1138 else
1139 fprintf (file, "%s", reg_names [REGNO (op)]);
1140 break;
1142 case CONST_INT:
1143 if (letter == 'Q')
1144 fprintf (file, "%ld", INTVAL (op) >> 8);
1145 else if (letter == 'H')
1146 fprintf (file, "%ld", INTVAL (op) >> 16);
1147 else if (letter == 'q')
1148 fprintf (file, "%ld", INTVAL (op) & 0xff);
1149 else if (letter == 'h')
1150 fprintf (file, "%ld", INTVAL (op) & 0xffff);
1151 else if (letter == 'e')
1152 fprintf (file, "%ld", (INTVAL (op) >> 16) & 0xff);
1153 else if (letter == 'm')
1154 fprintf (file, "%ld", - INTVAL (op));
1155 else
1156 fprintf(file, "%ld", INTVAL (op));
1157 break;
1159 case CONST:
1160 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1161 break;
1163 case ZERO_EXTRACT:
1165 int bits = INTVAL (XEXP (op, 1));
1166 int ofs = INTVAL (XEXP (op, 2));
1167 if (bits == 16 && ofs == 0)
1168 fprintf (file, "%%lo16(");
1169 else if (bits == 16 && ofs == 16)
1170 fprintf (file, "%%hi16(");
1171 else if (bits == 8 && ofs == 16)
1172 fprintf (file, "%%hi8(");
1173 else
1174 gcc_unreachable ();
1175 rl78_print_operand_1 (file, XEXP (op, 0), 0);
1176 fprintf (file, ")");
1178 break;
1180 case ZERO_EXTEND:
1181 if (GET_CODE (XEXP (op, 0)) == REG)
1182 fprintf (file, "%s", reg_names [REGNO (XEXP (op, 0))]);
1183 else
1184 print_rtl (file, op);
1185 break;
1187 case PLUS:
1188 need_paren = 0;
1189 if (letter == 'H')
1191 fprintf (file, "%%hi16(");
1192 need_paren = 1;
1193 letter = 0;
1195 if (letter == 'h')
1197 fprintf (file, "%%lo16(");
1198 need_paren = 1;
1199 letter = 0;
1201 if (letter == 'e')
1203 fprintf (file, "%%hi8(");
1204 need_paren = 1;
1205 letter = 0;
1207 if (letter == 'q' || letter == 'Q')
1208 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1210 if (GET_CODE (XEXP (op, 0)) == ZERO_EXTEND)
1212 rl78_print_operand_1 (file, XEXP (op, 1), letter);
1213 fprintf (file, "+");
1214 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1216 else
1218 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1219 fprintf (file, "+");
1220 rl78_print_operand_1 (file, XEXP (op, 1), letter);
1222 if (need_paren)
1223 fprintf (file, ")");
1224 break;
1226 case SYMBOL_REF:
1227 need_paren = 0;
1228 if (letter == 'H')
1230 fprintf (file, "%%hi16(");
1231 need_paren = 1;
1232 letter = 0;
1234 if (letter == 'h')
1236 fprintf (file, "%%lo16(");
1237 need_paren = 1;
1238 letter = 0;
1240 if (letter == 'e')
1242 fprintf (file, "%%hi8(");
1243 need_paren = 1;
1244 letter = 0;
1246 if (letter == 'q' || letter == 'Q')
1247 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1249 output_addr_const (file, op);
1250 if (need_paren)
1251 fprintf (file, ")");
1252 break;
1254 case CODE_LABEL:
1255 case LABEL_REF:
1256 output_asm_label (op);
1257 break;
1259 case LTU:
1260 fprintf (file, letter == 'c' ? "nc" : "c");
1261 break;
1262 case LEU:
1263 fprintf (file, letter == 'c' ? "h" : "nh");
1264 break;
1265 case GEU:
1266 fprintf (file, letter == 'c' ? "c" : "nc");
1267 break;
1268 case GTU:
1269 fprintf (file, letter == 'c' ? "nh" : "h");
1270 break;
1271 case EQ:
1272 fprintf (file, letter == 'c' ? "nz" : "z");
1273 break;
1274 case NE:
1275 fprintf (file, letter == 'c' ? "z" : "nz");
1276 break;
1278 default:
1279 fprintf (file, "(%s)", GET_RTX_NAME (GET_CODE (op)));
1280 break;
1284 #undef TARGET_PRINT_OPERAND
1285 #define TARGET_PRINT_OPERAND rl78_print_operand
1287 static void
1288 rl78_print_operand (FILE * file, rtx op, int letter)
1290 if (CONSTANT_P (op) && letter != 'u')
1291 fprintf (file, "#");
1292 rl78_print_operand_1 (file, op, letter);
1295 #undef TARGET_TRAMPOLINE_INIT
1296 #define TARGET_TRAMPOLINE_INIT rl78_trampoline_init
1298 /* Note that the RL78's addressing makes it very difficult to do
1299 trampolines on the stack. So, libgcc has a small pool of
1300 trampolines from which one is allocated to this task. */
1301 static void
1302 rl78_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
1304 rtx mov_addr, thunk_addr;
1305 rtx function = XEXP (DECL_RTL (fndecl), 0);
1307 mov_addr = adjust_address (m_tramp, HImode, 0);
1308 thunk_addr = gen_reg_rtx (HImode);
1310 function = force_reg (HImode, function);
1311 static_chain = force_reg (HImode, static_chain);
1313 emit_insn (gen_trampoline_init (thunk_addr, function, static_chain));
1314 emit_move_insn (mov_addr, thunk_addr);
1316 cfun->machine->trampolines_used = 1;
1319 #undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
1320 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS rl78_trampoline_adjust_address
1322 static rtx
1323 rl78_trampoline_adjust_address (rtx m_tramp)
1325 rtx x = gen_rtx_MEM (HImode, m_tramp);
1326 return x;
1329 /* Expander for cbranchqi4 and cbranchhi4. RL78 is missing some of
1330 the "normal" compares, specifically, it only has unsigned compares,
1331 so we must synthesize the missing ones. */
1332 void
1333 rl78_expand_compare (rtx *operands)
1335 /* RL78 does not have signed comparisons. We must modify the
1336 operands to be in the unsigned range, and emit an unsigned
1337 comparison. */
1339 enum machine_mode mode;
1340 rtx high_bit;
1341 int i;
1342 RTX_CODE new_cond;
1344 switch (GET_CODE (operands[0]))
1346 case GE:
1347 new_cond = GEU;
1348 break;
1349 case LE:
1350 new_cond = LEU;
1351 break;
1352 case GT:
1353 new_cond = GTU;
1354 break;
1355 case LT:
1356 new_cond = LTU;
1357 break;
1358 default:
1359 return;
1362 #if DEBUG0
1363 fprintf (stderr, "\033[38;5;129mrl78_expand_compare\n");
1364 debug_rtx (operands[0]);
1365 fprintf (stderr, "\033[0m");
1366 #endif
1368 mode = GET_MODE (operands[1]);
1369 if (mode == VOIDmode)
1370 mode = GET_MODE (operands[2]);
1371 high_bit = GEN_INT (~0 << (GET_MODE_BITSIZE (mode) - 1));
1373 /* 0: conditional 1,2: operands */
1374 for (i = 1; i <= 2; i ++)
1376 rtx r = operands[i];
1378 if (GET_CODE (r) == CONST_INT)
1379 r = GEN_INT (INTVAL (r) ^ INTVAL (high_bit));
1380 else
1382 r = gen_rtx_PLUS (mode, operands[i], high_bit);
1383 r = copy_to_mode_reg (mode, r);
1385 operands[i] = r;
1388 operands[0] = gen_rtx_fmt_ee (new_cond, GET_MODE (operands[0]), operands[1], operands[2]);
1390 #if DEBUG0
1391 fprintf (stderr, "\033[38;5;142mrl78_expand_compare\n");
1392 debug_rtx (operands[0]);
1393 fprintf (stderr, "\033[0m");
1394 #endif
1399 /* Define this to 1 if you are debugging the peephole optimizers. */
1400 #define DEBUG_PEEP 0
1402 /* Predicate used to enable the peephole2 patterns in rl78-virt.md.
1403 The default "word" size is a byte so we can effectively use all the
1404 registers, but we want to do 16-bit moves whenever possible. This
1405 function determines when such a move is an option. */
1406 bool
1407 rl78_peep_movhi_p (rtx *operands)
1409 int i;
1410 rtx m, a;
1412 /* (set (op0) (op1))
1413 (set (op2) (op3)) */
1415 #if DEBUG_PEEP
1416 fprintf (stderr, "\033[33m");
1417 debug_rtx(operands[0]);
1418 debug_rtx(operands[1]);
1419 debug_rtx(operands[2]);
1420 debug_rtx(operands[3]);
1421 fprintf (stderr, "\033[0m");
1422 #endif
1424 if (rtx_equal_p (operands[0], operands[3]))
1426 #if DEBUG_PEEP
1427 fprintf (stderr, "no peep: overlapping\n");
1428 #endif
1429 return false;
1432 for (i = 0; i < 2; i ++)
1434 if (GET_CODE (operands[i]) != GET_CODE (operands[i+2]))
1436 #if DEBUG_PEEP
1437 fprintf (stderr, "no peep: different codes\n");
1438 #endif
1439 return false;
1441 if (GET_MODE (operands[i]) != GET_MODE (operands[i+2]))
1443 #if DEBUG_PEEP
1444 fprintf (stderr, "no peep: different modes\n");
1445 #endif
1446 return false;
1449 switch (GET_CODE (operands[i]))
1451 case REG:
1452 /* LSB MSB */
1453 if (REGNO (operands[i]) + 1 != REGNO (operands[i+2])
1454 || GET_MODE (operands[i]) != QImode)
1456 #if DEBUG_PEEP
1457 fprintf (stderr, "no peep: wrong regnos %d %d %d\n",
1458 REGNO (operands[i]), REGNO (operands[i+2]),
1460 #endif
1461 return false;
1463 if (! rl78_hard_regno_mode_ok (REGNO (operands[i]), HImode))
1465 #if DEBUG_PEEP
1466 fprintf (stderr, "no peep: reg %d not HI\n", REGNO (operands[i]));
1467 #endif
1468 return false;
1470 break;
1472 case CONST_INT:
1473 break;
1475 case MEM:
1476 if (GET_MODE (operands[i]) != QImode)
1477 return false;
1478 if (MEM_ALIGN (operands[i]) < 16)
1479 return false;
1480 a = XEXP (operands[i], 0);
1481 if (GET_CODE (a) == CONST)
1482 a = XEXP (a, 0);
1483 if (GET_CODE (a) == PLUS)
1484 a = XEXP (a, 1);
1485 if (GET_CODE (a) == CONST_INT
1486 && INTVAL (a) & 1)
1488 #if DEBUG_PEEP
1489 fprintf (stderr, "no peep: misaligned mem %d\n", i);
1490 debug_rtx (operands[i]);
1491 #endif
1492 return false;
1494 m = adjust_address (operands[i], QImode, 1);
1495 if (! rtx_equal_p (m, operands[i+2]))
1497 #if DEBUG_PEEP
1498 fprintf (stderr, "no peep: wrong mem %d\n", i);
1499 debug_rtx(m);
1500 debug_rtx (operands[i+2]);
1501 #endif
1502 return false;
1504 break;
1506 default:
1507 #if DEBUG_PEEP
1508 fprintf (stderr, "no peep: wrong rtx %d\n", i);
1509 #endif
1510 return false;
1513 #if DEBUG_PEEP
1514 fprintf (stderr, "\033[32mpeep!\033[0m\n");
1515 #endif
1516 return true;
1519 /* Likewise, when a peephole is activated, this function helps compute
1520 the new operands. */
1521 void
1522 rl78_setup_peep_movhi (rtx *operands)
1524 int i;
1526 for (i = 0; i < 2; i ++)
1528 switch (GET_CODE (operands[i]))
1530 case REG:
1531 operands[i+4] = gen_rtx_REG (HImode, REGNO (operands[i]));
1532 break;
1534 case CONST_INT:
1535 operands[i+4] = GEN_INT ((INTVAL (operands[i]) & 0xff) + ((char)INTVAL (operands[i+2])) * 256);
1536 break;
1538 case MEM:
1539 operands[i+4] = adjust_address (operands[i], HImode, 0);
1540 break;
1542 default:
1543 break;
1549 How Devirtualization works in the RL78 GCC port
1551 Background
1553 The RL78 is an 8-bit port with some 16-bit operations. It has 32
1554 bytes of register space, in four banks, memory-mapped. One bank is
1555 the "selected" bank and holds the registers used for primary
1556 operations. Since the registers are memory mapped, often you can
1557 still refer to the unselected banks via memory accesses.
1559 Virtual Registers
1561 The GCC port uses bank 0 as the "selected" registers (A, X, BC, etc)
1562 and refers to the other banks via their memory addresses, although
1563 they're treated as regular registers internally. These "virtual"
1564 registers are R8 through R23 (bank3 is reserved for asm-based
1565 interrupt handlers).
1567 There are four machine description files:
1569 rl78.md - common register-independent patterns and definitions
1570 rl78-expand.md - expanders
1571 rl78-virt.md - patterns that match BEFORE devirtualization
1572 rl78-real.md - patterns that match AFTER devirtualization
1574 At least through register allocation and reload, gcc is told that it
1575 can do pretty much anything - but may only use the virtual registers.
1576 GCC cannot properly create the varying addressing modes that the RL78
1577 supports in an efficient way.
1579 Sometime after reload, the RL78 backend "devirtualizes" the RTL. It
1580 uses the "valloc" attribute in rl78-virt.md for determining the rules
1581 by which it will replace virtual registers with real registers (or
1582 not) and how to make up addressing modes. For example, insns tagged
1583 with "ro1" have a single read-only parameter, which may need to be
1584 moved from memory/constant/vreg to a suitable real register. As part
1585 of devirtualization, a flag is toggled, disabling the rl78-virt.md
1586 patterns and enabling the rl78-real.md patterns. The new patterns'
1587 constraints are used to determine the real registers used. NOTE:
1588 patterns in rl78-virt.md essentially ignore the constrains and rely on
1589 predicates, where the rl78-real.md ones essentially ignore the
1590 predicates and rely on the constraints.
1592 The devirtualization pass is scheduled via the pass manager (despite
1593 being called "rl78_reorg") so it can be scheduled prior to var-track
1594 (the idea is to let gdb know about the new registers). Ideally, it
1595 would be scheduled right after pro/epilogue generation, so the
1596 post-reload optimizers could operate on the real registers, but when I
1597 tried that there were some issues building the target libraries.
1599 During devirtualization, a simple register move optimizer is run. It
1600 would be better to run a full CSE/propogation pass on it through, or
1601 re-run regmove, but that has not yet been attempted.
1604 #define DEBUG_ALLOC 0
1606 /* Rescans an insn to see if it's recognized again. This is done
1607 carefully to ensure that all the constraint information is accurate
1608 for the newly matched insn. */
1609 static bool
1610 insn_ok_now (rtx insn)
1612 INSN_CODE (insn) = -1;
1613 if (recog (PATTERN (insn), insn, 0) > -1)
1615 extract_insn (insn);
1616 if (constrain_operands (1))
1618 #if DEBUG_ALLOC
1619 fprintf (stderr, "\033[32m");
1620 debug_rtx (insn);
1621 fprintf (stderr, "\033[0m");
1622 #endif
1623 return true;
1626 else
1628 fprintf (stderr, "\033[41;30m Unrecognized insn \033[0m\n");
1629 debug_rtx (insn);
1630 gcc_unreachable ();
1632 #if DEBUG_ALLOC
1633 fprintf (stderr, "\033[31m");
1634 debug_rtx (insn);
1635 fprintf (stderr, "\033[0m");
1636 #endif
1637 return false;
1640 #if DEBUG_ALLOC
1641 #define WORKED fprintf (stderr, "\033[48;5;22m Worked at line %d \033[0m\n", __LINE__)
1642 #define FAILEDSOFAR fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__)
1643 #define FAILED fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__), gcc_unreachable()
1644 #define MAYBE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } else { FAILEDSOFAR; }
1645 #else
1646 #define WORKED
1647 #define FAILEDSOFAR
1648 #define FAILED gcc_unreachable ()
1649 #define MAYBE_OK(insn) if (insn_ok_now (insn)) return;
1650 #endif
1652 /* Registers into which we move the contents of virtual registers. */
1653 #define X gen_rtx_REG (QImode, 0)
1654 #define A gen_rtx_REG (QImode, 1)
1655 #define C gen_rtx_REG (QImode, 2)
1656 #define B gen_rtx_REG (QImode, 3)
1657 #define E gen_rtx_REG (QImode, 4)
1658 #define D gen_rtx_REG (QImode, 5)
1659 #define L gen_rtx_REG (QImode, 6)
1660 #define H gen_rtx_REG (QImode, 7)
1662 #define AX gen_rtx_REG (HImode, 0)
1663 #define BC gen_rtx_REG (HImode, 2)
1664 #define DE gen_rtx_REG (HImode, 4)
1665 #define HL gen_rtx_REG (HImode, 6)
1667 #define OP(x) (*recog_data.operand_loc[x])
1669 /* Returns TRUE if R is a virtual register. */
1670 static bool
1671 is_virtual_register (rtx r)
1673 return (GET_CODE (r) == REG
1674 && REGNO (r) >= 8
1675 && REGNO (r) < 24);
1678 /* In all these alloc routines, we expect the following: the insn
1679 pattern is unshared, the insn was previously recognized and failed
1680 due to predicates or constraints, and the operand data is in
1681 recog_data. */
1683 static int virt_insn_was_frame;
1685 /* Hook for all insns we emit. Re-mark them as FRAME_RELATED if
1686 needed. */
1687 static rtx
1688 EM2 (int line ATTRIBUTE_UNUSED, rtx r)
1690 #if DEBUG_ALLOC
1691 fprintf (stderr, "\033[36m%d: ", line);
1692 debug_rtx(r);
1693 fprintf (stderr, "\033[0m");
1694 #endif
1695 /*SCHED_GROUP_P (r) = 1;*/
1696 if (virt_insn_was_frame)
1697 RTX_FRAME_RELATED_P (r) = 1;
1698 return r;
1701 #define EM(x) EM2 (__LINE__, x)
1703 /* Return a suitable RTX for the low half of a __far address. */
1704 static rtx
1705 rl78_lo16 (rtx addr)
1707 if (GET_CODE (addr) == SYMBOL_REF
1708 || GET_CODE (addr) == CONST)
1710 rtx r = gen_rtx_ZERO_EXTRACT (HImode, addr, GEN_INT (16), GEN_INT (0));
1711 r = gen_rtx_CONST (HImode, r);
1712 return r;
1714 return rl78_subreg (HImode, addr, SImode, 0);
1717 /* Return a suitable RTX for the high half's lower byte of a __far address. */
1718 static rtx
1719 rl78_hi8 (rtx addr)
1721 if (GET_CODE (addr) == SYMBOL_REF
1722 || GET_CODE (addr) == CONST)
1724 rtx r = gen_rtx_ZERO_EXTRACT (QImode, addr, GEN_INT (8), GEN_INT (16));
1725 r = gen_rtx_CONST (QImode, r);
1726 return r;
1728 return rl78_subreg (QImode, addr, SImode, 2);
1731 /* Copy any register values into real registers and return an RTX for
1732 the same memory, now addressed by real registers. Any needed insns
1733 are emitted before BEFORE. */
1734 static rtx
1735 transcode_memory_rtx (rtx m, rtx newbase, rtx before)
1737 rtx base, index, addendr;
1738 int addend = 0;
1740 if (GET_CODE (m) != MEM)
1741 return m;
1743 if (GET_MODE (XEXP (m, 0)) == SImode)
1745 rtx seg = rl78_hi8 (XEXP (m, 0));
1746 #if DEBUG_ALLOC
1747 fprintf (stderr, "setting ES:\n");
1748 debug_rtx(seg);
1749 #endif
1750 emit_insn_before (EM(gen_movqi (A, seg)), before);
1751 emit_insn_before (EM(gen_movqi_es (A)), before);
1752 m = change_address (m, GET_MODE (m), rl78_lo16 (XEXP (m, 0)));
1755 characterize_address (XEXP (m, 0), &base, &index, &addendr);
1756 gcc_assert (index == NULL_RTX);
1758 #if DEBUG_ALLOC
1759 fprintf (stderr, "\033[33m"); debug_rtx(m); fprintf (stderr, "\033[0m");
1760 debug_rtx (base);
1761 #endif
1762 if (base == NULL_RTX)
1763 return m;
1765 if (addendr && GET_CODE (addendr) == CONST_INT)
1766 addend = INTVAL (addendr);
1768 if (REGNO (base) == SP_REG)
1770 if (addend >= 0 && addend <= 255)
1771 return m;
1774 /* BASE should be a virtual register. We copy it to NEWBASE. If
1775 the addend is out of range for DE/HL, we use AX to compute the full
1776 address. */
1778 if (addend < 0
1779 || (addend > 255 && REGNO (newbase) != 2)
1780 || (addendr && GET_CODE (addendr) != CONST_INT))
1782 /* mov ax, vreg
1783 add ax, #imm
1784 mov hl, ax */
1785 EM (emit_insn_before (gen_movhi (AX, base), before));
1786 EM (emit_insn_before (gen_addhi3 (AX, AX, addendr), before));
1787 EM (emit_insn_before (gen_movhi (newbase, AX), before));
1788 base = newbase;
1789 addend = 0;
1791 else
1793 EM (emit_insn_before (gen_movhi (newbase, base), before));
1794 base = newbase;
1797 if (addend)
1798 base = gen_rtx_PLUS (HImode, base, GEN_INT (addend));
1800 #if DEBUG_ALLOC
1801 fprintf (stderr, "\033[33m");
1802 debug_rtx (m);
1803 #endif
1804 m = change_address (m, GET_MODE (m), base);
1805 #if DEBUG_ALLOC
1806 debug_rtx (m);
1807 fprintf (stderr, "\033[0m");
1808 #endif
1809 return m;
1812 /* Copy SRC to accumulator (A or AX), placing any generated insns
1813 before BEFORE. Returns accumulator RTX. */
1815 static rtx
1816 move_to_acc (int opno, rtx before)
1818 rtx src = OP(opno);
1819 enum machine_mode mode = GET_MODE (src);
1821 if (GET_CODE (src) == REG
1822 && REGNO (src) < 2)
1823 return src;
1825 if (mode == VOIDmode)
1826 mode = recog_data.operand_mode[opno];
1828 if (mode == QImode)
1830 EM (emit_insn_before (gen_movqi (A, src), before));
1831 return A;
1833 else
1835 EM (emit_insn_before (gen_movhi (AX, src), before));
1836 return AX;
1840 /* Copy accumulator (A or AX) to DEST, placing any generated insns
1841 after AFTER. Returns accumulator RTX. */
1843 static rtx
1844 move_from_acc (rtx dest, rtx after)
1846 enum machine_mode mode = GET_MODE (dest);
1848 if (REG_P (dest) && REGNO (dest) < 2)
1849 return dest;
1851 if (mode == QImode)
1853 EM (emit_insn_after (gen_movqi (dest, A), after));
1854 return A;
1856 else
1858 EM (emit_insn_after (gen_movhi (dest, AX), after));
1859 return AX;
1863 /* Copy accumulator (A or AX) to REGNO, placing any generated insns
1864 before BEFORE. Returns reg RTX. */
1866 static rtx
1867 move_acc_to_reg (rtx acc, int regno, rtx before)
1869 enum machine_mode mode = GET_MODE (acc);
1870 rtx reg;
1872 reg = gen_rtx_REG (mode, regno);
1874 if (mode == QImode)
1876 EM (emit_insn_before (gen_movqi (reg, A), before));
1877 return reg;
1879 else
1881 EM (emit_insn_before (gen_movhi (reg, AX), before));
1882 return reg;
1886 /* Copy SRC to X, placing any generated insns before BEFORE.
1887 Returns X RTX. */
1889 static rtx
1890 move_to_x (int opno, rtx before)
1892 rtx src = OP(opno);
1893 enum machine_mode mode = GET_MODE (src);
1894 rtx reg;
1896 if (mode == VOIDmode)
1897 mode = recog_data.operand_mode[opno];
1898 reg = (mode == QImode) ? X : AX;
1900 if (mode == QImode || ! is_virtual_register (OP (opno)))
1902 OP(opno) = move_to_acc (opno, before);
1903 OP(opno) = move_acc_to_reg (OP(opno), X_REG, before);
1904 return reg;
1907 if (mode == QImode)
1908 EM (emit_insn_before (gen_movqi (reg, src), before));
1909 else
1910 EM (emit_insn_before (gen_movhi (reg, src), before));
1912 return reg;
1915 /* Copy OP(opno) to H or HL, placing any generated insns before BEFORE.
1916 Returns H/HL RTX. */
1918 static rtx
1919 move_to_hl (int opno, rtx before)
1921 rtx src = OP (opno);
1922 enum machine_mode mode = GET_MODE (src);
1923 rtx reg;
1925 if (mode == VOIDmode)
1926 mode = recog_data.operand_mode[opno];
1927 reg = (mode == QImode) ? L : HL;
1929 if (mode == QImode || ! is_virtual_register (OP (opno)))
1931 OP (opno) = move_to_acc (opno, before);
1932 OP (opno) = move_acc_to_reg (OP (opno), L_REG, before);
1933 return reg;
1936 if (mode == QImode)
1937 EM (emit_insn_before (gen_movqi (reg, src), before));
1938 else
1939 EM (emit_insn_before (gen_movhi (reg, src), before));
1941 return reg;
1944 /* Copy OP(opno) to E or DE, placing any generated insns before BEFORE.
1945 Returns E/DE RTX. */
1947 static rtx
1948 move_to_de (int opno, rtx before)
1950 rtx src = OP (opno);
1951 enum machine_mode mode = GET_MODE (src);
1952 rtx reg;
1954 if (mode == VOIDmode)
1955 mode = recog_data.operand_mode[opno];
1957 reg = (mode == QImode) ? E : DE;
1959 if (mode == QImode || ! is_virtual_register (OP (opno)))
1961 OP (opno) = move_to_acc (opno, before);
1962 OP (opno) = move_acc_to_reg (OP (opno), E_REG, before);
1964 else
1966 rtx move = mode == QImode ? gen_movqi (reg, src) : gen_movhi (reg, src);
1968 EM (emit_insn_before (move, before));
1971 return reg;
1974 /* Devirtualize an insn of the form (SET (op) (unop (op))). */
1975 static void
1976 rl78_alloc_physical_registers_op1 (rtx insn)
1978 /* op[0] = func op[1] */
1980 /* We first try using A as the destination, then copying it
1981 back. */
1982 if (rtx_equal_p (OP(0), OP(1)))
1984 OP(0) =
1985 OP(1) = transcode_memory_rtx (OP(1), DE, insn);
1987 else
1989 OP(0) = transcode_memory_rtx (OP(0), BC, insn);
1990 OP(1) = transcode_memory_rtx (OP(1), HL, insn);
1993 MAYBE_OK (insn);
1995 OP(0) = move_from_acc (OP(0), insn);
1997 MAYBE_OK (insn);
1999 /* Try copying the src to acc first, then. This is for, for
2000 example, ZERO_EXTEND or NOT. */
2001 OP(1) = move_to_acc (1, insn);
2003 MAYBE_OK (insn);
2005 FAILED;
2008 /* Devirtualize an insn of the form (SET (op) (unop (op) (op))). */
2009 static void
2010 rl78_alloc_physical_registers_op2 (rtx insn)
2012 /* op[0] = op[1] func op[2] */
2013 rtx prev = prev_nonnote_nondebug_insn (insn);
2014 rtx first;
2015 bool hl_used;
2017 if (rtx_equal_p (OP(0), OP(1)))
2019 OP(0) =
2020 OP(1) = transcode_memory_rtx (OP(1), DE, insn);
2021 prev = next_nonnote_nondebug_insn (prev);
2022 OP(2) = transcode_memory_rtx (OP(2), HL, insn);
2023 prev = prev_nonnote_nondebug_insn (prev);
2025 else if (rtx_equal_p (OP(0), OP(2)))
2027 OP(1) = transcode_memory_rtx (OP(1), DE, insn);
2028 prev = next_nonnote_nondebug_insn (prev);
2029 OP(0) =
2030 OP(2) = transcode_memory_rtx (OP(2), HL, insn);
2031 prev = prev_nonnote_nondebug_insn (prev);
2033 else
2035 OP(0) = transcode_memory_rtx (OP(0), BC, insn);
2036 OP(1) = transcode_memory_rtx (OP(1), DE, insn);
2037 prev = next_nonnote_nondebug_insn (prev);
2038 OP(2) = transcode_memory_rtx (OP(2), HL, insn);
2041 MAYBE_OK (insn);
2043 prev = prev_nonnote_nondebug_insn (insn);
2044 if (recog_data.constraints[1][0] == '%'
2045 && is_virtual_register (OP (1))
2046 && ! is_virtual_register (OP (2))
2047 && ! CONSTANT_P (OP (2)))
2049 rtx tmp = OP (1);
2050 OP (1) = OP (2);
2051 OP (2) = tmp;
2054 /* Make a note of wether (H)L is being used. It matters
2055 because if OP(2) alsoneeds reloading, then we must take
2056 care not to corrupt HL. */
2057 hl_used = reg_mentioned_p (L, OP (0)) || reg_mentioned_p (L, OP (1));
2059 OP(0) = move_from_acc (OP (0), insn);
2060 OP(1) = move_to_acc (1, insn);
2062 MAYBE_OK (insn);
2064 /* We have to copy op2 to HL, but that involves AX, which
2065 already has a live value. Emit it before those insns. */
2067 if (prev)
2068 first = next_nonnote_nondebug_insn (prev);
2069 else
2070 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
2073 OP (2) = hl_used ? move_to_de (2, first) : move_to_hl (2, first);
2075 MAYBE_OK (insn);
2077 FAILED;
2080 /* Devirtualize an insn of the form (SET () (unop (op))). */
2082 static void
2083 rl78_alloc_physical_registers_ro1 (rtx insn)
2085 /* (void) op[0] */
2086 OP(0) = transcode_memory_rtx (OP(0), BC, insn);
2088 MAYBE_OK (insn);
2090 OP(0) = move_to_acc (0, insn);
2092 MAYBE_OK (insn);
2094 FAILED;
2097 /* Devirtualize a compare insn. */
2098 static void
2099 rl78_alloc_physical_registers_cmp (rtx insn)
2101 /* op[1] cmp_op[0] op[2] */
2102 rtx prev = prev_nonnote_nondebug_insn (insn);
2103 rtx first;
2105 OP(1) = transcode_memory_rtx (OP(1), DE, insn);
2106 OP(2) = transcode_memory_rtx (OP(2), HL, insn);
2108 MAYBE_OK (insn);
2110 OP(1) = move_to_acc (1, insn);
2112 MAYBE_OK (insn);
2114 /* We have to copy op2 to HL, but that involves the acc, which
2115 already has a live value. Emit it before those insns. */
2117 if (prev)
2118 first = next_nonnote_nondebug_insn (prev);
2119 else
2120 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
2122 OP(2) = move_to_hl (2, first);
2124 MAYBE_OK (insn);
2126 FAILED;
2129 /* Like op2, but AX = A op X. */
2130 static void
2131 rl78_alloc_physical_registers_umul (rtx insn)
2133 /* op[0] = op[1] func op[2] */
2134 rtx prev = prev_nonnote_nondebug_insn (insn);
2135 rtx first;
2137 OP(0) = transcode_memory_rtx (OP(0), BC, insn);
2138 OP(1) = transcode_memory_rtx (OP(1), DE, insn);
2139 OP(2) = transcode_memory_rtx (OP(2), HL, insn);
2141 MAYBE_OK (insn);
2143 if (recog_data.constraints[1][0] == '%'
2144 && is_virtual_register (OP(1))
2145 && !is_virtual_register (OP(2))
2146 && !CONSTANT_P (OP(2)))
2148 rtx tmp = OP(1);
2149 OP(1) = OP(2);
2150 OP(2) = tmp;
2153 OP(0) = move_from_acc (OP(0), insn);
2154 OP(1) = move_to_acc (1, insn);
2156 MAYBE_OK (insn);
2158 /* We have to copy op2 to X, but that involves the acc, which
2159 already has a live value. Emit it before those insns. */
2161 if (prev)
2162 first = next_nonnote_nondebug_insn (prev);
2163 else
2164 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
2166 OP(2) = move_to_x (2, first);
2168 MAYBE_OK (insn);
2170 FAILED;
2173 /* Scan all insns and devirtualize them. */
2174 static void
2175 rl78_alloc_physical_registers (void)
2177 /* During most of the compile, gcc is dealing with virtual
2178 registers. At this point, we need to assign physical registers
2179 to the vitual ones, and copy in/out as needed. */
2181 rtx insn, curr;
2182 enum attr_valloc valloc_method;
2184 for (insn = get_insns (); insn; insn = curr)
2186 int i;
2188 curr = next_nonnote_nondebug_insn (insn);
2190 if (INSN_P (insn)
2191 && (GET_CODE (PATTERN (insn)) == SET
2192 || GET_CODE (PATTERN (insn)) == CALL)
2193 && INSN_CODE (insn) == -1)
2195 if (GET_CODE (SET_SRC (PATTERN (insn))) == ASM_OPERANDS)
2196 continue;
2197 i = recog (PATTERN (insn), insn, 0);
2198 if (i == -1)
2200 debug_rtx (insn);
2201 gcc_unreachable ();
2203 INSN_CODE (insn) = i;
2207 cfun->machine->virt_insns_ok = 0;
2208 cfun->machine->real_insns_ok = 1;
2210 for (insn = get_insns (); insn; insn = curr)
2212 curr = insn ? next_nonnote_nondebug_insn (insn) : NULL;
2214 if (!INSN_P (insn))
2215 continue;
2216 if (GET_CODE (PATTERN (insn)) != SET
2217 && GET_CODE (PATTERN (insn)) != CALL)
2218 continue;
2220 if (GET_CODE (PATTERN (insn)) == SET
2221 && GET_CODE (SET_SRC (PATTERN (insn))) == ASM_OPERANDS)
2222 continue;
2224 valloc_method = get_attr_valloc (insn);
2226 PATTERN (insn)= copy_rtx_if_shared (PATTERN (insn));
2228 if (insn_ok_now (insn))
2229 continue;
2231 INSN_CODE (insn) = -1;
2233 if (RTX_FRAME_RELATED_P (insn))
2234 virt_insn_was_frame = 1;
2235 else
2236 virt_insn_was_frame = 0;
2238 switch (valloc_method)
2240 case VALLOC_OP1:
2241 rl78_alloc_physical_registers_op1 (insn);
2242 break;
2243 case VALLOC_OP2:
2244 rl78_alloc_physical_registers_op2 (insn);
2245 break;
2246 case VALLOC_RO1:
2247 rl78_alloc_physical_registers_ro1 (insn);
2248 break;
2249 case VALLOC_CMP:
2250 rl78_alloc_physical_registers_cmp (insn);
2251 break;
2252 case VALLOC_UMUL:
2253 rl78_alloc_physical_registers_umul (insn);
2254 break;
2255 case VALLOC_MACAX:
2256 /* Macro that clobbers AX */
2257 break;
2260 #if DEBUG_ALLOC
2261 fprintf (stderr, "\033[0m");
2262 #endif
2265 /* Add REG_DEAD notes using DEAD[reg] for rtx S which is part of INSN.
2266 This function scans for uses of registers; the last use (i.e. first
2267 encounter when scanning backwards) triggers a REG_DEAD note if the
2268 reg was previously in DEAD[]. */
2269 static void
2270 rl78_note_reg_uses (char *dead, rtx s, rtx insn)
2272 const char *fmt;
2273 int i, r;
2274 enum rtx_code code;
2276 if (!s)
2277 return;
2279 code = GET_CODE (s);
2281 switch (code)
2283 /* Compare registers by number. */
2284 case REG:
2285 r = REGNO (s);
2286 if (dump_file)
2288 fprintf (dump_file, "note use reg %d size %d on insn %d\n",
2289 r, GET_MODE_SIZE (GET_MODE (s)), INSN_UID (insn));
2290 print_rtl_single (dump_file, s);
2292 if (dead [r])
2293 add_reg_note (insn, REG_DEAD, gen_rtx_REG (GET_MODE (s), r));
2294 for (i = 0; i < GET_MODE_SIZE (GET_MODE (s)); i ++)
2295 dead [r + i] = 0;
2296 return;
2298 /* These codes have no constituent expressions
2299 and are unique. */
2300 case SCRATCH:
2301 case CC0:
2302 case PC:
2303 return;
2305 case CONST_INT:
2306 case CONST_VECTOR:
2307 case CONST_DOUBLE:
2308 case CONST_FIXED:
2309 /* These are kept unique for a given value. */
2310 return;
2312 default:
2313 break;
2316 fmt = GET_RTX_FORMAT (code);
2318 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
2320 if (fmt[i] == 'E')
2322 int j;
2323 for (j = XVECLEN (s, i) - 1; j >= 0; j--)
2324 rl78_note_reg_uses (dead, XVECEXP (s, i, j), insn);
2326 else if (fmt[i] == 'e')
2327 rl78_note_reg_uses (dead, XEXP (s, i), insn);
2331 /* Like the previous function, but scan for SETs instead. */
2332 static void
2333 rl78_note_reg_set (char *dead, rtx d, rtx insn)
2335 int r, i;
2337 if (GET_CODE (d) != REG)
2338 return;
2340 r = REGNO (d);
2341 if (dead [r])
2342 add_reg_note (insn, REG_UNUSED, gen_rtx_REG (GET_MODE (d), r));
2343 if (dump_file)
2344 fprintf (dump_file, "note set reg %d size %d\n", r, GET_MODE_SIZE (GET_MODE (d)));
2345 for (i = 0; i < GET_MODE_SIZE (GET_MODE (d)); i ++)
2346 dead [r + i] = 1;
2349 /* This is a rather crude register death pass. Death status is reset
2350 at every jump or call insn. */
2351 static void
2352 rl78_calculate_death_notes (void)
2354 char dead[FIRST_PSEUDO_REGISTER];
2355 rtx insn, p, s, d;
2356 int i;
2358 memset (dead, 0, sizeof (dead));
2360 for (insn = get_last_insn ();
2361 insn;
2362 insn = prev_nonnote_nondebug_insn (insn))
2364 if (dump_file)
2366 fprintf (dump_file, "\n--------------------------------------------------");
2367 fprintf (dump_file, "\nDead:");
2368 for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
2369 if (dead[i])
2370 fprintf(dump_file, " %s", reg_names[i]);
2371 fprintf (dump_file, "\n");
2372 print_rtl_single (dump_file, insn);
2375 switch (GET_CODE (insn))
2377 case INSN:
2378 p = PATTERN (insn);
2379 switch (GET_CODE (p))
2381 case SET:
2382 s = SET_SRC (p);
2383 d = SET_DEST (p);
2384 rl78_note_reg_set (dead, d, insn);
2385 rl78_note_reg_uses (dead, s, insn);
2386 break;
2388 case USE:
2389 rl78_note_reg_uses (dead, p, insn);
2390 break;
2392 default:
2393 break;
2395 break;
2397 case JUMP_INSN:
2398 if (INSN_CODE (insn) == CODE_FOR_rl78_return)
2400 memset (dead, 1, sizeof (dead));
2401 /* We expect a USE just prior to this, which will mark
2402 the actual return registers. The USE will have a
2403 death note, but we aren't going to be modifying it
2404 after this pass. */
2405 break;
2407 case CALL_INSN:
2408 memset (dead, 0, sizeof (dead));
2409 break;
2411 default:
2412 break;
2414 if (dump_file)
2415 print_rtl_single (dump_file, insn);
2419 /* Helper function to reset the origins in RP and the age in AGE for
2420 all registers. */
2421 static void
2422 reset_origins (int *rp, int *age)
2424 int i;
2425 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2427 rp[i] = i;
2428 age[i] = 0;
2432 /* The idea behind this optimization is to look for cases where we
2433 move data from A to B to C, and instead move from A to B, and A to
2434 C. If B is a virtual register or memory, this is a big win on its
2435 own. If B turns out to be unneeded after this, it's a bigger win.
2436 For each register, we try to determine where it's value originally
2437 came from, if it's propogated purely through moves (and not
2438 computes). The ORIGINS[] array has the regno for the "origin" of
2439 the value in the [regno] it's indexed by. */
2440 static void
2441 rl78_propogate_register_origins (void)
2443 int origins[FIRST_PSEUDO_REGISTER];
2444 int age[FIRST_PSEUDO_REGISTER];
2445 int i;
2446 rtx insn, ninsn = NULL_RTX;
2447 rtx pat;
2449 reset_origins (origins, age);
2451 for (insn = get_insns (); insn; insn = ninsn)
2453 ninsn = next_nonnote_nondebug_insn (insn);
2455 if (dump_file)
2457 fprintf (dump_file, "\n");
2458 fprintf (dump_file, "Origins:");
2459 for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
2460 if (origins[i] != i)
2461 fprintf (dump_file, " r%d=r%d", i, origins[i]);
2462 fprintf (dump_file, "\n");
2463 print_rtl_single (dump_file, insn);
2466 switch (GET_CODE (insn))
2468 case CODE_LABEL:
2469 case BARRIER:
2470 case CALL_INSN:
2471 case JUMP_INSN:
2472 reset_origins (origins, age);
2473 break;
2475 default:
2476 break;
2478 case INSN:
2479 pat = PATTERN (insn);
2481 if (GET_CODE (pat) == PARALLEL)
2483 rtx clobber = XVECEXP (pat, 0, 1);
2484 pat = XVECEXP (pat, 0, 0);
2485 if (GET_CODE (clobber) == CLOBBER)
2487 int cr = REGNO (XEXP (clobber, 0));
2488 int mb = GET_MODE_SIZE (GET_MODE (XEXP (clobber, 0)));
2489 if (dump_file)
2490 fprintf (dump_file, "reset origins of %d regs at %d\n", mb, cr);
2491 for (i = 0; i < mb; i++)
2493 origins[cr + i] = cr + i;
2494 age[cr + i] = 0;
2497 else
2498 break;
2501 if (GET_CODE (pat) == SET)
2503 rtx src = SET_SRC (pat);
2504 rtx dest = SET_DEST (pat);
2505 int mb = GET_MODE_SIZE (GET_MODE (dest));
2507 if (GET_CODE (dest) == REG)
2509 int dr = REGNO (dest);
2511 if (GET_CODE (src) == REG)
2513 int sr = REGNO (src);
2514 int same = 1;
2515 int best_age, best_reg;
2517 /* See if the copy is not needed. */
2518 for (i = 0; i < mb; i ++)
2519 if (origins[dr + i] != origins[sr + i])
2520 same = 0;
2521 if (same)
2523 if (dump_file)
2524 fprintf (dump_file, "deleting because dest already has correct value\n");
2525 delete_insn (insn);
2526 break;
2529 if (dr < 8 || sr >= 8)
2531 int ar;
2533 best_age = -1;
2534 best_reg = -1;
2535 /* See if the copy can be made from another
2536 bank 0 register instead, instead of the
2537 virtual src register. */
2538 for (ar = 0; ar < 8; ar += mb)
2540 same = 1;
2541 for (i = 0; i < mb; i ++)
2542 if (origins[ar + i] != origins[sr + i])
2543 same = 0;
2545 /* The chip has some reg-reg move limitations. */
2546 if (mb == 1 && dr > 3)
2547 same = 0;
2549 if (same)
2551 if (best_age == -1 || best_age > age[sr + i])
2553 best_age = age[sr + i];
2554 best_reg = sr;
2559 if (best_reg != -1)
2561 /* FIXME: copy debug info too. */
2562 SET_SRC (pat) = gen_rtx_REG (GET_MODE (src), best_reg);
2563 sr = best_reg;
2567 for (i = 0; i < mb; i++)
2569 origins[dr + i] = origins[sr + i];
2570 age[dr + i] = age[sr + i] + 1;
2573 else
2575 /* The destination is computed, its origin is itself. */
2576 if (dump_file)
2577 fprintf (dump_file, "resetting origin of r%d for %d byte%s\n",
2578 dr, mb, mb == 1 ? "" : "s");
2579 for (i = 0; i < mb; i ++)
2581 origins[dr + i] = dr + i;
2582 age[dr + i] = 0;
2586 /* Any registers marked with that reg as an origin are reset. */
2587 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2588 if (origins[i] >= dr && origins[i] < dr + mb)
2590 origins[i] = i;
2591 age[i] = 0;
2595 /* Special case - our ADDSI3 macro uses AX */
2596 if (get_attr_valloc (insn) == VALLOC_MACAX)
2598 if (dump_file)
2599 fprintf (dump_file, "Resetting origin of AX for macro.\n");
2600 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2601 if (i <= 1 || origins[i] <= 1)
2603 origins[i] = i;
2604 age[i] = 0;
2608 if (GET_CODE (src) == ASHIFT
2609 || GET_CODE (src) == ASHIFTRT
2610 || GET_CODE (src) == LSHIFTRT)
2612 rtx count = XEXP (src, 1);
2613 if (GET_CODE (count) == REG)
2615 /* Special case - our pattern clobbers the count register. */
2616 int r = REGNO (count);
2617 if (dump_file)
2618 fprintf (dump_file, "Resetting origin of r%d for shift.\n", r);
2619 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2620 if (i == r || origins[i] == r)
2622 origins[i] = i;
2623 age[i] = 0;
2632 /* Remove any SETs where the destination is unneeded. */
2633 static void
2634 rl78_remove_unused_sets (void)
2636 rtx insn, ninsn = NULL_RTX;
2637 rtx dest;
2639 for (insn = get_insns (); insn; insn = ninsn)
2641 ninsn = next_nonnote_nondebug_insn (insn);
2643 if ((insn = single_set (insn)) == NULL_RTX)
2644 continue;
2646 dest = SET_DEST (insn);
2648 if (GET_CODE (dest) != REG || REGNO (dest) > 23)
2649 continue;
2651 if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
2652 delete_insn (insn);
2656 #undef xTARGET_MACHINE_DEPENDENT_REORG
2657 #define xTARGET_MACHINE_DEPENDENT_REORG rl78_reorg
2659 /* This is the top of the devritualization pass. */
2660 static void
2661 rl78_reorg (void)
2663 rl78_alloc_physical_registers ();
2665 if (dump_file)
2667 fprintf (dump_file, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n");
2668 print_rtl_with_bb (dump_file, get_insns (), 0);
2671 rl78_propogate_register_origins ();
2672 rl78_calculate_death_notes ();
2674 if (dump_file)
2676 fprintf (dump_file, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n");
2677 print_rtl_with_bb (dump_file, get_insns (), 0);
2678 fprintf (dump_file, "\n======================================================================\n");
2681 rl78_remove_unused_sets ();
2683 /* The code after devirtualizing has changed so much that at this point
2684 we might as well just rescan everything. Note that
2685 df_rescan_all_insns is not going to help here because it does not
2686 touch the artificial uses and defs. */
2687 df_finish_pass (true);
2688 if (optimize > 1)
2689 df_live_add_problem ();
2690 df_scan_alloc (NULL);
2691 df_scan_blocks ();
2693 if (optimize)
2694 df_analyze ();
2697 #undef TARGET_RETURN_IN_MEMORY
2698 #define TARGET_RETURN_IN_MEMORY rl78_return_in_memory
2700 static bool
2701 rl78_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
2703 const HOST_WIDE_INT size = int_size_in_bytes (type);
2704 return (size == -1 || size > 8);
2708 struct gcc_target targetm = TARGET_INITIALIZER;
2710 #include "gt-rl78.h"