* config/rl78/rl78.c (rl78_expand_prologue): Always select
[official-gcc.git] / gcc / config / rl78 / rl78.c
blob7b58be8f81c3e810e2bb1dcb1ce2c857081005d1
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 OPTGROUP_NONE, /* optinfo_flags */
137 devirt_gate,
138 devirt_pass,
139 NULL,
140 NULL,
141 212,
142 TV_MACH_DEP,
143 0, 0, 0,
148 static struct register_pass_info rl78_devirt_info =
150 & rl78_devirt_pass,
151 "vartrack",
153 PASS_POS_INSERT_BEFORE
156 #undef TARGET_ASM_FILE_START
157 #define TARGET_ASM_FILE_START rl78_asm_file_start
159 static void
160 rl78_asm_file_start (void)
162 int i;
164 for (i = 0; i < 8; i++)
166 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 8 + i, 0xffef0 + i);
167 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 16 + i, 0xffee8 + i);
170 register_pass (& rl78_devirt_info);
174 #undef TARGET_OPTION_OVERRIDE
175 #define TARGET_OPTION_OVERRIDE rl78_option_override
177 static void
178 rl78_option_override (void)
180 flag_omit_frame_pointer = 1;
181 flag_no_function_cse = 1;
182 flag_split_wide_types = 0;
184 init_machine_status = rl78_init_machine_status;
187 /* Most registers are 8 bits. Some are 16 bits because, for example,
188 gcc doesn't like dealing with $FP as a register pair. This table
189 maps register numbers to size in bytes. */
190 static const int register_sizes[] =
192 1, 1, 1, 1, 1, 1, 1, 1,
193 1, 1, 1, 1, 1, 1, 1, 1,
194 1, 1, 1, 1, 1, 1, 2, 1,
195 1, 1, 1, 1, 1, 1, 1, 1,
196 2, 2, 1, 1, 1
199 /* Predicates used in the MD patterns. This one is true when virtual
200 insns may be matched, which typically means before (or during) the
201 devirt pass. */
202 bool
203 rl78_virt_insns_ok (void)
205 if (cfun)
206 return cfun->machine->virt_insns_ok;
207 return true;
210 /* Predicates used in the MD patterns. This one is true when real
211 insns may be matched, which typically means after (or during) the
212 devirt pass. */
213 bool
214 rl78_real_insns_ok (void)
216 if (cfun)
217 return cfun->machine->real_insns_ok;
218 return false;
221 /* Implements HARD_REGNO_NREGS. */
223 rl78_hard_regno_nregs (int regno, enum machine_mode mode)
225 int rs = register_sizes[regno];
226 if (rs < 1)
227 rs = 1;
228 return ((GET_MODE_SIZE (mode) + rs - 1) / rs);
231 /* Implements HARD_REGNO_MODE_OK. */
233 rl78_hard_regno_mode_ok (int regno, enum machine_mode mode)
235 int s = GET_MODE_SIZE (mode);
237 if (s < 1)
238 return 0;
239 /* These are not to be used by gcc. */
240 if (regno == 23 || regno == ES_REG || regno == CS_REG)
241 return 0;
242 /* $fp can alway sbe accessed as a 16-bit value. */
243 if (regno == FP_REG && s == 2)
244 return 1;
245 if (regno < SP_REG)
247 /* Since a reg-reg move is really a reg-mem move, we must
248 enforce alignment. */
249 if (s > 1 && (regno % 2))
250 return 0;
251 return 1;
253 if (s == CC_REGNUM)
254 return (mode == BImode);
255 /* All other registers must be accessed in their natural sizes. */
256 if (s == register_sizes [regno])
257 return 1;
258 return 0;
261 /* Simplify_gen_subreg() doesn't handle memory references the way we
262 need it to below, so we use this function for when we must get a
263 valid subreg in a "natural" state. */
264 static rtx
265 rl78_subreg (enum machine_mode mode, rtx r, enum machine_mode omode, int byte)
267 if (GET_CODE (r) == MEM)
268 return adjust_address (r, mode, byte);
269 else
270 return simplify_gen_subreg (mode, r, omode, byte);
273 /* Used by movsi. Split SImode moves into two HImode moves, using
274 appropriate patterns for the upper and lower halves of symbols. */
275 void
276 rl78_expand_movsi (rtx *operands)
278 rtx op00, op02, op10, op12;
280 op00 = rl78_subreg (HImode, operands[0], SImode, 0);
281 op02 = rl78_subreg (HImode, operands[0], SImode, 2);
282 if (GET_CODE (operands[1]) == CONST
283 || GET_CODE (operands[1]) == SYMBOL_REF)
285 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
286 op10 = gen_rtx_CONST (HImode, op10);
287 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
288 op12 = gen_rtx_CONST (HImode, op12);
290 else
292 op10 = rl78_subreg (HImode, operands[1], SImode, 0);
293 op12 = rl78_subreg (HImode, operands[1], SImode, 2);
296 if (rtx_equal_p (operands[0], operands[1]))
298 else if (rtx_equal_p (op00, op12))
300 emit_move_insn (op02, op12);
301 emit_move_insn (op00, op10);
303 else
305 emit_move_insn (op00, op10);
306 emit_move_insn (op02, op12);
310 /* Used by various two-operand expanders which cannot accept all
311 operands in the "far" namespace. Force some such operands into
312 registers so that each pattern has at most one far operand. */
314 rl78_force_nonfar_2 (rtx *operands, rtx (*gen)(rtx,rtx))
316 int did = 0;
317 rtx temp_reg = NULL;
319 /* FIXME: in the future, be smarter about only doing this if the
320 other operand is also far, assuming the devirtualizer can also
321 handle that. */
322 if (rl78_far_p (operands[0]))
324 temp_reg = operands[0];
325 operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
326 did = 1;
328 if (!did)
329 return 0;
331 emit_insn (gen (operands[0], operands[1]));
332 if (temp_reg)
333 emit_move_insn (temp_reg, operands[0]);
334 return 1;
337 /* Likewise, but for three-operand expanders. */
339 rl78_force_nonfar_3 (rtx *operands, rtx (*gen)(rtx,rtx,rtx))
341 int did = 0;
342 rtx temp_reg = NULL;
344 /* FIXME: Likewise. */
345 if (rl78_far_p (operands[1]))
347 rtx temp_reg = gen_reg_rtx (GET_MODE (operands[1]));
348 emit_move_insn (temp_reg, operands[1]);
349 operands[1] = temp_reg;
350 did = 1;
352 if (rl78_far_p (operands[0]))
354 temp_reg = operands[0];
355 operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
356 did = 1;
358 if (!did)
359 return 0;
361 emit_insn (gen (operands[0], operands[1], operands[2]));
362 if (temp_reg)
363 emit_move_insn (temp_reg, operands[0]);
364 return 1;
367 #undef TARGET_CAN_ELIMINATE
368 #define TARGET_CAN_ELIMINATE rl78_can_eliminate
370 static bool
371 rl78_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to ATTRIBUTE_UNUSED)
373 return true;
376 /* Returns nonzero if the given register needs to be saved by the
377 current function. */
378 static int
379 need_to_save (int regno)
381 if (is_interrupt_func (cfun->decl))
383 if (regno < 8)
384 return 1; /* don't know what devirt will need */
385 if (regno > 23)
386 return 0; /* don't need to save interrupt registers */
387 if (crtl->is_leaf)
389 return df_regs_ever_live_p (regno);
391 else
392 return 1;
394 if (regno == FRAME_POINTER_REGNUM && frame_pointer_needed)
395 return 1;
396 if (fixed_regs[regno])
397 return 0;
398 if (crtl->calls_eh_return)
399 return 1;
400 if (df_regs_ever_live_p (regno)
401 && !call_used_regs[regno])
402 return 1;
403 return 0;
406 /* We use this to wrap all emitted insns in the prologue. */
407 static rtx
408 F (rtx x)
410 RTX_FRAME_RELATED_P (x) = 1;
411 return x;
414 /* Compute all the frame-related fields in our machine_function
415 structure. */
416 static void
417 rl78_compute_frame_info (void)
419 int i;
421 cfun->machine->computed = 1;
422 cfun->machine->framesize_regs = 0;
423 cfun->machine->framesize_locals = get_frame_size ();
424 cfun->machine->framesize_outgoing = crtl->outgoing_args_size;
426 for (i = 0; i < 16; i ++)
427 if (need_to_save (i * 2) || need_to_save (i * 2 + 1))
429 cfun->machine->need_to_push [i] = 1;
430 cfun->machine->framesize_regs += 2;
432 else
433 cfun->machine->need_to_push [i] = 0;
435 if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1)
436 cfun->machine->framesize_locals ++;
438 cfun->machine->framesize = (cfun->machine->framesize_regs
439 + cfun->machine->framesize_locals
440 + cfun->machine->framesize_outgoing);
443 /* Returns true if the provided function has the specified attribute. */
444 static inline bool
445 has_func_attr (const_tree decl, const char * func_attr)
447 if (decl == NULL_TREE)
448 decl = current_function_decl;
450 return lookup_attribute (func_attr, DECL_ATTRIBUTES (decl)) != NULL_TREE;
453 /* Returns true if the provided function has the "interrupt" attribute. */
454 static inline bool
455 is_interrupt_func (const_tree decl)
457 return has_func_attr (decl, "interrupt") || has_func_attr (decl, "brk_interrupt");
460 /* Returns true if the provided function has the "brk_interrupt" attribute. */
461 static inline bool
462 is_brk_interrupt_func (const_tree decl)
464 return has_func_attr (decl, "brk_interrupt");
467 /* Check "interrupt" attributes. */
468 static tree
469 rl78_handle_func_attribute (tree * node,
470 tree name,
471 tree args,
472 int flags ATTRIBUTE_UNUSED,
473 bool * no_add_attrs)
475 gcc_assert (DECL_P (* node));
476 gcc_assert (args == NULL_TREE);
478 if (TREE_CODE (* node) != FUNCTION_DECL)
480 warning (OPT_Wattributes, "%qE attribute only applies to functions",
481 name);
482 * no_add_attrs = true;
485 /* FIXME: We ought to check that the interrupt and exception
486 handler attributes have been applied to void functions. */
487 return NULL_TREE;
490 #undef TARGET_ATTRIBUTE_TABLE
491 #define TARGET_ATTRIBUTE_TABLE rl78_attribute_table
493 /* Table of RL78-specific attributes. */
494 const struct attribute_spec rl78_attribute_table[] =
496 /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
497 affects_type_identity. */
498 { "interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
499 false },
500 { "brk_interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
501 false },
502 { NULL, 0, 0, false, false, false, NULL, false }
507 /* Break down an address RTX into its component base/index/addend
508 portions and return TRUE if the address is of a valid form, else
509 FALSE. */
510 static bool
511 characterize_address (rtx x, rtx *base, rtx *index, rtx *addend)
513 *base = NULL_RTX;
514 *index = NULL_RTX;
515 *addend = NULL_RTX;
517 if (GET_CODE (x) == REG)
519 *base = x;
520 return true;
523 /* We sometimes get these without the CONST wrapper */
524 if (GET_CODE (x) == PLUS
525 && GET_CODE (XEXP (x, 0)) == SYMBOL_REF
526 && GET_CODE (XEXP (x, 1)) == CONST_INT)
528 *addend = x;
529 return true;
532 if (GET_CODE (x) == PLUS)
534 *base = XEXP (x, 0);
535 x = XEXP (x, 1);
537 if (GET_CODE (*base) != REG
538 && GET_CODE (x) == REG)
540 rtx tmp = *base;
541 *base = x;
542 x = tmp;
545 if (GET_CODE (*base) != REG)
546 return false;
548 if (GET_CODE (x) == ZERO_EXTEND
549 && GET_CODE (XEXP (x, 0)) == REG)
551 *index = XEXP (x, 0);
552 return false;
556 switch (GET_CODE (x))
558 case PLUS:
559 if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
560 && GET_CODE (XEXP (x, 0)) == CONST_INT)
562 *addend = x;
563 return true;
565 /* fall through */
566 case MEM:
567 case REG:
568 return false;
570 case CONST:
571 case SYMBOL_REF:
572 case CONST_INT:
573 *addend = x;
574 return true;
576 default:
577 return false;
580 return false;
583 /* Used by the Whb constraint. Match addresses that use HL+B or HL+C
584 addressing. */
585 bool
586 rl78_hl_b_c_addr_p (rtx op)
588 rtx hl, bc;
590 if (GET_CODE (op) != PLUS)
591 return false;
592 hl = XEXP (op, 0);
593 bc = XEXP (op, 1);
594 if (GET_CODE (hl) == ZERO_EXTEND)
596 rtx tmp = hl;
597 hl = bc;
598 bc = tmp;
600 if (GET_CODE (hl) != REG)
601 return false;
602 if (GET_CODE (bc) != ZERO_EXTEND)
603 return false;
604 bc = XEXP (bc, 0);
605 if (GET_CODE (bc) != REG)
606 return false;
607 if (REGNO (hl) != HL_REG)
608 return false;
609 if (REGNO (bc) != B_REG && REGNO (bc) != C_REG)
610 return false;
612 return true;
615 #define REG_IS(r, regno) (((r) == (regno)) || ((r) >= FIRST_PSEUDO_REGISTER && !(strict)))
617 /* Used in various constraints and predicates to match operands in the
618 "far" address space. */
620 rl78_far_p (rtx x)
622 if (GET_CODE (x) != MEM)
623 return 0;
624 #if DEBUG0
625 fprintf(stderr, "\033[35mrl78_far_p: "); debug_rtx(x);
626 fprintf(stderr, " = %d\033[0m\n", MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR);
627 #endif
628 return MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR;
631 /* Return the appropriate mode for a named address pointer. */
632 #undef TARGET_ADDR_SPACE_POINTER_MODE
633 #define TARGET_ADDR_SPACE_POINTER_MODE rl78_addr_space_pointer_mode
634 static enum machine_mode
635 rl78_addr_space_pointer_mode (addr_space_t addrspace)
637 switch (addrspace)
639 case ADDR_SPACE_GENERIC:
640 return HImode;
641 case ADDR_SPACE_FAR:
642 return SImode;
643 default:
644 gcc_unreachable ();
648 /* Return the appropriate mode for a named address address. */
649 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
650 #define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode
651 static enum machine_mode
652 rl78_addr_space_address_mode (addr_space_t addrspace)
654 switch (addrspace)
656 case ADDR_SPACE_GENERIC:
657 return HImode;
658 case ADDR_SPACE_FAR:
659 return SImode;
660 default:
661 gcc_unreachable ();
665 #undef TARGET_LEGITIMATE_CONSTANT_P
666 #define TARGET_LEGITIMATE_CONSTANT_P rl78_is_legitimate_constant
668 static bool
669 rl78_is_legitimate_constant (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED)
671 return true;
674 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
675 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P rl78_as_legitimate_address
677 bool
678 rl78_as_legitimate_address (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x,
679 bool strict ATTRIBUTE_UNUSED, addr_space_t as ATTRIBUTE_UNUSED)
681 rtx base, index, addend;
683 if (as == ADDR_SPACE_GENERIC
684 && GET_MODE (x) == SImode)
685 return false;
687 if (! characterize_address (x, &base, &index, &addend))
688 return false;
690 /* We can't extract the high/low portions of a PLUS address
691 involving a register during devirtualization, so make sure all
692 such __far addresses do not have addends. This forces GCC to do
693 the sum separately. */
694 if (addend && base && as == ADDR_SPACE_FAR)
695 return false;
697 if (base && index)
699 int ir = REGNO (index);
700 int br = REGNO (base);
702 #define OK(test, debug) if (test) { /*fprintf(stderr, "%d: OK %s\n", __LINE__, debug);*/ return true; }
703 OK (REG_IS (br, HL_REG) && REG_IS (ir, B_REG), "[hl+b]");
704 OK (REG_IS (br, HL_REG) && REG_IS (ir, C_REG), "[hl+c]");
705 return false;
708 if (strict && base && GET_CODE (base) == REG && REGNO (base) >= FIRST_PSEUDO_REGISTER)
709 return false;
711 return true;
714 /* Determine if one named address space is a subset of another. */
715 #undef TARGET_ADDR_SPACE_SUBSET_P
716 #define TARGET_ADDR_SPACE_SUBSET_P rl78_addr_space_subset_p
717 static bool
718 rl78_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
720 gcc_assert (subset == ADDR_SPACE_GENERIC || subset == ADDR_SPACE_FAR);
721 gcc_assert (superset == ADDR_SPACE_GENERIC || superset == ADDR_SPACE_FAR);
723 if (subset == superset)
724 return true;
726 else
727 return (subset == ADDR_SPACE_GENERIC && superset == ADDR_SPACE_FAR);
730 #undef TARGET_ADDR_SPACE_CONVERT
731 #define TARGET_ADDR_SPACE_CONVERT rl78_addr_space_convert
732 /* Convert from one address space to another. */
733 static rtx
734 rl78_addr_space_convert (rtx op, tree from_type, tree to_type)
736 addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
737 addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
738 rtx result;
740 gcc_assert (from_as == ADDR_SPACE_GENERIC || from_as == ADDR_SPACE_FAR);
741 gcc_assert (to_as == ADDR_SPACE_GENERIC || to_as == ADDR_SPACE_FAR);
743 if (to_as == ADDR_SPACE_GENERIC && from_as == ADDR_SPACE_FAR)
745 /* This is unpredictable, as we're truncating off usable address
746 bits. */
748 result = gen_reg_rtx (HImode);
749 emit_move_insn (result, simplify_subreg (HImode, op, SImode, 0));
750 return result;
752 else if (to_as == ADDR_SPACE_FAR && from_as == ADDR_SPACE_GENERIC)
754 /* This always works. */
755 result = gen_reg_rtx (SImode);
756 debug_rtx(result);
757 debug_rtx(op);
758 emit_move_insn (rl78_subreg (HImode, result, SImode, 0), op);
759 emit_move_insn (rl78_subreg (HImode, result, SImode, 2), const0_rtx);
760 return result;
762 else
763 gcc_unreachable ();
766 /* Implements REGNO_MODE_CODE_OK_FOR_BASE_P. */
767 bool
768 rl78_regno_mode_code_ok_for_base_p (int regno, enum machine_mode mode ATTRIBUTE_UNUSED,
769 addr_space_t address_space ATTRIBUTE_UNUSED,
770 int outer_code ATTRIBUTE_UNUSED, int index_code)
772 if (regno < 24 && regno >= 16)
773 return true;
774 if (index_code == REG)
775 return (regno == HL_REG);
776 if (regno == C_REG || regno == B_REG || regno == E_REG || regno == L_REG)
777 return true;
778 return false;
781 /* Implements MODE_CODE_BASE_REG_CLASS. */
782 enum reg_class
783 rl78_mode_code_base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED,
784 addr_space_t address_space ATTRIBUTE_UNUSED,
785 int outer_code ATTRIBUTE_UNUSED,
786 int index_code ATTRIBUTE_UNUSED)
788 return V_REGS;
791 /* Implements INITIAL_ELIMINATION_OFFSET. The frame layout is
792 described in the machine_Function struct definition, above. */
794 rl78_initial_elimination_offset (int from, int to)
796 int rv = 0; /* as if arg to arg */
798 rl78_compute_frame_info ();
800 switch (to)
802 case STACK_POINTER_REGNUM:
803 rv += cfun->machine->framesize_outgoing;
804 rv += cfun->machine->framesize_locals;
805 /* Fall through. */
806 case FRAME_POINTER_REGNUM:
807 rv += cfun->machine->framesize_regs;
808 rv += 4;
809 break;
810 default:
811 gcc_unreachable ();
814 switch (from)
816 case FRAME_POINTER_REGNUM:
817 rv -= 4;
818 rv -= cfun->machine->framesize_regs;
819 case ARG_POINTER_REGNUM:
820 break;
821 default:
822 gcc_unreachable ();
825 return rv;
828 /* Expand the function prologue (from the prologue pattern). */
829 void
830 rl78_expand_prologue (void)
832 int i, fs;
833 rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
834 int rb = 0;
836 if (!cfun->machine->computed)
837 rl78_compute_frame_info ();
839 if (flag_stack_usage_info)
840 current_function_static_stack_size = cfun->machine->framesize;
842 if (is_interrupt_func (cfun->decl))
843 emit_insn (gen_sel_rb (GEN_INT (0)));
845 for (i = 0; i < 16; i++)
846 if (cfun->machine->need_to_push [i])
848 int need_bank = i/4;
849 if (need_bank != rb)
851 emit_insn (gen_sel_rb (GEN_INT (need_bank)));
852 rb = need_bank;
854 F (emit_insn (gen_push (gen_rtx_REG (HImode, i*2))));
856 if (rb != 0)
857 emit_insn (gen_sel_rb (GEN_INT (0)));
859 if (frame_pointer_needed)
860 F (emit_move_insn (gen_rtx_REG (HImode, FRAME_POINTER_REGNUM),
861 gen_rtx_REG (HImode, STACK_POINTER_REGNUM)));
863 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
864 while (fs > 0)
866 int fs_byte = (fs > 254) ? 254 : fs;
867 F (emit_insn (gen_subhi3 (sp, sp, GEN_INT (fs_byte))));
868 fs -= fs_byte;
872 /* Expand the function epilogue (from the epilogue pattern). */
873 void
874 rl78_expand_epilogue (void)
876 int i, fs;
877 rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
878 int rb = 0;
880 if (frame_pointer_needed)
882 emit_move_insn (gen_rtx_REG (HImode, STACK_POINTER_REGNUM),
883 gen_rtx_REG (HImode, FRAME_POINTER_REGNUM));
885 else
887 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
888 while (fs > 0)
890 int fs_byte = (fs > 254) ? 254 : fs;
892 emit_insn (gen_addhi3 (sp, sp, GEN_INT (fs_byte)));
893 fs -= fs_byte;
897 for (i = 15; i >= 0; i--)
898 if (cfun->machine->need_to_push [i])
900 int need_bank = i / 4;
902 if (need_bank != rb)
904 emit_insn (gen_sel_rb (GEN_INT (need_bank)));
905 rb = need_bank;
907 emit_insn (gen_pop (gen_rtx_REG (HImode, i * 2)));
910 if (rb != 0)
911 emit_insn (gen_sel_rb (GEN_INT (0)));
913 if (cfun->machine->trampolines_used)
914 emit_insn (gen_trampoline_uninit ());
916 if (is_brk_interrupt_func (cfun->decl))
917 emit_jump_insn (gen_brk_interrupt_return ());
918 else if (is_interrupt_func (cfun->decl))
919 emit_jump_insn (gen_interrupt_return ());
920 else
921 emit_jump_insn (gen_rl78_return ());
924 /* Likewise, for exception handlers. */
925 void
926 rl78_expand_eh_epilogue (rtx x ATTRIBUTE_UNUSED)
928 /* FIXME - replace this with an indirect jump with stack adjust. */
929 emit_jump_insn (gen_rl78_return ());
932 #undef TARGET_ASM_FUNCTION_PROLOGUE
933 #define TARGET_ASM_FUNCTION_PROLOGUE rl78_start_function
935 /* We don't use this to actually emit the function prologue. We use
936 this to insert a comment in the asm file describing the
937 function. */
938 static void
939 rl78_start_function (FILE *file, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED)
941 int i;
943 if (cfun->machine->framesize == 0)
944 return;
945 fprintf (file, "\t; start of function\n");
947 if (cfun->machine->framesize_regs)
949 fprintf (file, "\t; push %d:", cfun->machine->framesize_regs);
950 for (i = 0; i < 16; i ++)
951 if (cfun->machine->need_to_push[i])
952 fprintf (file, " %s", word_regnames[i*2]);
953 fprintf(file, "\n");
956 if (frame_pointer_needed)
957 fprintf (file, "\t; $fp points here (r22)\n");
959 if (cfun->machine->framesize_locals)
960 fprintf (file, "\t; locals: %d byte%s\n", cfun->machine->framesize_locals,
961 cfun->machine->framesize_locals == 1 ? "" : "s");
963 if (cfun->machine->framesize_outgoing)
964 fprintf (file, "\t; outgoing: %d byte%s\n", cfun->machine->framesize_outgoing,
965 cfun->machine->framesize_outgoing == 1 ? "" : "s");
968 /* Return an RTL describing where a function return value of type RET_TYPE
969 is held. */
971 #undef TARGET_FUNCTION_VALUE
972 #define TARGET_FUNCTION_VALUE rl78_function_value
974 static rtx
975 rl78_function_value (const_tree ret_type,
976 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
977 bool outgoing ATTRIBUTE_UNUSED)
979 enum machine_mode mode = TYPE_MODE (ret_type);
981 return gen_rtx_REG (mode, 8);
984 #undef TARGET_PROMOTE_FUNCTION_MODE
985 #define TARGET_PROMOTE_FUNCTION_MODE rl78_promote_function_mode
987 static enum machine_mode
988 rl78_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
989 enum machine_mode mode,
990 int *punsignedp ATTRIBUTE_UNUSED,
991 const_tree funtype ATTRIBUTE_UNUSED, int for_return ATTRIBUTE_UNUSED)
993 return mode;
996 /* Return an RTL expression describing the register holding a function
997 parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
998 be passed on the stack. CUM describes the previous parameters to the
999 function and NAMED is false if the parameter is part of a variable
1000 parameter list, or the last named parameter before the start of a
1001 variable parameter list. */
1003 #undef TARGET_FUNCTION_ARG
1004 #define TARGET_FUNCTION_ARG rl78_function_arg
1006 static rtx
1007 rl78_function_arg (cumulative_args_t cum_v ATTRIBUTE_UNUSED,
1008 enum machine_mode mode ATTRIBUTE_UNUSED,
1009 const_tree type ATTRIBUTE_UNUSED,
1010 bool named ATTRIBUTE_UNUSED)
1012 return NULL_RTX;
1015 #undef TARGET_FUNCTION_ARG_ADVANCE
1016 #define TARGET_FUNCTION_ARG_ADVANCE rl78_function_arg_advance
1018 static void
1019 rl78_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode, const_tree type,
1020 bool named ATTRIBUTE_UNUSED)
1022 int rounded_size;
1023 CUMULATIVE_ARGS * cum = get_cumulative_args (cum_v);
1025 rounded_size = ((mode == BLKmode)
1026 ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
1027 if (rounded_size & 1)
1028 rounded_size ++;
1029 (*cum) += rounded_size;
1032 #undef TARGET_FUNCTION_ARG_BOUNDARY
1033 #define TARGET_FUNCTION_ARG_BOUNDARY rl78_function_arg_boundary
1035 static unsigned int
1036 rl78_function_arg_boundary (enum machine_mode mode ATTRIBUTE_UNUSED,
1037 const_tree type ATTRIBUTE_UNUSED)
1039 return 16;
1042 /* Supported modifier letters:
1044 A - address of a MEM
1045 S - SADDR form of a real register
1046 v - real register corresponding to a virtual register
1047 m - minus - negative of CONST_INT value.
1048 c - inverse of a conditional (NE vs EQ for example)
1050 h - bottom HI of an SI
1051 H - top HI of an SI
1052 q - bottom QI of an HI
1053 Q - top QI of an HI
1054 e - third QI of an SI (i.e. where the ES register gets values from)
1058 /* Implements the bulk of rl78_print_operand, below. We do it this
1059 way because we need to test for a constant at the top level and
1060 insert the '#', but not test for it anywhere else as we recurse
1061 down into the operand. */
1062 static void
1063 rl78_print_operand_1 (FILE * file, rtx op, int letter)
1065 int need_paren;
1067 switch (GET_CODE (op))
1069 case MEM:
1070 if (letter == 'A')
1071 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1072 else
1074 if (rl78_far_p (op))
1075 fprintf(file, "es:");
1076 if (letter == 'H')
1078 op = adjust_address (op, HImode, 2);
1079 letter = 0;
1081 if (letter == 'h')
1083 op = adjust_address (op, HImode, 0);
1084 letter = 0;
1086 if (letter == 'Q')
1088 op = adjust_address (op, QImode, 1);
1089 letter = 0;
1091 if (letter == 'q')
1093 op = adjust_address (op, QImode, 0);
1094 letter = 0;
1096 if (letter == 'e')
1098 op = adjust_address (op, QImode, 2);
1099 letter = 0;
1101 if (CONSTANT_P (XEXP (op, 0)))
1103 fprintf(file, "!");
1104 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1106 else if (GET_CODE (XEXP (op, 0)) == PLUS
1107 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF)
1109 fprintf(file, "!");
1110 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1112 else if (GET_CODE (XEXP (op, 0)) == PLUS
1113 && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
1114 && REGNO (XEXP (XEXP (op, 0), 0)) == 2)
1116 rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 1), 'u');
1117 fprintf(file, "[");
1118 rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 0), 0);
1119 fprintf(file, "]");
1121 else
1123 fprintf(file, "[");
1124 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1125 fprintf(file, "]");
1128 break;
1130 case REG:
1131 if (letter == 'Q')
1132 fprintf (file, "%s", reg_names [REGNO (op) | 1]);
1133 else if (letter == 'H')
1134 fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1135 else if (letter == 'q')
1136 fprintf (file, "%s", reg_names [REGNO (op) & ~1]);
1137 else if (letter == 'e')
1138 fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1139 else if (letter == 'S')
1140 fprintf (file, "0x%x", 0xffef8 + REGNO (op));
1141 else if (GET_MODE (op) == HImode
1142 && ! (REGNO (op) & ~0xfe))
1144 if (letter == 'v')
1145 fprintf (file, "%s", word_regnames [REGNO (op) % 8]);
1146 else
1147 fprintf (file, "%s", word_regnames [REGNO (op)]);
1149 else
1150 fprintf (file, "%s", reg_names [REGNO (op)]);
1151 break;
1153 case CONST_INT:
1154 if (letter == 'Q')
1155 fprintf (file, "%ld", INTVAL (op) >> 8);
1156 else if (letter == 'H')
1157 fprintf (file, "%ld", INTVAL (op) >> 16);
1158 else if (letter == 'q')
1159 fprintf (file, "%ld", INTVAL (op) & 0xff);
1160 else if (letter == 'h')
1161 fprintf (file, "%ld", INTVAL (op) & 0xffff);
1162 else if (letter == 'e')
1163 fprintf (file, "%ld", (INTVAL (op) >> 16) & 0xff);
1164 else if (letter == 'm')
1165 fprintf (file, "%ld", - INTVAL (op));
1166 else
1167 fprintf(file, "%ld", INTVAL (op));
1168 break;
1170 case CONST:
1171 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1172 break;
1174 case ZERO_EXTRACT:
1176 int bits = INTVAL (XEXP (op, 1));
1177 int ofs = INTVAL (XEXP (op, 2));
1178 if (bits == 16 && ofs == 0)
1179 fprintf (file, "%%lo16(");
1180 else if (bits == 16 && ofs == 16)
1181 fprintf (file, "%%hi16(");
1182 else if (bits == 8 && ofs == 16)
1183 fprintf (file, "%%hi8(");
1184 else
1185 gcc_unreachable ();
1186 rl78_print_operand_1 (file, XEXP (op, 0), 0);
1187 fprintf (file, ")");
1189 break;
1191 case ZERO_EXTEND:
1192 if (GET_CODE (XEXP (op, 0)) == REG)
1193 fprintf (file, "%s", reg_names [REGNO (XEXP (op, 0))]);
1194 else
1195 print_rtl (file, op);
1196 break;
1198 case PLUS:
1199 need_paren = 0;
1200 if (letter == 'H')
1202 fprintf (file, "%%hi16(");
1203 need_paren = 1;
1204 letter = 0;
1206 if (letter == 'h')
1208 fprintf (file, "%%lo16(");
1209 need_paren = 1;
1210 letter = 0;
1212 if (letter == 'e')
1214 fprintf (file, "%%hi8(");
1215 need_paren = 1;
1216 letter = 0;
1218 if (letter == 'q' || letter == 'Q')
1219 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1221 if (GET_CODE (XEXP (op, 0)) == ZERO_EXTEND)
1223 rl78_print_operand_1 (file, XEXP (op, 1), letter);
1224 fprintf (file, "+");
1225 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1227 else
1229 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1230 fprintf (file, "+");
1231 rl78_print_operand_1 (file, XEXP (op, 1), letter);
1233 if (need_paren)
1234 fprintf (file, ")");
1235 break;
1237 case SYMBOL_REF:
1238 need_paren = 0;
1239 if (letter == 'H')
1241 fprintf (file, "%%hi16(");
1242 need_paren = 1;
1243 letter = 0;
1245 if (letter == 'h')
1247 fprintf (file, "%%lo16(");
1248 need_paren = 1;
1249 letter = 0;
1251 if (letter == 'e')
1253 fprintf (file, "%%hi8(");
1254 need_paren = 1;
1255 letter = 0;
1257 if (letter == 'q' || letter == 'Q')
1258 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1260 output_addr_const (file, op);
1261 if (need_paren)
1262 fprintf (file, ")");
1263 break;
1265 case CODE_LABEL:
1266 case LABEL_REF:
1267 output_asm_label (op);
1268 break;
1270 case LTU:
1271 fprintf (file, letter == 'c' ? "nc" : "c");
1272 break;
1273 case LEU:
1274 fprintf (file, letter == 'c' ? "h" : "nh");
1275 break;
1276 case GEU:
1277 fprintf (file, letter == 'c' ? "c" : "nc");
1278 break;
1279 case GTU:
1280 fprintf (file, letter == 'c' ? "nh" : "h");
1281 break;
1282 case EQ:
1283 fprintf (file, letter == 'c' ? "nz" : "z");
1284 break;
1285 case NE:
1286 fprintf (file, letter == 'c' ? "z" : "nz");
1287 break;
1289 default:
1290 fprintf (file, "(%s)", GET_RTX_NAME (GET_CODE (op)));
1291 break;
1295 #undef TARGET_PRINT_OPERAND
1296 #define TARGET_PRINT_OPERAND rl78_print_operand
1298 static void
1299 rl78_print_operand (FILE * file, rtx op, int letter)
1301 if (CONSTANT_P (op) && letter != 'u')
1302 fprintf (file, "#");
1303 rl78_print_operand_1 (file, op, letter);
1306 #undef TARGET_TRAMPOLINE_INIT
1307 #define TARGET_TRAMPOLINE_INIT rl78_trampoline_init
1309 /* Note that the RL78's addressing makes it very difficult to do
1310 trampolines on the stack. So, libgcc has a small pool of
1311 trampolines from which one is allocated to this task. */
1312 static void
1313 rl78_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
1315 rtx mov_addr, thunk_addr;
1316 rtx function = XEXP (DECL_RTL (fndecl), 0);
1318 mov_addr = adjust_address (m_tramp, HImode, 0);
1319 thunk_addr = gen_reg_rtx (HImode);
1321 function = force_reg (HImode, function);
1322 static_chain = force_reg (HImode, static_chain);
1324 emit_insn (gen_trampoline_init (thunk_addr, function, static_chain));
1325 emit_move_insn (mov_addr, thunk_addr);
1327 cfun->machine->trampolines_used = 1;
1330 #undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
1331 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS rl78_trampoline_adjust_address
1333 static rtx
1334 rl78_trampoline_adjust_address (rtx m_tramp)
1336 rtx x = gen_rtx_MEM (HImode, m_tramp);
1337 return x;
1340 /* Expander for cbranchqi4 and cbranchhi4. RL78 is missing some of
1341 the "normal" compares, specifically, it only has unsigned compares,
1342 so we must synthesize the missing ones. */
1343 void
1344 rl78_expand_compare (rtx *operands)
1346 /* RL78 does not have signed comparisons. We must modify the
1347 operands to be in the unsigned range, and emit an unsigned
1348 comparison. */
1350 enum machine_mode mode;
1351 rtx high_bit;
1352 int i;
1353 RTX_CODE new_cond;
1355 switch (GET_CODE (operands[0]))
1357 case GE:
1358 new_cond = GEU;
1359 break;
1360 case LE:
1361 new_cond = LEU;
1362 break;
1363 case GT:
1364 new_cond = GTU;
1365 break;
1366 case LT:
1367 new_cond = LTU;
1368 break;
1369 default:
1370 return;
1373 #if DEBUG0
1374 fprintf (stderr, "\033[38;5;129mrl78_expand_compare\n");
1375 debug_rtx (operands[0]);
1376 fprintf (stderr, "\033[0m");
1377 #endif
1379 mode = GET_MODE (operands[1]);
1380 if (mode == VOIDmode)
1381 mode = GET_MODE (operands[2]);
1382 high_bit = GEN_INT (~0 << (GET_MODE_BITSIZE (mode) - 1));
1384 /* 0: conditional 1,2: operands */
1385 for (i = 1; i <= 2; i ++)
1387 rtx r = operands[i];
1389 if (GET_CODE (r) == CONST_INT)
1390 r = GEN_INT (INTVAL (r) ^ INTVAL (high_bit));
1391 else
1393 r = gen_rtx_PLUS (mode, operands[i], high_bit);
1394 r = copy_to_mode_reg (mode, r);
1396 operands[i] = r;
1399 operands[0] = gen_rtx_fmt_ee (new_cond, GET_MODE (operands[0]), operands[1], operands[2]);
1401 #if DEBUG0
1402 fprintf (stderr, "\033[38;5;142mrl78_expand_compare\n");
1403 debug_rtx (operands[0]);
1404 fprintf (stderr, "\033[0m");
1405 #endif
1410 /* Define this to 1 if you are debugging the peephole optimizers. */
1411 #define DEBUG_PEEP 0
1413 /* Predicate used to enable the peephole2 patterns in rl78-virt.md.
1414 The default "word" size is a byte so we can effectively use all the
1415 registers, but we want to do 16-bit moves whenever possible. This
1416 function determines when such a move is an option. */
1417 bool
1418 rl78_peep_movhi_p (rtx *operands)
1420 int i;
1421 rtx m, a;
1423 /* (set (op0) (op1))
1424 (set (op2) (op3)) */
1426 #if DEBUG_PEEP
1427 fprintf (stderr, "\033[33m");
1428 debug_rtx(operands[0]);
1429 debug_rtx(operands[1]);
1430 debug_rtx(operands[2]);
1431 debug_rtx(operands[3]);
1432 fprintf (stderr, "\033[0m");
1433 #endif
1435 if (rtx_equal_p (operands[0], operands[3]))
1437 #if DEBUG_PEEP
1438 fprintf (stderr, "no peep: overlapping\n");
1439 #endif
1440 return false;
1443 for (i = 0; i < 2; i ++)
1445 if (GET_CODE (operands[i]) != GET_CODE (operands[i+2]))
1447 #if DEBUG_PEEP
1448 fprintf (stderr, "no peep: different codes\n");
1449 #endif
1450 return false;
1452 if (GET_MODE (operands[i]) != GET_MODE (operands[i+2]))
1454 #if DEBUG_PEEP
1455 fprintf (stderr, "no peep: different modes\n");
1456 #endif
1457 return false;
1460 switch (GET_CODE (operands[i]))
1462 case REG:
1463 /* LSB MSB */
1464 if (REGNO (operands[i]) + 1 != REGNO (operands[i+2])
1465 || GET_MODE (operands[i]) != QImode)
1467 #if DEBUG_PEEP
1468 fprintf (stderr, "no peep: wrong regnos %d %d %d\n",
1469 REGNO (operands[i]), REGNO (operands[i+2]),
1471 #endif
1472 return false;
1474 if (! rl78_hard_regno_mode_ok (REGNO (operands[i]), HImode))
1476 #if DEBUG_PEEP
1477 fprintf (stderr, "no peep: reg %d not HI\n", REGNO (operands[i]));
1478 #endif
1479 return false;
1481 break;
1483 case CONST_INT:
1484 break;
1486 case MEM:
1487 if (GET_MODE (operands[i]) != QImode)
1488 return false;
1489 if (MEM_ALIGN (operands[i]) < 16)
1490 return false;
1491 a = XEXP (operands[i], 0);
1492 if (GET_CODE (a) == CONST)
1493 a = XEXP (a, 0);
1494 if (GET_CODE (a) == PLUS)
1495 a = XEXP (a, 1);
1496 if (GET_CODE (a) == CONST_INT
1497 && INTVAL (a) & 1)
1499 #if DEBUG_PEEP
1500 fprintf (stderr, "no peep: misaligned mem %d\n", i);
1501 debug_rtx (operands[i]);
1502 #endif
1503 return false;
1505 m = adjust_address (operands[i], QImode, 1);
1506 if (! rtx_equal_p (m, operands[i+2]))
1508 #if DEBUG_PEEP
1509 fprintf (stderr, "no peep: wrong mem %d\n", i);
1510 debug_rtx(m);
1511 debug_rtx (operands[i+2]);
1512 #endif
1513 return false;
1515 break;
1517 default:
1518 #if DEBUG_PEEP
1519 fprintf (stderr, "no peep: wrong rtx %d\n", i);
1520 #endif
1521 return false;
1524 #if DEBUG_PEEP
1525 fprintf (stderr, "\033[32mpeep!\033[0m\n");
1526 #endif
1527 return true;
1530 /* Likewise, when a peephole is activated, this function helps compute
1531 the new operands. */
1532 void
1533 rl78_setup_peep_movhi (rtx *operands)
1535 int i;
1537 for (i = 0; i < 2; i ++)
1539 switch (GET_CODE (operands[i]))
1541 case REG:
1542 operands[i+4] = gen_rtx_REG (HImode, REGNO (operands[i]));
1543 break;
1545 case CONST_INT:
1546 operands[i+4] = GEN_INT ((INTVAL (operands[i]) & 0xff) + ((char)INTVAL (operands[i+2])) * 256);
1547 break;
1549 case MEM:
1550 operands[i+4] = adjust_address (operands[i], HImode, 0);
1551 break;
1553 default:
1554 break;
1560 How Devirtualization works in the RL78 GCC port
1562 Background
1564 The RL78 is an 8-bit port with some 16-bit operations. It has 32
1565 bytes of register space, in four banks, memory-mapped. One bank is
1566 the "selected" bank and holds the registers used for primary
1567 operations. Since the registers are memory mapped, often you can
1568 still refer to the unselected banks via memory accesses.
1570 Virtual Registers
1572 The GCC port uses bank 0 as the "selected" registers (A, X, BC, etc)
1573 and refers to the other banks via their memory addresses, although
1574 they're treated as regular registers internally. These "virtual"
1575 registers are R8 through R23 (bank3 is reserved for asm-based
1576 interrupt handlers).
1578 There are four machine description files:
1580 rl78.md - common register-independent patterns and definitions
1581 rl78-expand.md - expanders
1582 rl78-virt.md - patterns that match BEFORE devirtualization
1583 rl78-real.md - patterns that match AFTER devirtualization
1585 At least through register allocation and reload, gcc is told that it
1586 can do pretty much anything - but may only use the virtual registers.
1587 GCC cannot properly create the varying addressing modes that the RL78
1588 supports in an efficient way.
1590 Sometime after reload, the RL78 backend "devirtualizes" the RTL. It
1591 uses the "valloc" attribute in rl78-virt.md for determining the rules
1592 by which it will replace virtual registers with real registers (or
1593 not) and how to make up addressing modes. For example, insns tagged
1594 with "ro1" have a single read-only parameter, which may need to be
1595 moved from memory/constant/vreg to a suitable real register. As part
1596 of devirtualization, a flag is toggled, disabling the rl78-virt.md
1597 patterns and enabling the rl78-real.md patterns. The new patterns'
1598 constraints are used to determine the real registers used. NOTE:
1599 patterns in rl78-virt.md essentially ignore the constrains and rely on
1600 predicates, where the rl78-real.md ones essentially ignore the
1601 predicates and rely on the constraints.
1603 The devirtualization pass is scheduled via the pass manager (despite
1604 being called "rl78_reorg") so it can be scheduled prior to var-track
1605 (the idea is to let gdb know about the new registers). Ideally, it
1606 would be scheduled right after pro/epilogue generation, so the
1607 post-reload optimizers could operate on the real registers, but when I
1608 tried that there were some issues building the target libraries.
1610 During devirtualization, a simple register move optimizer is run. It
1611 would be better to run a full CSE/propogation pass on it through, or
1612 re-run regmove, but that has not yet been attempted.
1615 #define DEBUG_ALLOC 0
1617 /* Rescans an insn to see if it's recognized again. This is done
1618 carefully to ensure that all the constraint information is accurate
1619 for the newly matched insn. */
1620 static bool
1621 insn_ok_now (rtx insn)
1623 INSN_CODE (insn) = -1;
1624 if (recog (PATTERN (insn), insn, 0) > -1)
1626 extract_insn (insn);
1627 if (constrain_operands (1))
1629 #if DEBUG_ALLOC
1630 fprintf (stderr, "\033[32m");
1631 debug_rtx (insn);
1632 fprintf (stderr, "\033[0m");
1633 #endif
1634 return true;
1637 else
1639 fprintf (stderr, "\033[41;30m Unrecognized insn \033[0m\n");
1640 debug_rtx (insn);
1641 gcc_unreachable ();
1643 #if DEBUG_ALLOC
1644 fprintf (stderr, "\033[31m");
1645 debug_rtx (insn);
1646 fprintf (stderr, "\033[0m");
1647 #endif
1648 return false;
1651 #if DEBUG_ALLOC
1652 #define WORKED fprintf (stderr, "\033[48;5;22m Worked at line %d \033[0m\n", __LINE__)
1653 #define FAILEDSOFAR fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__)
1654 #define FAILED fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__), gcc_unreachable()
1655 #define MAYBE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } else { FAILEDSOFAR; }
1656 #else
1657 #define WORKED
1658 #define FAILEDSOFAR
1659 #define FAILED gcc_unreachable ()
1660 #define MAYBE_OK(insn) if (insn_ok_now (insn)) return;
1661 #endif
1663 /* Registers into which we move the contents of virtual registers. */
1664 #define X gen_rtx_REG (QImode, 0)
1665 #define A gen_rtx_REG (QImode, 1)
1666 #define C gen_rtx_REG (QImode, 2)
1667 #define B gen_rtx_REG (QImode, 3)
1668 #define E gen_rtx_REG (QImode, 4)
1669 #define D gen_rtx_REG (QImode, 5)
1670 #define L gen_rtx_REG (QImode, 6)
1671 #define H gen_rtx_REG (QImode, 7)
1673 #define AX gen_rtx_REG (HImode, 0)
1674 #define BC gen_rtx_REG (HImode, 2)
1675 #define DE gen_rtx_REG (HImode, 4)
1676 #define HL gen_rtx_REG (HImode, 6)
1678 #define OP(x) (*recog_data.operand_loc[x])
1680 /* Returns TRUE if R is a virtual register. */
1681 static bool
1682 is_virtual_register (rtx r)
1684 return (GET_CODE (r) == REG
1685 && REGNO (r) >= 8
1686 && REGNO (r) < 24);
1689 /* In all these alloc routines, we expect the following: the insn
1690 pattern is unshared, the insn was previously recognized and failed
1691 due to predicates or constraints, and the operand data is in
1692 recog_data. */
1694 static int virt_insn_was_frame;
1696 /* Hook for all insns we emit. Re-mark them as FRAME_RELATED if
1697 needed. */
1698 static rtx
1699 EM2 (int line ATTRIBUTE_UNUSED, rtx r)
1701 #if DEBUG_ALLOC
1702 fprintf (stderr, "\033[36m%d: ", line);
1703 debug_rtx(r);
1704 fprintf (stderr, "\033[0m");
1705 #endif
1706 /*SCHED_GROUP_P (r) = 1;*/
1707 if (virt_insn_was_frame)
1708 RTX_FRAME_RELATED_P (r) = 1;
1709 return r;
1712 #define EM(x) EM2 (__LINE__, x)
1714 /* Return a suitable RTX for the low half of a __far address. */
1715 static rtx
1716 rl78_lo16 (rtx addr)
1718 if (GET_CODE (addr) == SYMBOL_REF
1719 || GET_CODE (addr) == CONST)
1721 rtx r = gen_rtx_ZERO_EXTRACT (HImode, addr, GEN_INT (16), GEN_INT (0));
1722 r = gen_rtx_CONST (HImode, r);
1723 return r;
1725 return rl78_subreg (HImode, addr, SImode, 0);
1728 /* Return a suitable RTX for the high half's lower byte of a __far address. */
1729 static rtx
1730 rl78_hi8 (rtx addr)
1732 if (GET_CODE (addr) == SYMBOL_REF
1733 || GET_CODE (addr) == CONST)
1735 rtx r = gen_rtx_ZERO_EXTRACT (QImode, addr, GEN_INT (8), GEN_INT (16));
1736 r = gen_rtx_CONST (QImode, r);
1737 return r;
1739 return rl78_subreg (QImode, addr, SImode, 2);
1742 /* Copy any register values into real registers and return an RTX for
1743 the same memory, now addressed by real registers. Any needed insns
1744 are emitted before BEFORE. */
1745 static rtx
1746 transcode_memory_rtx (rtx m, rtx newbase, rtx before)
1748 rtx base, index, addendr;
1749 int addend = 0;
1751 if (GET_CODE (m) != MEM)
1752 return m;
1754 if (GET_MODE (XEXP (m, 0)) == SImode)
1756 rtx seg = rl78_hi8 (XEXP (m, 0));
1757 #if DEBUG_ALLOC
1758 fprintf (stderr, "setting ES:\n");
1759 debug_rtx(seg);
1760 #endif
1761 emit_insn_before (EM(gen_movqi (A, seg)), before);
1762 emit_insn_before (EM(gen_movqi_es (A)), before);
1763 m = change_address (m, GET_MODE (m), rl78_lo16 (XEXP (m, 0)));
1766 characterize_address (XEXP (m, 0), &base, &index, &addendr);
1767 gcc_assert (index == NULL_RTX);
1769 #if DEBUG_ALLOC
1770 fprintf (stderr, "\033[33m"); debug_rtx(m); fprintf (stderr, "\033[0m");
1771 debug_rtx (base);
1772 #endif
1773 if (base == NULL_RTX)
1774 return m;
1776 if (addendr && GET_CODE (addendr) == CONST_INT)
1777 addend = INTVAL (addendr);
1779 if (REGNO (base) == SP_REG)
1781 if (addend >= 0 && addend <= 255)
1782 return m;
1785 /* BASE should be a virtual register. We copy it to NEWBASE. If
1786 the addend is out of range for DE/HL, we use AX to compute the full
1787 address. */
1789 if (addend < 0
1790 || (addend > 255 && REGNO (newbase) != 2)
1791 || (addendr && GET_CODE (addendr) != CONST_INT))
1793 /* mov ax, vreg
1794 add ax, #imm
1795 mov hl, ax */
1796 EM (emit_insn_before (gen_movhi (AX, base), before));
1797 EM (emit_insn_before (gen_addhi3 (AX, AX, addendr), before));
1798 EM (emit_insn_before (gen_movhi (newbase, AX), before));
1799 base = newbase;
1800 addend = 0;
1802 else
1804 EM (emit_insn_before (gen_movhi (newbase, base), before));
1805 base = newbase;
1808 if (addend)
1809 base = gen_rtx_PLUS (HImode, base, GEN_INT (addend));
1811 #if DEBUG_ALLOC
1812 fprintf (stderr, "\033[33m");
1813 debug_rtx (m);
1814 #endif
1815 m = change_address (m, GET_MODE (m), base);
1816 #if DEBUG_ALLOC
1817 debug_rtx (m);
1818 fprintf (stderr, "\033[0m");
1819 #endif
1820 return m;
1823 /* Copy SRC to accumulator (A or AX), placing any generated insns
1824 before BEFORE. Returns accumulator RTX. */
1826 static rtx
1827 move_to_acc (int opno, rtx before)
1829 rtx src = OP(opno);
1830 enum machine_mode mode = GET_MODE (src);
1832 if (GET_CODE (src) == REG
1833 && REGNO (src) < 2)
1834 return src;
1836 if (mode == VOIDmode)
1837 mode = recog_data.operand_mode[opno];
1839 if (mode == QImode)
1841 EM (emit_insn_before (gen_movqi (A, src), before));
1842 return A;
1844 else
1846 EM (emit_insn_before (gen_movhi (AX, src), before));
1847 return AX;
1851 /* Copy accumulator (A or AX) to DEST, placing any generated insns
1852 after AFTER. Returns accumulator RTX. */
1854 static rtx
1855 move_from_acc (rtx dest, rtx after)
1857 enum machine_mode mode = GET_MODE (dest);
1859 if (REG_P (dest) && REGNO (dest) < 2)
1860 return dest;
1862 if (mode == QImode)
1864 EM (emit_insn_after (gen_movqi (dest, A), after));
1865 return A;
1867 else
1869 EM (emit_insn_after (gen_movhi (dest, AX), after));
1870 return AX;
1874 /* Copy accumulator (A or AX) to REGNO, placing any generated insns
1875 before BEFORE. Returns reg RTX. */
1877 static rtx
1878 move_acc_to_reg (rtx acc, int regno, rtx before)
1880 enum machine_mode mode = GET_MODE (acc);
1881 rtx reg;
1883 reg = gen_rtx_REG (mode, regno);
1885 if (mode == QImode)
1887 EM (emit_insn_before (gen_movqi (reg, A), before));
1888 return reg;
1890 else
1892 EM (emit_insn_before (gen_movhi (reg, AX), before));
1893 return reg;
1897 /* Copy SRC to X, placing any generated insns before BEFORE.
1898 Returns X RTX. */
1900 static rtx
1901 move_to_x (int opno, rtx before)
1903 rtx src = OP(opno);
1904 enum machine_mode mode = GET_MODE (src);
1905 rtx reg;
1907 if (mode == VOIDmode)
1908 mode = recog_data.operand_mode[opno];
1909 reg = (mode == QImode) ? X : AX;
1911 if (mode == QImode || ! is_virtual_register (OP (opno)))
1913 OP(opno) = move_to_acc (opno, before);
1914 OP(opno) = move_acc_to_reg (OP(opno), X_REG, before);
1915 return reg;
1918 if (mode == QImode)
1919 EM (emit_insn_before (gen_movqi (reg, src), before));
1920 else
1921 EM (emit_insn_before (gen_movhi (reg, src), before));
1923 return reg;
1926 /* Copy OP(opno) to H or HL, placing any generated insns before BEFORE.
1927 Returns H/HL RTX. */
1929 static rtx
1930 move_to_hl (int opno, rtx before)
1932 rtx src = OP (opno);
1933 enum machine_mode mode = GET_MODE (src);
1934 rtx reg;
1936 if (mode == VOIDmode)
1937 mode = recog_data.operand_mode[opno];
1938 reg = (mode == QImode) ? L : HL;
1940 if (mode == QImode || ! is_virtual_register (OP (opno)))
1942 OP (opno) = move_to_acc (opno, before);
1943 OP (opno) = move_acc_to_reg (OP (opno), L_REG, before);
1944 return reg;
1947 if (mode == QImode)
1948 EM (emit_insn_before (gen_movqi (reg, src), before));
1949 else
1950 EM (emit_insn_before (gen_movhi (reg, src), before));
1952 return reg;
1955 /* Copy OP(opno) to E or DE, placing any generated insns before BEFORE.
1956 Returns E/DE RTX. */
1958 static rtx
1959 move_to_de (int opno, rtx before)
1961 rtx src = OP (opno);
1962 enum machine_mode mode = GET_MODE (src);
1963 rtx reg;
1965 if (mode == VOIDmode)
1966 mode = recog_data.operand_mode[opno];
1968 reg = (mode == QImode) ? E : DE;
1970 if (mode == QImode || ! is_virtual_register (OP (opno)))
1972 OP (opno) = move_to_acc (opno, before);
1973 OP (opno) = move_acc_to_reg (OP (opno), E_REG, before);
1975 else
1977 rtx move = mode == QImode ? gen_movqi (reg, src) : gen_movhi (reg, src);
1979 EM (emit_insn_before (move, before));
1982 return reg;
1985 /* Devirtualize an insn of the form (SET (op) (unop (op))). */
1986 static void
1987 rl78_alloc_physical_registers_op1 (rtx insn)
1989 /* op[0] = func op[1] */
1991 /* We first try using A as the destination, then copying it
1992 back. */
1993 if (rtx_equal_p (OP(0), OP(1)))
1995 OP(0) =
1996 OP(1) = transcode_memory_rtx (OP(1), DE, insn);
1998 else
2000 OP(0) = transcode_memory_rtx (OP(0), BC, insn);
2001 OP(1) = transcode_memory_rtx (OP(1), HL, insn);
2004 MAYBE_OK (insn);
2006 OP(0) = move_from_acc (OP(0), insn);
2008 MAYBE_OK (insn);
2010 /* Try copying the src to acc first, then. This is for, for
2011 example, ZERO_EXTEND or NOT. */
2012 OP(1) = move_to_acc (1, insn);
2014 MAYBE_OK (insn);
2016 FAILED;
2019 /* Devirtualize an insn of the form (SET (op) (unop (op) (op))). */
2020 static void
2021 rl78_alloc_physical_registers_op2 (rtx insn)
2023 /* op[0] = op[1] func op[2] */
2024 rtx prev = prev_nonnote_nondebug_insn (insn);
2025 rtx first;
2026 bool hl_used;
2028 if (rtx_equal_p (OP(0), OP(1)))
2030 OP(0) =
2031 OP(1) = transcode_memory_rtx (OP(1), DE, insn);
2032 prev = next_nonnote_nondebug_insn (prev);
2033 OP(2) = transcode_memory_rtx (OP(2), HL, insn);
2034 prev = prev_nonnote_nondebug_insn (prev);
2036 else if (rtx_equal_p (OP(0), OP(2)))
2038 OP(1) = transcode_memory_rtx (OP(1), DE, insn);
2039 prev = next_nonnote_nondebug_insn (prev);
2040 OP(0) =
2041 OP(2) = transcode_memory_rtx (OP(2), HL, insn);
2042 prev = prev_nonnote_nondebug_insn (prev);
2044 else
2046 OP(0) = transcode_memory_rtx (OP(0), BC, insn);
2047 OP(1) = transcode_memory_rtx (OP(1), DE, insn);
2048 prev = next_nonnote_nondebug_insn (prev);
2049 OP(2) = transcode_memory_rtx (OP(2), HL, insn);
2052 MAYBE_OK (insn);
2054 prev = prev_nonnote_nondebug_insn (insn);
2055 if (recog_data.constraints[1][0] == '%'
2056 && is_virtual_register (OP (1))
2057 && ! is_virtual_register (OP (2))
2058 && ! CONSTANT_P (OP (2)))
2060 rtx tmp = OP (1);
2061 OP (1) = OP (2);
2062 OP (2) = tmp;
2065 /* Make a note of wether (H)L is being used. It matters
2066 because if OP(2) alsoneeds reloading, then we must take
2067 care not to corrupt HL. */
2068 hl_used = reg_mentioned_p (L, OP (0)) || reg_mentioned_p (L, OP (1));
2070 OP(0) = move_from_acc (OP (0), insn);
2071 OP(1) = move_to_acc (1, insn);
2073 MAYBE_OK (insn);
2075 /* We have to copy op2 to HL, but that involves AX, which
2076 already has a live value. Emit it before those insns. */
2078 if (prev)
2079 first = next_nonnote_nondebug_insn (prev);
2080 else
2081 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
2084 OP (2) = hl_used ? move_to_de (2, first) : move_to_hl (2, first);
2086 MAYBE_OK (insn);
2088 FAILED;
2091 /* Devirtualize an insn of the form (SET () (unop (op))). */
2093 static void
2094 rl78_alloc_physical_registers_ro1 (rtx insn)
2096 /* (void) op[0] */
2097 OP(0) = transcode_memory_rtx (OP(0), BC, insn);
2099 MAYBE_OK (insn);
2101 OP(0) = move_to_acc (0, insn);
2103 MAYBE_OK (insn);
2105 FAILED;
2108 /* Devirtualize a compare insn. */
2109 static void
2110 rl78_alloc_physical_registers_cmp (rtx insn)
2112 /* op[1] cmp_op[0] op[2] */
2113 rtx prev = prev_nonnote_nondebug_insn (insn);
2114 rtx first;
2116 OP(1) = transcode_memory_rtx (OP(1), DE, insn);
2117 OP(2) = transcode_memory_rtx (OP(2), HL, insn);
2119 MAYBE_OK (insn);
2121 OP(1) = move_to_acc (1, insn);
2123 MAYBE_OK (insn);
2125 /* We have to copy op2 to HL, but that involves the acc, which
2126 already has a live value. Emit it before those insns. */
2128 if (prev)
2129 first = next_nonnote_nondebug_insn (prev);
2130 else
2131 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
2133 OP(2) = move_to_hl (2, first);
2135 MAYBE_OK (insn);
2137 FAILED;
2140 /* Like op2, but AX = A op X. */
2141 static void
2142 rl78_alloc_physical_registers_umul (rtx insn)
2144 /* op[0] = op[1] func op[2] */
2145 rtx prev = prev_nonnote_nondebug_insn (insn);
2146 rtx first;
2148 OP(0) = transcode_memory_rtx (OP(0), BC, insn);
2149 OP(1) = transcode_memory_rtx (OP(1), DE, insn);
2150 OP(2) = transcode_memory_rtx (OP(2), HL, insn);
2152 MAYBE_OK (insn);
2154 if (recog_data.constraints[1][0] == '%'
2155 && is_virtual_register (OP(1))
2156 && !is_virtual_register (OP(2))
2157 && !CONSTANT_P (OP(2)))
2159 rtx tmp = OP(1);
2160 OP(1) = OP(2);
2161 OP(2) = tmp;
2164 OP(0) = move_from_acc (OP(0), insn);
2165 OP(1) = move_to_acc (1, insn);
2167 MAYBE_OK (insn);
2169 /* We have to copy op2 to X, but that involves the acc, which
2170 already has a live value. Emit it before those insns. */
2172 if (prev)
2173 first = next_nonnote_nondebug_insn (prev);
2174 else
2175 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
2177 OP(2) = move_to_x (2, first);
2179 MAYBE_OK (insn);
2181 FAILED;
2184 /* Scan all insns and devirtualize them. */
2185 static void
2186 rl78_alloc_physical_registers (void)
2188 /* During most of the compile, gcc is dealing with virtual
2189 registers. At this point, we need to assign physical registers
2190 to the vitual ones, and copy in/out as needed. */
2192 rtx insn, curr;
2193 enum attr_valloc valloc_method;
2195 for (insn = get_insns (); insn; insn = curr)
2197 int i;
2199 curr = next_nonnote_nondebug_insn (insn);
2201 if (INSN_P (insn)
2202 && (GET_CODE (PATTERN (insn)) == SET
2203 || GET_CODE (PATTERN (insn)) == CALL)
2204 && INSN_CODE (insn) == -1)
2206 if (GET_CODE (SET_SRC (PATTERN (insn))) == ASM_OPERANDS)
2207 continue;
2208 i = recog (PATTERN (insn), insn, 0);
2209 if (i == -1)
2211 debug_rtx (insn);
2212 gcc_unreachable ();
2214 INSN_CODE (insn) = i;
2218 cfun->machine->virt_insns_ok = 0;
2219 cfun->machine->real_insns_ok = 1;
2221 for (insn = get_insns (); insn; insn = curr)
2223 curr = insn ? next_nonnote_nondebug_insn (insn) : NULL;
2225 if (!INSN_P (insn))
2226 continue;
2227 if (GET_CODE (PATTERN (insn)) != SET
2228 && GET_CODE (PATTERN (insn)) != CALL)
2229 continue;
2231 if (GET_CODE (PATTERN (insn)) == SET
2232 && GET_CODE (SET_SRC (PATTERN (insn))) == ASM_OPERANDS)
2233 continue;
2235 valloc_method = get_attr_valloc (insn);
2237 PATTERN (insn)= copy_rtx_if_shared (PATTERN (insn));
2239 if (insn_ok_now (insn))
2240 continue;
2242 INSN_CODE (insn) = -1;
2244 if (RTX_FRAME_RELATED_P (insn))
2245 virt_insn_was_frame = 1;
2246 else
2247 virt_insn_was_frame = 0;
2249 switch (valloc_method)
2251 case VALLOC_OP1:
2252 rl78_alloc_physical_registers_op1 (insn);
2253 break;
2254 case VALLOC_OP2:
2255 rl78_alloc_physical_registers_op2 (insn);
2256 break;
2257 case VALLOC_RO1:
2258 rl78_alloc_physical_registers_ro1 (insn);
2259 break;
2260 case VALLOC_CMP:
2261 rl78_alloc_physical_registers_cmp (insn);
2262 break;
2263 case VALLOC_UMUL:
2264 rl78_alloc_physical_registers_umul (insn);
2265 break;
2266 case VALLOC_MACAX:
2267 /* Macro that clobbers AX */
2268 break;
2271 #if DEBUG_ALLOC
2272 fprintf (stderr, "\033[0m");
2273 #endif
2276 /* Add REG_DEAD notes using DEAD[reg] for rtx S which is part of INSN.
2277 This function scans for uses of registers; the last use (i.e. first
2278 encounter when scanning backwards) triggers a REG_DEAD note if the
2279 reg was previously in DEAD[]. */
2280 static void
2281 rl78_note_reg_uses (char *dead, rtx s, rtx insn)
2283 const char *fmt;
2284 int i, r;
2285 enum rtx_code code;
2287 if (!s)
2288 return;
2290 code = GET_CODE (s);
2292 switch (code)
2294 /* Compare registers by number. */
2295 case REG:
2296 r = REGNO (s);
2297 if (dump_file)
2299 fprintf (dump_file, "note use reg %d size %d on insn %d\n",
2300 r, GET_MODE_SIZE (GET_MODE (s)), INSN_UID (insn));
2301 print_rtl_single (dump_file, s);
2303 if (dead [r])
2304 add_reg_note (insn, REG_DEAD, gen_rtx_REG (GET_MODE (s), r));
2305 for (i = 0; i < GET_MODE_SIZE (GET_MODE (s)); i ++)
2306 dead [r + i] = 0;
2307 return;
2309 /* These codes have no constituent expressions
2310 and are unique. */
2311 case SCRATCH:
2312 case CC0:
2313 case PC:
2314 return;
2316 case CONST_INT:
2317 case CONST_VECTOR:
2318 case CONST_DOUBLE:
2319 case CONST_FIXED:
2320 /* These are kept unique for a given value. */
2321 return;
2323 default:
2324 break;
2327 fmt = GET_RTX_FORMAT (code);
2329 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
2331 if (fmt[i] == 'E')
2333 int j;
2334 for (j = XVECLEN (s, i) - 1; j >= 0; j--)
2335 rl78_note_reg_uses (dead, XVECEXP (s, i, j), insn);
2337 else if (fmt[i] == 'e')
2338 rl78_note_reg_uses (dead, XEXP (s, i), insn);
2342 /* Like the previous function, but scan for SETs instead. */
2343 static void
2344 rl78_note_reg_set (char *dead, rtx d, rtx insn)
2346 int r, i;
2348 if (GET_CODE (d) != REG)
2349 return;
2351 r = REGNO (d);
2352 if (dead [r])
2353 add_reg_note (insn, REG_UNUSED, gen_rtx_REG (GET_MODE (d), r));
2354 if (dump_file)
2355 fprintf (dump_file, "note set reg %d size %d\n", r, GET_MODE_SIZE (GET_MODE (d)));
2356 for (i = 0; i < GET_MODE_SIZE (GET_MODE (d)); i ++)
2357 dead [r + i] = 1;
2360 /* This is a rather crude register death pass. Death status is reset
2361 at every jump or call insn. */
2362 static void
2363 rl78_calculate_death_notes (void)
2365 char dead[FIRST_PSEUDO_REGISTER];
2366 rtx insn, p, s, d;
2367 int i;
2369 memset (dead, 0, sizeof (dead));
2371 for (insn = get_last_insn ();
2372 insn;
2373 insn = prev_nonnote_nondebug_insn (insn))
2375 if (dump_file)
2377 fprintf (dump_file, "\n--------------------------------------------------");
2378 fprintf (dump_file, "\nDead:");
2379 for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
2380 if (dead[i])
2381 fprintf(dump_file, " %s", reg_names[i]);
2382 fprintf (dump_file, "\n");
2383 print_rtl_single (dump_file, insn);
2386 switch (GET_CODE (insn))
2388 case INSN:
2389 p = PATTERN (insn);
2390 switch (GET_CODE (p))
2392 case SET:
2393 s = SET_SRC (p);
2394 d = SET_DEST (p);
2395 rl78_note_reg_set (dead, d, insn);
2396 rl78_note_reg_uses (dead, s, insn);
2397 break;
2399 case USE:
2400 rl78_note_reg_uses (dead, p, insn);
2401 break;
2403 default:
2404 break;
2406 break;
2408 case JUMP_INSN:
2409 if (INSN_CODE (insn) == CODE_FOR_rl78_return)
2411 memset (dead, 1, sizeof (dead));
2412 /* We expect a USE just prior to this, which will mark
2413 the actual return registers. The USE will have a
2414 death note, but we aren't going to be modifying it
2415 after this pass. */
2416 break;
2418 case CALL_INSN:
2419 memset (dead, 0, sizeof (dead));
2420 break;
2422 default:
2423 break;
2425 if (dump_file)
2426 print_rtl_single (dump_file, insn);
2430 /* Helper function to reset the origins in RP and the age in AGE for
2431 all registers. */
2432 static void
2433 reset_origins (int *rp, int *age)
2435 int i;
2436 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2438 rp[i] = i;
2439 age[i] = 0;
2443 /* The idea behind this optimization is to look for cases where we
2444 move data from A to B to C, and instead move from A to B, and A to
2445 C. If B is a virtual register or memory, this is a big win on its
2446 own. If B turns out to be unneeded after this, it's a bigger win.
2447 For each register, we try to determine where it's value originally
2448 came from, if it's propogated purely through moves (and not
2449 computes). The ORIGINS[] array has the regno for the "origin" of
2450 the value in the [regno] it's indexed by. */
2451 static void
2452 rl78_propogate_register_origins (void)
2454 int origins[FIRST_PSEUDO_REGISTER];
2455 int age[FIRST_PSEUDO_REGISTER];
2456 int i;
2457 rtx insn, ninsn = NULL_RTX;
2458 rtx pat;
2460 reset_origins (origins, age);
2462 for (insn = get_insns (); insn; insn = ninsn)
2464 ninsn = next_nonnote_nondebug_insn (insn);
2466 if (dump_file)
2468 fprintf (dump_file, "\n");
2469 fprintf (dump_file, "Origins:");
2470 for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
2471 if (origins[i] != i)
2472 fprintf (dump_file, " r%d=r%d", i, origins[i]);
2473 fprintf (dump_file, "\n");
2474 print_rtl_single (dump_file, insn);
2477 switch (GET_CODE (insn))
2479 case CODE_LABEL:
2480 case BARRIER:
2481 case CALL_INSN:
2482 case JUMP_INSN:
2483 reset_origins (origins, age);
2484 break;
2486 default:
2487 break;
2489 case INSN:
2490 pat = PATTERN (insn);
2492 if (GET_CODE (pat) == PARALLEL)
2494 rtx clobber = XVECEXP (pat, 0, 1);
2495 pat = XVECEXP (pat, 0, 0);
2496 if (GET_CODE (clobber) == CLOBBER)
2498 int cr = REGNO (XEXP (clobber, 0));
2499 int mb = GET_MODE_SIZE (GET_MODE (XEXP (clobber, 0)));
2500 if (dump_file)
2501 fprintf (dump_file, "reset origins of %d regs at %d\n", mb, cr);
2502 for (i = 0; i < mb; i++)
2504 origins[cr + i] = cr + i;
2505 age[cr + i] = 0;
2508 else
2509 break;
2512 if (GET_CODE (pat) == SET)
2514 rtx src = SET_SRC (pat);
2515 rtx dest = SET_DEST (pat);
2516 int mb = GET_MODE_SIZE (GET_MODE (dest));
2518 if (GET_CODE (dest) == REG)
2520 int dr = REGNO (dest);
2522 if (GET_CODE (src) == REG)
2524 int sr = REGNO (src);
2525 int same = 1;
2526 int best_age, best_reg;
2528 /* See if the copy is not needed. */
2529 for (i = 0; i < mb; i ++)
2530 if (origins[dr + i] != origins[sr + i])
2531 same = 0;
2532 if (same)
2534 if (dump_file)
2535 fprintf (dump_file, "deleting because dest already has correct value\n");
2536 delete_insn (insn);
2537 break;
2540 if (dr < 8 || sr >= 8)
2542 int ar;
2544 best_age = -1;
2545 best_reg = -1;
2546 /* See if the copy can be made from another
2547 bank 0 register instead, instead of the
2548 virtual src register. */
2549 for (ar = 0; ar < 8; ar += mb)
2551 same = 1;
2552 for (i = 0; i < mb; i ++)
2553 if (origins[ar + i] != origins[sr + i])
2554 same = 0;
2556 /* The chip has some reg-reg move limitations. */
2557 if (mb == 1 && dr > 3)
2558 same = 0;
2560 if (same)
2562 if (best_age == -1 || best_age > age[sr + i])
2564 best_age = age[sr + i];
2565 best_reg = sr;
2570 if (best_reg != -1)
2572 /* FIXME: copy debug info too. */
2573 SET_SRC (pat) = gen_rtx_REG (GET_MODE (src), best_reg);
2574 sr = best_reg;
2578 for (i = 0; i < mb; i++)
2580 origins[dr + i] = origins[sr + i];
2581 age[dr + i] = age[sr + i] + 1;
2584 else
2586 /* The destination is computed, its origin is itself. */
2587 if (dump_file)
2588 fprintf (dump_file, "resetting origin of r%d for %d byte%s\n",
2589 dr, mb, mb == 1 ? "" : "s");
2590 for (i = 0; i < mb; i ++)
2592 origins[dr + i] = dr + i;
2593 age[dr + i] = 0;
2597 /* Any registers marked with that reg as an origin are reset. */
2598 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2599 if (origins[i] >= dr && origins[i] < dr + mb)
2601 origins[i] = i;
2602 age[i] = 0;
2606 /* Special case - our ADDSI3 macro uses AX */
2607 if (get_attr_valloc (insn) == VALLOC_MACAX)
2609 if (dump_file)
2610 fprintf (dump_file, "Resetting origin of AX for macro.\n");
2611 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2612 if (i <= 1 || origins[i] <= 1)
2614 origins[i] = i;
2615 age[i] = 0;
2619 if (GET_CODE (src) == ASHIFT
2620 || GET_CODE (src) == ASHIFTRT
2621 || GET_CODE (src) == LSHIFTRT)
2623 rtx count = XEXP (src, 1);
2624 if (GET_CODE (count) == REG)
2626 /* Special case - our pattern clobbers the count register. */
2627 int r = REGNO (count);
2628 if (dump_file)
2629 fprintf (dump_file, "Resetting origin of r%d for shift.\n", r);
2630 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2631 if (i == r || origins[i] == r)
2633 origins[i] = i;
2634 age[i] = 0;
2643 /* Remove any SETs where the destination is unneeded. */
2644 static void
2645 rl78_remove_unused_sets (void)
2647 rtx insn, ninsn = NULL_RTX;
2648 rtx dest;
2650 for (insn = get_insns (); insn; insn = ninsn)
2652 ninsn = next_nonnote_nondebug_insn (insn);
2654 if ((insn = single_set (insn)) == NULL_RTX)
2655 continue;
2657 dest = SET_DEST (insn);
2659 if (GET_CODE (dest) != REG || REGNO (dest) > 23)
2660 continue;
2662 if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
2663 delete_insn (insn);
2667 #undef xTARGET_MACHINE_DEPENDENT_REORG
2668 #define xTARGET_MACHINE_DEPENDENT_REORG rl78_reorg
2670 /* This is the top of the devritualization pass. */
2671 static void
2672 rl78_reorg (void)
2674 rl78_alloc_physical_registers ();
2676 if (dump_file)
2678 fprintf (dump_file, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n");
2679 print_rtl_with_bb (dump_file, get_insns (), 0);
2682 rl78_propogate_register_origins ();
2683 rl78_calculate_death_notes ();
2685 if (dump_file)
2687 fprintf (dump_file, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n");
2688 print_rtl_with_bb (dump_file, get_insns (), 0);
2689 fprintf (dump_file, "\n======================================================================\n");
2692 rl78_remove_unused_sets ();
2694 /* The code after devirtualizing has changed so much that at this point
2695 we might as well just rescan everything. Note that
2696 df_rescan_all_insns is not going to help here because it does not
2697 touch the artificial uses and defs. */
2698 df_finish_pass (true);
2699 if (optimize > 1)
2700 df_live_add_problem ();
2701 df_scan_alloc (NULL);
2702 df_scan_blocks ();
2704 if (optimize)
2705 df_analyze ();
2708 #undef TARGET_RETURN_IN_MEMORY
2709 #define TARGET_RETURN_IN_MEMORY rl78_return_in_memory
2711 static bool
2712 rl78_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
2714 const HOST_WIDE_INT size = int_size_in_bytes (type);
2715 return (size == -1 || size > 8);
2719 struct gcc_target targetm = TARGET_INITIALIZER;
2721 #include "gt-rl78.h"