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