]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/rl78/rl78.c
gcc/
[thirdparty/gcc.git] / gcc / config / rl78 / rl78.c
CommitLineData
78e515f7 1/* Subroutines used for code generation on Renesas RL78 processors.
2 Copyright (C) 2011 Free Software Foundation, Inc.
3 Contributed by Red Hat.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
20
21#include "config.h"
22#include "system.h"
23#include "coretypes.h"
24#include "tm.h"
25#include "tree.h"
26#include "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 "tree-pass.h"
51\f
52static inline bool is_interrupt_func (const_tree decl);
53static inline bool is_brk_interrupt_func (const_tree decl);
54static void rl78_reorg (void);
55\f
56
57/* Debugging statements are tagged with DEBUG0 only so that they can
58 be easily enabled individually, by replacing the '0' with '1' as
59 needed. */
60#define DEBUG0 0
61#define DEBUG1 1
62
63/* REGISTER_NAMES has the names for individual 8-bit registers, but
64 these have the names we need to use when referring to 16-bit
65 register pairs. */
66static const char * const word_regnames[] =
67{
68 "ax", "AX", "bc", "BC", "de", "DE", "hl", "HL",
69 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
70 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
71 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
72 "sp", "ap", "psw", "es", "cs"
73};
74
75struct GTY(()) machine_function
76{
77 /* If set, the rest of the fields have been computed. */
78 int computed;
79 /* Which register pairs need to be pushed in the prologue. */
80 int need_to_push [FIRST_PSEUDO_REGISTER / 2];
81
82 /* These fields describe the frame layout... */
83 /* arg pointer */
84 /* 4 bytes for saved PC */
85 int framesize_regs;
86 /* frame pointer */
87 int framesize_locals;
88 int framesize_outgoing;
89 /* stack pointer */
90 int framesize;
91
92 /* If set, recog is allowed to match against the "real" patterns. */
93 int real_insns_ok;
94 /* If set, recog is allowed to match against the "virtual" patterns. */
95 int virt_insns_ok;
96 /* Set if the current function needs to clean up any trampolines. */
97 int trampolines_used;
98};
99
100/* This is our init_machine_status, as set in
101 rl78_option_override. */
102static struct machine_function *
103rl78_init_machine_status (void)
104{
105 struct machine_function *m;
106
107 m = ggc_alloc_cleared_machine_function ();
108 m->virt_insns_ok = 1;
109
110 return m;
111}
112
113/* Returns whether to run the devirtualization pass. */
114static bool
115devirt_gate (void)
116{
117 return true;
118}
119
120/* Runs the devirtualization pass. */
121static unsigned int
122devirt_pass (void)
123{
124 rl78_reorg ();
125 return 0;
126}
127
128/* This pass converts virtual instructions using virtual registers, to
129 real instructions using real registers. Rather than run it as
130 reorg, we reschedule it before vartrack to help with debugging. */
131static struct opt_pass rl78_devirt_pass =
132{
133 RTL_PASS,
134 "devirt",
135 devirt_gate,
136 devirt_pass,
137 NULL,
138 NULL,
139 212,
140 TV_MACH_DEP,
141 0, 0, 0,
142 0,
143 TODO_dump_func
144};
145
146static struct register_pass_info rl78_devirt_info =
147{
148 & rl78_devirt_pass,
149 "vartrack",
150 1,
151 PASS_POS_INSERT_BEFORE
152};
153
154#undef TARGET_ASM_FILE_START
155#define TARGET_ASM_FILE_START rl78_asm_file_start
156
157static void
158rl78_asm_file_start (void)
159{
160 int i;
161
162 for (i = 0; i < 8; i++)
163 {
164 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 8 + i, 0xffef0 + i);
165 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 16 + i, 0xffee8 + i);
166 }
167
168 register_pass (& rl78_devirt_info);
169}
170
171\f
172#undef TARGET_OPTION_OVERRIDE
173#define TARGET_OPTION_OVERRIDE rl78_option_override
174
175static void
176rl78_option_override (void)
177{
178 flag_omit_frame_pointer = 1;
179 flag_no_function_cse = 1;
180 flag_split_wide_types = 0;
181
182 init_machine_status = rl78_init_machine_status;
183}
184
185/* Most registers are 8 bits. Some are 16 bits because, for example,
186 gcc doesn't like dealing with $FP as a register pair. This table
187 maps register numbers to size in bytes. */
188static const int register_sizes[] =
189{
190 1, 1, 1, 1, 1, 1, 1, 1,
191 1, 1, 1, 1, 1, 1, 1, 1,
192 1, 1, 1, 1, 1, 1, 2, 1,
193 1, 1, 1, 1, 1, 1, 1, 1,
194 2, 2, 1, 1, 1
195};
196
197/* Predicates used in the MD patterns. This one is true when virtual
198 insns may be matched, which typically means before (or during) the
199 devirt pass. */
200bool
201rl78_virt_insns_ok (void)
202{
203 if (cfun)
204 return cfun->machine->virt_insns_ok;
205 return true;
206}
207
208/* Predicates used in the MD patterns. This one is true when real
209 insns may be matched, which typically means after (or during) the
210 devirt pass. */
211bool
212rl78_real_insns_ok (void)
213{
214 if (cfun)
215 return cfun->machine->real_insns_ok;
216 return false;
217}
218
219/* Implements HARD_REGNO_NREGS. */
220int
221rl78_hard_regno_nregs (int regno, enum machine_mode mode)
222{
223 int rs = register_sizes[regno];
224 if (rs < 1)
225 rs = 1;
226 return ((GET_MODE_SIZE (mode) + rs - 1) / rs);
227}
228
229/* Implements HARD_REGNO_MODE_OK. */
230int
231rl78_hard_regno_mode_ok (int regno, enum machine_mode mode)
232{
233 int s = GET_MODE_SIZE (mode);
234
235 if (s < 1)
236 return 0;
237 /* These are not to be used by gcc. */
238 if (regno == 23 || regno == ES_REG || regno == CS_REG)
239 return 0;
240 /* $fp can alway sbe accessed as a 16-bit value. */
241 if (regno == FP_REG && s == 2)
242 return 1;
243 if (regno < SP_REG)
244 {
245 /* Since a reg-reg move is really a reg-mem move, we must
246 enforce alignment. */
247 if (s > 1 && (regno % 2))
248 return 0;
249 return 1;
250 }
251 if (s == CC_REGNUM)
252 return (mode == BImode);
253 /* All other registers must be accessed in their natural sizes. */
254 if (s == register_sizes [regno])
255 return 1;
256 return 0;
257}
258
259/* Simplify_gen_subreg() doesn't handle memory references the way we
260 need it to below, so we use this function for when we must get a
261 valid subreg in a "natural" state. */
262static rtx
263rl78_subreg (enum machine_mode mode, rtx r, enum machine_mode omode, int byte)
264{
265 if (GET_CODE (r) == MEM)
266 return adjust_address (r, mode, byte);
267 else
268 return simplify_gen_subreg (mode, r, omode, byte);
269}
270
271/* Used by movsi. Split SImode moves into two HImode moves, using
272 appropriate patterns for the upper and lower halves of symbols. */
273void
274rl78_expand_movsi (rtx *operands)
275{
276 rtx op00, op02, op10, op12;
277
278 op00 = rl78_subreg (HImode, operands[0], SImode, 0);
279 op02 = rl78_subreg (HImode, operands[0], SImode, 2);
280 if (GET_CODE (operands[1]) == CONST
281 || GET_CODE (operands[1]) == SYMBOL_REF)
282 {
283 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
284 op10 = gen_rtx_CONST (HImode, op10);
285 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
286 op12 = gen_rtx_CONST (HImode, op12);
287 }
288 else
289 {
290 op10 = rl78_subreg (HImode, operands[1], SImode, 0);
291 op12 = rl78_subreg (HImode, operands[1], SImode, 2);
292 }
293
294 if (rtx_equal_p (operands[0], operands[1]))
295 ;
296 else if (rtx_equal_p (op00, op12))
297 {
298 emit_move_insn (op02, op12);
299 emit_move_insn (op00, op10);
300 }
301 else
302 {
303 emit_move_insn (op00, op10);
304 emit_move_insn (op02, op12);
305 }
306}
307
308/* Used by various two-operand expanders which cannot accept all
309 operands in the "far" namespace. Force some such operands into
310 registers so that each pattern has at most one far operand. */
311int
312rl78_force_nonfar_2 (rtx *operands, rtx (*gen)(rtx,rtx))
313{
314 int did = 0;
315 rtx temp_reg = NULL;
316
317 /* FIXME: in the future, be smarter about only doing this if the
318 other operand is also far, assuming the devirtualizer can also
319 handle that. */
320 if (rl78_far_p (operands[0]))
321 {
322 temp_reg = operands[0];
323 operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
324 did = 1;
325 }
326 if (!did)
327 return 0;
328
329 emit_insn (gen (operands[0], operands[1]));
330 if (temp_reg)
331 emit_move_insn (temp_reg, operands[0]);
332 return 1;
333}
334
335/* Likewise, but for three-operand expanders. */
336int
337rl78_force_nonfar_3 (rtx *operands, rtx (*gen)(rtx,rtx,rtx))
338{
339 int did = 0;
340 rtx temp_reg = NULL;
341
342 /* FIXME: Likewise. */
343 if (rl78_far_p (operands[1]))
344 {
345 rtx temp_reg = gen_reg_rtx (GET_MODE (operands[1]));
346 emit_move_insn (temp_reg, operands[1]);
347 operands[1] = temp_reg;
348 did = 1;
349 }
350 if (rl78_far_p (operands[0]))
351 {
352 temp_reg = operands[0];
353 operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
354 did = 1;
355 }
356 if (!did)
357 return 0;
358
359 emit_insn (gen (operands[0], operands[1], operands[2]));
360 if (temp_reg)
361 emit_move_insn (temp_reg, operands[0]);
362 return 1;
363}
364
365#undef TARGET_CAN_ELIMINATE
366#define TARGET_CAN_ELIMINATE rl78_can_eliminate
367
368static bool
369rl78_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to ATTRIBUTE_UNUSED)
370{
371 return true;
372}
373
374/* Returns nonzero if the given register needs to be saved by the
375 current function. */
376static int
377need_to_save (int regno)
378{
379 if (is_interrupt_func (cfun->decl))
380 {
381 if (regno < 8)
382 return 1; /* don't know what devirt will need */
383 if (regno > 23)
384 return 0; /* don't need to save interrupt registers */
385 if (current_function_is_leaf)
386 {
387 return df_regs_ever_live_p (regno);
388 }
389 else
390 return 1;
391 }
392 if (regno == FRAME_POINTER_REGNUM && frame_pointer_needed)
393 return 1;
394 if (fixed_regs[regno])
395 return 0;
396 if (crtl->calls_eh_return)
397 return 1;
398 if (df_regs_ever_live_p (regno)
399 && !call_used_regs[regno])
400 return 1;
401 return 0;
402}
403
404/* We use this to wrap all emitted insns in the prologue. */
405static rtx
406F (rtx x)
407{
408 RTX_FRAME_RELATED_P (x) = 1;
409 return x;
410}
411
412/* Compute all the frame-related fields in our machine_function
413 structure. */
414static void
415rl78_compute_frame_info (void)
416{
417 int i;
418
419 cfun->machine->computed = 1;
420 cfun->machine->framesize_regs = 0;
421 cfun->machine->framesize_locals = get_frame_size ();
422 cfun->machine->framesize_outgoing = crtl->outgoing_args_size;
423
424 for (i = 0; i < 16; i ++)
425 if (need_to_save (i * 2) || need_to_save (i * 2 + 1))
426 {
427 cfun->machine->need_to_push [i] = 1;
428 cfun->machine->framesize_regs += 2;
429 }
430 else
431 cfun->machine->need_to_push [i] = 0;
432
433 if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1)
434 cfun->machine->framesize_locals ++;
435
436 cfun->machine->framesize = (cfun->machine->framesize_regs
437 + cfun->machine->framesize_locals
438 + cfun->machine->framesize_outgoing);
439}
440\f
441/* Returns true if the provided function has the specified attribute. */
442static inline bool
443has_func_attr (const_tree decl, const char * func_attr)
444{
445 if (decl == NULL_TREE)
446 decl = current_function_decl;
447
448 return lookup_attribute (func_attr, DECL_ATTRIBUTES (decl)) != NULL_TREE;
449}
450
451/* Returns true if the provided function has the "interrupt" attribute. */
452static inline bool
453is_interrupt_func (const_tree decl)
454{
455 return has_func_attr (decl, "interrupt") || has_func_attr (decl, "brk_interrupt");
456}
457
458/* Returns true if the provided function has the "brk_interrupt" attribute. */
459static inline bool
460is_brk_interrupt_func (const_tree decl)
461{
462 return has_func_attr (decl, "brk_interrupt");
463}
464
465/* Check "interrupt" attributes. */
466static tree
467rl78_handle_func_attribute (tree * node,
468 tree name,
469 tree args,
470 int flags ATTRIBUTE_UNUSED,
471 bool * no_add_attrs)
472{
473 gcc_assert (DECL_P (* node));
474 gcc_assert (args == NULL_TREE);
475
476 if (TREE_CODE (* node) != FUNCTION_DECL)
477 {
478 warning (OPT_Wattributes, "%qE attribute only applies to functions",
479 name);
480 * no_add_attrs = true;
481 }
482
483 /* FIXME: We ought to check that the interrupt and exception
484 handler attributes have been applied to void functions. */
485 return NULL_TREE;
486}
487
488#undef TARGET_ATTRIBUTE_TABLE
489#define TARGET_ATTRIBUTE_TABLE rl78_attribute_table
490
491/* Table of RL78-specific attributes. */
492const struct attribute_spec rl78_attribute_table[] =
493{
494 /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
495 affects_type_identity. */
496 { "interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
497 false },
498 { "brk_interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
499 false },
500 { NULL, 0, 0, false, false, false, NULL, false }
501};
502
503
504\f
505/* Break down an address RTX into its component base/index/addend
506 portions and return TRUE if the address is of a valid form, else
507 FALSE. */
508static bool
509characterize_address (rtx x, rtx *base, rtx *index, rtx *addend)
510{
511 *base = NULL_RTX;
512 *index = NULL_RTX;
513 *addend = NULL_RTX;
514
515 if (GET_CODE (x) == REG)
516 {
517 *base = x;
518 return true;
519 }
520
521 /* We sometimes get these without the CONST wrapper */
522 if (GET_CODE (x) == PLUS
523 && GET_CODE (XEXP (x, 0)) == SYMBOL_REF
524 && GET_CODE (XEXP (x, 1)) == CONST_INT)
525 {
526 *addend = x;
527 return true;
528 }
529
530 if (GET_CODE (x) == PLUS)
531 {
532 *base = XEXP (x, 0);
533 x = XEXP (x, 1);
534
535 if (GET_CODE (*base) != REG
536 && GET_CODE (x) == REG)
537 {
538 rtx tmp = *base;
539 *base = x;
540 x = tmp;
541 }
542
543 if (GET_CODE (*base) != REG)
544 return false;
545
546 if (GET_CODE (x) == ZERO_EXTEND
547 && GET_CODE (XEXP (x, 0)) == REG)
548 {
549 *index = XEXP (x, 0);
550 return false;
551 }
552 }
553
554 switch (GET_CODE (x))
555 {
556 case PLUS:
557 if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
558 && GET_CODE (XEXP (x, 0)) == CONST_INT)
559 {
560 *addend = x;
561 return true;
562 }
563 /* fall through */
564 case MEM:
565 case REG:
566 return false;
567
568 case CONST:
569 case SYMBOL_REF:
570 case CONST_INT:
571 *addend = x;
572 return true;
573
574 default:
575 return false;
576 }
577
578 return false;
579}
580
581/* Used by the Whb constraint. Match addresses that use HL+B or HL+C
582 addressing. */
583bool
584rl78_hl_b_c_addr_p (rtx op)
585{
586 rtx hl, bc;
587
588 if (GET_CODE (op) != PLUS)
589 return false;
590 hl = XEXP (op, 0);
591 bc = XEXP (op, 1);
592 if (GET_CODE (hl) == ZERO_EXTEND)
593 {
594 rtx tmp = hl;
595 hl = bc;
596 bc = tmp;
597 }
598 if (GET_CODE (hl) != REG)
599 return false;
600 if (GET_CODE (bc) != ZERO_EXTEND)
601 return false;
602 bc = XEXP (bc, 0);
603 if (GET_CODE (bc) != REG)
604 return false;
605 if (REGNO (hl) != HL_REG)
606 return false;
607 if (REGNO (bc) != B_REG && REGNO (bc) != C_REG)
608 return false;
609
610 return true;
611}
612
613#define REG_IS(r, regno) (((r) == (regno)) || ((r) >= FIRST_PSEUDO_REGISTER && !(strict)))
614
615/* Used in various constraints and predicates to match operands in the
616 "far" address space. */
617int
618rl78_far_p (rtx x)
619{
620 if (GET_CODE (x) != MEM)
621 return 0;
622#if DEBUG0
623 fprintf(stderr, "\033[35mrl78_far_p: "); debug_rtx(x);
624 fprintf(stderr, " = %d\033[0m\n", MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR);
625#endif
626 return MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR;
627}
628
629/* Return the appropriate mode for a named address pointer. */
630#undef TARGET_ADDR_SPACE_POINTER_MODE
631#define TARGET_ADDR_SPACE_POINTER_MODE rl78_addr_space_pointer_mode
632static enum machine_mode
633rl78_addr_space_pointer_mode (addr_space_t addrspace)
634{
635 switch (addrspace)
636 {
637 case ADDR_SPACE_GENERIC:
638 return HImode;
639 case ADDR_SPACE_FAR:
640 return SImode;
641 default:
642 gcc_unreachable ();
643 }
644}
645
646/* Return the appropriate mode for a named address address. */
647#undef TARGET_ADDR_SPACE_ADDRESS_MODE
648#define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode
649static enum machine_mode
650rl78_addr_space_address_mode (addr_space_t addrspace)
651{
652 switch (addrspace)
653 {
654 case ADDR_SPACE_GENERIC:
655 return HImode;
656 case ADDR_SPACE_FAR:
657 return SImode;
658 default:
659 gcc_unreachable ();
660 }
661}
662
663#undef TARGET_LEGITIMATE_CONSTANT_P
664#define TARGET_LEGITIMATE_CONSTANT_P rl78_is_legitimate_constant
665
666static bool
667rl78_is_legitimate_constant (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED)
668{
669 return true;
670}
671
672#undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
673#define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P rl78_as_legitimate_address
674
675bool
676rl78_as_legitimate_address (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x,
677 bool strict ATTRIBUTE_UNUSED, addr_space_t as ATTRIBUTE_UNUSED)
678{
679 rtx base, index, addend;
680
681 if (as == ADDR_SPACE_GENERIC
682 && GET_MODE (x) == SImode)
683 return false;
684
685 if (! characterize_address (x, &base, &index, &addend))
686 return false;
687
688 if (base && index)
689 {
690 int ir = REGNO (index);
691 int br = REGNO (base);
692
693#define OK(test, debug) if (test) { /*fprintf(stderr, "%d: OK %s\n", __LINE__, debug);*/ return true; }
694 OK (REG_IS (br, HL_REG) && REG_IS (ir, B_REG), "[hl+b]");
695 OK (REG_IS (br, HL_REG) && REG_IS (ir, C_REG), "[hl+c]");
696 return false;
697 }
698
699 if (strict && base && GET_CODE (base) == REG && REGNO (base) >= FIRST_PSEUDO_REGISTER)
700 return false;
701
702 return true;
703}
704
705/* Determine if one named address space is a subset of another. */
706#undef TARGET_ADDR_SPACE_SUBSET_P
707#define TARGET_ADDR_SPACE_SUBSET_P rl78_addr_space_subset_p
708static bool
709rl78_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
710{
711 gcc_assert (subset == ADDR_SPACE_GENERIC || subset == ADDR_SPACE_FAR);
712 gcc_assert (superset == ADDR_SPACE_GENERIC || superset == ADDR_SPACE_FAR);
713
714 if (subset == superset)
715 return true;
716
717 else
718 return (subset == ADDR_SPACE_GENERIC && superset == ADDR_SPACE_FAR);
719}
720
721#undef TARGET_ADDR_SPACE_CONVERT
722#define TARGET_ADDR_SPACE_CONVERT rl78_addr_space_convert
723/* Convert from one address space to another. */
724static rtx
725rl78_addr_space_convert (rtx op, tree from_type, tree to_type)
726{
727 addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
728 addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
729 rtx result;
730
731 gcc_assert (from_as == ADDR_SPACE_GENERIC || from_as == ADDR_SPACE_FAR);
732 gcc_assert (to_as == ADDR_SPACE_GENERIC || to_as == ADDR_SPACE_FAR);
733
734 if (to_as == ADDR_SPACE_GENERIC && from_as == ADDR_SPACE_FAR)
735 {
736 /* This is unpredictable, as we're truncating off usable address
737 bits. */
738
739 result = gen_reg_rtx (HImode);
740 emit_move_insn (result, simplify_subreg (HImode, op, SImode, 0));
741 return result;
742 }
743 else if (to_as == ADDR_SPACE_FAR && from_as == ADDR_SPACE_GENERIC)
744 {
745 /* This always works. */
746 result = gen_reg_rtx (SImode);
747 debug_rtx(result);
748 debug_rtx(op);
749 emit_move_insn (rl78_subreg (HImode, result, SImode, 0), op);
750 emit_move_insn (rl78_subreg (HImode, result, SImode, 2), const0_rtx);
751 return result;
752 }
753 else
754 gcc_unreachable ();
755}
756
757/* Implements REGNO_MODE_CODE_OK_FOR_BASE_P. */
758bool
759rl78_regno_mode_code_ok_for_base_p (int regno, enum machine_mode mode ATTRIBUTE_UNUSED,
760 addr_space_t address_space ATTRIBUTE_UNUSED,
761 int outer_code ATTRIBUTE_UNUSED, int index_code)
762{
763 if (regno < 24 && regno >= 16)
764 return true;
765 if (index_code == REG)
766 return (regno == HL_REG);
767 if (regno == C_REG || regno == B_REG || regno == E_REG || regno == L_REG)
768 return true;
769 return false;
770}
771
772/* Implements MODE_CODE_BASE_REG_CLASS. */
773enum reg_class
774rl78_mode_code_base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED,
775 addr_space_t address_space ATTRIBUTE_UNUSED,
776 int outer_code ATTRIBUTE_UNUSED,
777 int index_code ATTRIBUTE_UNUSED)
778{
779 return V_REGS;
780}
781
782/* Implements INITIAL_ELIMINATION_OFFSET. The frame layout is
783 described in the machine_Function struct definition, above. */
784int
785rl78_initial_elimination_offset (int from, int to)
786{
787 int rv = 0; /* as if arg to arg */
788
789 rl78_compute_frame_info ();
790
791 switch (to)
792 {
793 case STACK_POINTER_REGNUM:
794 rv += cfun->machine->framesize_outgoing;
795 rv += cfun->machine->framesize_locals;
796 /* Fall through. */
797 case FRAME_POINTER_REGNUM:
798 rv += cfun->machine->framesize_regs;
799 rv += 4;
800 break;
801 default:
802 gcc_unreachable ();
803 }
804
805 switch (from)
806 {
807 case FRAME_POINTER_REGNUM:
808 rv -= 4;
809 rv -= cfun->machine->framesize_regs;
810 case ARG_POINTER_REGNUM:
811 break;
812 default:
813 gcc_unreachable ();
814 }
815
816 return rv;
817}
818
819/* Expand the function prologue (from the prologue pattern). */
820void
821rl78_expand_prologue (void)
822{
823 int i, fs;
824 rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
825 int rb = 0;
826
827 if (!cfun->machine->computed)
828 rl78_compute_frame_info ();
829
830 for (i = 0; i < 16; i++)
831 if (cfun->machine->need_to_push [i])
832 {
833 int need_bank = i/4;
834 if (need_bank != rb)
835 {
836 emit_insn (gen_sel_rb (GEN_INT (need_bank)));
837 rb = need_bank;
838 }
839 F (emit_insn (gen_push (gen_rtx_REG (HImode, i*2))));
840 }
841 if (rb != 0)
842 emit_insn (gen_sel_rb (GEN_INT (0)));
843
844 if (frame_pointer_needed)
845 F (emit_move_insn (gen_rtx_REG (HImode, FRAME_POINTER_REGNUM),
846 gen_rtx_REG (HImode, STACK_POINTER_REGNUM)));
847
848 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
849 while (fs > 0)
850 {
851 int fs_byte = (fs > 254) ? 254 : fs;
852 F (emit_insn (gen_subhi3 (sp, sp, GEN_INT (fs_byte))));
853 fs -= fs_byte;
854 }
855}
856
857/* Expand the function epilogue (from the epilogue pattern). */
858void
859rl78_expand_epilogue (void)
860{
861 int i, fs;
862 rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
863 int rb = 0;
864
865 if (frame_pointer_needed)
866 {
867 emit_move_insn (gen_rtx_REG (HImode, STACK_POINTER_REGNUM),
868 gen_rtx_REG (HImode, FRAME_POINTER_REGNUM));
869 }
870 else
871 {
872 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
873 while (fs > 0)
874 {
875 int fs_byte = (fs > 254) ? 254 : fs;
876
877 emit_insn (gen_addhi3 (sp, sp, GEN_INT (fs_byte)));
878 fs -= fs_byte;
879 }
880 }
881
882 for (i = 15; i >= 0; i--)
883 if (cfun->machine->need_to_push [i])
884 {
885 int need_bank = i / 4;
886
887 if (need_bank != rb)
888 {
889 emit_insn (gen_sel_rb (GEN_INT (need_bank)));
890 rb = need_bank;
891 }
892 emit_insn (gen_pop (gen_rtx_REG (HImode, i * 2)));
893 }
894
895 if (rb != 0)
896 emit_insn (gen_sel_rb (GEN_INT (0)));
897
898 if (cfun->machine->trampolines_used)
899 emit_insn (gen_trampoline_uninit ());
900
901 if (is_brk_interrupt_func (cfun->decl))
902 emit_jump_insn (gen_brk_interrupt_return ());
903 else if (is_interrupt_func (cfun->decl))
904 emit_jump_insn (gen_interrupt_return ());
905 else
edf1f7ba 906 emit_jump_insn (gen_rl78_return ());
78e515f7 907}
908
909/* Likewise, for exception handlers. */
910void
911rl78_expand_eh_epilogue (rtx x ATTRIBUTE_UNUSED)
912{
913 /* FIXME - replace this with an indirect jump with stack adjust. */
edf1f7ba 914 emit_jump_insn (gen_rl78_return ());
78e515f7 915}
916
917#undef TARGET_ASM_FUNCTION_PROLOGUE
918#define TARGET_ASM_FUNCTION_PROLOGUE rl78_start_function
919
920/* We don't use this to actually emit the function prologue. We use
921 this to insert a comment in the asm file describing the
922 function. */
923static void
924rl78_start_function (FILE *file, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED)
925{
926 int i;
927
928 if (cfun->machine->framesize == 0)
929 return;
930 fprintf (file, "\t; start of function\n");
931
932 if (cfun->machine->framesize_regs)
933 {
934 fprintf (file, "\t; push %d:", cfun->machine->framesize_regs);
935 for (i = 0; i < 16; i ++)
936 if (cfun->machine->need_to_push[i])
937 fprintf (file, " %s", word_regnames[i*2]);
938 fprintf(file, "\n");
939 }
940
941 if (frame_pointer_needed)
942 fprintf (file, "\t; $fp points here (r22)\n");
943
944 if (cfun->machine->framesize_locals)
945 fprintf (file, "\t; locals: %d byte%s\n", cfun->machine->framesize_locals,
946 cfun->machine->framesize_locals == 1 ? "" : "s");
947
948 if (cfun->machine->framesize_outgoing)
949 fprintf (file, "\t; outgoing: %d byte%s\n", cfun->machine->framesize_outgoing,
950 cfun->machine->framesize_outgoing == 1 ? "" : "s");
951}
952
953/* Return an RTL describing where a function return value of type RET_TYPE
954 is held. */
955
956#undef TARGET_FUNCTION_VALUE
957#define TARGET_FUNCTION_VALUE rl78_function_value
958
959static rtx
960rl78_function_value (const_tree ret_type,
961 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
962 bool outgoing ATTRIBUTE_UNUSED)
963{
964 enum machine_mode mode = TYPE_MODE (ret_type);
965
966 return gen_rtx_REG (mode, 8);
967}
968
969#undef TARGET_PROMOTE_FUNCTION_MODE
970#define TARGET_PROMOTE_FUNCTION_MODE rl78_promote_function_mode
971
972static enum machine_mode
973rl78_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
974 enum machine_mode mode,
975 int *punsignedp ATTRIBUTE_UNUSED,
976 const_tree funtype ATTRIBUTE_UNUSED, int for_return ATTRIBUTE_UNUSED)
977{
978 return mode;
979}
980
981/* Return an RTL expression describing the register holding a function
982 parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
983 be passed on the stack. CUM describes the previous parameters to the
984 function and NAMED is false if the parameter is part of a variable
985 parameter list, or the last named parameter before the start of a
986 variable parameter list. */
987
988#undef TARGET_FUNCTION_ARG
989#define TARGET_FUNCTION_ARG rl78_function_arg
990
991static rtx
992rl78_function_arg (cumulative_args_t cum_v ATTRIBUTE_UNUSED,
993 enum machine_mode mode ATTRIBUTE_UNUSED,
994 const_tree type ATTRIBUTE_UNUSED,
995 bool named ATTRIBUTE_UNUSED)
996{
997 return NULL_RTX;
998}
999
1000#undef TARGET_FUNCTION_ARG_ADVANCE
1001#define TARGET_FUNCTION_ARG_ADVANCE rl78_function_arg_advance
1002
1003static void
1004rl78_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode, const_tree type,
1005 bool named ATTRIBUTE_UNUSED)
1006{
1007 int rounded_size;
1008 CUMULATIVE_ARGS * cum = get_cumulative_args (cum_v);
1009
1010 rounded_size = ((mode == BLKmode)
1011 ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
1012 if (rounded_size & 1)
1013 rounded_size ++;
1014 (*cum) += rounded_size;
1015}
1016
1017#undef TARGET_FUNCTION_ARG_BOUNDARY
1018#define TARGET_FUNCTION_ARG_BOUNDARY rl78_function_arg_boundary
1019
1020static unsigned int
1021rl78_function_arg_boundary (enum machine_mode mode ATTRIBUTE_UNUSED,
1022 const_tree type ATTRIBUTE_UNUSED)
1023{
1024 return 16;
1025}
1026
1027/* Supported modifier letters:
1028
1029 A - address of a MEM
1030 S - SADDR form of a real register
1031 v - real register corresponding to a virtual register
1032 m - minus - negative of CONST_INT value.
1033 c - inverse of a conditional (NE vs EQ for example)
1034
1035 h - bottom HI of an SI
1036 H - top HI of an SI
1037 q - bottom QI of an HI
1038 Q - top QI of an HI
1039 e - third QI of an SI (i.e. where the ES register gets values from)
1040
1041*/
1042
1043/* Implements the bulk of rl78_print_operand, below. We do it this
1044 way because we need to test for a constant at the top level and
1045 insert the '#', but not test for it anywhere else as we recurse
1046 down into the operand. */
1047static void
1048rl78_print_operand_1 (FILE * file, rtx op, int letter)
1049{
1050 int need_paren;
1051
1052 switch (GET_CODE (op))
1053 {
1054 case MEM:
1055 if (letter == 'A')
1056 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1057 else
1058 {
1059 if (rl78_far_p (op))
1060 fprintf(file, "es:");
1061 if (letter == 'H')
1062 {
1063 op = adjust_address (op, HImode, 2);
1064 letter = 0;
1065 }
1066 if (letter == 'h')
1067 {
1068 op = adjust_address (op, HImode, 0);
1069 letter = 0;
1070 }
1071 if (letter == 'Q')
1072 {
1073 op = adjust_address (op, QImode, 1);
1074 letter = 0;
1075 }
1076 if (letter == 'q')
1077 {
1078 op = adjust_address (op, QImode, 0);
1079 letter = 0;
1080 }
1081 if (letter == 'e')
1082 {
1083 op = adjust_address (op, QImode, 2);
1084 letter = 0;
1085 }
1086 if (CONSTANT_P (XEXP (op, 0)))
1087 {
1088 fprintf(file, "!");
1089 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1090 }
1091 else if (GET_CODE (XEXP (op, 0)) == PLUS
1092 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF)
1093 {
1094 fprintf(file, "!");
1095 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1096 }
1097 else if (GET_CODE (XEXP (op, 0)) == PLUS
1098 && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
1099 && REGNO (XEXP (XEXP (op, 0), 0)) == 2)
1100 {
1101 rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 1), 'u');
1102 fprintf(file, "[");
1103 rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 0), 0);
1104 fprintf(file, "]");
1105 }
1106 else
1107 {
1108 fprintf(file, "[");
1109 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1110 fprintf(file, "]");
1111 }
1112 }
1113 break;
1114
1115 case REG:
1116 if (letter == 'Q')
1117 fprintf (file, "%s", reg_names [REGNO (op) | 1]);
1118 else if (letter == 'H')
1119 fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1120 else if (letter == 'q')
1121 fprintf (file, "%s", reg_names [REGNO (op) & ~1]);
1122 else if (letter == 'e')
1123 fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1124 else if (letter == 'S')
1125 fprintf (file, "0x%x", 0xffef8 + REGNO (op));
1126 else if (GET_MODE (op) == HImode
1127 && ! (REGNO (op) & ~0xfe))
1128 {
1129 if (letter == 'v')
1130 fprintf (file, "%s", word_regnames [REGNO (op) % 8]);
1131 else
1132 fprintf (file, "%s", word_regnames [REGNO (op)]);
1133 }
1134 else
1135 fprintf (file, "%s", reg_names [REGNO (op)]);
1136 break;
1137
1138 case CONST_INT:
1139 if (letter == 'Q')
1140 fprintf (file, "%ld", INTVAL (op) >> 8);
1141 else if (letter == 'H')
1142 fprintf (file, "%ld", INTVAL (op) >> 16);
1143 else if (letter == 'q')
1144 fprintf (file, "%ld", INTVAL (op) & 0xff);
1145 else if (letter == 'h')
1146 fprintf (file, "%ld", INTVAL (op) & 0xffff);
1147 else if (letter == 'e')
1148 fprintf (file, "%ld", (INTVAL (op) >> 16) & 0xff);
1149 else if (letter == 'm')
1150 fprintf (file, "%ld", - INTVAL (op));
1151 else
1152 fprintf(file, "%ld", INTVAL (op));
1153 break;
1154
1155 case CONST:
1156 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1157 break;
1158
1159 case ZERO_EXTRACT:
1160 {
1161 int bits = INTVAL (XEXP (op, 1));
1162 int ofs = INTVAL (XEXP (op, 2));
1163 if (bits == 16 && ofs == 0)
1164 fprintf (file, "%%lo16(");
1165 else if (bits == 16 && ofs == 16)
1166 fprintf (file, "%%hi16(");
1167 else if (bits == 8 && ofs == 16)
1168 fprintf (file, "%%hi8(");
1169 else
1170 gcc_unreachable ();
1171 rl78_print_operand_1 (file, XEXP (op, 0), 0);
1172 fprintf (file, ")");
1173 }
1174 break;
1175
1176 case ZERO_EXTEND:
1177 if (GET_CODE (XEXP (op, 0)) == REG)
1178 fprintf (file, "%s", reg_names [REGNO (XEXP (op, 0))]);
1179 else
1180 print_rtl (file, op);
1181 break;
1182
1183 case PLUS:
1184 need_paren = 0;
1185 if (letter == 'H')
1186 {
1187 fprintf (file, "%%hi16(");
1188 need_paren = 1;
1189 letter = 0;
1190 }
1191 if (letter == 'h')
1192 {
1193 fprintf (file, "%%lo16(");
1194 need_paren = 1;
1195 letter = 0;
1196 }
1197 if (letter == 'e')
1198 {
1199 fprintf (file, "%%hi8(");
1200 need_paren = 1;
1201 letter = 0;
1202 }
1203 if (letter == 'q' || letter == 'Q')
1204 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1205
1206 if (GET_CODE (XEXP (op, 0)) == ZERO_EXTEND)
1207 {
1208 rl78_print_operand_1 (file, XEXP (op, 1), letter);
1209 fprintf (file, "+");
1210 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1211 }
1212 else
1213 {
1214 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1215 fprintf (file, "+");
1216 rl78_print_operand_1 (file, XEXP (op, 1), letter);
1217 }
1218 if (need_paren)
1219 fprintf (file, ")");
1220 break;
1221
1222 case SYMBOL_REF:
1223 need_paren = 0;
1224 if (letter == 'H')
1225 {
1226 fprintf (file, "%%hi16(");
1227 need_paren = 1;
1228 letter = 0;
1229 }
1230 if (letter == 'h')
1231 {
1232 fprintf (file, "%%lo16(");
1233 need_paren = 1;
1234 letter = 0;
1235 }
1236 if (letter == 'e')
1237 {
1238 fprintf (file, "%%hi8(");
1239 need_paren = 1;
1240 letter = 0;
1241 }
1242 if (letter == 'q' || letter == 'Q')
1243 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1244
1245 output_addr_const (file, op);
1246 if (need_paren)
1247 fprintf (file, ")");
1248 break;
1249
1250 case CODE_LABEL:
1251 case LABEL_REF:
1252 output_asm_label (op);
1253 break;
1254
1255 case LTU:
1256 fprintf (file, letter == 'c' ? "nc" : "c");
1257 break;
1258 case LEU:
1259 fprintf (file, letter == 'c' ? "h" : "nh");
1260 break;
1261 case GEU:
1262 fprintf (file, letter == 'c' ? "c" : "nc");
1263 break;
1264 case GTU:
1265 fprintf (file, letter == 'c' ? "nh" : "h");
1266 break;
1267 case EQ:
1268 fprintf (file, letter == 'c' ? "nz" : "z");
1269 break;
1270 case NE:
1271 fprintf (file, letter == 'c' ? "z" : "nz");
1272 break;
1273
1274 default:
1275 fprintf (file, "(%s)", GET_RTX_NAME (GET_CODE (op)));
1276 break;
1277 }
1278}
1279
1280#undef TARGET_PRINT_OPERAND
1281#define TARGET_PRINT_OPERAND rl78_print_operand
1282
1283static void
1284rl78_print_operand (FILE * file, rtx op, int letter)
1285{
1286 if (CONSTANT_P (op) && letter != 'u')
1287 fprintf (file, "#");
1288 rl78_print_operand_1 (file, op, letter);
1289}
1290
1291#undef TARGET_TRAMPOLINE_INIT
1292#define TARGET_TRAMPOLINE_INIT rl78_trampoline_init
1293
1294/* Note that the RL78's addressing makes it very difficult to do
1295 trampolines on the stack. So, libgcc has a small pool of
1296 trampolines from which one is allocated to this task. */
1297static void
1298rl78_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
1299{
1300 rtx mov_addr, thunk_addr;
1301 rtx function = XEXP (DECL_RTL (fndecl), 0);
1302
1303 mov_addr = adjust_address (m_tramp, HImode, 0);
1304 thunk_addr = gen_reg_rtx (HImode);
1305
1306 function = force_reg (HImode, function);
1307 static_chain = force_reg (HImode, static_chain);
1308
1309 emit_insn (gen_trampoline_init (thunk_addr, function, static_chain));
1310 emit_move_insn (mov_addr, thunk_addr);
1311
1312 cfun->machine->trampolines_used = 1;
1313}
1314
1315#undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
1316#define TARGET_TRAMPOLINE_ADJUST_ADDRESS rl78_trampoline_adjust_address
1317
1318static rtx
1319rl78_trampoline_adjust_address (rtx m_tramp)
1320{
1321 rtx x = gen_rtx_MEM (HImode, m_tramp);
1322 return x;
1323}
1324\f
1325/* Expander for cbranchqi4 and cbranchhi4. RL78 is missing some of
1326 the "normal" compares, specifically, it only has unsigned compares,
1327 so we must synthesize the missing ones. */
1328void
1329rl78_expand_compare (rtx *operands)
1330{
1331 /* RL78 does not have signed comparisons. We must modify the
1332 operands to be in the unsigned range, and emit an unsigned
1333 comparison. */
1334
1335 enum machine_mode mode;
1336 rtx high_bit;
1337 int i;
1338 RTX_CODE new_cond;
1339
1340 switch (GET_CODE (operands[0]))
1341 {
1342 case GE:
1343 new_cond = GEU;
1344 break;
1345 case LE:
1346 new_cond = LEU;
1347 break;
1348 case GT:
1349 new_cond = GTU;
1350 break;
1351 case LT:
1352 new_cond = LTU;
1353 break;
1354 default:
1355 return;
1356 }
1357
1358#if DEBUG0
1359 fprintf (stderr, "\033[38;5;129mrl78_expand_compare\n");
1360 debug_rtx (operands[0]);
1361 fprintf (stderr, "\033[0m");
1362#endif
1363
1364 mode = GET_MODE (operands[1]);
1365 if (mode == VOIDmode)
1366 mode = GET_MODE (operands[2]);
1367 high_bit = GEN_INT (~0 << (GET_MODE_BITSIZE (mode) - 1));
1368
1369 /* 0: conditional 1,2: operands */
1370 for (i = 1; i <= 2; i ++)
1371 {
1372 rtx r = operands[i];
1373
1374 if (GET_CODE (r) == CONST_INT)
1375 r = GEN_INT (INTVAL (r) ^ INTVAL (high_bit));
1376 else
1377 {
1378 r = gen_rtx_PLUS (mode, operands[i], high_bit);
1379 r = copy_to_mode_reg (mode, r);
1380 }
1381 operands[i] = r;
1382 }
1383
1384 operands[0] = gen_rtx_fmt_ee (new_cond, GET_MODE (operands[0]), operands[1], operands[2]);
1385
1386#if DEBUG0
1387 fprintf (stderr, "\033[38;5;142mrl78_expand_compare\n");
1388 debug_rtx (operands[0]);
1389 fprintf (stderr, "\033[0m");
1390#endif
1391}
1392
1393\f
1394
1395/* Define this to 1 if you are debugging the peephole optimizers. */
1396#define DEBUG_PEEP 0
1397
1398/* Predicate used to enable the peephole2 patterns in rl78-virt.md.
1399 The default "word" size is a byte so we can effectively use all the
1400 registers, but we want to do 16-bit moves whenever possible. This
1401 function determines when such a move is an option. */
1402bool
1403rl78_peep_movhi_p (rtx *operands)
1404{
1405 int i;
1406 rtx m, a;
1407
1408 /* (set (op0) (op1))
1409 (set (op2) (op3)) */
1410
1411#if DEBUG_PEEP
1412 fprintf (stderr, "\033[33m");
1413 debug_rtx(operands[0]);
1414 debug_rtx(operands[1]);
1415 debug_rtx(operands[2]);
1416 debug_rtx(operands[3]);
1417 fprintf (stderr, "\033[0m");
1418#endif
1419
1420 if (rtx_equal_p (operands[0], operands[3]))
1421 {
1422#if DEBUG_PEEP
1423 fprintf (stderr, "no peep: overlapping\n");
1424#endif
1425 return false;
1426 }
1427
1428 for (i = 0; i < 2; i ++)
1429 {
1430 if (GET_CODE (operands[i]) != GET_CODE (operands[i+2]))
1431 {
1432#if DEBUG_PEEP
1433 fprintf (stderr, "no peep: different codes\n");
1434#endif
1435 return false;
1436 }
1437 if (GET_MODE (operands[i]) != GET_MODE (operands[i+2]))
1438 {
1439#if DEBUG_PEEP
1440 fprintf (stderr, "no peep: different modes\n");
1441#endif
1442 return false;
1443 }
1444
1445 switch (GET_CODE (operands[i]))
1446 {
1447 case REG:
1448 /* LSB MSB */
1449 if (REGNO (operands[i]) + 1 != REGNO (operands[i+2])
1450 || GET_MODE (operands[i]) != QImode)
1451 {
1452#if DEBUG_PEEP
1453 fprintf (stderr, "no peep: wrong regnos %d %d %d\n",
1454 REGNO (operands[i]), REGNO (operands[i+2]),
1455 i);
1456#endif
1457 return false;
1458 }
1459 if (! rl78_hard_regno_mode_ok (REGNO (operands[i]), HImode))
1460 {
1461#if DEBUG_PEEP
1462 fprintf (stderr, "no peep: reg %d not HI\n", REGNO (operands[i]));
1463#endif
1464 return false;
1465 }
1466 break;
1467
1468 case CONST_INT:
1469 break;
1470
1471 case MEM:
1472 if (GET_MODE (operands[i]) != QImode)
1473 return false;
1474 if (MEM_ALIGN (operands[i]) < 16)
1475 return false;
1476 a = XEXP (operands[i], 0);
1477 if (GET_CODE (a) == CONST)
1478 a = XEXP (a, 0);
1479 if (GET_CODE (a) == PLUS)
1480 a = XEXP (a, 1);
1481 if (GET_CODE (a) == CONST_INT
1482 && INTVAL (a) & 1)
1483 {
1484#if DEBUG_PEEP
1485 fprintf (stderr, "no peep: misaligned mem %d\n", i);
1486 debug_rtx (operands[i]);
1487#endif
1488 return false;
1489 }
1490 m = adjust_address (operands[i], QImode, 1);
1491 if (! rtx_equal_p (m, operands[i+2]))
1492 {
1493#if DEBUG_PEEP
1494 fprintf (stderr, "no peep: wrong mem %d\n", i);
1495 debug_rtx(m);
1496 debug_rtx (operands[i+2]);
1497#endif
1498 return false;
1499 }
1500 break;
1501
1502 default:
1503#if DEBUG_PEEP
1504 fprintf (stderr, "no peep: wrong rtx %d\n", i);
1505#endif
1506 return false;
1507 }
1508 }
1509#if DEBUG_PEEP
1510 fprintf (stderr, "\033[32mpeep!\033[0m\n");
1511#endif
1512 return true;
1513}
1514
1515/* Likewise, when a peephole is activated, this function helps compute
1516 the new operands. */
1517void
1518rl78_setup_peep_movhi (rtx *operands)
1519{
1520 int i;
1521
1522 for (i = 0; i < 2; i ++)
1523 {
1524 switch (GET_CODE (operands[i]))
1525 {
1526 case REG:
1527 operands[i+4] = gen_rtx_REG (HImode, REGNO (operands[i]));
1528 break;
1529
1530 case CONST_INT:
1531 operands[i+4] = GEN_INT ((INTVAL (operands[i]) & 0xff) + ((char)INTVAL (operands[i+2])) * 256);
1532 break;
1533
1534 case MEM:
1535 operands[i+4] = adjust_address (operands[i], HImode, 0);
1536 break;
1537
1538 default:
1539 break;
1540 }
1541 }
1542}
1543\f
1544/*
1545 How Devirtualization works in the RL78 GCC port
1546
1547Background
1548
1549The RL78 is an 8-bit port with some 16-bit operations. It has 32
1550bytes of register space, in four banks, memory-mapped. One bank is
1551the "selected" bank and holds the registers used for primary
1552operations. Since the registers are memory mapped, often you can
1553still refer to the unselected banks via memory accesses.
1554
1555Virtual Registers
1556
1557The GCC port uses bank 0 as the "selected" registers (A, X, BC, etc)
1558and refers to the other banks via their memory addresses, although
1559they're treated as regular registers internally. These "virtual"
1560registers are R8 through R23 (bank3 is reserved for asm-based
1561interrupt handlers).
1562
1563There are four machine description files:
1564
1565rl78.md - common register-independent patterns and definitions
1566rl78-expand.md - expanders
1567rl78-virt.md - patterns that match BEFORE devirtualization
1568rl78-real.md - patterns that match AFTER devirtualization
1569
1570At least through register allocation and reload, gcc is told that it
1571can do pretty much anything - but may only use the virtual registers.
1572GCC cannot properly create the varying addressing modes that the RL78
1573supports in an efficient way.
1574
1575Sometime after reload, the RL78 backend "devirtualizes" the RTL. It
1576uses the "valloc" attribute in rl78-virt.md for determining the rules
1577by which it will replace virtual registers with real registers (or
1578not) and how to make up addressing modes. For example, insns tagged
1579with "ro1" have a single read-only parameter, which may need to be
1580moved from memory/constant/vreg to a suitable real register. As part
1581of devirtualization, a flag is toggled, disabling the rl78-virt.md
1582patterns and enabling the rl78-real.md patterns. The new patterns'
1583constraints are used to determine the real registers used. NOTE:
1584patterns in rl78-virt.md essentially ignore the constrains and rely on
1585predicates, where the rl78-real.md ones essentially ignore the
1586predicates and rely on the constraints.
1587
1588The devirtualization pass is scheduled via the pass manager (despite
1589being called "rl78_reorg") so it can be scheduled prior to var-track
1590(the idea is to let gdb know about the new registers). Ideally, it
1591would be scheduled right after pro/epilogue generation, so the
1592post-reload optimizers could operate on the real registers, but when I
1593tried that there were some issues building the target libraries.
1594
1595During devirtualization, a simple register move optimizer is run. It
1596would be better to run a full CSE/propogation pass on it through, or
1597re-run regmove, but that has not yet been attempted.
1598
1599 */
1600#define DEBUG_ALLOC 0
1601
1602/* Rescans an insn to see if it's recognized again. This is done
1603 carefully to ensure that all the constraint information is accurate
1604 for the newly matched insn. */
1605static bool
1606insn_ok_now (rtx insn)
1607{
1608 INSN_CODE (insn) = -1;
1609 if (recog (PATTERN (insn), insn, 0) > -1)
1610 {
1611 extract_insn (insn);
1612 if (constrain_operands (1))
1613 {
1614#if DEBUG_ALLOC
1615 fprintf (stderr, "\033[32m");
1616 debug_rtx (insn);
1617 fprintf (stderr, "\033[0m");
1618#endif
1619 return true;
1620 }
1621 }
1622 else
1623 {
1624 fprintf (stderr, "\033[41;30m Unrecognized insn \033[0m\n");
1625 debug_rtx (insn);
1626 gcc_unreachable ();
1627 }
1628#if DEBUG_ALLOC
1629 fprintf (stderr, "\033[31m");
1630 debug_rtx (insn);
1631 fprintf (stderr, "\033[0m");
1632#endif
1633 return false;
1634}
1635
1636#if DEBUG_ALLOC
1637#define WORKED fprintf (stderr, "\033[48;5;22m Worked at line %d \033[0m\n", __LINE__)
1638#define FAILEDSOFAR fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__)
1639#define FAILED fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__), gcc_unreachable()
1640#define MAYBE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } else { FAILEDSOFAR; }
1641#else
1642#define WORKED
1643#define FAILEDSOFAR
1644#define FAILED gcc_unreachable ()
1645#define MAYBE_OK(insn) if (insn_ok_now (insn)) return;
1646#endif
1647
1648/* Registers into which we move the contents of virtual registers. */
1649#define X gen_rtx_REG (QImode, 0)
1650#define A gen_rtx_REG (QImode, 1)
1651#define C gen_rtx_REG (QImode, 2)
1652#define B gen_rtx_REG (QImode, 3)
1653#define E gen_rtx_REG (QImode, 4)
1654#define D gen_rtx_REG (QImode, 5)
1655#define L gen_rtx_REG (QImode, 6)
1656#define H gen_rtx_REG (QImode, 7)
1657
1658#define AX gen_rtx_REG (HImode, 0)
1659#define BC gen_rtx_REG (HImode, 2)
1660#define DE gen_rtx_REG (HImode, 4)
1661#define HL gen_rtx_REG (HImode, 6)
1662
1663#define OP(x) (*recog_data.operand_loc[x])
1664
1665/* Returns TRUE if R is a virtual register. */
1666static bool
1667is_virtual_register (rtx r)
1668{
1669 return (GET_CODE (r) == REG
1670 && REGNO (r) >= 8
1671 && REGNO (r) < 24);
1672}
1673
1674/* In all these alloc routines, we expect the following: the insn
1675 pattern is unshared, the insn was previously recognized and failed
1676 due to predicates or constraints, and the operand data is in
1677 recog_data. */
1678
1679static int virt_insn_was_frame;
1680
1681/* Hook for all insns we emit. Re-mark them as FRAME_RELATED if
1682 needed. */
1683static rtx
1684EM2 (int line ATTRIBUTE_UNUSED, rtx r)
1685{
1686#if DEBUG_ALLOC
1687 fprintf (stderr, "\033[36m%d: ", line);
1688 debug_rtx(r);
1689 fprintf (stderr, "\033[0m");
1690#endif
1691 /*SCHED_GROUP_P (r) = 1;*/
1692 if (virt_insn_was_frame)
1693 RTX_FRAME_RELATED_P (r) = 1;
1694 return r;
1695}
1696
1697#define EM(x) EM2 (__LINE__, x)
1698
1699/* Return a suitable RTX for the low half of a __far address. */
1700static rtx
1701rl78_lo16 (rtx addr)
1702{
1703 if (GET_CODE (addr) == SYMBOL_REF
1704 || GET_CODE (addr) == CONST)
1705 {
1706 rtx r = gen_rtx_ZERO_EXTRACT (HImode, addr, GEN_INT (16), GEN_INT (0));
1707 r = gen_rtx_CONST (HImode, r);
1708 return r;
1709 }
1710 return rl78_subreg (HImode, addr, SImode, 0);
1711}
1712
1713/* Return a suitable RTX for the high half's lower byte of a __far address. */
1714static rtx
1715rl78_hi8 (rtx addr)
1716{
1717 if (GET_CODE (addr) == SYMBOL_REF
1718 || GET_CODE (addr) == CONST)
1719 {
1720 rtx r = gen_rtx_ZERO_EXTRACT (QImode, addr, GEN_INT (8), GEN_INT (16));
1721 r = gen_rtx_CONST (QImode, r);
1722 return r;
1723 }
1724 return rl78_subreg (QImode, addr, SImode, 2);
1725}
1726
1727/* Copy any register values into real registers and return an RTX for
1728 the same memory, now addressed by real registers. Any needed insns
1729 are emitted before BEFORE. */
1730static rtx
1731transcode_memory_rtx (rtx m, rtx newbase, rtx before)
1732{
1733 rtx base, index, addendr;
1734 int addend = 0;
1735
1736 if (GET_CODE (m) != MEM)
1737 return m;
1738
1739 if (GET_MODE (XEXP (m, 0)) == SImode)
1740 {
1741 rtx seg = rl78_hi8 (XEXP (m, 0));
1742#if DEBUG_ALLOC
1743 fprintf (stderr, "setting ES:\n");
1744 debug_rtx(seg);
1745#endif
1746 emit_insn_before (EM(gen_movqi (A, seg)), before);
1747 emit_insn_before (EM(gen_movqi_es (A)), before);
1748 m = change_address (m, GET_MODE (m), rl78_lo16 (XEXP (m, 0)));
1749 }
1750
1751 characterize_address (XEXP (m, 0), &base, &index, &addendr);
1752 gcc_assert (index == NULL_RTX);
1753
1754#if DEBUG_ALLOC
1755 fprintf (stderr, "\033[33m"); debug_rtx(m); fprintf (stderr, "\033[0m");
1756 debug_rtx (base);
1757#endif
1758 if (base == NULL_RTX)
1759 return m;
1760
1761 if (addendr && GET_CODE (addendr) == CONST_INT)
1762 addend = INTVAL (addendr);
1763
1764 if (REGNO (base) == SP_REG)
1765 {
1766 if (addend >= 0 && addend <= 255)
1767 return m;
1768 }
1769
1770 /* BASE should be a virtual register. We copy it to NEWBASE. If
1771 the addend is out of range for DE/HL, we use AX to compute the full
1772 address. */
1773
1774 if (addend < 0
1775 || (addend > 255 && REGNO (newbase) != 2)
1776 || (addendr && GET_CODE (addendr) != CONST_INT))
1777 {
1778 /* mov ax, vreg
1779 add ax, #imm
1780 mov hl, ax */
1781 EM (emit_insn_before (gen_movhi (AX, base), before));
1782 EM (emit_insn_before (gen_addhi3 (AX, AX, addendr), before));
1783 EM (emit_insn_before (gen_movhi (newbase, AX), before));
1784 base = newbase;
1785 addend = 0;
1786 }
1787 else
1788 {
1789 EM (emit_insn_before (gen_movhi (newbase, base), before));
1790 base = newbase;
1791 }
1792
1793 if (addend)
1794 base = gen_rtx_PLUS (HImode, base, GEN_INT (addend));
1795
1796#if DEBUG_ALLOC
1797 fprintf (stderr, "\033[33m");
1798 debug_rtx (m);
1799#endif
1800 m = change_address (m, GET_MODE (m), base);
1801#if DEBUG_ALLOC
1802 debug_rtx (m);
1803 fprintf (stderr, "\033[0m");
1804#endif
1805 return m;
1806}
1807
1808/* Copy SRC to accumulator (A or AX), placing any generated insns
1809 before BEFORE. Returns accumulator RTX. */
1810
1811static rtx
1812move_to_acc (int opno, rtx before)
1813{
1814 rtx src = OP(opno);
1815 enum machine_mode mode = GET_MODE (src);
1816
1817 if (GET_CODE (src) == REG
1818 && REGNO (src) < 2)
1819 return src;
1820
1821 if (mode == VOIDmode)
1822 mode = recog_data.operand_mode[opno];
1823
1824 if (mode == QImode)
1825 {
1826 EM (emit_insn_before (gen_movqi (A, src), before));
1827 return A;
1828 }
1829 else
1830 {
1831 EM (emit_insn_before (gen_movhi (AX, src), before));
1832 return AX;
1833 }
1834}
1835
1836/* Copy accumulator (A or AX) to DEST, placing any generated insns
1837 after AFTER. Returns accumulator RTX. */
1838
1839static rtx
1840move_from_acc (rtx dest, rtx after)
1841{
1842 enum machine_mode mode = GET_MODE (dest);
1843
1844 if (REG_P (dest) && REGNO (dest) < 2)
1845 return dest;
1846
1847 if (mode == QImode)
1848 {
1849 EM (emit_insn_after (gen_movqi (dest, A), after));
1850 return A;
1851 }
1852 else
1853 {
1854 EM (emit_insn_after (gen_movhi (dest, AX), after));
1855 return AX;
1856 }
1857}
1858
1859/* Copy accumulator (A or AX) to REGNO, placing any generated insns
1860 before BEFORE. Returns reg RTX. */
1861
1862static rtx
1863move_acc_to_reg (rtx acc, int regno, rtx before)
1864{
1865 enum machine_mode mode = GET_MODE (acc);
1866 rtx reg;
1867
1868 reg = gen_rtx_REG (mode, regno);
1869
1870 if (mode == QImode)
1871 {
1872 EM (emit_insn_before (gen_movqi (reg, A), before));
1873 return reg;
1874 }
1875 else
1876 {
1877 EM (emit_insn_before (gen_movhi (reg, AX), before));
1878 return reg;
1879 }
1880}
1881
1882/* Copy SRC to X, placing any generated insns before BEFORE.
1883 Returns X RTX. */
1884
1885static rtx
1886move_to_x (int opno, rtx before)
1887{
1888 rtx src = OP(opno);
1889 enum machine_mode mode = GET_MODE (src);
1890 rtx reg;
1891
1892 if (mode == VOIDmode)
1893 mode = recog_data.operand_mode[opno];
1894 reg = (mode == QImode) ? X : AX;
1895
1896 if (mode == QImode || ! is_virtual_register (OP (opno)))
1897 {
1898 OP(opno) = move_to_acc (opno, before);
1899 OP(opno) = move_acc_to_reg (OP(opno), X_REG, before);
1900 return reg;
1901 }
1902
1903 if (mode == QImode)
1904 EM (emit_insn_before (gen_movqi (reg, src), before));
1905 else
1906 EM (emit_insn_before (gen_movhi (reg, src), before));
1907
1908 return reg;
1909}
1910
1911/* Copy OP(opno) to H or HL, placing any generated insns before BEFORE.
1912 Returns H/HL RTX. */
1913
1914static rtx
1915move_to_hl (int opno, rtx before)
1916{
1917 rtx src = OP (opno);
1918 enum machine_mode mode = GET_MODE (src);
1919 rtx reg;
1920
1921 if (mode == VOIDmode)
1922 mode = recog_data.operand_mode[opno];
1923 reg = (mode == QImode) ? L : HL;
1924
1925 if (mode == QImode || ! is_virtual_register (OP (opno)))
1926 {
1927 OP (opno) = move_to_acc (opno, before);
1928 OP (opno) = move_acc_to_reg (OP (opno), L_REG, before);
1929 return reg;
1930 }
1931
1932 if (mode == QImode)
1933 EM (emit_insn_before (gen_movqi (reg, src), before));
1934 else
1935 EM (emit_insn_before (gen_movhi (reg, src), before));
1936
1937 return reg;
1938}
1939
1940/* Copy OP(opno) to E or DE, placing any generated insns before BEFORE.
1941 Returns E/DE RTX. */
1942
1943static rtx
1944move_to_de (int opno, rtx before)
1945{
1946 rtx src = OP (opno);
1947 enum machine_mode mode = GET_MODE (src);
1948 rtx reg;
1949
1950 if (mode == VOIDmode)
1951 mode = recog_data.operand_mode[opno];
1952
1953 reg = (mode == QImode) ? E : DE;
1954
1955 if (mode == QImode || ! is_virtual_register (OP (opno)))
1956 {
1957 OP (opno) = move_to_acc (opno, before);
1958 OP (opno) = move_acc_to_reg (OP (opno), E_REG, before);
1959 }
1960 else
1961 {
1962 rtx move = mode == QImode ? gen_movqi (reg, src) : gen_movhi (reg, src);
1963
1964 EM (emit_insn_before (move, before));
1965 }
1966
1967 return reg;
1968}
1969
1970/* Devirtualize an insn of the form (SET (op) (unop (op))). */
1971static void
1972rl78_alloc_physical_registers_op1 (rtx insn)
1973{
1974 /* op[0] = func op[1] */
1975
1976 /* We first try using A as the destination, then copying it
1977 back. */
1978 if (rtx_equal_p (OP(0), OP(1)))
1979 {
1980 OP(0) =
1981 OP(1) = transcode_memory_rtx (OP(1), DE, insn);
1982 }
1983 else
1984 {
1985 OP(0) = transcode_memory_rtx (OP(0), BC, insn);
1986 OP(1) = transcode_memory_rtx (OP(1), HL, insn);
1987 }
1988
1989 MAYBE_OK (insn);
1990
1991 OP(0) = move_from_acc (OP(0), insn);
1992
1993 MAYBE_OK (insn);
1994
1995 /* Try copying the src to acc first, then. This is for, for
1996 example, ZERO_EXTEND or NOT. */
1997 OP(1) = move_to_acc (1, insn);
1998
1999 MAYBE_OK (insn);
2000
2001 FAILED;
2002}
2003
2004/* Devirtualize an insn of the form (SET (op) (unop (op) (op))). */
2005static void
2006rl78_alloc_physical_registers_op2 (rtx insn)
2007{
2008 /* op[0] = op[1] func op[2] */
2009 rtx prev = prev_nonnote_nondebug_insn (insn);
2010 rtx first;
2011 bool hl_used;
2012
2013 if (rtx_equal_p (OP(0), OP(1)))
2014 {
2015 OP(0) =
2016 OP(1) = transcode_memory_rtx (OP(1), DE, insn);
2017 prev = next_nonnote_nondebug_insn (prev);
2018 OP(2) = transcode_memory_rtx (OP(2), HL, insn);
2019 prev = prev_nonnote_nondebug_insn (prev);
2020 }
2021 else if (rtx_equal_p (OP(0), OP(2)))
2022 {
2023 OP(1) = transcode_memory_rtx (OP(1), DE, insn);
2024 prev = next_nonnote_nondebug_insn (prev);
2025 OP(0) =
2026 OP(2) = transcode_memory_rtx (OP(2), HL, insn);
2027 prev = prev_nonnote_nondebug_insn (prev);
2028 }
2029 else
2030 {
2031 OP(0) = transcode_memory_rtx (OP(0), BC, insn);
2032 OP(1) = transcode_memory_rtx (OP(1), DE, insn);
2033 prev = next_nonnote_nondebug_insn (prev);
2034 OP(2) = transcode_memory_rtx (OP(2), HL, insn);
2035 }
2036
2037 MAYBE_OK (insn);
2038
2039 prev = prev_nonnote_nondebug_insn (insn);
2040 if (recog_data.constraints[1][0] == '%'
2041 && is_virtual_register (OP (1))
2042 && ! is_virtual_register (OP (2))
2043 && ! CONSTANT_P (OP (2)))
2044 {
2045 rtx tmp = OP (1);
2046 OP (1) = OP (2);
2047 OP (2) = tmp;
2048 }
2049
2050 /* Make a note of wether (H)L is being used. It matters
2051 because if OP(2) alsoneeds reloading, then we must take
2052 care not to corrupt HL. */
2053 hl_used = reg_mentioned_p (L, OP (0)) || reg_mentioned_p (L, OP (1));
2054
2055 OP(0) = move_from_acc (OP (0), insn);
2056 OP(1) = move_to_acc (1, insn);
2057
2058 MAYBE_OK (insn);
2059
2060 /* We have to copy op2 to HL, but that involves AX, which
2061 already has a live value. Emit it before those insns. */
2062
2063 if (prev)
2064 first = next_nonnote_nondebug_insn (prev);
2065 else
2066 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
2067 ;
2068
2069 OP (2) = hl_used ? move_to_de (2, first) : move_to_hl (2, first);
2070
2071 MAYBE_OK (insn);
2072
2073 FAILED;
2074}
2075
2076/* Devirtualize an insn of the form (SET () (unop (op))). */
2077
2078static void
2079rl78_alloc_physical_registers_ro1 (rtx insn)
2080{
2081 /* (void) op[0] */
2082 OP(0) = transcode_memory_rtx (OP(0), BC, insn);
2083
2084 MAYBE_OK (insn);
2085
2086 OP(0) = move_to_acc (0, insn);
2087
2088 MAYBE_OK (insn);
2089
2090 FAILED;
2091}
2092
2093/* Devirtualize a compare insn. */
2094static void
2095rl78_alloc_physical_registers_cmp (rtx insn)
2096{
2097 /* op[1] cmp_op[0] op[2] */
2098 rtx prev = prev_nonnote_nondebug_insn (insn);
2099 rtx first;
2100
2101 OP(1) = transcode_memory_rtx (OP(1), DE, insn);
2102 OP(2) = transcode_memory_rtx (OP(2), HL, insn);
2103
2104 MAYBE_OK (insn);
2105
2106 OP(1) = move_to_acc (1, insn);
2107
2108 MAYBE_OK (insn);
2109
2110 /* We have to copy op2 to HL, but that involves the acc, which
2111 already has a live value. Emit it before those insns. */
2112
2113 if (prev)
2114 first = next_nonnote_nondebug_insn (prev);
2115 else
2116 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
2117 ;
2118 OP(2) = move_to_hl (2, first);
2119
2120 MAYBE_OK (insn);
2121
2122 FAILED;
2123}
2124
2125/* Like op2, but AX = A op X. */
2126static void
2127rl78_alloc_physical_registers_umul (rtx insn)
2128{
2129 /* op[0] = op[1] func op[2] */
2130 rtx prev = prev_nonnote_nondebug_insn (insn);
2131 rtx first;
2132
2133 OP(0) = transcode_memory_rtx (OP(0), BC, insn);
2134 OP(1) = transcode_memory_rtx (OP(1), DE, insn);
2135 OP(2) = transcode_memory_rtx (OP(2), HL, insn);
2136
2137 MAYBE_OK (insn);
2138
2139 if (recog_data.constraints[1][0] == '%'
2140 && is_virtual_register (OP(1))
2141 && !is_virtual_register (OP(2))
2142 && !CONSTANT_P (OP(2)))
2143 {
2144 rtx tmp = OP(1);
2145 OP(1) = OP(2);
2146 OP(2) = tmp;
2147 }
2148
2149 OP(0) = move_from_acc (OP(0), insn);
2150 OP(1) = move_to_acc (1, insn);
2151
2152 MAYBE_OK (insn);
2153
2154 /* We have to copy op2 to X, but that involves the acc, which
2155 already has a live value. Emit it before those insns. */
2156
2157 if (prev)
2158 first = next_nonnote_nondebug_insn (prev);
2159 else
2160 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
2161 ;
2162 OP(2) = move_to_x (2, first);
2163
2164 MAYBE_OK (insn);
2165
2166 FAILED;
2167}
2168
2169/* Scan all insns and devirtualize them. */
2170static void
2171rl78_alloc_physical_registers (void)
2172{
2173 /* During most of the compile, gcc is dealing with virtual
2174 registers. At this point, we need to assign physical registers
2175 to the vitual ones, and copy in/out as needed. */
2176
2177 rtx insn, curr;
2178 enum attr_valloc valloc_method;
2179
2180 for (insn = get_insns (); insn; insn = curr)
2181 {
2182 int i;
2183
2184 curr = next_nonnote_nondebug_insn (insn);
2185
2186 if (INSN_P (insn)
2187 && (GET_CODE (PATTERN (insn)) == SET
2188 || GET_CODE (PATTERN (insn)) == CALL)
2189 && INSN_CODE (insn) == -1)
2190 {
2191 if (GET_CODE (SET_SRC (PATTERN (insn))) == ASM_OPERANDS)
2192 continue;
2193 i = recog (PATTERN (insn), insn, 0);
2194 if (i == -1)
2195 {
2196 debug_rtx (insn);
2197 gcc_unreachable ();
2198 }
2199 INSN_CODE (insn) = i;
2200 }
2201 }
2202
2203 cfun->machine->virt_insns_ok = 0;
2204 cfun->machine->real_insns_ok = 1;
2205
2206 for (insn = get_insns (); insn; insn = curr)
2207 {
2208 curr = insn ? next_nonnote_nondebug_insn (insn) : NULL;
2209
2210 if (!INSN_P (insn))
2211 continue;
2212 if (GET_CODE (PATTERN (insn)) != SET
2213 && GET_CODE (PATTERN (insn)) != CALL)
2214 continue;
2215
2216 if (GET_CODE (SET_SRC (PATTERN (insn))) == ASM_OPERANDS)
2217 continue;
2218
2219 valloc_method = get_attr_valloc (insn);
2220
2221 PATTERN (insn)= copy_rtx_if_shared (PATTERN (insn));
2222
2223 if (insn_ok_now (insn))
2224 continue;
2225
2226 INSN_CODE (insn) = -1;
2227
2228 if (RTX_FRAME_RELATED_P (insn))
2229 virt_insn_was_frame = 1;
2230 else
2231 virt_insn_was_frame = 0;
2232
2233 switch (valloc_method)
2234 {
2235 case VALLOC_OP1:
2236 rl78_alloc_physical_registers_op1 (insn);
2237 break;
2238 case VALLOC_OP2:
2239 rl78_alloc_physical_registers_op2 (insn);
2240 break;
2241 case VALLOC_RO1:
2242 rl78_alloc_physical_registers_ro1 (insn);
2243 break;
2244 case VALLOC_CMP:
2245 rl78_alloc_physical_registers_cmp (insn);
2246 break;
2247 case VALLOC_UMUL:
2248 rl78_alloc_physical_registers_umul (insn);
2249 break;
2250 case VALLOC_MACAX:
2251 /* Macro that clobbers AX */
2252 break;
2253 }
2254 }
2255#if DEBUG_ALLOC
2256 fprintf (stderr, "\033[0m");
2257#endif
2258}
2259
2260/* Add REG_DEAD notes using DEAD[reg] for rtx S which is part of INSN.
2261 This function scans for uses of registers; the last use (i.e. first
2262 encounter when scanning backwards) triggers a REG_DEAD note if the
2263 reg was previously in DEAD[]. */
2264static void
2265rl78_note_reg_uses (char *dead, rtx s, rtx insn)
2266{
2267 const char *fmt;
2268 int i, r;
2269 enum rtx_code code;
2270
2271 if (!s)
2272 return;
2273
2274 code = GET_CODE (s);
2275
2276 switch (code)
2277 {
2278 /* Compare registers by number. */
2279 case REG:
2280 r = REGNO (s);
2281 if (dump_file)
2282 {
2283 fprintf (dump_file, "note use reg %d size %d on insn %d\n",
2284 r, GET_MODE_SIZE (GET_MODE (s)), INSN_UID (insn));
2285 print_rtl_single (dump_file, s);
2286 }
2287 if (dead [r])
2288 add_reg_note (insn, REG_DEAD, gen_rtx_REG (GET_MODE (s), r));
2289 for (i = 0; i < GET_MODE_SIZE (GET_MODE (s)); i ++)
2290 dead [r + i] = 0;
2291 return;
2292
2293 /* These codes have no constituent expressions
2294 and are unique. */
2295 case SCRATCH:
2296 case CC0:
2297 case PC:
2298 return;
2299
2300 case CONST_INT:
2301 case CONST_VECTOR:
2302 case CONST_DOUBLE:
2303 case CONST_FIXED:
2304 /* These are kept unique for a given value. */
2305 return;
2306
2307 default:
2308 break;
2309 }
2310
2311 fmt = GET_RTX_FORMAT (code);
2312
2313 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
2314 {
2315 if (fmt[i] == 'E')
2316 {
2317 int j;
2318 for (j = XVECLEN (s, i) - 1; j >= 0; j--)
2319 rl78_note_reg_uses (dead, XVECEXP (s, i, j), insn);
2320 }
2321 else if (fmt[i] == 'e')
2322 rl78_note_reg_uses (dead, XEXP (s, i), insn);
2323 }
2324}
2325
2326/* Like the previous function, but scan for SETs instead. */
2327static void
2328rl78_note_reg_set (char *dead, rtx d, rtx insn)
2329{
2330 int r, i;
2331
2332 if (GET_CODE (d) != REG)
2333 return;
2334
2335 r = REGNO (d);
2336 if (dead [r])
2337 add_reg_note (insn, REG_UNUSED, gen_rtx_REG (GET_MODE (d), r));
2338 if (dump_file)
2339 fprintf (dump_file, "note set reg %d size %d\n", r, GET_MODE_SIZE (GET_MODE (d)));
2340 for (i = 0; i < GET_MODE_SIZE (GET_MODE (d)); i ++)
2341 dead [r + i] = 1;
2342}
2343
2344/* This is a rather crude register death pass. Death status is reset
2345 at every jump or call insn. */
2346static void
2347rl78_calculate_death_notes (void)
2348{
2349 char dead[FIRST_PSEUDO_REGISTER];
2350 rtx insn, p, s, d;
2351 int i;
2352
2353 memset (dead, 0, sizeof (dead));
2354
2355 for (insn = get_last_insn ();
2356 insn;
2357 insn = prev_nonnote_nondebug_insn (insn))
2358 {
2359 if (dump_file)
2360 {
2361 fprintf (dump_file, "\n--------------------------------------------------");
2362 fprintf (dump_file, "\nDead:");
2363 for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
2364 if (dead[i])
2365 fprintf(dump_file, " %s", reg_names[i]);
2366 fprintf (dump_file, "\n");
2367 print_rtl_single (dump_file, insn);
2368 }
2369
2370 switch (GET_CODE (insn))
2371 {
2372 case INSN:
2373 p = PATTERN (insn);
2374 switch (GET_CODE (p))
2375 {
2376 case SET:
2377 s = SET_SRC (p);
2378 d = SET_DEST (p);
2379 rl78_note_reg_set (dead, d, insn);
2380 rl78_note_reg_uses (dead, s, insn);
2381 break;
2382
2383 case USE:
2384 rl78_note_reg_uses (dead, p, insn);
2385 break;
2386
2387 default:
2388 break;
2389 }
2390 break;
2391
2392 case JUMP_INSN:
edf1f7ba 2393 if (INSN_CODE (insn) == CODE_FOR_rl78_return)
78e515f7 2394 {
2395 memset (dead, 1, sizeof (dead));
2396 /* We expect a USE just prior to this, which will mark
2397 the actual return registers. The USE will have a
2398 death note, but we aren't going to be modifying it
2399 after this pass. */
2400 break;
2401 }
2402 case CALL_INSN:
2403 memset (dead, 0, sizeof (dead));
2404 break;
2405
2406 default:
2407 break;
2408 }
2409 if (dump_file)
2410 print_rtl_single (dump_file, insn);
2411 }
2412}
2413
2414/* Helper function to reset the origins in RP and the age in AGE for
2415 all registers. */
2416static void
2417reset_origins (int *rp, int *age)
2418{
2419 int i;
2420 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2421 {
2422 rp[i] = i;
2423 age[i] = 0;
2424 }
2425}
2426
2427/* The idea behind this optimization is to look for cases where we
2428 move data from A to B to C, and instead move from A to B, and A to
2429 C. If B is a virtual register or memory, this is a big win on its
2430 own. If B turns out to be unneeded after this, it's a bigger win.
2431 For each register, we try to determine where it's value originally
2432 came from, if it's propogated purely through moves (and not
2433 computes). The ORIGINS[] array has the regno for the "origin" of
2434 the value in the [regno] it's indexed by. */
2435static void
2436rl78_propogate_register_origins (void)
2437{
2438 int origins[FIRST_PSEUDO_REGISTER];
2439 int age[FIRST_PSEUDO_REGISTER];
2440 int i;
2441 rtx insn, ninsn = NULL_RTX;
2442 rtx pat;
2443
2444 reset_origins (origins, age);
2445
2446 for (insn = get_insns (); insn; insn = ninsn)
2447 {
2448 ninsn = next_nonnote_nondebug_insn (insn);
2449
2450 if (dump_file)
2451 {
2452 fprintf (dump_file, "\n");
2453 fprintf (dump_file, "Origins:");
2454 for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
2455 if (origins[i] != i)
2456 fprintf (dump_file, " r%d=r%d", i, origins[i]);
2457 fprintf (dump_file, "\n");
2458 print_rtl_single (dump_file, insn);
2459 }
2460
2461 switch (GET_CODE (insn))
2462 {
2463 case CODE_LABEL:
2464 case BARRIER:
2465 case CALL_INSN:
2466 case JUMP_INSN:
2467 reset_origins (origins, age);
2468 break;
2469
2470 default:
2471 break;
2472
2473 case INSN:
2474 pat = PATTERN (insn);
2475
2476 if (GET_CODE (pat) == PARALLEL)
2477 {
2478 rtx clobber = XVECEXP (pat, 0, 1);
2479 pat = XVECEXP (pat, 0, 0);
2480 if (GET_CODE (clobber) == CLOBBER)
2481 {
2482 int cr = REGNO (XEXP (clobber, 0));
2483 int mb = GET_MODE_SIZE (GET_MODE (XEXP (clobber, 0)));
2484 if (dump_file)
2485 fprintf (dump_file, "reset origins of %d regs at %d\n", mb, cr);
2486 for (i = 0; i < mb; i++)
2487 {
2488 origins[cr + i] = cr + i;
2489 age[cr + i] = 0;
2490 }
2491 }
2492 else
2493 break;
2494 }
2495
2496 if (GET_CODE (pat) == SET)
2497 {
2498 rtx src = SET_SRC (pat);
2499 rtx dest = SET_DEST (pat);
2500 int mb = GET_MODE_SIZE (GET_MODE (dest));
2501
2502 if (GET_CODE (dest) == REG)
2503 {
2504 int dr = REGNO (dest);
2505
2506 if (GET_CODE (src) == REG)
2507 {
2508 int sr = REGNO (src);
2509 int same = 1;
2510 int best_age, best_reg;
2511
2512 /* See if the copy is not needed. */
2513 for (i = 0; i < mb; i ++)
2514 if (origins[dr + i] != origins[sr + i])
2515 same = 0;
2516 if (same)
2517 {
2518 if (dump_file)
2519 fprintf (dump_file, "deleting because dest already has correct value\n");
2520 delete_insn (insn);
2521 break;
2522 }
2523
2524 if (dr < 8 || sr >= 8)
2525 {
2526 int ar;
2527
2528 best_age = -1;
2529 best_reg = -1;
2530 /* See if the copy can be made from another
2531 bank 0 register instead, instead of the
2532 virtual src register. */
2533 for (ar = 0; ar < 8; ar += mb)
2534 {
2535 same = 1;
2536 for (i = 0; i < mb; i ++)
2537 if (origins[ar + i] != origins[sr + i])
2538 same = 0;
2539
2540 /* The chip has some reg-reg move limitations. */
2541 if (mb == 1 && dr > 3)
2542 same = 0;
2543
2544 if (same)
2545 {
2546 if (best_age == -1 || best_age > age[sr + i])
2547 {
2548 best_age = age[sr + i];
2549 best_reg = sr;
2550 }
2551 }
2552 }
2553
2554 if (best_reg != -1)
2555 {
2556 /* FIXME: copy debug info too. */
2557 SET_SRC (pat) = gen_rtx_REG (GET_MODE (src), best_reg);
2558 sr = best_reg;
2559 }
2560 }
2561
2562 for (i = 0; i < mb; i++)
2563 {
2564 origins[dr + i] = origins[sr + i];
2565 age[dr + i] = age[sr + i] + 1;
2566 }
2567 }
2568 else
2569 {
2570 /* The destination is computed, its origin is itself. */
2571 if (dump_file)
2572 fprintf (dump_file, "resetting origin of r%d for %d byte%s\n",
2573 dr, mb, mb == 1 ? "" : "s");
2574 for (i = 0; i < mb; i ++)
2575 {
2576 origins[dr + i] = dr + i;
2577 age[dr + i] = 0;
2578 }
2579 }
2580
2581 /* Any registers marked with that reg as an origin are reset. */
2582 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2583 if (origins[i] >= dr && origins[i] < dr + mb)
2584 {
2585 origins[i] = i;
2586 age[i] = 0;
2587 }
2588 }
2589
2590 /* Special case - our ADDSI3 macro uses AX */
2591 if (get_attr_valloc (insn) == VALLOC_MACAX)
2592 {
2593 if (dump_file)
2594 fprintf (dump_file, "Resetting origin of AX for macro.\n");
2595 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2596 if (i <= 1 || origins[i] <= 1)
2597 {
2598 origins[i] = i;
2599 age[i] = 0;
2600 }
2601 }
2602
2603 if (GET_CODE (src) == ASHIFT
2604 || GET_CODE (src) == ASHIFTRT
2605 || GET_CODE (src) == LSHIFTRT)
2606 {
2607 rtx count = XEXP (src, 1);
2608 if (GET_CODE (count) == REG)
2609 {
2610 /* Special case - our pattern clobbers the count register. */
2611 int r = REGNO (count);
2612 if (dump_file)
2613 fprintf (dump_file, "Resetting origin of r%d for shift.\n", r);
2614 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2615 if (i == r || origins[i] == r)
2616 {
2617 origins[i] = i;
2618 age[i] = 0;
2619 }
2620 }
2621 }
2622 }
2623 }
2624 }
2625}
2626
2627/* Remove any SETs where the destination is unneeded. */
2628static void
2629rl78_remove_unused_sets (void)
2630{
2631 rtx insn, ninsn = NULL_RTX;
2632 rtx dest;
2633
2634 for (insn = get_insns (); insn; insn = ninsn)
2635 {
2636 ninsn = next_nonnote_nondebug_insn (insn);
2637
2638 if ((insn = single_set (insn)) == NULL_RTX)
2639 continue;
2640
2641 dest = SET_DEST (insn);
2642
2643 if (REGNO (dest) > 23)
2644 continue;
2645
2646 if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
2647 delete_insn (insn);
2648 }
2649}
2650
2651#undef xTARGET_MACHINE_DEPENDENT_REORG
2652#define xTARGET_MACHINE_DEPENDENT_REORG rl78_reorg
2653
2654/* This is the top of the devritualization pass. */
2655static void
2656rl78_reorg (void)
2657{
2658 rl78_alloc_physical_registers ();
2659
2660 if (dump_file)
2661 {
2662 fprintf (dump_file, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n");
2663 print_rtl_with_bb (dump_file, get_insns ());
2664 }
2665
2666 rl78_propogate_register_origins ();
2667 rl78_calculate_death_notes ();
2668
2669 if (dump_file)
2670 {
2671 fprintf (dump_file, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n");
2672 print_rtl_with_bb (dump_file, get_insns ());
2673 fprintf (dump_file, "\n======================================================================\n");
2674 }
2675
2676 rl78_remove_unused_sets ();
2677
2678 /* The code after devirtualizing has changed so much that at this point
2679 we might as well just rescan everything. Note that
2680 df_rescan_all_insns is not going to help here because it does not
2681 touch the artificial uses and defs. */
2682 df_finish_pass (true);
2683 if (optimize > 1)
2684 df_live_add_problem ();
2685 df_scan_alloc (NULL);
2686 df_scan_blocks ();
2687
2688 if (optimize)
2689 df_analyze ();
2690}
2691
2692#undef TARGET_RETURN_IN_MEMORY
2693#define TARGET_RETURN_IN_MEMORY rl78_return_in_memory
2694
2695static bool
2696rl78_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
2697{
2698 const HOST_WIDE_INT size = int_size_in_bytes (type);
2699 return (size == -1 || size > 8);
2700}
2701
2702\f
2703struct gcc_target targetm = TARGET_INITIALIZER;
2704
2705#include "gt-rl78.h"