rl78.cc revision 1.1 1 1.1 mrg /* Subroutines used for code generation on Renesas RL78 processors.
2 1.1 mrg Copyright (C) 2011-2022 Free Software Foundation, Inc.
3 1.1 mrg Contributed by Red Hat.
4 1.1 mrg
5 1.1 mrg This file is part of GCC.
6 1.1 mrg
7 1.1 mrg GCC is free software; you can redistribute it and/or modify
8 1.1 mrg it under the terms of the GNU General Public License as published by
9 1.1 mrg the Free Software Foundation; either version 3, or (at your option)
10 1.1 mrg any later version.
11 1.1 mrg
12 1.1 mrg GCC is distributed in the hope that it will be useful,
13 1.1 mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 mrg GNU General Public License for more details.
16 1.1 mrg
17 1.1 mrg You should have received a copy of the GNU General Public License
18 1.1 mrg along with GCC; see the file COPYING3. If not see
19 1.1 mrg <http://www.gnu.org/licenses/>. */
20 1.1 mrg
21 1.1 mrg #define IN_TARGET_CODE 1
22 1.1 mrg
23 1.1 mrg #include "config.h"
24 1.1 mrg #include "system.h"
25 1.1 mrg #include "coretypes.h"
26 1.1 mrg #include "backend.h"
27 1.1 mrg #include "target.h"
28 1.1 mrg #include "rtl.h"
29 1.1 mrg #include "tree.h"
30 1.1 mrg #include "df.h"
31 1.1 mrg #include "memmodel.h"
32 1.1 mrg #include "tm_p.h"
33 1.1 mrg #include "stringpool.h"
34 1.1 mrg #include "attribs.h"
35 1.1 mrg #include "optabs.h"
36 1.1 mrg #include "emit-rtl.h"
37 1.1 mrg #include "recog.h"
38 1.1 mrg #include "diagnostic-core.h"
39 1.1 mrg #include "varasm.h"
40 1.1 mrg #include "stor-layout.h"
41 1.1 mrg #include "calls.h"
42 1.1 mrg #include "output.h"
43 1.1 mrg #include "insn-attr.h"
44 1.1 mrg #include "explow.h"
45 1.1 mrg #include "expr.h"
46 1.1 mrg #include "reload.h"
47 1.1 mrg #include "cfgrtl.h"
48 1.1 mrg #include "langhooks.h"
49 1.1 mrg #include "tree-pass.h"
50 1.1 mrg #include "context.h"
51 1.1 mrg #include "tm-constrs.h" /* for satisfies_constraint_*(). */
52 1.1 mrg #include "builtins.h"
53 1.1 mrg
54 1.1 mrg /* This file should be included last. */
55 1.1 mrg #include "target-def.h"
56 1.1 mrg
57 1.1 mrg static inline bool is_interrupt_func (const_tree decl);
59 1.1 mrg static inline bool is_brk_interrupt_func (const_tree decl);
60 1.1 mrg static void rl78_reorg (void);
61 1.1 mrg static const char *rl78_strip_name_encoding (const char *);
62 1.1 mrg static const char *rl78_strip_nonasm_name_encoding (const char *);
63 1.1 mrg static section * rl78_select_section (tree, int, unsigned HOST_WIDE_INT);
64 1.1 mrg
65 1.1 mrg
67 1.1 mrg /* Debugging statements are tagged with DEBUG0 only so that they can
68 1.1 mrg be easily enabled individually, by replacing the '0' with '1' as
69 1.1 mrg needed. */
70 1.1 mrg #define DEBUG0 0
71 1.1 mrg #define DEBUG1 1
72 1.1 mrg
73 1.1 mrg /* REGISTER_NAMES has the names for individual 8-bit registers, but
74 1.1 mrg these have the names we need to use when referring to 16-bit
75 1.1 mrg register pairs. */
76 1.1 mrg static const char * const word_regnames[] =
77 1.1 mrg {
78 1.1 mrg "ax", "AX", "bc", "BC", "de", "DE", "hl", "HL",
79 1.1 mrg "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
80 1.1 mrg "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
81 1.1 mrg "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
82 1.1 mrg "sp", "ap", "psw", "es", "cs"
83 1.1 mrg };
84 1.1 mrg
85 1.1 mrg /* used by rl78_addsi3_internal for formatting insns output */
86 1.1 mrg static char fmt_buffer[1024];
87 1.1 mrg
88 1.1 mrg /* Structure for G13 MDUC registers. */
89 1.1 mrg struct mduc_reg_type
90 1.1 mrg {
91 1.1 mrg unsigned int address;
92 1.1 mrg enum machine_mode mode;
93 1.1 mrg };
94 1.1 mrg
95 1.1 mrg struct mduc_reg_type mduc_regs[] =
96 1.1 mrg {
97 1.1 mrg {0xf00e8, E_QImode},
98 1.1 mrg {0xffff0, E_HImode},
99 1.1 mrg {0xffff2, E_HImode},
100 1.1 mrg {0xf2224, E_HImode},
101 1.1 mrg {0xf00e0, E_HImode},
102 1.1 mrg {0xf00e2, E_HImode}
103 1.1 mrg };
104 1.1 mrg
105 1.1 mrg struct GTY(()) machine_function
106 1.1 mrg {
107 1.1 mrg /* If set, the rest of the fields have been computed. */
108 1.1 mrg int computed;
109 1.1 mrg /* Which register pairs need to be pushed in the prologue. */
110 1.1 mrg int need_to_push [FIRST_PSEUDO_REGISTER / 2];
111 1.1 mrg
112 1.1 mrg /* These fields describe the frame layout... */
113 1.1 mrg /* arg pointer */
114 1.1 mrg /* 4 bytes for saved PC */
115 1.1 mrg int framesize_regs;
116 1.1 mrg /* frame pointer */
117 1.1 mrg int framesize_locals;
118 1.1 mrg int framesize_outgoing;
119 1.1 mrg /* stack pointer */
120 1.1 mrg int framesize;
121 1.1 mrg
122 1.1 mrg /* If set, recog is allowed to match against the "real" patterns. */
123 1.1 mrg int real_insns_ok;
124 1.1 mrg /* If set, recog is allowed to match against the "virtual" patterns. */
125 1.1 mrg int virt_insns_ok;
126 1.1 mrg /* Set if the current function needs to clean up any trampolines. */
127 1.1 mrg int trampolines_used;
128 1.1 mrg /* True if the ES register is used and hence
129 1.1 mrg needs to be saved inside interrupt handlers. */
130 1.1 mrg bool uses_es;
131 1.1 mrg };
132 1.1 mrg
133 1.1 mrg /* This is our init_machine_status, as set in
134 1.1 mrg rl78_option_override. */
135 1.1 mrg static struct machine_function *
136 1.1 mrg rl78_init_machine_status (void)
137 1.1 mrg {
138 1.1 mrg struct machine_function *m;
139 1.1 mrg
140 1.1 mrg m = ggc_cleared_alloc<machine_function> ();
141 1.1 mrg m->virt_insns_ok = 1;
142 1.1 mrg
143 1.1 mrg return m;
144 1.1 mrg }
145 1.1 mrg
146 1.1 mrg /* This pass converts virtual instructions using virtual registers, to
147 1.1 mrg real instructions using real registers. Rather than run it as
148 1.1 mrg reorg, we reschedule it before vartrack to help with debugging. */
149 1.1 mrg namespace
150 1.1 mrg {
151 1.1 mrg const pass_data pass_data_rl78_devirt =
152 1.1 mrg {
153 1.1 mrg RTL_PASS, /* type */
154 1.1 mrg "devirt", /* name */
155 1.1 mrg OPTGROUP_NONE, /* optinfo_flags */
156 1.1 mrg TV_MACH_DEP, /* tv_id */
157 1.1 mrg 0, /* properties_required */
158 1.1 mrg 0, /* properties_provided */
159 1.1 mrg 0, /* properties_destroyed */
160 1.1 mrg 0, /* todo_flags_start */
161 1.1 mrg 0, /* todo_flags_finish */
162 1.1 mrg };
163 1.1 mrg
164 1.1 mrg class pass_rl78_devirt : public rtl_opt_pass
165 1.1 mrg {
166 1.1 mrg public:
167 1.1 mrg pass_rl78_devirt (gcc::context *ctxt)
168 1.1 mrg : rtl_opt_pass (pass_data_rl78_devirt, ctxt)
169 1.1 mrg {
170 1.1 mrg }
171 1.1 mrg
172 1.1 mrg /* opt_pass methods: */
173 1.1 mrg virtual unsigned int execute (function *)
174 1.1 mrg {
175 1.1 mrg rl78_reorg ();
176 1.1 mrg return 0;
177 1.1 mrg }
178 1.1 mrg };
179 1.1 mrg } // anon namespace
180 1.1 mrg
181 1.1 mrg rtl_opt_pass *
182 1.1 mrg make_pass_rl78_devirt (gcc::context *ctxt)
183 1.1 mrg {
184 1.1 mrg return new pass_rl78_devirt (ctxt);
185 1.1 mrg }
186 1.1 mrg
187 1.1 mrg /* Redundant move elimination pass. Must be run after the basic block
188 1.1 mrg reordering pass for the best effect. */
189 1.1 mrg
190 1.1 mrg static unsigned int
191 1.1 mrg move_elim_pass (void)
192 1.1 mrg {
193 1.1 mrg rtx_insn *insn, *ninsn;
194 1.1 mrg rtx prev = NULL_RTX;
195 1.1 mrg
196 1.1 mrg for (insn = get_insns (); insn; insn = ninsn)
197 1.1 mrg {
198 1.1 mrg rtx set;
199 1.1 mrg
200 1.1 mrg ninsn = next_nonnote_nondebug_insn (insn);
201 1.1 mrg
202 1.1 mrg if ((set = single_set (insn)) == NULL_RTX)
203 1.1 mrg {
204 1.1 mrg prev = NULL_RTX;
205 1.1 mrg continue;
206 1.1 mrg }
207 1.1 mrg
208 1.1 mrg /* If we have two SET insns in a row (without anything
209 1.1 mrg between them) and the source of the second one is the
210 1.1 mrg destination of the first one, and vice versa, then we
211 1.1 mrg can eliminate the second SET. */
212 1.1 mrg if (prev
213 1.1 mrg && rtx_equal_p (SET_DEST (prev), SET_SRC (set))
214 1.1 mrg && rtx_equal_p (SET_DEST (set), SET_SRC (prev))
215 1.1 mrg /* ... and none of the operands are volatile. */
216 1.1 mrg && ! volatile_refs_p (SET_SRC (prev))
217 1.1 mrg && ! volatile_refs_p (SET_DEST (prev))
218 1.1 mrg && ! volatile_refs_p (SET_SRC (set))
219 1.1 mrg && ! volatile_refs_p (SET_DEST (set)))
220 1.1 mrg {
221 1.1 mrg if (dump_file)
222 1.1 mrg fprintf (dump_file, " Delete insn %d because it is redundant\n",
223 1.1 mrg INSN_UID (insn));
224 1.1 mrg
225 1.1 mrg delete_insn (insn);
226 1.1 mrg prev = NULL_RTX;
227 1.1 mrg }
228 1.1 mrg else
229 1.1 mrg prev = set;
230 1.1 mrg }
231 1.1 mrg
232 1.1 mrg if (dump_file)
233 1.1 mrg print_rtl_with_bb (dump_file, get_insns (), TDF_NONE);
234 1.1 mrg
235 1.1 mrg return 0;
236 1.1 mrg }
237 1.1 mrg
238 1.1 mrg namespace
239 1.1 mrg {
240 1.1 mrg const pass_data pass_data_rl78_move_elim =
241 1.1 mrg {
242 1.1 mrg RTL_PASS, /* type */
243 1.1 mrg "move_elim", /* name */
244 1.1 mrg OPTGROUP_NONE, /* optinfo_flags */
245 1.1 mrg TV_MACH_DEP, /* tv_id */
246 1.1 mrg 0, /* properties_required */
247 1.1 mrg 0, /* properties_provided */
248 1.1 mrg 0, /* properties_destroyed */
249 1.1 mrg 0, /* todo_flags_start */
250 1.1 mrg 0, /* todo_flags_finish */
251 1.1 mrg };
252 1.1 mrg
253 1.1 mrg class pass_rl78_move_elim : public rtl_opt_pass
254 1.1 mrg {
255 1.1 mrg public:
256 1.1 mrg pass_rl78_move_elim (gcc::context *ctxt)
257 1.1 mrg : rtl_opt_pass (pass_data_rl78_move_elim, ctxt)
258 1.1 mrg {
259 1.1 mrg }
260 1.1 mrg
261 1.1 mrg /* opt_pass methods: */
262 1.1 mrg virtual unsigned int execute (function *) { return move_elim_pass (); }
263 1.1 mrg };
264 1.1 mrg } // anon namespace
265 1.1 mrg
266 1.1 mrg rtl_opt_pass *
267 1.1 mrg make_pass_rl78_move_elim (gcc::context *ctxt)
268 1.1 mrg {
269 1.1 mrg return new pass_rl78_move_elim (ctxt);
270 1.1 mrg }
271 1.1 mrg
272 1.1 mrg #undef TARGET_ASM_FILE_START
273 1.1 mrg #define TARGET_ASM_FILE_START rl78_asm_file_start
274 1.1 mrg
275 1.1 mrg static void
276 1.1 mrg rl78_asm_file_start (void)
277 1.1 mrg {
278 1.1 mrg int i;
279 1.1 mrg
280 1.1 mrg if (TARGET_G10)
281 1.1 mrg {
282 1.1 mrg /* The memory used is 0xffec8 to 0xffedf; real registers are in
283 1.1 mrg 0xffee0 to 0xffee7. */
284 1.1 mrg for (i = 8; i < 32; i++)
285 1.1 mrg fprintf (asm_out_file, "r%d\t=\t0x%x\n", i, 0xffec0 + i);
286 1.1 mrg }
287 1.1 mrg else
288 1.1 mrg {
289 1.1 mrg for (i = 0; i < 8; i++)
290 1.1 mrg {
291 1.1 mrg fprintf (asm_out_file, "r%d\t=\t0x%x\n", 8 + i, 0xffef0 + i);
292 1.1 mrg fprintf (asm_out_file, "r%d\t=\t0x%x\n", 16 + i, 0xffee8 + i);
293 1.1 mrg fprintf (asm_out_file, "r%d\t=\t0x%x\n", 24 + i, 0xffee0 + i);
294 1.1 mrg }
295 1.1 mrg }
296 1.1 mrg
297 1.1 mrg opt_pass *rl78_devirt_pass = make_pass_rl78_devirt (g);
298 1.1 mrg struct register_pass_info rl78_devirt_info =
299 1.1 mrg {
300 1.1 mrg rl78_devirt_pass,
301 1.1 mrg "pro_and_epilogue",
302 1.1 mrg 1,
303 1.1 mrg PASS_POS_INSERT_BEFORE
304 1.1 mrg };
305 1.1 mrg
306 1.1 mrg opt_pass *rl78_move_elim_pass = make_pass_rl78_move_elim (g);
307 1.1 mrg struct register_pass_info rl78_move_elim_info =
308 1.1 mrg {
309 1.1 mrg rl78_move_elim_pass,
310 1.1 mrg "bbro",
311 1.1 mrg 1,
312 1.1 mrg PASS_POS_INSERT_AFTER
313 1.1 mrg };
314 1.1 mrg
315 1.1 mrg register_pass (& rl78_devirt_info);
316 1.1 mrg register_pass (& rl78_move_elim_info);
317 1.1 mrg }
318 1.1 mrg
319 1.1 mrg void
320 1.1 mrg rl78_output_symbol_ref (FILE * file, rtx sym)
321 1.1 mrg {
322 1.1 mrg tree type = SYMBOL_REF_DECL (sym);
323 1.1 mrg const char *str = XSTR (sym, 0);
324 1.1 mrg
325 1.1 mrg if (str[0] == '*')
326 1.1 mrg {
327 1.1 mrg fputs (str + 1, file);
328 1.1 mrg }
329 1.1 mrg else
330 1.1 mrg {
331 1.1 mrg str = rl78_strip_nonasm_name_encoding (str);
332 1.1 mrg if (type && TREE_CODE (type) == FUNCTION_DECL)
333 1.1 mrg {
334 1.1 mrg fprintf (file, "%%code(");
335 1.1 mrg assemble_name (file, str);
336 1.1 mrg fprintf (file, ")");
337 1.1 mrg }
338 1.1 mrg else
339 1.1 mrg assemble_name (file, str);
340 1.1 mrg }
341 1.1 mrg }
342 1.1 mrg
343 1.1 mrg #undef TARGET_OPTION_OVERRIDE
345 1.1 mrg #define TARGET_OPTION_OVERRIDE rl78_option_override
346 1.1 mrg
347 1.1 mrg #define MUST_SAVE_MDUC_REGISTERS \
348 1.1 mrg (TARGET_SAVE_MDUC_REGISTERS \
349 1.1 mrg && (is_interrupt_func (NULL_TREE)) && RL78_MUL_G13)
350 1.1 mrg
351 1.1 mrg static void
352 1.1 mrg rl78_option_override (void)
353 1.1 mrg {
354 1.1 mrg flag_omit_frame_pointer = 1;
355 1.1 mrg flag_no_function_cse = 1;
356 1.1 mrg flag_split_wide_types = 0;
357 1.1 mrg
358 1.1 mrg init_machine_status = rl78_init_machine_status;
359 1.1 mrg
360 1.1 mrg if (TARGET_ALLREGS)
361 1.1 mrg {
362 1.1 mrg int i;
363 1.1 mrg
364 1.1 mrg for (i = 24; i < 32; i++)
365 1.1 mrg fixed_regs[i] = 0;
366 1.1 mrg }
367 1.1 mrg
368 1.1 mrg if (TARGET_ES0
369 1.1 mrg && strcmp (lang_hooks.name, "GNU C")
370 1.1 mrg && strcmp (lang_hooks.name, "GNU C11")
371 1.1 mrg && strcmp (lang_hooks.name, "GNU C17")
372 1.1 mrg && strcmp (lang_hooks.name, "GNU C2X")
373 1.1 mrg && strcmp (lang_hooks.name, "GNU C89")
374 1.1 mrg && strcmp (lang_hooks.name, "GNU C99")
375 1.1 mrg /* Compiling with -flto results in a language of GNU GIMPLE being used... */
376 1.1 mrg && strcmp (lang_hooks.name, "GNU GIMPLE"))
377 1.1 mrg /* Address spaces are currently only supported by C. */
378 1.1 mrg error ("%<-mes0%> can only be used with C");
379 1.1 mrg
380 1.1 mrg if (TARGET_SAVE_MDUC_REGISTERS && !(TARGET_G13 || RL78_MUL_G13))
381 1.1 mrg warning (0, "mduc registers only saved for G13 target");
382 1.1 mrg
383 1.1 mrg switch (rl78_cpu_type)
384 1.1 mrg {
385 1.1 mrg case CPU_UNINIT:
386 1.1 mrg rl78_cpu_type = CPU_G14;
387 1.1 mrg if (rl78_mul_type == MUL_UNINIT)
388 1.1 mrg rl78_mul_type = MUL_NONE;
389 1.1 mrg break;
390 1.1 mrg
391 1.1 mrg case CPU_G10:
392 1.1 mrg switch (rl78_mul_type)
393 1.1 mrg {
394 1.1 mrg case MUL_UNINIT: rl78_mul_type = MUL_NONE; break;
395 1.1 mrg case MUL_NONE: break;
396 1.1 mrg case MUL_G13: error ("%<-mmul=g13%> cannot be used with "
397 1.1 mrg "%<-mcpu=g10%>"); break;
398 1.1 mrg case MUL_G14: error ("%<-mmul=g14%> cannot be used with "
399 1.1 mrg "%<-mcpu=g10%>"); break;
400 1.1 mrg }
401 1.1 mrg break;
402 1.1 mrg
403 1.1 mrg case CPU_G13:
404 1.1 mrg switch (rl78_mul_type)
405 1.1 mrg {
406 1.1 mrg case MUL_UNINIT: rl78_mul_type = MUL_G13; break;
407 1.1 mrg case MUL_NONE: break;
408 1.1 mrg case MUL_G13: break;
409 1.1 mrg /* The S2 core does not have mul/div instructions. */
410 1.1 mrg case MUL_G14: error ("%<-mmul=g14%> cannot be used with "
411 1.1 mrg "%<-mcpu=g13%>"); break;
412 1.1 mrg }
413 1.1 mrg break;
414 1.1 mrg
415 1.1 mrg case CPU_G14:
416 1.1 mrg switch (rl78_mul_type)
417 1.1 mrg {
418 1.1 mrg case MUL_UNINIT: rl78_mul_type = MUL_G14; break;
419 1.1 mrg case MUL_NONE: break;
420 1.1 mrg case MUL_G14: break;
421 1.1 mrg /* The G14 core does not have the hardware multiply peripheral used by the
422 1.1 mrg G13 core, hence you cannot use G13 multipliy routines on G14 hardware. */
423 1.1 mrg case MUL_G13: error ("%<-mmul=g13%> cannot be used with "
424 1.1 mrg "%<-mcpu=g14%>"); break;
425 1.1 mrg }
426 1.1 mrg break;
427 1.1 mrg }
428 1.1 mrg }
429 1.1 mrg
430 1.1 mrg /* Most registers are 8 bits. Some are 16 bits because, for example,
431 1.1 mrg gcc doesn't like dealing with $FP as a register pair (the second
432 1.1 mrg half of $fp is also 2 to keep reload happy wrt register pairs, but
433 1.1 mrg no register class includes it). This table maps register numbers
434 1.1 mrg to size in bytes. */
435 1.1 mrg static const int register_sizes[] =
436 1.1 mrg {
437 1.1 mrg 1, 1, 1, 1, 1, 1, 1, 1,
438 1.1 mrg 1, 1, 1, 1, 1, 1, 1, 1,
439 1.1 mrg 1, 1, 1, 1, 1, 1, 2, 2,
440 1.1 mrg 1, 1, 1, 1, 1, 1, 1, 1,
441 1.1 mrg 2, 2, 1, 1, 1
442 1.1 mrg };
443 1.1 mrg
444 1.1 mrg /* Predicates used in the MD patterns. This one is true when virtual
445 1.1 mrg insns may be matched, which typically means before (or during) the
446 1.1 mrg devirt pass. */
447 1.1 mrg bool
448 1.1 mrg rl78_virt_insns_ok (void)
449 1.1 mrg {
450 1.1 mrg if (cfun)
451 1.1 mrg return cfun->machine->virt_insns_ok;
452 1.1 mrg return true;
453 1.1 mrg }
454 1.1 mrg
455 1.1 mrg /* Predicates used in the MD patterns. This one is true when real
456 1.1 mrg insns may be matched, which typically means after (or during) the
457 1.1 mrg devirt pass. */
458 1.1 mrg bool
459 1.1 mrg rl78_real_insns_ok (void)
460 1.1 mrg {
461 1.1 mrg if (cfun)
462 1.1 mrg return cfun->machine->real_insns_ok;
463 1.1 mrg return false;
464 1.1 mrg }
465 1.1 mrg
466 1.1 mrg #undef TARGET_HARD_REGNO_NREGS
467 1.1 mrg #define TARGET_HARD_REGNO_NREGS rl78_hard_regno_nregs
468 1.1 mrg
469 1.1 mrg static unsigned int
470 1.1 mrg rl78_hard_regno_nregs (unsigned int regno, machine_mode mode)
471 1.1 mrg {
472 1.1 mrg int rs = register_sizes[regno];
473 1.1 mrg if (rs < 1)
474 1.1 mrg rs = 1;
475 1.1 mrg return ((GET_MODE_SIZE (mode) + rs - 1) / rs);
476 1.1 mrg }
477 1.1 mrg
478 1.1 mrg #undef TARGET_HARD_REGNO_MODE_OK
479 1.1 mrg #define TARGET_HARD_REGNO_MODE_OK rl78_hard_regno_mode_ok
480 1.1 mrg
481 1.1 mrg static bool
482 1.1 mrg rl78_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
483 1.1 mrg {
484 1.1 mrg int s = GET_MODE_SIZE (mode);
485 1.1 mrg
486 1.1 mrg if (s < 1)
487 1.1 mrg return false;
488 1.1 mrg /* These are not to be used by gcc. */
489 1.1 mrg if (regno == 23 || regno == ES_REG || regno == CS_REG)
490 1.1 mrg return false;
491 1.1 mrg /* $fp can always be accessed as a 16-bit value. */
492 1.1 mrg if (regno == FP_REG && s == 2)
493 1.1 mrg return true;
494 1.1 mrg if (regno < SP_REG)
495 1.1 mrg {
496 1.1 mrg /* Since a reg-reg move is really a reg-mem move, we must
497 1.1 mrg enforce alignment. */
498 1.1 mrg if (s > 1 && (regno % 2))
499 1.1 mrg return false;
500 1.1 mrg return true;
501 1.1 mrg }
502 1.1 mrg if (s == CC_REGNUM)
503 1.1 mrg return (mode == BImode);
504 1.1 mrg /* All other registers must be accessed in their natural sizes. */
505 1.1 mrg if (s == register_sizes [regno])
506 1.1 mrg return true;
507 1.1 mrg return false;
508 1.1 mrg }
509 1.1 mrg
510 1.1 mrg #undef TARGET_MODES_TIEABLE_P
511 1.1 mrg #define TARGET_MODES_TIEABLE_P rl78_modes_tieable_p
512 1.1 mrg
513 1.1 mrg static bool
514 1.1 mrg rl78_modes_tieable_p (machine_mode mode1, machine_mode mode2)
515 1.1 mrg {
516 1.1 mrg return ((GET_MODE_CLASS (mode1) == MODE_FLOAT
517 1.1 mrg || GET_MODE_CLASS (mode1) == MODE_COMPLEX_FLOAT)
518 1.1 mrg == (GET_MODE_CLASS (mode2) == MODE_FLOAT
519 1.1 mrg || GET_MODE_CLASS (mode2) == MODE_COMPLEX_FLOAT));
520 1.1 mrg }
521 1.1 mrg
522 1.1 mrg /* Simplify_gen_subreg() doesn't handle memory references the way we
523 1.1 mrg need it to below, so we use this function for when we must get a
524 1.1 mrg valid subreg in a "natural" state. */
525 1.1 mrg static rtx
526 1.1 mrg rl78_subreg (machine_mode mode, rtx r, machine_mode omode, int byte)
527 1.1 mrg {
528 1.1 mrg if (GET_CODE (r) == MEM)
529 1.1 mrg return adjust_address (r, mode, byte);
530 1.1 mrg else
531 1.1 mrg return simplify_gen_subreg (mode, r, omode, byte);
532 1.1 mrg }
533 1.1 mrg
534 1.1 mrg /* Used by movsi. Split SImode moves into two HImode moves, using
535 1.1 mrg appropriate patterns for the upper and lower halves of symbols. */
536 1.1 mrg void
537 1.1 mrg rl78_expand_movsi (rtx *operands)
538 1.1 mrg {
539 1.1 mrg rtx op00, op02, op10, op12;
540 1.1 mrg
541 1.1 mrg op00 = rl78_subreg (HImode, operands[0], SImode, 0);
542 1.1 mrg op02 = rl78_subreg (HImode, operands[0], SImode, 2);
543 1.1 mrg if (GET_CODE (operands[1]) == CONST
544 1.1 mrg || GET_CODE (operands[1]) == SYMBOL_REF)
545 1.1 mrg {
546 1.1 mrg op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
547 1.1 mrg op10 = gen_rtx_CONST (HImode, op10);
548 1.1 mrg op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
549 1.1 mrg op12 = gen_rtx_CONST (HImode, op12);
550 1.1 mrg }
551 1.1 mrg else
552 1.1 mrg {
553 1.1 mrg op10 = rl78_subreg (HImode, operands[1], SImode, 0);
554 1.1 mrg op12 = rl78_subreg (HImode, operands[1], SImode, 2);
555 1.1 mrg }
556 1.1 mrg
557 1.1 mrg if (rtx_equal_p (operands[0], operands[1]))
558 1.1 mrg ;
559 1.1 mrg else if (rtx_equal_p (op00, op12))
560 1.1 mrg {
561 1.1 mrg emit_move_insn (op02, op12);
562 1.1 mrg emit_move_insn (op00, op10);
563 1.1 mrg }
564 1.1 mrg else
565 1.1 mrg {
566 1.1 mrg emit_move_insn (op00, op10);
567 1.1 mrg emit_move_insn (op02, op12);
568 1.1 mrg }
569 1.1 mrg }
570 1.1 mrg
571 1.1 mrg /* Generate code to move an SImode value. */
572 1.1 mrg void
573 1.1 mrg rl78_split_movsi (rtx *operands, machine_mode omode)
574 1.1 mrg {
575 1.1 mrg rtx op00, op02, op10, op12;
576 1.1 mrg
577 1.1 mrg op00 = rl78_subreg (HImode, operands[0], omode, 0);
578 1.1 mrg op02 = rl78_subreg (HImode, operands[0], omode, 2);
579 1.1 mrg
580 1.1 mrg if (GET_CODE (operands[1]) == CONST
581 1.1 mrg || GET_CODE (operands[1]) == SYMBOL_REF)
582 1.1 mrg {
583 1.1 mrg op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
584 1.1 mrg op10 = gen_rtx_CONST (HImode, op10);
585 1.1 mrg op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
586 1.1 mrg op12 = gen_rtx_CONST (HImode, op12);
587 1.1 mrg }
588 1.1 mrg else
589 1.1 mrg {
590 1.1 mrg op10 = rl78_subreg (HImode, operands[1], omode, 0);
591 1.1 mrg op12 = rl78_subreg (HImode, operands[1], omode, 2);
592 1.1 mrg }
593 1.1 mrg
594 1.1 mrg if (rtx_equal_p (operands[0], operands[1]))
595 1.1 mrg ;
596 1.1 mrg else if (rtx_equal_p (op00, op12))
597 1.1 mrg {
598 1.1 mrg operands[2] = op02;
599 1.1 mrg operands[4] = op12;
600 1.1 mrg operands[3] = op00;
601 1.1 mrg operands[5] = op10;
602 1.1 mrg }
603 1.1 mrg else
604 1.1 mrg {
605 1.1 mrg operands[2] = op00;
606 1.1 mrg operands[4] = op10;
607 1.1 mrg operands[3] = op02;
608 1.1 mrg operands[5] = op12;
609 1.1 mrg }
610 1.1 mrg }
611 1.1 mrg
612 1.1 mrg void
613 1.1 mrg rl78_split_movdi (rtx *operands, enum machine_mode omode)
614 1.1 mrg {
615 1.1 mrg rtx op00, op04, op10, op14;
616 1.1 mrg op00 = rl78_subreg (SImode, operands[0], omode, 0);
617 1.1 mrg op04 = rl78_subreg (SImode, operands[0], omode, 4);
618 1.1 mrg op10 = rl78_subreg (SImode, operands[1], omode, 0);
619 1.1 mrg op14 = rl78_subreg (SImode, operands[1], omode, 4);
620 1.1 mrg emit_insn (gen_movsi (op00, op10));
621 1.1 mrg emit_insn (gen_movsi (op04, op14));
622 1.1 mrg }
623 1.1 mrg
624 1.1 mrg /* Used by various two-operand expanders which cannot accept all
625 1.1 mrg operands in the "far" namespace. Force some such operands into
626 1.1 mrg registers so that each pattern has at most one far operand. */
627 1.1 mrg int
628 1.1 mrg rl78_force_nonfar_2 (rtx *operands, rtx (*gen)(rtx,rtx))
629 1.1 mrg {
630 1.1 mrg int did = 0;
631 1.1 mrg rtx temp_reg = NULL;
632 1.1 mrg
633 1.1 mrg /* FIXME: in the future, be smarter about only doing this if the
634 1.1 mrg other operand is also far, assuming the devirtualizer can also
635 1.1 mrg handle that. */
636 1.1 mrg if (rl78_far_p (operands[0]))
637 1.1 mrg {
638 1.1 mrg temp_reg = operands[0];
639 1.1 mrg operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
640 1.1 mrg did = 1;
641 1.1 mrg }
642 1.1 mrg if (!did)
643 1.1 mrg return 0;
644 1.1 mrg
645 1.1 mrg emit_insn (gen (operands[0], operands[1]));
646 1.1 mrg if (temp_reg)
647 1.1 mrg emit_move_insn (temp_reg, operands[0]);
648 1.1 mrg return 1;
649 1.1 mrg }
650 1.1 mrg
651 1.1 mrg /* Likewise, but for three-operand expanders. */
652 1.1 mrg int
653 1.1 mrg rl78_force_nonfar_3 (rtx *operands, rtx (*gen)(rtx,rtx,rtx))
654 1.1 mrg {
655 1.1 mrg int did = 0;
656 1.1 mrg rtx temp_reg = NULL;
657 1.1 mrg
658 1.1 mrg /* FIXME: Likewise. */
659 1.1 mrg if (rl78_far_p (operands[1]))
660 1.1 mrg {
661 1.1 mrg rtx temp_reg = gen_reg_rtx (GET_MODE (operands[1]));
662 1.1 mrg emit_move_insn (temp_reg, operands[1]);
663 1.1 mrg operands[1] = temp_reg;
664 1.1 mrg did = 1;
665 1.1 mrg }
666 1.1 mrg if (rl78_far_p (operands[0]))
667 1.1 mrg {
668 1.1 mrg temp_reg = operands[0];
669 1.1 mrg operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
670 1.1 mrg did = 1;
671 1.1 mrg }
672 1.1 mrg if (!did)
673 1.1 mrg return 0;
674 1.1 mrg
675 1.1 mrg emit_insn (gen (operands[0], operands[1], operands[2]));
676 1.1 mrg if (temp_reg)
677 1.1 mrg emit_move_insn (temp_reg, operands[0]);
678 1.1 mrg return 1;
679 1.1 mrg }
680 1.1 mrg
681 1.1 mrg int
682 1.1 mrg rl78_one_far_p (rtx *operands, int n)
683 1.1 mrg {
684 1.1 mrg rtx which = NULL;
685 1.1 mrg int i, c = 0;
686 1.1 mrg
687 1.1 mrg for (i = 0; i < n; i ++)
688 1.1 mrg if (rl78_far_p (operands[i]))
689 1.1 mrg {
690 1.1 mrg if (which == NULL)
691 1.1 mrg which = operands[i];
692 1.1 mrg else if (rtx_equal_p (operands[i], which))
693 1.1 mrg continue;
694 1.1 mrg c ++;
695 1.1 mrg }
696 1.1 mrg return c <= 1;
697 1.1 mrg }
698 1.1 mrg
699 1.1 mrg #undef TARGET_CAN_ELIMINATE
700 1.1 mrg #define TARGET_CAN_ELIMINATE rl78_can_eliminate
701 1.1 mrg
702 1.1 mrg static bool
703 1.1 mrg rl78_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to ATTRIBUTE_UNUSED)
704 1.1 mrg {
705 1.1 mrg return true;
706 1.1 mrg }
707 1.1 mrg
708 1.1 mrg /* Returns true if the given register needs to be saved by the
709 1.1 mrg current function. */
710 1.1 mrg static bool
711 1.1 mrg need_to_save (unsigned int regno)
712 1.1 mrg {
713 1.1 mrg if (is_interrupt_func (cfun->decl))
714 1.1 mrg {
715 1.1 mrg /* We don't know what devirt will need */
716 1.1 mrg if (regno < 8)
717 1.1 mrg return true;
718 1.1 mrg
719 1.1 mrg /* We don't need to save registers that have
720 1.1 mrg been reserved for interrupt handlers. */
721 1.1 mrg if (regno > 23)
722 1.1 mrg return false;
723 1.1 mrg
724 1.1 mrg /* If the handler is a non-leaf function then it may call
725 1.1 mrg non-interrupt aware routines which will happily clobber
726 1.1 mrg any call_used registers, so we have to preserve them.
727 1.1 mrg We do not have to worry about the frame pointer register
728 1.1 mrg though, as that is handled below. */
729 1.1 mrg if (!crtl->is_leaf && call_used_or_fixed_reg_p (regno) && regno < 22)
730 1.1 mrg return true;
731 1.1 mrg
732 1.1 mrg /* Otherwise we only have to save a register, call_used
733 1.1 mrg or not, if it is used by this handler. */
734 1.1 mrg return df_regs_ever_live_p (regno);
735 1.1 mrg }
736 1.1 mrg
737 1.1 mrg if (regno == FRAME_POINTER_REGNUM
738 1.1 mrg && (frame_pointer_needed || df_regs_ever_live_p (regno)))
739 1.1 mrg return true;
740 1.1 mrg if (fixed_regs[regno])
741 1.1 mrg return false;
742 1.1 mrg if (crtl->calls_eh_return)
743 1.1 mrg return true;
744 1.1 mrg if (df_regs_ever_live_p (regno)
745 1.1 mrg && !call_used_or_fixed_reg_p (regno))
746 1.1 mrg return true;
747 1.1 mrg return false;
748 1.1 mrg }
749 1.1 mrg
750 1.1 mrg /* We use this to wrap all emitted insns in the prologue. */
751 1.1 mrg static rtx
752 1.1 mrg F (rtx x)
753 1.1 mrg {
754 1.1 mrg RTX_FRAME_RELATED_P (x) = 1;
755 1.1 mrg return x;
756 1.1 mrg }
757 1.1 mrg
758 1.1 mrg /* Compute all the frame-related fields in our machine_function
759 1.1 mrg structure. */
760 1.1 mrg static void
761 1.1 mrg rl78_compute_frame_info (void)
762 1.1 mrg {
763 1.1 mrg int i;
764 1.1 mrg
765 1.1 mrg cfun->machine->computed = 1;
766 1.1 mrg cfun->machine->framesize_regs = 0;
767 1.1 mrg cfun->machine->framesize_locals = get_frame_size ();
768 1.1 mrg cfun->machine->framesize_outgoing = crtl->outgoing_args_size;
769 1.1 mrg
770 1.1 mrg for (i = 0; i < 16; i ++)
771 1.1 mrg if (need_to_save (i * 2) || need_to_save (i * 2 + 1))
772 1.1 mrg {
773 1.1 mrg cfun->machine->need_to_push [i] = 1;
774 1.1 mrg cfun->machine->framesize_regs += 2;
775 1.1 mrg }
776 1.1 mrg else
777 1.1 mrg cfun->machine->need_to_push [i] = 0;
778 1.1 mrg
779 1.1 mrg if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1)
780 1.1 mrg cfun->machine->framesize_locals ++;
781 1.1 mrg
782 1.1 mrg cfun->machine->framesize = (cfun->machine->framesize_regs
783 1.1 mrg + cfun->machine->framesize_locals
784 1.1 mrg + cfun->machine->framesize_outgoing);
785 1.1 mrg }
786 1.1 mrg
787 1.1 mrg /* Returns true if the provided function has the specified attribute. */
789 1.1 mrg static inline bool
790 1.1 mrg has_func_attr (const_tree decl, const char * func_attr)
791 1.1 mrg {
792 1.1 mrg if (decl == NULL_TREE)
793 1.1 mrg decl = current_function_decl;
794 1.1 mrg
795 1.1 mrg return lookup_attribute (func_attr, DECL_ATTRIBUTES (decl)) != NULL_TREE;
796 1.1 mrg }
797 1.1 mrg
798 1.1 mrg /* Returns true if the provided function has the "interrupt" attribute. */
799 1.1 mrg static inline bool
800 1.1 mrg is_interrupt_func (const_tree decl)
801 1.1 mrg {
802 1.1 mrg return has_func_attr (decl, "interrupt") || has_func_attr (decl, "brk_interrupt");
803 1.1 mrg }
804 1.1 mrg
805 1.1 mrg /* Returns true if the provided function has the "brk_interrupt" attribute. */
806 1.1 mrg static inline bool
807 1.1 mrg is_brk_interrupt_func (const_tree decl)
808 1.1 mrg {
809 1.1 mrg return has_func_attr (decl, "brk_interrupt");
810 1.1 mrg }
811 1.1 mrg
812 1.1 mrg /* Check "interrupt" attributes. */
813 1.1 mrg static tree
814 1.1 mrg rl78_handle_func_attribute (tree * node,
815 1.1 mrg tree name,
816 1.1 mrg tree args ATTRIBUTE_UNUSED,
817 1.1 mrg int flags ATTRIBUTE_UNUSED,
818 1.1 mrg bool * no_add_attrs)
819 1.1 mrg {
820 1.1 mrg gcc_assert (DECL_P (* node));
821 1.1 mrg
822 1.1 mrg if (TREE_CODE (* node) != FUNCTION_DECL)
823 1.1 mrg {
824 1.1 mrg warning (OPT_Wattributes, "%qE attribute only applies to functions",
825 1.1 mrg name);
826 1.1 mrg * no_add_attrs = true;
827 1.1 mrg }
828 1.1 mrg
829 1.1 mrg /* FIXME: We ought to check that the interrupt and exception
830 1.1 mrg handler attributes have been applied to void functions. */
831 1.1 mrg return NULL_TREE;
832 1.1 mrg }
833 1.1 mrg
834 1.1 mrg /* Check "naked" attributes. */
835 1.1 mrg static tree
836 1.1 mrg rl78_handle_naked_attribute (tree * node,
837 1.1 mrg tree name ATTRIBUTE_UNUSED,
838 1.1 mrg tree args,
839 1.1 mrg int flags ATTRIBUTE_UNUSED,
840 1.1 mrg bool * no_add_attrs)
841 1.1 mrg {
842 1.1 mrg gcc_assert (DECL_P (* node));
843 1.1 mrg gcc_assert (args == NULL_TREE);
844 1.1 mrg
845 1.1 mrg if (TREE_CODE (* node) != FUNCTION_DECL)
846 1.1 mrg {
847 1.1 mrg warning (OPT_Wattributes, "naked attribute only applies to functions");
848 1.1 mrg * no_add_attrs = true;
849 1.1 mrg }
850 1.1 mrg
851 1.1 mrg /* Disable warnings about this function - eg reaching the end without
852 1.1 mrg seeing a return statement - because the programmer is doing things
853 1.1 mrg that gcc does not know about. */
854 1.1 mrg TREE_NO_WARNING (* node) = 1;
855 1.1 mrg
856 1.1 mrg return NULL_TREE;
857 1.1 mrg }
858 1.1 mrg
859 1.1 mrg /* Check "saddr" attributes. */
860 1.1 mrg static tree
861 1.1 mrg rl78_handle_saddr_attribute (tree * node,
862 1.1 mrg tree name,
863 1.1 mrg tree args ATTRIBUTE_UNUSED,
864 1.1 mrg int flags ATTRIBUTE_UNUSED,
865 1.1 mrg bool * no_add_attrs)
866 1.1 mrg {
867 1.1 mrg gcc_assert (DECL_P (* node));
868 1.1 mrg
869 1.1 mrg if (TREE_CODE (* node) == FUNCTION_DECL)
870 1.1 mrg {
871 1.1 mrg warning (OPT_Wattributes, "%qE attribute doesn%'t apply to functions",
872 1.1 mrg name);
873 1.1 mrg * no_add_attrs = true;
874 1.1 mrg }
875 1.1 mrg
876 1.1 mrg return NULL_TREE;
877 1.1 mrg }
878 1.1 mrg
879 1.1 mrg /* Check "vector" attribute. */
880 1.1 mrg
881 1.1 mrg static tree
882 1.1 mrg rl78_handle_vector_attribute (tree * node,
883 1.1 mrg tree name,
884 1.1 mrg tree args,
885 1.1 mrg int flags ATTRIBUTE_UNUSED,
886 1.1 mrg bool * no_add_attrs)
887 1.1 mrg {
888 1.1 mrg gcc_assert (DECL_P (* node));
889 1.1 mrg gcc_assert (args != NULL_TREE);
890 1.1 mrg
891 1.1 mrg if (TREE_CODE (* node) != FUNCTION_DECL)
892 1.1 mrg {
893 1.1 mrg warning (OPT_Wattributes, "%qE attribute only applies to functions",
894 1.1 mrg name);
895 1.1 mrg * no_add_attrs = true;
896 1.1 mrg }
897 1.1 mrg
898 1.1 mrg return NULL_TREE;
899 1.1 mrg }
900 1.1 mrg
901 1.1 mrg #undef TARGET_ATTRIBUTE_TABLE
902 1.1 mrg #define TARGET_ATTRIBUTE_TABLE rl78_attribute_table
903 1.1 mrg
904 1.1 mrg /* Table of RL78-specific attributes. */
905 1.1 mrg const struct attribute_spec rl78_attribute_table[] =
906 1.1 mrg {
907 1.1 mrg /* Name, min_len, max_len, decl_req, type_req, fn_type_req,
908 1.1 mrg affects_type_identity, handler, exclude. */
909 1.1 mrg { "interrupt", 0, -1, true, false, false, false,
910 1.1 mrg rl78_handle_func_attribute, NULL },
911 1.1 mrg { "brk_interrupt", 0, 0, true, false, false, false,
912 1.1 mrg rl78_handle_func_attribute, NULL },
913 1.1 mrg { "naked", 0, 0, true, false, false, false,
914 1.1 mrg rl78_handle_naked_attribute, NULL },
915 1.1 mrg { "saddr", 0, 0, true, false, false, false,
916 1.1 mrg rl78_handle_saddr_attribute, NULL },
917 1.1 mrg { "vector", 1, -1, true, false, false, false,
918 1.1 mrg rl78_handle_vector_attribute, NULL },
919 1.1 mrg { NULL, 0, 0, false, false, false, false, NULL, NULL }
920 1.1 mrg };
921 1.1 mrg
922 1.1 mrg
923 1.1 mrg
924 1.1 mrg /* Break down an address RTX into its component base/index/addend
926 1.1 mrg portions and return TRUE if the address is of a valid form, else
927 1.1 mrg FALSE. */
928 1.1 mrg static bool
929 1.1 mrg characterize_address (rtx x, rtx *base, rtx *index, rtx *addend)
930 1.1 mrg {
931 1.1 mrg *base = NULL_RTX;
932 1.1 mrg *index = NULL_RTX;
933 1.1 mrg *addend = NULL_RTX;
934 1.1 mrg
935 1.1 mrg if (GET_CODE (x) == UNSPEC
936 1.1 mrg && XINT (x, 1) == UNS_ES_ADDR)
937 1.1 mrg x = XVECEXP (x, 0, 1);
938 1.1 mrg
939 1.1 mrg if (GET_CODE (x) == REG)
940 1.1 mrg {
941 1.1 mrg *base = x;
942 1.1 mrg return true;
943 1.1 mrg }
944 1.1 mrg
945 1.1 mrg /* We sometimes get these without the CONST wrapper */
946 1.1 mrg if (GET_CODE (x) == PLUS
947 1.1 mrg && GET_CODE (XEXP (x, 0)) == SYMBOL_REF
948 1.1 mrg && GET_CODE (XEXP (x, 1)) == CONST_INT)
949 1.1 mrg {
950 1.1 mrg *addend = x;
951 1.1 mrg return true;
952 1.1 mrg }
953 1.1 mrg
954 1.1 mrg if (GET_CODE (x) == PLUS)
955 1.1 mrg {
956 1.1 mrg *base = XEXP (x, 0);
957 1.1 mrg x = XEXP (x, 1);
958 1.1 mrg
959 1.1 mrg if (GET_CODE (*base) == SUBREG)
960 1.1 mrg {
961 1.1 mrg if (GET_MODE (*base) == HImode
962 1.1 mrg && GET_MODE (XEXP (*base, 0)) == SImode
963 1.1 mrg && GET_CODE (XEXP (*base, 0)) == REG)
964 1.1 mrg {
965 1.1 mrg /* This is a throw-away rtx just to tell everyone
966 1.1 mrg else what effective register we're using. */
967 1.1 mrg *base = gen_rtx_REG (HImode, REGNO (XEXP (*base, 0)));
968 1.1 mrg }
969 1.1 mrg }
970 1.1 mrg
971 1.1 mrg if (GET_CODE (*base) != REG
972 1.1 mrg && GET_CODE (x) == REG)
973 1.1 mrg {
974 1.1 mrg rtx tmp = *base;
975 1.1 mrg *base = x;
976 1.1 mrg x = tmp;
977 1.1 mrg }
978 1.1 mrg
979 1.1 mrg if (GET_CODE (*base) != REG)
980 1.1 mrg return false;
981 1.1 mrg
982 1.1 mrg if (GET_CODE (x) == ZERO_EXTEND
983 1.1 mrg && GET_CODE (XEXP (x, 0)) == REG)
984 1.1 mrg {
985 1.1 mrg *index = XEXP (x, 0);
986 1.1 mrg return false;
987 1.1 mrg }
988 1.1 mrg }
989 1.1 mrg
990 1.1 mrg switch (GET_CODE (x))
991 1.1 mrg {
992 1.1 mrg case PLUS:
993 1.1 mrg if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
994 1.1 mrg && GET_CODE (XEXP (x, 0)) == CONST_INT)
995 1.1 mrg {
996 1.1 mrg *addend = x;
997 1.1 mrg return true;
998 1.1 mrg }
999 1.1 mrg /* fall through */
1000 1.1 mrg case MEM:
1001 1.1 mrg case REG:
1002 1.1 mrg return false;
1003 1.1 mrg
1004 1.1 mrg case SUBREG:
1005 1.1 mrg switch (GET_CODE (XEXP (x, 0)))
1006 1.1 mrg {
1007 1.1 mrg case CONST:
1008 1.1 mrg case SYMBOL_REF:
1009 1.1 mrg case CONST_INT:
1010 1.1 mrg *addend = x;
1011 1.1 mrg return true;
1012 1.1 mrg default:
1013 1.1 mrg return false;
1014 1.1 mrg }
1015 1.1 mrg
1016 1.1 mrg case CONST:
1017 1.1 mrg case SYMBOL_REF:
1018 1.1 mrg case CONST_INT:
1019 1.1 mrg *addend = x;
1020 1.1 mrg return true;
1021 1.1 mrg
1022 1.1 mrg default:
1023 1.1 mrg return false;
1024 1.1 mrg }
1025 1.1 mrg
1026 1.1 mrg return false;
1027 1.1 mrg }
1028 1.1 mrg
1029 1.1 mrg /* Used by the Whb constraint. Match addresses that use HL+B or HL+C
1030 1.1 mrg addressing. */
1031 1.1 mrg bool
1032 1.1 mrg rl78_hl_b_c_addr_p (rtx op)
1033 1.1 mrg {
1034 1.1 mrg rtx hl, bc;
1035 1.1 mrg
1036 1.1 mrg if (GET_CODE (op) != PLUS)
1037 1.1 mrg return false;
1038 1.1 mrg hl = XEXP (op, 0);
1039 1.1 mrg bc = XEXP (op, 1);
1040 1.1 mrg if (GET_CODE (hl) == ZERO_EXTEND)
1041 1.1 mrg {
1042 1.1 mrg rtx tmp = hl;
1043 1.1 mrg hl = bc;
1044 1.1 mrg bc = tmp;
1045 1.1 mrg }
1046 1.1 mrg if (GET_CODE (hl) != REG)
1047 1.1 mrg return false;
1048 1.1 mrg if (GET_CODE (bc) != ZERO_EXTEND)
1049 1.1 mrg return false;
1050 1.1 mrg bc = XEXP (bc, 0);
1051 1.1 mrg if (GET_CODE (bc) != REG)
1052 1.1 mrg return false;
1053 1.1 mrg if (REGNO (hl) != HL_REG)
1054 1.1 mrg return false;
1055 1.1 mrg if (REGNO (bc) != B_REG && REGNO (bc) != C_REG)
1056 1.1 mrg return false;
1057 1.1 mrg
1058 1.1 mrg return true;
1059 1.1 mrg }
1060 1.1 mrg
1061 1.1 mrg #define REG_IS(r, regno) (((r) == (regno)) || ((r) >= FIRST_PSEUDO_REGISTER && !(strict)))
1062 1.1 mrg
1063 1.1 mrg /* Return the appropriate mode for a named address address. */
1064 1.1 mrg
1065 1.1 mrg #undef TARGET_ADDR_SPACE_ADDRESS_MODE
1066 1.1 mrg #define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode
1067 1.1 mrg
1068 1.1 mrg static scalar_int_mode
1069 1.1 mrg rl78_addr_space_address_mode (addr_space_t addrspace)
1070 1.1 mrg {
1071 1.1 mrg switch (addrspace)
1072 1.1 mrg {
1073 1.1 mrg case ADDR_SPACE_GENERIC:
1074 1.1 mrg return HImode;
1075 1.1 mrg case ADDR_SPACE_NEAR:
1076 1.1 mrg return HImode;
1077 1.1 mrg case ADDR_SPACE_FAR:
1078 1.1 mrg return SImode;
1079 1.1 mrg default:
1080 1.1 mrg gcc_unreachable ();
1081 1.1 mrg }
1082 1.1 mrg }
1083 1.1 mrg
1084 1.1 mrg /* Used in various constraints and predicates to match operands in the
1085 1.1 mrg "far" address space. */
1086 1.1 mrg int
1087 1.1 mrg rl78_far_p (rtx x)
1088 1.1 mrg {
1089 1.1 mrg if (! MEM_P (x))
1090 1.1 mrg return 0;
1091 1.1 mrg #if DEBUG0
1092 1.1 mrg fprintf (stderr, "\033[35mrl78_far_p: "); debug_rtx (x);
1093 1.1 mrg fprintf (stderr, " = %d\033[0m\n", MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR);
1094 1.1 mrg #endif
1095 1.1 mrg
1096 1.1 mrg /* Not all far addresses are legitimate, because the devirtualizer
1097 1.1 mrg can't handle them. */
1098 1.1 mrg if (! rl78_as_legitimate_address (GET_MODE (x), XEXP (x, 0), false, ADDR_SPACE_FAR))
1099 1.1 mrg return 0;
1100 1.1 mrg
1101 1.1 mrg return GET_MODE_BITSIZE (rl78_addr_space_address_mode (MEM_ADDR_SPACE (x))) == 32;
1102 1.1 mrg }
1103 1.1 mrg
1104 1.1 mrg /* Return the appropriate mode for a named address pointer. */
1105 1.1 mrg #undef TARGET_ADDR_SPACE_POINTER_MODE
1106 1.1 mrg #define TARGET_ADDR_SPACE_POINTER_MODE rl78_addr_space_pointer_mode
1107 1.1 mrg
1108 1.1 mrg static scalar_int_mode
1109 1.1 mrg rl78_addr_space_pointer_mode (addr_space_t addrspace)
1110 1.1 mrg {
1111 1.1 mrg switch (addrspace)
1112 1.1 mrg {
1113 1.1 mrg case ADDR_SPACE_GENERIC:
1114 1.1 mrg return HImode;
1115 1.1 mrg case ADDR_SPACE_NEAR:
1116 1.1 mrg return HImode;
1117 1.1 mrg case ADDR_SPACE_FAR:
1118 1.1 mrg return SImode;
1119 1.1 mrg default:
1120 1.1 mrg gcc_unreachable ();
1121 1.1 mrg }
1122 1.1 mrg }
1123 1.1 mrg
1124 1.1 mrg /* Returns TRUE for valid addresses. */
1125 1.1 mrg #undef TARGET_VALID_POINTER_MODE
1126 1.1 mrg #define TARGET_VALID_POINTER_MODE rl78_valid_pointer_mode
1127 1.1 mrg
1128 1.1 mrg static bool
1129 1.1 mrg rl78_valid_pointer_mode (scalar_int_mode m)
1130 1.1 mrg {
1131 1.1 mrg return (m == HImode || m == SImode);
1132 1.1 mrg }
1133 1.1 mrg
1134 1.1 mrg #undef TARGET_LEGITIMATE_CONSTANT_P
1135 1.1 mrg #define TARGET_LEGITIMATE_CONSTANT_P rl78_is_legitimate_constant
1136 1.1 mrg
1137 1.1 mrg static bool
1138 1.1 mrg rl78_is_legitimate_constant (machine_mode mode ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED)
1139 1.1 mrg {
1140 1.1 mrg return true;
1141 1.1 mrg }
1142 1.1 mrg
1143 1.1 mrg #undef TARGET_LRA_P
1144 1.1 mrg #define TARGET_LRA_P hook_bool_void_false
1145 1.1 mrg
1146 1.1 mrg #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
1147 1.1 mrg #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P rl78_as_legitimate_address
1148 1.1 mrg
1149 1.1 mrg bool
1150 1.1 mrg rl78_as_legitimate_address (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
1151 1.1 mrg bool strict ATTRIBUTE_UNUSED, addr_space_t as ATTRIBUTE_UNUSED)
1152 1.1 mrg {
1153 1.1 mrg rtx base, index, addend;
1154 1.1 mrg bool is_far_addr = false;
1155 1.1 mrg int as_bits;
1156 1.1 mrg
1157 1.1 mrg as_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (as));
1158 1.1 mrg
1159 1.1 mrg if (GET_CODE (x) == UNSPEC
1160 1.1 mrg && XINT (x, 1) == UNS_ES_ADDR)
1161 1.1 mrg {
1162 1.1 mrg x = XVECEXP (x, 0, 1);
1163 1.1 mrg is_far_addr = true;
1164 1.1 mrg }
1165 1.1 mrg
1166 1.1 mrg if (as_bits == 16 && is_far_addr)
1167 1.1 mrg return false;
1168 1.1 mrg
1169 1.1 mrg if (! characterize_address (x, &base, &index, &addend))
1170 1.1 mrg return false;
1171 1.1 mrg
1172 1.1 mrg /* We can't extract the high/low portions of a PLUS address
1173 1.1 mrg involving a register during devirtualization, so make sure all
1174 1.1 mrg such __far addresses do not have addends. This forces GCC to do
1175 1.1 mrg the sum separately. */
1176 1.1 mrg if (addend && base && as_bits == 32 && GET_MODE (base) == SImode)
1177 1.1 mrg return false;
1178 1.1 mrg
1179 1.1 mrg if (base && index)
1180 1.1 mrg {
1181 1.1 mrg int ir = REGNO (index);
1182 1.1 mrg int br = REGNO (base);
1183 1.1 mrg
1184 1.1 mrg #define OK(test, debug) if (test) { /*fprintf(stderr, "%d: OK %s\n", __LINE__, debug);*/ return true; }
1185 1.1 mrg OK (REG_IS (br, HL_REG) && REG_IS (ir, B_REG), "[hl+b]");
1186 1.1 mrg OK (REG_IS (br, HL_REG) && REG_IS (ir, C_REG), "[hl+c]");
1187 1.1 mrg return false;
1188 1.1 mrg }
1189 1.1 mrg
1190 1.1 mrg if (strict && base && GET_CODE (base) == REG && REGNO (base) >= FIRST_PSEUDO_REGISTER)
1191 1.1 mrg return false;
1192 1.1 mrg
1193 1.1 mrg if (! cfun->machine->virt_insns_ok && base && GET_CODE (base) == REG
1194 1.1 mrg && REGNO (base) >= 8 && REGNO (base) <= 31)
1195 1.1 mrg return false;
1196 1.1 mrg
1197 1.1 mrg return true;
1198 1.1 mrg }
1199 1.1 mrg
1200 1.1 mrg /* Determine if one named address space is a subset of another. */
1201 1.1 mrg #undef TARGET_ADDR_SPACE_SUBSET_P
1202 1.1 mrg #define TARGET_ADDR_SPACE_SUBSET_P rl78_addr_space_subset_p
1203 1.1 mrg
1204 1.1 mrg static bool
1205 1.1 mrg rl78_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
1206 1.1 mrg {
1207 1.1 mrg int subset_bits;
1208 1.1 mrg int superset_bits;
1209 1.1 mrg
1210 1.1 mrg subset_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (subset));
1211 1.1 mrg superset_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (superset));
1212 1.1 mrg
1213 1.1 mrg return (subset_bits <= superset_bits);
1214 1.1 mrg }
1215 1.1 mrg
1216 1.1 mrg #undef TARGET_ADDR_SPACE_CONVERT
1217 1.1 mrg #define TARGET_ADDR_SPACE_CONVERT rl78_addr_space_convert
1218 1.1 mrg
1219 1.1 mrg /* Convert from one address space to another. */
1220 1.1 mrg static rtx
1221 1.1 mrg rl78_addr_space_convert (rtx op, tree from_type, tree to_type)
1222 1.1 mrg {
1223 1.1 mrg addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
1224 1.1 mrg addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
1225 1.1 mrg rtx result;
1226 1.1 mrg int to_bits;
1227 1.1 mrg int from_bits;
1228 1.1 mrg
1229 1.1 mrg to_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (to_as));
1230 1.1 mrg from_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (from_as));
1231 1.1 mrg
1232 1.1 mrg if (to_bits < from_bits)
1233 1.1 mrg {
1234 1.1 mrg rtx tmp;
1235 1.1 mrg /* This is unpredictable, as we're truncating off usable address
1236 1.1 mrg bits. */
1237 1.1 mrg
1238 1.1 mrg warning (OPT_Waddress, "converting far pointer to near pointer");
1239 1.1 mrg result = gen_reg_rtx (HImode);
1240 1.1 mrg if (GET_CODE (op) == SYMBOL_REF
1241 1.1 mrg || (GET_CODE (op) == REG && REGNO (op) >= FIRST_PSEUDO_REGISTER))
1242 1.1 mrg tmp = gen_rtx_raw_SUBREG (HImode, op, 0);
1243 1.1 mrg else
1244 1.1 mrg tmp = simplify_subreg (HImode, op, SImode, 0);
1245 1.1 mrg gcc_assert (tmp != NULL_RTX);
1246 1.1 mrg emit_move_insn (result, tmp);
1247 1.1 mrg return result;
1248 1.1 mrg }
1249 1.1 mrg else if (to_bits > from_bits)
1250 1.1 mrg {
1251 1.1 mrg /* This always works. */
1252 1.1 mrg result = gen_reg_rtx (SImode);
1253 1.1 mrg emit_move_insn (rl78_subreg (HImode, result, SImode, 0), op);
1254 1.1 mrg if (TREE_CODE (from_type) == POINTER_TYPE
1255 1.1 mrg && TREE_CODE (TREE_TYPE (from_type)) == FUNCTION_TYPE)
1256 1.1 mrg emit_move_insn (rl78_subreg (HImode, result, SImode, 2), const0_rtx);
1257 1.1 mrg else
1258 1.1 mrg emit_move_insn (rl78_subreg (HImode, result, SImode, 2), GEN_INT (0x0f));
1259 1.1 mrg return result;
1260 1.1 mrg }
1261 1.1 mrg else
1262 1.1 mrg return op;
1263 1.1 mrg gcc_unreachable ();
1264 1.1 mrg }
1265 1.1 mrg
1266 1.1 mrg /* Implements REGNO_MODE_CODE_OK_FOR_BASE_P. */
1267 1.1 mrg bool
1268 1.1 mrg rl78_regno_mode_code_ok_for_base_p (int regno, machine_mode mode ATTRIBUTE_UNUSED,
1269 1.1 mrg addr_space_t address_space ATTRIBUTE_UNUSED,
1270 1.1 mrg int outer_code ATTRIBUTE_UNUSED, int index_code)
1271 1.1 mrg {
1272 1.1 mrg if (regno <= SP_REG && regno >= 16)
1273 1.1 mrg return true;
1274 1.1 mrg if (index_code == REG)
1275 1.1 mrg return (regno == HL_REG);
1276 1.1 mrg if (regno == C_REG || regno == B_REG || regno == E_REG || regno == L_REG)
1277 1.1 mrg return true;
1278 1.1 mrg return false;
1279 1.1 mrg }
1280 1.1 mrg
1281 1.1 mrg /* Implements MODE_CODE_BASE_REG_CLASS. */
1282 1.1 mrg enum reg_class
1283 1.1 mrg rl78_mode_code_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED,
1284 1.1 mrg addr_space_t address_space ATTRIBUTE_UNUSED,
1285 1.1 mrg int outer_code ATTRIBUTE_UNUSED,
1286 1.1 mrg int index_code ATTRIBUTE_UNUSED)
1287 1.1 mrg {
1288 1.1 mrg return V_REGS;
1289 1.1 mrg }
1290 1.1 mrg
1291 1.1 mrg /* Typical stack layout should looks like this after the function's prologue:
1292 1.1 mrg
1293 1.1 mrg | |
1294 1.1 mrg -- ^
1295 1.1 mrg | | \ |
1296 1.1 mrg | | arguments saved | Increasing
1297 1.1 mrg | | on the stack | addresses
1298 1.1 mrg PARENT arg pointer -> | | /
1299 1.1 mrg -------------------------- ---- -------------------
1300 1.1 mrg CHILD |ret | return address
1301 1.1 mrg --
1302 1.1 mrg | | \
1303 1.1 mrg | | call saved
1304 1.1 mrg | | registers
1305 1.1 mrg frame pointer -> | | /
1306 1.1 mrg --
1307 1.1 mrg | | \
1308 1.1 mrg | | local
1309 1.1 mrg | | variables
1310 1.1 mrg | | /
1311 1.1 mrg --
1312 1.1 mrg | | \
1313 1.1 mrg | | outgoing | Decreasing
1314 1.1 mrg | | arguments | addresses
1315 1.1 mrg current stack pointer -> | | / |
1316 1.1 mrg -------------------------- ---- ------------------ V
1317 1.1 mrg | | */
1318 1.1 mrg
1319 1.1 mrg /* Implements INITIAL_ELIMINATION_OFFSET. The frame layout is
1320 1.1 mrg described in the machine_Function struct definition, above. */
1321 1.1 mrg int
1322 1.1 mrg rl78_initial_elimination_offset (int from, int to)
1323 1.1 mrg {
1324 1.1 mrg int rv = 0; /* as if arg to arg */
1325 1.1 mrg
1326 1.1 mrg rl78_compute_frame_info ();
1327 1.1 mrg
1328 1.1 mrg switch (to)
1329 1.1 mrg {
1330 1.1 mrg case STACK_POINTER_REGNUM:
1331 1.1 mrg rv += cfun->machine->framesize_outgoing;
1332 1.1 mrg rv += cfun->machine->framesize_locals;
1333 1.1 mrg /* Fall through. */
1334 1.1 mrg case FRAME_POINTER_REGNUM:
1335 1.1 mrg rv += cfun->machine->framesize_regs;
1336 1.1 mrg rv += 4;
1337 1.1 mrg break;
1338 1.1 mrg default:
1339 1.1 mrg gcc_unreachable ();
1340 1.1 mrg }
1341 1.1 mrg
1342 1.1 mrg switch (from)
1343 1.1 mrg {
1344 1.1 mrg case FRAME_POINTER_REGNUM:
1345 1.1 mrg rv -= 4;
1346 1.1 mrg rv -= cfun->machine->framesize_regs;
1347 1.1 mrg case ARG_POINTER_REGNUM:
1348 1.1 mrg break;
1349 1.1 mrg default:
1350 1.1 mrg gcc_unreachable ();
1351 1.1 mrg }
1352 1.1 mrg
1353 1.1 mrg return rv;
1354 1.1 mrg }
1355 1.1 mrg
1356 1.1 mrg static bool
1357 1.1 mrg rl78_is_naked_func (void)
1358 1.1 mrg {
1359 1.1 mrg return (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE);
1360 1.1 mrg }
1361 1.1 mrg
1362 1.1 mrg /* Check if the block uses mul/div insns for G13 target. */
1363 1.1 mrg
1364 1.1 mrg static bool
1365 1.1 mrg check_mduc_usage (void)
1366 1.1 mrg {
1367 1.1 mrg rtx_insn * insn;
1368 1.1 mrg basic_block bb;
1369 1.1 mrg
1370 1.1 mrg FOR_EACH_BB_FN (bb, cfun)
1371 1.1 mrg {
1372 1.1 mrg FOR_BB_INSNS (bb, insn)
1373 1.1 mrg {
1374 1.1 mrg if (INSN_P (insn)
1375 1.1 mrg && (get_attr_is_g13_muldiv_insn (insn) == IS_G13_MULDIV_INSN_YES))
1376 1.1 mrg return true;
1377 1.1 mrg }
1378 1.1 mrg }
1379 1.1 mrg return false;
1380 1.1 mrg }
1381 1.1 mrg
1382 1.1 mrg /* Expand the function prologue (from the prologue pattern). */
1383 1.1 mrg
1384 1.1 mrg void
1385 1.1 mrg rl78_expand_prologue (void)
1386 1.1 mrg {
1387 1.1 mrg int i, fs;
1388 1.1 mrg rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
1389 1.1 mrg rtx ax = gen_rtx_REG (HImode, AX_REG);
1390 1.1 mrg int rb = 0;
1391 1.1 mrg
1392 1.1 mrg if (rl78_is_naked_func ())
1393 1.1 mrg return;
1394 1.1 mrg
1395 1.1 mrg /* Always re-compute the frame info - the register usage may have changed. */
1396 1.1 mrg rl78_compute_frame_info ();
1397 1.1 mrg
1398 1.1 mrg if (MUST_SAVE_MDUC_REGISTERS && (!crtl->is_leaf || check_mduc_usage ()))
1399 1.1 mrg cfun->machine->framesize += ARRAY_SIZE (mduc_regs) * 2;
1400 1.1 mrg
1401 1.1 mrg if (flag_stack_usage_info)
1402 1.1 mrg current_function_static_stack_size = cfun->machine->framesize;
1403 1.1 mrg
1404 1.1 mrg if (is_interrupt_func (cfun->decl) && !TARGET_G10)
1405 1.1 mrg for (i = 0; i < 4; i++)
1406 1.1 mrg if (cfun->machine->need_to_push [i])
1407 1.1 mrg {
1408 1.1 mrg /* Select Bank 0 if we are using any registers from Bank 0. */
1409 1.1 mrg emit_insn (gen_sel_rb (GEN_INT (0)));
1410 1.1 mrg break;
1411 1.1 mrg }
1412 1.1 mrg
1413 1.1 mrg for (i = 0; i < 16; i++)
1414 1.1 mrg if (cfun->machine->need_to_push [i])
1415 1.1 mrg {
1416 1.1 mrg int reg = i * 2;
1417 1.1 mrg
1418 1.1 mrg if (TARGET_G10)
1419 1.1 mrg {
1420 1.1 mrg if (reg >= 8)
1421 1.1 mrg {
1422 1.1 mrg emit_move_insn (ax, gen_rtx_REG (HImode, reg));
1423 1.1 mrg reg = AX_REG;
1424 1.1 mrg }
1425 1.1 mrg }
1426 1.1 mrg else
1427 1.1 mrg {
1428 1.1 mrg int need_bank = i/4;
1429 1.1 mrg
1430 1.1 mrg if (need_bank != rb)
1431 1.1 mrg {
1432 1.1 mrg emit_insn (gen_sel_rb (GEN_INT (need_bank)));
1433 1.1 mrg rb = need_bank;
1434 1.1 mrg }
1435 1.1 mrg }
1436 1.1 mrg
1437 1.1 mrg F (emit_insn (gen_push (gen_rtx_REG (HImode, reg))));
1438 1.1 mrg }
1439 1.1 mrg
1440 1.1 mrg if (rb != 0)
1441 1.1 mrg emit_insn (gen_sel_rb (GEN_INT (0)));
1442 1.1 mrg
1443 1.1 mrg /* Save ES register inside interrupt functions if it is used. */
1444 1.1 mrg if (is_interrupt_func (cfun->decl) && cfun->machine->uses_es)
1445 1.1 mrg {
1446 1.1 mrg emit_insn (gen_movqi_from_es (gen_rtx_REG (QImode, A_REG)));
1447 1.1 mrg F (emit_insn (gen_push (ax)));
1448 1.1 mrg }
1449 1.1 mrg
1450 1.1 mrg /* Save MDUC registers inside interrupt routine. */
1451 1.1 mrg if (MUST_SAVE_MDUC_REGISTERS && (!crtl->is_leaf || check_mduc_usage ()))
1452 1.1 mrg {
1453 1.1 mrg for (unsigned i = 0; i < ARRAY_SIZE (mduc_regs); i++)
1454 1.1 mrg {
1455 1.1 mrg mduc_reg_type *reg = mduc_regs + i;
1456 1.1 mrg rtx mem_mduc = gen_rtx_MEM (reg->mode, GEN_INT (reg->address));
1457 1.1 mrg
1458 1.1 mrg MEM_VOLATILE_P (mem_mduc) = 1;
1459 1.1 mrg if (reg->mode == QImode)
1460 1.1 mrg emit_insn (gen_movqi (gen_rtx_REG (QImode, A_REG), mem_mduc));
1461 1.1 mrg else
1462 1.1 mrg emit_insn (gen_movhi (gen_rtx_REG (HImode, AX_REG), mem_mduc));
1463 1.1 mrg
1464 1.1 mrg emit_insn (gen_push (gen_rtx_REG (HImode, AX_REG)));
1465 1.1 mrg }
1466 1.1 mrg }
1467 1.1 mrg
1468 1.1 mrg if (frame_pointer_needed)
1469 1.1 mrg {
1470 1.1 mrg F (emit_move_insn (ax, sp));
1471 1.1 mrg F (emit_move_insn (gen_rtx_REG (HImode, FRAME_POINTER_REGNUM), ax));
1472 1.1 mrg }
1473 1.1 mrg
1474 1.1 mrg fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1475 1.1 mrg if (fs > 0)
1476 1.1 mrg {
1477 1.1 mrg /* If we need to subtract more than 254*3 then it is faster and
1478 1.1 mrg smaller to move SP into AX and perform the subtraction there. */
1479 1.1 mrg if (fs > 254 * 3)
1480 1.1 mrg {
1481 1.1 mrg rtx insn;
1482 1.1 mrg
1483 1.1 mrg emit_move_insn (ax, sp);
1484 1.1 mrg emit_insn (gen_subhi3 (ax, ax, GEN_INT (fs)));
1485 1.1 mrg insn = F (emit_move_insn (sp, ax));
1486 1.1 mrg add_reg_note (insn, REG_FRAME_RELATED_EXPR,
1487 1.1 mrg gen_rtx_SET (sp, gen_rtx_PLUS (HImode, sp,
1488 1.1 mrg GEN_INT (-fs))));
1489 1.1 mrg }
1490 1.1 mrg else
1491 1.1 mrg {
1492 1.1 mrg while (fs > 0)
1493 1.1 mrg {
1494 1.1 mrg int fs_byte = (fs > 254) ? 254 : fs;
1495 1.1 mrg
1496 1.1 mrg F (emit_insn (gen_subhi3 (sp, sp, GEN_INT (fs_byte))));
1497 1.1 mrg fs -= fs_byte;
1498 1.1 mrg }
1499 1.1 mrg }
1500 1.1 mrg }
1501 1.1 mrg }
1502 1.1 mrg
1503 1.1 mrg /* Expand the function epilogue (from the epilogue pattern). */
1504 1.1 mrg void
1505 1.1 mrg rl78_expand_epilogue (void)
1506 1.1 mrg {
1507 1.1 mrg int i, fs;
1508 1.1 mrg rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
1509 1.1 mrg rtx ax = gen_rtx_REG (HImode, AX_REG);
1510 1.1 mrg int rb = 0;
1511 1.1 mrg
1512 1.1 mrg if (rl78_is_naked_func ())
1513 1.1 mrg return;
1514 1.1 mrg
1515 1.1 mrg if (frame_pointer_needed)
1516 1.1 mrg {
1517 1.1 mrg emit_move_insn (ax, gen_rtx_REG (HImode, FRAME_POINTER_REGNUM));
1518 1.1 mrg emit_move_insn (sp, ax);
1519 1.1 mrg }
1520 1.1 mrg else
1521 1.1 mrg {
1522 1.1 mrg fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1523 1.1 mrg if (fs > 254 * 3)
1524 1.1 mrg {
1525 1.1 mrg emit_move_insn (ax, sp);
1526 1.1 mrg emit_insn (gen_addhi3 (ax, ax, GEN_INT (fs)));
1527 1.1 mrg emit_move_insn (sp, ax);
1528 1.1 mrg }
1529 1.1 mrg else
1530 1.1 mrg {
1531 1.1 mrg while (fs > 0)
1532 1.1 mrg {
1533 1.1 mrg int fs_byte = (fs > 254) ? 254 : fs;
1534 1.1 mrg
1535 1.1 mrg emit_insn (gen_addhi3 (sp, sp, GEN_INT (fs_byte)));
1536 1.1 mrg fs -= fs_byte;
1537 1.1 mrg }
1538 1.1 mrg }
1539 1.1 mrg }
1540 1.1 mrg
1541 1.1 mrg /* Restore MDUC registers from interrupt routine. */
1542 1.1 mrg if (MUST_SAVE_MDUC_REGISTERS && (!crtl->is_leaf || check_mduc_usage ()))
1543 1.1 mrg {
1544 1.1 mrg for (int i = ARRAY_SIZE (mduc_regs) - 1; i >= 0; i--)
1545 1.1 mrg {
1546 1.1 mrg mduc_reg_type *reg = mduc_regs + i;
1547 1.1 mrg rtx mem_mduc = gen_rtx_MEM (reg->mode, GEN_INT (reg->address));
1548 1.1 mrg
1549 1.1 mrg emit_insn (gen_pop (gen_rtx_REG (HImode, AX_REG)));
1550 1.1 mrg MEM_VOLATILE_P (mem_mduc) = 1;
1551 1.1 mrg if (reg->mode == QImode)
1552 1.1 mrg emit_insn (gen_movqi (mem_mduc, gen_rtx_REG (QImode, A_REG)));
1553 1.1 mrg else
1554 1.1 mrg emit_insn (gen_movhi (mem_mduc, gen_rtx_REG (HImode, AX_REG)));
1555 1.1 mrg }
1556 1.1 mrg }
1557 1.1 mrg
1558 1.1 mrg if (is_interrupt_func (cfun->decl) && cfun->machine->uses_es)
1559 1.1 mrg {
1560 1.1 mrg emit_insn (gen_pop (gen_rtx_REG (HImode, AX_REG)));
1561 1.1 mrg emit_insn (gen_movqi_to_es (gen_rtx_REG (QImode, A_REG)));
1562 1.1 mrg }
1563 1.1 mrg
1564 1.1 mrg for (i = 15; i >= 0; i--)
1565 1.1 mrg if (cfun->machine->need_to_push [i])
1566 1.1 mrg {
1567 1.1 mrg rtx dest = gen_rtx_REG (HImode, i * 2);
1568 1.1 mrg
1569 1.1 mrg if (TARGET_G10)
1570 1.1 mrg {
1571 1.1 mrg if (i < 8)
1572 1.1 mrg emit_insn (gen_pop (dest));
1573 1.1 mrg else
1574 1.1 mrg {
1575 1.1 mrg emit_insn (gen_pop (ax));
1576 1.1 mrg emit_move_insn (dest, ax);
1577 1.1 mrg /* Generate a USE of the pop'd register so that DCE will not eliminate the move. */
1578 1.1 mrg emit_insn (gen_use (dest));
1579 1.1 mrg }
1580 1.1 mrg }
1581 1.1 mrg else
1582 1.1 mrg {
1583 1.1 mrg int need_bank = i / 4;
1584 1.1 mrg
1585 1.1 mrg if (need_bank != rb)
1586 1.1 mrg {
1587 1.1 mrg emit_insn (gen_sel_rb (GEN_INT (need_bank)));
1588 1.1 mrg rb = need_bank;
1589 1.1 mrg }
1590 1.1 mrg emit_insn (gen_pop (dest));
1591 1.1 mrg }
1592 1.1 mrg }
1593 1.1 mrg
1594 1.1 mrg if (rb != 0)
1595 1.1 mrg emit_insn (gen_sel_rb (GEN_INT (0)));
1596 1.1 mrg
1597 1.1 mrg if (cfun->machine->trampolines_used)
1598 1.1 mrg emit_insn (gen_trampoline_uninit ());
1599 1.1 mrg
1600 1.1 mrg if (is_brk_interrupt_func (cfun->decl))
1601 1.1 mrg emit_jump_insn (gen_brk_interrupt_return ());
1602 1.1 mrg else if (is_interrupt_func (cfun->decl))
1603 1.1 mrg emit_jump_insn (gen_interrupt_return ());
1604 1.1 mrg else
1605 1.1 mrg emit_jump_insn (gen_rl78_return ());
1606 1.1 mrg }
1607 1.1 mrg
1608 1.1 mrg /* Likewise, for exception handlers. */
1609 1.1 mrg void
1610 1.1 mrg rl78_expand_eh_epilogue (rtx x ATTRIBUTE_UNUSED)
1611 1.1 mrg {
1612 1.1 mrg /* FIXME - replace this with an indirect jump with stack adjust. */
1613 1.1 mrg emit_jump_insn (gen_rl78_return ());
1614 1.1 mrg }
1615 1.1 mrg
1616 1.1 mrg #undef TARGET_ASM_FUNCTION_PROLOGUE
1617 1.1 mrg #define TARGET_ASM_FUNCTION_PROLOGUE rl78_start_function
1618 1.1 mrg
1619 1.1 mrg static void
1620 1.1 mrg add_vector_labels (FILE *file, const char *aname)
1621 1.1 mrg {
1622 1.1 mrg tree vec_attr;
1623 1.1 mrg tree val_attr;
1624 1.1 mrg const char *vname = "vect";
1625 1.1 mrg const char *s;
1626 1.1 mrg int vnum;
1627 1.1 mrg
1628 1.1 mrg /* This node is for the vector/interrupt tag itself */
1629 1.1 mrg vec_attr = lookup_attribute (aname, DECL_ATTRIBUTES (current_function_decl));
1630 1.1 mrg if (!vec_attr)
1631 1.1 mrg return;
1632 1.1 mrg
1633 1.1 mrg /* Now point it at the first argument */
1634 1.1 mrg vec_attr = TREE_VALUE (vec_attr);
1635 1.1 mrg
1636 1.1 mrg /* Iterate through the arguments. */
1637 1.1 mrg while (vec_attr)
1638 1.1 mrg {
1639 1.1 mrg val_attr = TREE_VALUE (vec_attr);
1640 1.1 mrg switch (TREE_CODE (val_attr))
1641 1.1 mrg {
1642 1.1 mrg case STRING_CST:
1643 1.1 mrg s = TREE_STRING_POINTER (val_attr);
1644 1.1 mrg goto string_id_common;
1645 1.1 mrg
1646 1.1 mrg case IDENTIFIER_NODE:
1647 1.1 mrg s = IDENTIFIER_POINTER (val_attr);
1648 1.1 mrg
1649 1.1 mrg string_id_common:
1650 1.1 mrg if (strcmp (s, "$default") == 0)
1651 1.1 mrg {
1652 1.1 mrg fprintf (file, "\t.global\t$tableentry$default$%s\n", vname);
1653 1.1 mrg fprintf (file, "$tableentry$default$%s:\n", vname);
1654 1.1 mrg }
1655 1.1 mrg else
1656 1.1 mrg vname = s;
1657 1.1 mrg break;
1658 1.1 mrg
1659 1.1 mrg case INTEGER_CST:
1660 1.1 mrg vnum = TREE_INT_CST_LOW (val_attr);
1661 1.1 mrg
1662 1.1 mrg fprintf (file, "\t.global\t$tableentry$%d$%s\n", vnum, vname);
1663 1.1 mrg fprintf (file, "$tableentry$%d$%s:\n", vnum, vname);
1664 1.1 mrg break;
1665 1.1 mrg
1666 1.1 mrg default:
1667 1.1 mrg ;
1668 1.1 mrg }
1669 1.1 mrg
1670 1.1 mrg vec_attr = TREE_CHAIN (vec_attr);
1671 1.1 mrg }
1672 1.1 mrg
1673 1.1 mrg }
1674 1.1 mrg
1675 1.1 mrg /* We don't use this to actually emit the function prologue. We use
1676 1.1 mrg this to insert a comment in the asm file describing the
1677 1.1 mrg function. */
1678 1.1 mrg static void
1679 1.1 mrg rl78_start_function (FILE *file)
1680 1.1 mrg {
1681 1.1 mrg int i;
1682 1.1 mrg
1683 1.1 mrg add_vector_labels (file, "interrupt");
1684 1.1 mrg add_vector_labels (file, "vector");
1685 1.1 mrg
1686 1.1 mrg if (cfun->machine->framesize == 0)
1687 1.1 mrg return;
1688 1.1 mrg fprintf (file, "\t; start of function\n");
1689 1.1 mrg
1690 1.1 mrg if (cfun->machine->framesize_regs)
1691 1.1 mrg {
1692 1.1 mrg fprintf (file, "\t; push %d:", cfun->machine->framesize_regs);
1693 1.1 mrg for (i = 0; i < 16; i ++)
1694 1.1 mrg if (cfun->machine->need_to_push[i])
1695 1.1 mrg fprintf (file, " %s", word_regnames[i*2]);
1696 1.1 mrg fprintf (file, "\n");
1697 1.1 mrg }
1698 1.1 mrg
1699 1.1 mrg if (frame_pointer_needed)
1700 1.1 mrg fprintf (file, "\t; $fp points here (r22)\n");
1701 1.1 mrg
1702 1.1 mrg if (cfun->machine->framesize_locals)
1703 1.1 mrg fprintf (file, "\t; locals: %d byte%s\n", cfun->machine->framesize_locals,
1704 1.1 mrg cfun->machine->framesize_locals == 1 ? "" : "s");
1705 1.1 mrg
1706 1.1 mrg if (cfun->machine->framesize_outgoing)
1707 1.1 mrg fprintf (file, "\t; outgoing: %d byte%s\n", cfun->machine->framesize_outgoing,
1708 1.1 mrg cfun->machine->framesize_outgoing == 1 ? "" : "s");
1709 1.1 mrg
1710 1.1 mrg if (cfun->machine->uses_es)
1711 1.1 mrg fprintf (file, "\t; uses ES register\n");
1712 1.1 mrg
1713 1.1 mrg if (MUST_SAVE_MDUC_REGISTERS)
1714 1.1 mrg fprintf (file, "\t; preserves MDUC registers\n");
1715 1.1 mrg }
1716 1.1 mrg
1717 1.1 mrg /* Return an RTL describing where a function return value of type RET_TYPE
1718 1.1 mrg is held. */
1719 1.1 mrg
1720 1.1 mrg #undef TARGET_FUNCTION_VALUE
1721 1.1 mrg #define TARGET_FUNCTION_VALUE rl78_function_value
1722 1.1 mrg
1723 1.1 mrg static rtx
1724 1.1 mrg rl78_function_value (const_tree ret_type,
1725 1.1 mrg const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
1726 1.1 mrg bool outgoing ATTRIBUTE_UNUSED)
1727 1.1 mrg {
1728 1.1 mrg machine_mode mode = TYPE_MODE (ret_type);
1729 1.1 mrg
1730 1.1 mrg return gen_rtx_REG (mode, 8);
1731 1.1 mrg }
1732 1.1 mrg
1733 1.1 mrg #undef TARGET_PROMOTE_FUNCTION_MODE
1734 1.1 mrg #define TARGET_PROMOTE_FUNCTION_MODE rl78_promote_function_mode
1735 1.1 mrg
1736 1.1 mrg static machine_mode
1737 1.1 mrg rl78_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
1738 1.1 mrg machine_mode mode,
1739 1.1 mrg int *punsignedp ATTRIBUTE_UNUSED,
1740 1.1 mrg const_tree funtype ATTRIBUTE_UNUSED, int for_return ATTRIBUTE_UNUSED)
1741 1.1 mrg {
1742 1.1 mrg return mode;
1743 1.1 mrg }
1744 1.1 mrg
1745 1.1 mrg #undef TARGET_FUNCTION_ARG
1746 1.1 mrg #define TARGET_FUNCTION_ARG rl78_function_arg
1747 1.1 mrg
1748 1.1 mrg static rtx
1749 1.1 mrg rl78_function_arg (cumulative_args_t, const function_arg_info &)
1750 1.1 mrg {
1751 1.1 mrg return NULL_RTX;
1752 1.1 mrg }
1753 1.1 mrg
1754 1.1 mrg #undef TARGET_FUNCTION_ARG_ADVANCE
1755 1.1 mrg #define TARGET_FUNCTION_ARG_ADVANCE rl78_function_arg_advance
1756 1.1 mrg
1757 1.1 mrg static void
1758 1.1 mrg rl78_function_arg_advance (cumulative_args_t cum_v,
1759 1.1 mrg const function_arg_info &arg)
1760 1.1 mrg {
1761 1.1 mrg int rounded_size;
1762 1.1 mrg CUMULATIVE_ARGS * cum = get_cumulative_args (cum_v);
1763 1.1 mrg
1764 1.1 mrg rounded_size = arg.promoted_size_in_bytes ();
1765 1.1 mrg if (rounded_size & 1)
1766 1.1 mrg rounded_size ++;
1767 1.1 mrg (*cum) += rounded_size;
1768 1.1 mrg }
1769 1.1 mrg
1770 1.1 mrg #undef TARGET_FUNCTION_ARG_BOUNDARY
1771 1.1 mrg #define TARGET_FUNCTION_ARG_BOUNDARY rl78_function_arg_boundary
1772 1.1 mrg
1773 1.1 mrg static unsigned int
1774 1.1 mrg rl78_function_arg_boundary (machine_mode mode ATTRIBUTE_UNUSED,
1775 1.1 mrg const_tree type ATTRIBUTE_UNUSED)
1776 1.1 mrg {
1777 1.1 mrg return 16;
1778 1.1 mrg }
1779 1.1 mrg
1780 1.1 mrg /* Supported modifier letters:
1781 1.1 mrg
1782 1.1 mrg A - address of a MEM
1783 1.1 mrg S - SADDR form of a real register
1784 1.1 mrg v - real register corresponding to a virtual register
1785 1.1 mrg m - minus - negative of CONST_INT value.
1786 1.1 mrg C - inverse of a conditional (NE vs EQ for example)
1787 1.1 mrg C - complement of an integer
1788 1.1 mrg z - collapsed conditional
1789 1.1 mrg s - shift count mod 8
1790 1.1 mrg S - shift count mod 16
1791 1.1 mrg r - reverse shift count (8-(count mod 8))
1792 1.1 mrg B - bit position
1793 1.1 mrg
1794 1.1 mrg h - bottom HI of an SI
1795 1.1 mrg H - top HI of an SI
1796 1.1 mrg q - bottom QI of an HI
1797 1.1 mrg Q - top QI of an HI
1798 1.1 mrg e - third QI of an SI (i.e. where the ES register gets values from)
1799 1.1 mrg E - fourth QI of an SI (i.e. MSB)
1800 1.1 mrg
1801 1.1 mrg p - Add +0 to a zero-indexed HL based address.
1802 1.1 mrg */
1803 1.1 mrg
1804 1.1 mrg /* Implements the bulk of rl78_print_operand, below. We do it this
1805 1.1 mrg way because we need to test for a constant at the top level and
1806 1.1 mrg insert the '#', but not test for it anywhere else as we recurse
1807 1.1 mrg down into the operand. */
1808 1.1 mrg static void
1809 1.1 mrg rl78_print_operand_1 (FILE * file, rtx op, int letter)
1810 1.1 mrg {
1811 1.1 mrg int need_paren;
1812 1.1 mrg
1813 1.1 mrg switch (GET_CODE (op))
1814 1.1 mrg {
1815 1.1 mrg case MEM:
1816 1.1 mrg if (letter == 'A')
1817 1.1 mrg rl78_print_operand_1 (file, XEXP (op, 0), letter);
1818 1.1 mrg else
1819 1.1 mrg {
1820 1.1 mrg if (rl78_far_p (op))
1821 1.1 mrg {
1822 1.1 mrg fprintf (file, "es:");
1823 1.1 mrg if (GET_CODE (XEXP (op, 0)) == UNSPEC)
1824 1.1 mrg op = gen_rtx_MEM (GET_MODE (op), XVECEXP (XEXP (op, 0), 0, 1));
1825 1.1 mrg }
1826 1.1 mrg if (letter == 'H')
1827 1.1 mrg {
1828 1.1 mrg op = adjust_address (op, HImode, 2);
1829 1.1 mrg letter = 0;
1830 1.1 mrg }
1831 1.1 mrg if (letter == 'h')
1832 1.1 mrg {
1833 1.1 mrg op = adjust_address (op, HImode, 0);
1834 1.1 mrg letter = 0;
1835 1.1 mrg }
1836 1.1 mrg if (letter == 'Q')
1837 1.1 mrg {
1838 1.1 mrg op = adjust_address (op, QImode, 1);
1839 1.1 mrg letter = 0;
1840 1.1 mrg }
1841 1.1 mrg if (letter == 'q')
1842 1.1 mrg {
1843 1.1 mrg op = adjust_address (op, QImode, 0);
1844 1.1 mrg letter = 0;
1845 1.1 mrg }
1846 1.1 mrg if (letter == 'e')
1847 1.1 mrg {
1848 1.1 mrg op = adjust_address (op, QImode, 2);
1849 1.1 mrg letter = 0;
1850 1.1 mrg }
1851 1.1 mrg if (letter == 'E')
1852 1.1 mrg {
1853 1.1 mrg op = adjust_address (op, QImode, 3);
1854 1.1 mrg letter = 0;
1855 1.1 mrg }
1856 1.1 mrg if (CONSTANT_P (XEXP (op, 0)))
1857 1.1 mrg {
1858 1.1 mrg if (!rl78_saddr_p (op))
1859 1.1 mrg fprintf (file, "!");
1860 1.1 mrg rl78_print_operand_1 (file, XEXP (op, 0), letter);
1861 1.1 mrg }
1862 1.1 mrg else if (GET_CODE (XEXP (op, 0)) == PLUS
1863 1.1 mrg && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF)
1864 1.1 mrg {
1865 1.1 mrg if (!rl78_saddr_p (op))
1866 1.1 mrg fprintf (file, "!");
1867 1.1 mrg rl78_print_operand_1 (file, XEXP (op, 0), letter);
1868 1.1 mrg }
1869 1.1 mrg else if (GET_CODE (XEXP (op, 0)) == PLUS
1870 1.1 mrg && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
1871 1.1 mrg && REGNO (XEXP (XEXP (op, 0), 0)) == 2)
1872 1.1 mrg {
1873 1.1 mrg rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 1), 'u');
1874 1.1 mrg fprintf (file, "[");
1875 1.1 mrg rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 0), 0);
1876 1.1 mrg if (letter == 'p' && GET_CODE (XEXP (op, 0)) == REG)
1877 1.1 mrg fprintf (file, "+0");
1878 1.1 mrg fprintf (file, "]");
1879 1.1 mrg }
1880 1.1 mrg else
1881 1.1 mrg {
1882 1.1 mrg op = XEXP (op, 0);
1883 1.1 mrg fprintf (file, "[");
1884 1.1 mrg rl78_print_operand_1 (file, op, letter);
1885 1.1 mrg if (letter == 'p' && REG_P (op) && REGNO (op) == 6)
1886 1.1 mrg fprintf (file, "+0");
1887 1.1 mrg fprintf (file, "]");
1888 1.1 mrg }
1889 1.1 mrg }
1890 1.1 mrg break;
1891 1.1 mrg
1892 1.1 mrg case REG:
1893 1.1 mrg if (letter == 'Q')
1894 1.1 mrg fprintf (file, "%s", reg_names [REGNO (op) | 1]);
1895 1.1 mrg else if (letter == 'H')
1896 1.1 mrg fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1897 1.1 mrg else if (letter == 'q')
1898 1.1 mrg fprintf (file, "%s", reg_names [REGNO (op) & ~1]);
1899 1.1 mrg else if (letter == 'e')
1900 1.1 mrg fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1901 1.1 mrg else if (letter == 'E')
1902 1.1 mrg fprintf (file, "%s", reg_names [REGNO (op) + 3]);
1903 1.1 mrg else if (letter == 'S')
1904 1.1 mrg fprintf (file, "0x%x", 0xffef8 + REGNO (op));
1905 1.1 mrg else if (GET_MODE (op) == HImode
1906 1.1 mrg && ! (REGNO (op) & ~0xfe))
1907 1.1 mrg {
1908 1.1 mrg if (letter == 'v')
1909 1.1 mrg fprintf (file, "%s", word_regnames [REGNO (op) % 8]);
1910 1.1 mrg else
1911 1.1 mrg fprintf (file, "%s", word_regnames [REGNO (op)]);
1912 1.1 mrg }
1913 1.1 mrg else
1914 1.1 mrg fprintf (file, "%s", reg_names [REGNO (op)]);
1915 1.1 mrg break;
1916 1.1 mrg
1917 1.1 mrg case CONST_INT:
1918 1.1 mrg if (letter == 'Q')
1919 1.1 mrg fprintf (file, "%ld", INTVAL (op) >> 8);
1920 1.1 mrg else if (letter == 'H')
1921 1.1 mrg fprintf (file, "%ld", INTVAL (op) >> 16);
1922 1.1 mrg else if (letter == 'q')
1923 1.1 mrg fprintf (file, "%ld", INTVAL (op) & 0xff);
1924 1.1 mrg else if (letter == 'h')
1925 1.1 mrg fprintf (file, "%ld", INTVAL (op) & 0xffff);
1926 1.1 mrg else if (letter == 'e')
1927 1.1 mrg fprintf (file, "%ld", (INTVAL (op) >> 16) & 0xff);
1928 1.1 mrg else if (letter == 'B')
1929 1.1 mrg {
1930 1.1 mrg int ival = INTVAL (op);
1931 1.1 mrg if (ival == -128)
1932 1.1 mrg ival = 0x80;
1933 1.1 mrg if (exact_log2 (ival) >= 0)
1934 1.1 mrg fprintf (file, "%d", exact_log2 (ival));
1935 1.1 mrg else
1936 1.1 mrg fprintf (file, "%d", exact_log2 (~ival & 0xff));
1937 1.1 mrg }
1938 1.1 mrg else if (letter == 'E')
1939 1.1 mrg fprintf (file, "%ld", (INTVAL (op) >> 24) & 0xff);
1940 1.1 mrg else if (letter == 'm')
1941 1.1 mrg fprintf (file, "%ld", - INTVAL (op));
1942 1.1 mrg else if (letter == 's')
1943 1.1 mrg fprintf (file, "%ld", INTVAL (op) % 8);
1944 1.1 mrg else if (letter == 'S')
1945 1.1 mrg fprintf (file, "%ld", INTVAL (op) % 16);
1946 1.1 mrg else if (letter == 'r')
1947 1.1 mrg fprintf (file, "%ld", 8 - (INTVAL (op) % 8));
1948 1.1 mrg else if (letter == 'C')
1949 1.1 mrg fprintf (file, "%ld", (INTVAL (op) ^ 0x8000) & 0xffff);
1950 1.1 mrg else
1951 1.1 mrg fprintf (file, "%ld", INTVAL (op));
1952 1.1 mrg break;
1953 1.1 mrg
1954 1.1 mrg case CONST:
1955 1.1 mrg rl78_print_operand_1 (file, XEXP (op, 0), letter);
1956 1.1 mrg break;
1957 1.1 mrg
1958 1.1 mrg case ZERO_EXTRACT:
1959 1.1 mrg {
1960 1.1 mrg int bits = INTVAL (XEXP (op, 1));
1961 1.1 mrg int ofs = INTVAL (XEXP (op, 2));
1962 1.1 mrg if (bits == 16 && ofs == 0)
1963 1.1 mrg fprintf (file, "%%lo16(");
1964 1.1 mrg else if (bits == 16 && ofs == 16)
1965 1.1 mrg fprintf (file, "%%hi16(");
1966 1.1 mrg else if (bits == 8 && ofs == 16)
1967 1.1 mrg fprintf (file, "%%hi8(");
1968 1.1 mrg else
1969 1.1 mrg gcc_unreachable ();
1970 1.1 mrg rl78_print_operand_1 (file, XEXP (op, 0), 0);
1971 1.1 mrg fprintf (file, ")");
1972 1.1 mrg }
1973 1.1 mrg break;
1974 1.1 mrg
1975 1.1 mrg case ZERO_EXTEND:
1976 1.1 mrg if (GET_CODE (XEXP (op, 0)) == REG)
1977 1.1 mrg fprintf (file, "%s", reg_names [REGNO (XEXP (op, 0))]);
1978 1.1 mrg else
1979 1.1 mrg print_rtl (file, op);
1980 1.1 mrg break;
1981 1.1 mrg
1982 1.1 mrg case PLUS:
1983 1.1 mrg need_paren = 0;
1984 1.1 mrg if (letter == 'H')
1985 1.1 mrg {
1986 1.1 mrg fprintf (file, "%%hi16(");
1987 1.1 mrg need_paren = 1;
1988 1.1 mrg letter = 0;
1989 1.1 mrg }
1990 1.1 mrg if (letter == 'h')
1991 1.1 mrg {
1992 1.1 mrg fprintf (file, "%%lo16(");
1993 1.1 mrg need_paren = 1;
1994 1.1 mrg letter = 0;
1995 1.1 mrg }
1996 1.1 mrg if (letter == 'e')
1997 1.1 mrg {
1998 1.1 mrg fprintf (file, "%%hi8(");
1999 1.1 mrg need_paren = 1;
2000 1.1 mrg letter = 0;
2001 1.1 mrg }
2002 1.1 mrg if (letter == 'q' || letter == 'Q')
2003 1.1 mrg output_operand_lossage ("q/Q modifiers invalid for symbol references");
2004 1.1 mrg
2005 1.1 mrg if (GET_CODE (XEXP (op, 0)) == ZERO_EXTEND)
2006 1.1 mrg {
2007 1.1 mrg if (GET_CODE (XEXP (op, 1)) == SYMBOL_REF
2008 1.1 mrg && SYMBOL_REF_DECL (XEXP (op, 1))
2009 1.1 mrg && TREE_CODE (SYMBOL_REF_DECL (XEXP (op, 1))) == FUNCTION_DECL)
2010 1.1 mrg {
2011 1.1 mrg fprintf (file, "%%code(");
2012 1.1 mrg assemble_name (file, rl78_strip_nonasm_name_encoding (XSTR (XEXP (op, 1), 0)));
2013 1.1 mrg fprintf (file, "+");
2014 1.1 mrg rl78_print_operand_1 (file, XEXP (op, 0), letter);
2015 1.1 mrg fprintf (file, ")");
2016 1.1 mrg }
2017 1.1 mrg else
2018 1.1 mrg {
2019 1.1 mrg rl78_print_operand_1 (file, XEXP (op, 1), letter);
2020 1.1 mrg fprintf (file, "+");
2021 1.1 mrg rl78_print_operand_1 (file, XEXP (op, 0), letter);
2022 1.1 mrg }
2023 1.1 mrg }
2024 1.1 mrg else
2025 1.1 mrg {
2026 1.1 mrg if (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
2027 1.1 mrg && SYMBOL_REF_DECL (XEXP (op, 0))
2028 1.1 mrg && TREE_CODE (SYMBOL_REF_DECL (XEXP (op, 0))) == FUNCTION_DECL)
2029 1.1 mrg {
2030 1.1 mrg fprintf (file, "%%code(");
2031 1.1 mrg assemble_name (file, rl78_strip_nonasm_name_encoding (XSTR (XEXP (op, 0), 0)));
2032 1.1 mrg fprintf (file, "+");
2033 1.1 mrg rl78_print_operand_1 (file, XEXP (op, 1), letter);
2034 1.1 mrg fprintf (file, ")");
2035 1.1 mrg }
2036 1.1 mrg else
2037 1.1 mrg {
2038 1.1 mrg rl78_print_operand_1 (file, XEXP (op, 0), letter);
2039 1.1 mrg fprintf (file, "+");
2040 1.1 mrg rl78_print_operand_1 (file, XEXP (op, 1), letter);
2041 1.1 mrg }
2042 1.1 mrg }
2043 1.1 mrg if (need_paren)
2044 1.1 mrg fprintf (file, ")");
2045 1.1 mrg break;
2046 1.1 mrg
2047 1.1 mrg case SUBREG:
2048 1.1 mrg if (GET_MODE (op) == HImode
2049 1.1 mrg && SUBREG_BYTE (op) == 0)
2050 1.1 mrg {
2051 1.1 mrg fprintf (file, "%%lo16(");
2052 1.1 mrg rl78_print_operand_1 (file, SUBREG_REG (op), 0);
2053 1.1 mrg fprintf (file, ")");
2054 1.1 mrg }
2055 1.1 mrg else if (GET_MODE (op) == HImode
2056 1.1 mrg && SUBREG_BYTE (op) == 2)
2057 1.1 mrg {
2058 1.1 mrg fprintf (file, "%%hi16(");
2059 1.1 mrg rl78_print_operand_1 (file, SUBREG_REG (op), 0);
2060 1.1 mrg fprintf (file, ")");
2061 1.1 mrg }
2062 1.1 mrg else
2063 1.1 mrg {
2064 1.1 mrg fprintf (file, "(%s)", GET_RTX_NAME (GET_CODE (op)));
2065 1.1 mrg }
2066 1.1 mrg break;
2067 1.1 mrg
2068 1.1 mrg case SYMBOL_REF:
2069 1.1 mrg need_paren = 0;
2070 1.1 mrg if (letter == 'H')
2071 1.1 mrg {
2072 1.1 mrg fprintf (file, "%%hi16(");
2073 1.1 mrg need_paren = 1;
2074 1.1 mrg letter = 0;
2075 1.1 mrg }
2076 1.1 mrg if (letter == 'h')
2077 1.1 mrg {
2078 1.1 mrg fprintf (file, "%%lo16(");
2079 1.1 mrg need_paren = 1;
2080 1.1 mrg letter = 0;
2081 1.1 mrg }
2082 1.1 mrg if (letter == 'e')
2083 1.1 mrg {
2084 1.1 mrg fprintf (file, "%%hi8(");
2085 1.1 mrg need_paren = 1;
2086 1.1 mrg letter = 0;
2087 1.1 mrg }
2088 1.1 mrg if (letter == 'q' || letter == 'Q')
2089 1.1 mrg output_operand_lossage ("q/Q modifiers invalid for symbol references");
2090 1.1 mrg
2091 1.1 mrg if (SYMBOL_REF_DECL (op) && TREE_CODE (SYMBOL_REF_DECL (op)) == FUNCTION_DECL)
2092 1.1 mrg {
2093 1.1 mrg fprintf (file, "%%code(");
2094 1.1 mrg assemble_name (file, rl78_strip_nonasm_name_encoding (XSTR (op, 0)));
2095 1.1 mrg fprintf (file, ")");
2096 1.1 mrg }
2097 1.1 mrg else
2098 1.1 mrg assemble_name (file, rl78_strip_nonasm_name_encoding (XSTR (op, 0)));
2099 1.1 mrg if (need_paren)
2100 1.1 mrg fprintf (file, ")");
2101 1.1 mrg break;
2102 1.1 mrg
2103 1.1 mrg case CODE_LABEL:
2104 1.1 mrg case LABEL_REF:
2105 1.1 mrg output_asm_label (op);
2106 1.1 mrg break;
2107 1.1 mrg
2108 1.1 mrg case LTU:
2109 1.1 mrg if (letter == 'z')
2110 1.1 mrg fprintf (file, "#comparison eliminated");
2111 1.1 mrg else
2112 1.1 mrg fprintf (file, letter == 'C' ? "nc" : "c");
2113 1.1 mrg break;
2114 1.1 mrg case LEU:
2115 1.1 mrg if (letter == 'z')
2116 1.1 mrg fprintf (file, "br");
2117 1.1 mrg else
2118 1.1 mrg fprintf (file, letter == 'C' ? "h" : "nh");
2119 1.1 mrg break;
2120 1.1 mrg case GEU:
2121 1.1 mrg if (letter == 'z')
2122 1.1 mrg fprintf (file, "br");
2123 1.1 mrg else
2124 1.1 mrg fprintf (file, letter == 'C' ? "c" : "nc");
2125 1.1 mrg break;
2126 1.1 mrg case GTU:
2127 1.1 mrg if (letter == 'z')
2128 1.1 mrg fprintf (file, "#comparison eliminated");
2129 1.1 mrg else
2130 1.1 mrg fprintf (file, letter == 'C' ? "nh" : "h");
2131 1.1 mrg break;
2132 1.1 mrg case EQ:
2133 1.1 mrg if (letter == 'z')
2134 1.1 mrg fprintf (file, "br");
2135 1.1 mrg else
2136 1.1 mrg fprintf (file, letter == 'C' ? "nz" : "z");
2137 1.1 mrg break;
2138 1.1 mrg case NE:
2139 1.1 mrg if (letter == 'z')
2140 1.1 mrg fprintf (file, "#comparison eliminated");
2141 1.1 mrg else
2142 1.1 mrg fprintf (file, letter == 'C' ? "z" : "nz");
2143 1.1 mrg break;
2144 1.1 mrg
2145 1.1 mrg /* Note: these assume appropriate adjustments were made so that
2146 1.1 mrg unsigned comparisons, which is all this chip has, will
2147 1.1 mrg work. */
2148 1.1 mrg case LT:
2149 1.1 mrg if (letter == 'z')
2150 1.1 mrg fprintf (file, "#comparison eliminated");
2151 1.1 mrg else
2152 1.1 mrg fprintf (file, letter == 'C' ? "nc" : "c");
2153 1.1 mrg break;
2154 1.1 mrg case LE:
2155 1.1 mrg if (letter == 'z')
2156 1.1 mrg fprintf (file, "br");
2157 1.1 mrg else
2158 1.1 mrg fprintf (file, letter == 'C' ? "h" : "nh");
2159 1.1 mrg break;
2160 1.1 mrg case GE:
2161 1.1 mrg if (letter == 'z')
2162 1.1 mrg fprintf (file, "br");
2163 1.1 mrg else
2164 1.1 mrg fprintf (file, letter == 'C' ? "c" : "nc");
2165 1.1 mrg break;
2166 1.1 mrg case GT:
2167 1.1 mrg if (letter == 'z')
2168 1.1 mrg fprintf (file, "#comparison eliminated");
2169 1.1 mrg else
2170 1.1 mrg fprintf (file, letter == 'C' ? "nh" : "h");
2171 1.1 mrg break;
2172 1.1 mrg
2173 1.1 mrg default:
2174 1.1 mrg fprintf (file, "(%s)", GET_RTX_NAME (GET_CODE (op)));
2175 1.1 mrg break;
2176 1.1 mrg }
2177 1.1 mrg }
2178 1.1 mrg
2179 1.1 mrg #undef TARGET_PRINT_OPERAND
2180 1.1 mrg #define TARGET_PRINT_OPERAND rl78_print_operand
2181 1.1 mrg
2182 1.1 mrg static void
2183 1.1 mrg rl78_print_operand (FILE * file, rtx op, int letter)
2184 1.1 mrg {
2185 1.1 mrg if (CONSTANT_P (op) && letter != 'u' && letter != 's' && letter != 'r' && letter != 'S' && letter != 'B')
2186 1.1 mrg fprintf (file, "#");
2187 1.1 mrg rl78_print_operand_1 (file, op, letter);
2188 1.1 mrg }
2189 1.1 mrg
2190 1.1 mrg #undef TARGET_TRAMPOLINE_INIT
2191 1.1 mrg #define TARGET_TRAMPOLINE_INIT rl78_trampoline_init
2192 1.1 mrg
2193 1.1 mrg /* Note that the RL78's addressing makes it very difficult to do
2194 1.1 mrg trampolines on the stack. So, libgcc has a small pool of
2195 1.1 mrg trampolines from which one is allocated to this task. */
2196 1.1 mrg static void
2197 1.1 mrg rl78_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
2198 1.1 mrg {
2199 1.1 mrg rtx mov_addr, thunk_addr;
2200 1.1 mrg rtx function = XEXP (DECL_RTL (fndecl), 0);
2201 1.1 mrg
2202 1.1 mrg mov_addr = adjust_address (m_tramp, HImode, 0);
2203 1.1 mrg thunk_addr = gen_reg_rtx (HImode);
2204 1.1 mrg
2205 1.1 mrg function = force_reg (HImode, function);
2206 1.1 mrg static_chain = force_reg (HImode, static_chain);
2207 1.1 mrg
2208 1.1 mrg emit_insn (gen_trampoline_init (thunk_addr, function, static_chain));
2209 1.1 mrg emit_move_insn (mov_addr, thunk_addr);
2210 1.1 mrg
2211 1.1 mrg cfun->machine->trampolines_used = 1;
2212 1.1 mrg }
2213 1.1 mrg
2214 1.1 mrg #undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
2215 1.1 mrg #define TARGET_TRAMPOLINE_ADJUST_ADDRESS rl78_trampoline_adjust_address
2216 1.1 mrg
2217 1.1 mrg static rtx
2218 1.1 mrg rl78_trampoline_adjust_address (rtx m_tramp)
2219 1.1 mrg {
2220 1.1 mrg rtx x = gen_rtx_MEM (HImode, m_tramp);
2221 1.1 mrg return x;
2222 1.1 mrg }
2223 1.1 mrg
2224 1.1 mrg /* Expander for cbranchqi4 and cbranchhi4. RL78 is missing some of
2226 1.1 mrg the "normal" compares, specifically, it only has unsigned compares,
2227 1.1 mrg so we must synthesize the missing ones. */
2228 1.1 mrg void
2229 1.1 mrg rl78_expand_compare (rtx *operands)
2230 1.1 mrg {
2231 1.1 mrg if (GET_CODE (operands[2]) == MEM)
2232 1.1 mrg operands[2] = copy_to_mode_reg (GET_MODE (operands[2]), operands[2]);
2233 1.1 mrg }
2234 1.1 mrg
2235 1.1 mrg
2236 1.1 mrg
2238 1.1 mrg /* Define this to 1 if you are debugging the peephole optimizers. */
2239 1.1 mrg #define DEBUG_PEEP 0
2240 1.1 mrg
2241 1.1 mrg /* Predicate used to enable the peephole2 patterns in rl78-virt.md.
2242 1.1 mrg The default "word" size is a byte so we can effectively use all the
2243 1.1 mrg registers, but we want to do 16-bit moves whenever possible. This
2244 1.1 mrg function determines when such a move is an option. */
2245 1.1 mrg bool
2246 1.1 mrg rl78_peep_movhi_p (rtx *operands)
2247 1.1 mrg {
2248 1.1 mrg int i;
2249 1.1 mrg rtx m, a;
2250 1.1 mrg
2251 1.1 mrg /* (set (op0) (op1))
2252 1.1 mrg (set (op2) (op3)) */
2253 1.1 mrg
2254 1.1 mrg if (! rl78_virt_insns_ok ())
2255 1.1 mrg return false;
2256 1.1 mrg
2257 1.1 mrg #if DEBUG_PEEP
2258 1.1 mrg fprintf (stderr, "\033[33m");
2259 1.1 mrg debug_rtx (operands[0]);
2260 1.1 mrg debug_rtx (operands[1]);
2261 1.1 mrg debug_rtx (operands[2]);
2262 1.1 mrg debug_rtx (operands[3]);
2263 1.1 mrg fprintf (stderr, "\033[0m");
2264 1.1 mrg #endif
2265 1.1 mrg
2266 1.1 mrg /* You can move a constant to memory as QImode, but not HImode. */
2267 1.1 mrg if (GET_CODE (operands[0]) == MEM
2268 1.1 mrg && GET_CODE (operands[1]) != REG)
2269 1.1 mrg {
2270 1.1 mrg #if DEBUG_PEEP
2271 1.1 mrg fprintf (stderr, "no peep: move constant to memory\n");
2272 1.1 mrg #endif
2273 1.1 mrg return false;
2274 1.1 mrg }
2275 1.1 mrg
2276 1.1 mrg if (rtx_equal_p (operands[0], operands[3]))
2277 1.1 mrg {
2278 1.1 mrg #if DEBUG_PEEP
2279 1.1 mrg fprintf (stderr, "no peep: overlapping\n");
2280 1.1 mrg #endif
2281 1.1 mrg return false;
2282 1.1 mrg }
2283 1.1 mrg
2284 1.1 mrg for (i = 0; i < 2; i ++)
2285 1.1 mrg {
2286 1.1 mrg if (GET_CODE (operands[i]) != GET_CODE (operands[i+2]))
2287 1.1 mrg {
2288 1.1 mrg #if DEBUG_PEEP
2289 1.1 mrg fprintf (stderr, "no peep: different codes\n");
2290 1.1 mrg #endif
2291 1.1 mrg return false;
2292 1.1 mrg }
2293 1.1 mrg if (GET_MODE (operands[i]) != GET_MODE (operands[i+2]))
2294 1.1 mrg {
2295 1.1 mrg #if DEBUG_PEEP
2296 1.1 mrg fprintf (stderr, "no peep: different modes\n");
2297 1.1 mrg #endif
2298 1.1 mrg return false;
2299 1.1 mrg }
2300 1.1 mrg
2301 1.1 mrg switch (GET_CODE (operands[i]))
2302 1.1 mrg {
2303 1.1 mrg case REG:
2304 1.1 mrg /* LSB MSB */
2305 1.1 mrg if (REGNO (operands[i]) + 1 != REGNO (operands[i+2])
2306 1.1 mrg || GET_MODE (operands[i]) != QImode)
2307 1.1 mrg {
2308 1.1 mrg #if DEBUG_PEEP
2309 1.1 mrg fprintf (stderr, "no peep: wrong regnos %d %d %d\n",
2310 1.1 mrg REGNO (operands[i]), REGNO (operands[i+2]),
2311 1.1 mrg i);
2312 1.1 mrg #endif
2313 1.1 mrg return false;
2314 1.1 mrg }
2315 1.1 mrg if (! rl78_hard_regno_mode_ok (REGNO (operands[i]), HImode))
2316 1.1 mrg {
2317 1.1 mrg #if DEBUG_PEEP
2318 1.1 mrg fprintf (stderr, "no peep: reg %d not HI\n", REGNO (operands[i]));
2319 1.1 mrg #endif
2320 1.1 mrg return false;
2321 1.1 mrg }
2322 1.1 mrg break;
2323 1.1 mrg
2324 1.1 mrg case CONST_INT:
2325 1.1 mrg break;
2326 1.1 mrg
2327 1.1 mrg case MEM:
2328 1.1 mrg if (GET_MODE (operands[i]) != QImode)
2329 1.1 mrg return false;
2330 1.1 mrg if (MEM_ALIGN (operands[i]) < 16)
2331 1.1 mrg return false;
2332 1.1 mrg a = XEXP (operands[i], 0);
2333 1.1 mrg if (GET_CODE (a) == CONST)
2334 1.1 mrg a = XEXP (a, 0);
2335 1.1 mrg if (GET_CODE (a) == PLUS)
2336 1.1 mrg a = XEXP (a, 1);
2337 1.1 mrg if (GET_CODE (a) == CONST_INT
2338 1.1 mrg && INTVAL (a) & 1)
2339 1.1 mrg {
2340 1.1 mrg #if DEBUG_PEEP
2341 1.1 mrg fprintf (stderr, "no peep: misaligned mem %d\n", i);
2342 1.1 mrg debug_rtx (operands[i]);
2343 1.1 mrg #endif
2344 1.1 mrg return false;
2345 1.1 mrg }
2346 1.1 mrg m = adjust_address (operands[i], QImode, 1);
2347 1.1 mrg if (! rtx_equal_p (m, operands[i+2]))
2348 1.1 mrg {
2349 1.1 mrg #if DEBUG_PEEP
2350 1.1 mrg fprintf (stderr, "no peep: wrong mem %d\n", i);
2351 1.1 mrg debug_rtx (m);
2352 1.1 mrg debug_rtx (operands[i+2]);
2353 1.1 mrg #endif
2354 1.1 mrg return false;
2355 1.1 mrg }
2356 1.1 mrg break;
2357 1.1 mrg
2358 1.1 mrg default:
2359 1.1 mrg #if DEBUG_PEEP
2360 1.1 mrg fprintf (stderr, "no peep: wrong rtx %d\n", i);
2361 1.1 mrg #endif
2362 1.1 mrg return false;
2363 1.1 mrg }
2364 1.1 mrg }
2365 1.1 mrg #if DEBUG_PEEP
2366 1.1 mrg fprintf (stderr, "\033[32mpeep!\033[0m\n");
2367 1.1 mrg #endif
2368 1.1 mrg return true;
2369 1.1 mrg }
2370 1.1 mrg
2371 1.1 mrg /* Likewise, when a peephole is activated, this function helps compute
2372 1.1 mrg the new operands. */
2373 1.1 mrg void
2374 1.1 mrg rl78_setup_peep_movhi (rtx *operands)
2375 1.1 mrg {
2376 1.1 mrg int i;
2377 1.1 mrg
2378 1.1 mrg for (i = 0; i < 2; i ++)
2379 1.1 mrg {
2380 1.1 mrg switch (GET_CODE (operands[i]))
2381 1.1 mrg {
2382 1.1 mrg case REG:
2383 1.1 mrg operands[i+4] = gen_rtx_REG (HImode, REGNO (operands[i]));
2384 1.1 mrg break;
2385 1.1 mrg
2386 1.1 mrg case CONST_INT:
2387 1.1 mrg operands[i+4] = GEN_INT ((INTVAL (operands[i]) & 0xff) + ((char) INTVAL (operands[i+2])) * 256);
2388 1.1 mrg break;
2389 1.1 mrg
2390 1.1 mrg case MEM:
2391 1.1 mrg operands[i+4] = adjust_address (operands[i], HImode, 0);
2392 1.1 mrg break;
2393 1.1 mrg
2394 1.1 mrg default:
2395 1.1 mrg break;
2396 1.1 mrg }
2397 1.1 mrg }
2398 1.1 mrg }
2399 1.1 mrg
2400 1.1 mrg /*
2402 1.1 mrg How Devirtualization works in the RL78 GCC port
2403 1.1 mrg
2404 1.1 mrg Background
2405 1.1 mrg
2406 1.1 mrg The RL78 is an 8-bit port with some 16-bit operations. It has 32
2407 1.1 mrg bytes of register space, in four banks, memory-mapped. One bank is
2408 1.1 mrg the "selected" bank and holds the registers used for primary
2409 1.1 mrg operations. Since the registers are memory mapped, often you can
2410 1.1 mrg still refer to the unselected banks via memory accesses.
2411 1.1 mrg
2412 1.1 mrg Virtual Registers
2413 1.1 mrg
2414 1.1 mrg The GCC port uses bank 0 as the "selected" registers (A, X, BC, etc)
2415 1.1 mrg and refers to the other banks via their memory addresses, although
2416 1.1 mrg they're treated as regular registers internally. These "virtual"
2417 1.1 mrg registers are R8 through R23 (bank3 is reserved for asm-based
2418 1.1 mrg interrupt handlers).
2419 1.1 mrg
2420 1.1 mrg There are four machine description files:
2421 1.1 mrg
2422 1.1 mrg rl78.md - common register-independent patterns and definitions
2423 1.1 mrg rl78-expand.md - expanders
2424 1.1 mrg rl78-virt.md - patterns that match BEFORE devirtualization
2425 1.1 mrg rl78-real.md - patterns that match AFTER devirtualization
2426 1.1 mrg
2427 1.1 mrg At least through register allocation and reload, gcc is told that it
2428 1.1 mrg can do pretty much anything - but may only use the virtual registers.
2429 1.1 mrg GCC cannot properly create the varying addressing modes that the RL78
2430 1.1 mrg supports in an efficient way.
2431 1.1 mrg
2432 1.1 mrg Sometime after reload, the RL78 backend "devirtualizes" the RTL. It
2433 1.1 mrg uses the "valloc" attribute in rl78-virt.md for determining the rules
2434 1.1 mrg by which it will replace virtual registers with real registers (or
2435 1.1 mrg not) and how to make up addressing modes. For example, insns tagged
2436 1.1 mrg with "ro1" have a single read-only parameter, which may need to be
2437 1.1 mrg moved from memory/constant/vreg to a suitable real register. As part
2438 1.1 mrg of devirtualization, a flag is toggled, disabling the rl78-virt.md
2439 1.1 mrg patterns and enabling the rl78-real.md patterns. The new patterns'
2440 1.1 mrg constraints are used to determine the real registers used. NOTE:
2441 1.1 mrg patterns in rl78-virt.md essentially ignore the constrains and rely on
2442 1.1 mrg predicates, where the rl78-real.md ones essentially ignore the
2443 1.1 mrg predicates and rely on the constraints.
2444 1.1 mrg
2445 1.1 mrg The devirtualization pass is scheduled via the pass manager (despite
2446 1.1 mrg being called "rl78_reorg") so it can be scheduled prior to var-track
2447 1.1 mrg (the idea is to let gdb know about the new registers). Ideally, it
2448 1.1 mrg would be scheduled right after pro/epilogue generation, so the
2449 1.1 mrg post-reload optimizers could operate on the real registers, but when I
2450 1.1 mrg tried that there were some issues building the target libraries.
2451 1.1 mrg
2452 1.1 mrg During devirtualization, a simple register move optimizer is run. It
2453 1.1 mrg would be better to run a full CSE/propogation pass on it though, but
2454 1.1 mrg that has not yet been attempted.
2455 1.1 mrg
2456 1.1 mrg */
2457 1.1 mrg #define DEBUG_ALLOC 0
2458 1.1 mrg
2459 1.1 mrg #define OP(x) (*recog_data.operand_loc[x])
2460 1.1 mrg
2461 1.1 mrg /* This array is used to hold knowledge about the contents of the
2462 1.1 mrg real registers (A ... H), the memory-based registers (r8 ... r31)
2463 1.1 mrg and the first NUM_STACK_LOCS words on the stack. We use this to
2464 1.1 mrg avoid generating redundant move instructions.
2465 1.1 mrg
2466 1.1 mrg A value in the range 0 .. 31 indicates register A .. r31.
2467 1.1 mrg A value in the range 32 .. 63 indicates stack slot (value - 32).
2468 1.1 mrg A value of NOT_KNOWN indicates that the contents of that location
2469 1.1 mrg are not known. */
2470 1.1 mrg
2471 1.1 mrg #define NUM_STACK_LOCS 32
2472 1.1 mrg #define NOT_KNOWN 127
2473 1.1 mrg
2474 1.1 mrg static unsigned char content_memory [32 + NUM_STACK_LOCS];
2475 1.1 mrg
2476 1.1 mrg static unsigned char saved_update_index = NOT_KNOWN;
2477 1.1 mrg static unsigned char saved_update_value;
2478 1.1 mrg static machine_mode saved_update_mode;
2479 1.1 mrg
2480 1.1 mrg
2481 1.1 mrg static inline void
2482 1.1 mrg clear_content_memory (void)
2483 1.1 mrg {
2484 1.1 mrg memset (content_memory, NOT_KNOWN, sizeof content_memory);
2485 1.1 mrg if (dump_file)
2486 1.1 mrg fprintf (dump_file, " clear content memory\n");
2487 1.1 mrg saved_update_index = NOT_KNOWN;
2488 1.1 mrg }
2489 1.1 mrg
2490 1.1 mrg /* Convert LOC into an index into the content_memory array.
2491 1.1 mrg If LOC cannot be converted, return NOT_KNOWN. */
2492 1.1 mrg
2493 1.1 mrg static unsigned char
2494 1.1 mrg get_content_index (rtx loc)
2495 1.1 mrg {
2496 1.1 mrg machine_mode mode;
2497 1.1 mrg
2498 1.1 mrg if (loc == NULL_RTX)
2499 1.1 mrg return NOT_KNOWN;
2500 1.1 mrg
2501 1.1 mrg if (REG_P (loc))
2502 1.1 mrg {
2503 1.1 mrg if (REGNO (loc) < 32)
2504 1.1 mrg return REGNO (loc);
2505 1.1 mrg return NOT_KNOWN;
2506 1.1 mrg }
2507 1.1 mrg
2508 1.1 mrg mode = GET_MODE (loc);
2509 1.1 mrg
2510 1.1 mrg if (! rl78_stack_based_mem (loc, mode))
2511 1.1 mrg return NOT_KNOWN;
2512 1.1 mrg
2513 1.1 mrg loc = XEXP (loc, 0);
2514 1.1 mrg
2515 1.1 mrg if (REG_P (loc))
2516 1.1 mrg /* loc = MEM (SP) */
2517 1.1 mrg return 32;
2518 1.1 mrg
2519 1.1 mrg /* loc = MEM (PLUS (SP, INT)). */
2520 1.1 mrg loc = XEXP (loc, 1);
2521 1.1 mrg
2522 1.1 mrg if (INTVAL (loc) < NUM_STACK_LOCS)
2523 1.1 mrg return 32 + INTVAL (loc);
2524 1.1 mrg
2525 1.1 mrg return NOT_KNOWN;
2526 1.1 mrg }
2527 1.1 mrg
2528 1.1 mrg /* Return a string describing content INDEX in mode MODE.
2529 1.1 mrg WARNING: Can return a pointer to a static buffer. */
2530 1.1 mrg static const char *
2531 1.1 mrg get_content_name (unsigned char index, machine_mode mode)
2532 1.1 mrg {
2533 1.1 mrg static char buffer [128];
2534 1.1 mrg
2535 1.1 mrg if (index == NOT_KNOWN)
2536 1.1 mrg return "Unknown";
2537 1.1 mrg
2538 1.1 mrg if (index > 31)
2539 1.1 mrg sprintf (buffer, "stack slot %d", index - 32);
2540 1.1 mrg else if (mode == HImode)
2541 1.1 mrg sprintf (buffer, "%s%s",
2542 1.1 mrg reg_names [index + 1], reg_names [index]);
2543 1.1 mrg else
2544 1.1 mrg return reg_names [index];
2545 1.1 mrg
2546 1.1 mrg return buffer;
2547 1.1 mrg }
2548 1.1 mrg
2549 1.1 mrg #if DEBUG_ALLOC
2550 1.1 mrg
2551 1.1 mrg static void
2552 1.1 mrg display_content_memory (FILE * file)
2553 1.1 mrg {
2554 1.1 mrg unsigned int i;
2555 1.1 mrg
2556 1.1 mrg fprintf (file, " Known memory contents:\n");
2557 1.1 mrg
2558 1.1 mrg for (i = 0; i < sizeof content_memory; i++)
2559 1.1 mrg if (content_memory[i] != NOT_KNOWN)
2560 1.1 mrg {
2561 1.1 mrg fprintf (file, " %s contains a copy of ", get_content_name (i, QImode));
2562 1.1 mrg fprintf (file, "%s\n", get_content_name (content_memory [i], QImode));
2563 1.1 mrg }
2564 1.1 mrg }
2565 1.1 mrg #endif
2566 1.1 mrg
2567 1.1 mrg static void
2568 1.1 mrg update_content (unsigned char index, unsigned char val, machine_mode mode)
2569 1.1 mrg {
2570 1.1 mrg unsigned int i;
2571 1.1 mrg
2572 1.1 mrg gcc_assert (index < sizeof content_memory);
2573 1.1 mrg
2574 1.1 mrg content_memory [index] = val;
2575 1.1 mrg if (val != NOT_KNOWN)
2576 1.1 mrg content_memory [val] = index;
2577 1.1 mrg
2578 1.1 mrg /* Make the entry in dump_file *before* VAL is increased below. */
2579 1.1 mrg if (dump_file)
2580 1.1 mrg {
2581 1.1 mrg fprintf (dump_file, " %s now contains ", get_content_name (index, mode));
2582 1.1 mrg if (val == NOT_KNOWN)
2583 1.1 mrg fprintf (dump_file, "Unknown\n");
2584 1.1 mrg else
2585 1.1 mrg fprintf (dump_file, "%s and vice versa\n", get_content_name (val, mode));
2586 1.1 mrg }
2587 1.1 mrg
2588 1.1 mrg if (mode == HImode)
2589 1.1 mrg {
2590 1.1 mrg val = val == NOT_KNOWN ? val : val + 1;
2591 1.1 mrg
2592 1.1 mrg content_memory [index + 1] = val;
2593 1.1 mrg if (val != NOT_KNOWN)
2594 1.1 mrg {
2595 1.1 mrg content_memory [val] = index + 1;
2596 1.1 mrg -- val;
2597 1.1 mrg }
2598 1.1 mrg }
2599 1.1 mrg
2600 1.1 mrg /* Any other places that had INDEX recorded as their contents are now invalid. */
2601 1.1 mrg for (i = 0; i < sizeof content_memory; i++)
2602 1.1 mrg {
2603 1.1 mrg if (i == index
2604 1.1 mrg || (val != NOT_KNOWN && i == val))
2605 1.1 mrg {
2606 1.1 mrg if (mode == HImode)
2607 1.1 mrg ++ i;
2608 1.1 mrg continue;
2609 1.1 mrg }
2610 1.1 mrg
2611 1.1 mrg if (content_memory[i] == index
2612 1.1 mrg || (val != NOT_KNOWN && content_memory[i] == val))
2613 1.1 mrg {
2614 1.1 mrg content_memory[i] = NOT_KNOWN;
2615 1.1 mrg
2616 1.1 mrg if (dump_file)
2617 1.1 mrg fprintf (dump_file, " %s cleared\n", get_content_name (i, mode));
2618 1.1 mrg
2619 1.1 mrg if (mode == HImode)
2620 1.1 mrg content_memory[++ i] = NOT_KNOWN;
2621 1.1 mrg }
2622 1.1 mrg }
2623 1.1 mrg }
2624 1.1 mrg
2625 1.1 mrg /* Record that LOC contains VALUE.
2626 1.1 mrg For HImode locations record that LOC+1 contains VALUE+1.
2627 1.1 mrg If LOC is not a register or stack slot, do nothing.
2628 1.1 mrg If VALUE is not a register or stack slot, clear the recorded content. */
2629 1.1 mrg
2630 1.1 mrg static void
2631 1.1 mrg record_content (rtx loc, rtx value)
2632 1.1 mrg {
2633 1.1 mrg machine_mode mode;
2634 1.1 mrg unsigned char index;
2635 1.1 mrg unsigned char val;
2636 1.1 mrg
2637 1.1 mrg if ((index = get_content_index (loc)) == NOT_KNOWN)
2638 1.1 mrg return;
2639 1.1 mrg
2640 1.1 mrg val = get_content_index (value);
2641 1.1 mrg
2642 1.1 mrg mode = GET_MODE (loc);
2643 1.1 mrg
2644 1.1 mrg if (val == index)
2645 1.1 mrg {
2646 1.1 mrg if (! optimize)
2647 1.1 mrg return;
2648 1.1 mrg
2649 1.1 mrg /* This should not happen when optimizing. */
2650 1.1 mrg #if 1
2651 1.1 mrg fprintf (stderr, "ASSIGNMENT of location to itself detected! [%s]\n",
2652 1.1 mrg get_content_name (val, mode));
2653 1.1 mrg return;
2654 1.1 mrg #else
2655 1.1 mrg gcc_unreachable ();
2656 1.1 mrg #endif
2657 1.1 mrg }
2658 1.1 mrg
2659 1.1 mrg update_content (index, val, mode);
2660 1.1 mrg }
2661 1.1 mrg
2662 1.1 mrg /* Returns TRUE if LOC already contains a copy of VALUE. */
2663 1.1 mrg
2664 1.1 mrg static bool
2665 1.1 mrg already_contains (rtx loc, rtx value)
2666 1.1 mrg {
2667 1.1 mrg unsigned char index;
2668 1.1 mrg unsigned char val;
2669 1.1 mrg
2670 1.1 mrg if ((index = get_content_index (loc)) == NOT_KNOWN)
2671 1.1 mrg return false;
2672 1.1 mrg
2673 1.1 mrg if ((val = get_content_index (value)) == NOT_KNOWN)
2674 1.1 mrg return false;
2675 1.1 mrg
2676 1.1 mrg if (content_memory [index] != val)
2677 1.1 mrg return false;
2678 1.1 mrg
2679 1.1 mrg if (GET_MODE (loc) == HImode)
2680 1.1 mrg return content_memory [index + 1] == val + 1;
2681 1.1 mrg
2682 1.1 mrg return true;
2683 1.1 mrg }
2684 1.1 mrg
2685 1.1 mrg bool
2686 1.1 mrg rl78_es_addr (rtx addr)
2687 1.1 mrg {
2688 1.1 mrg if (GET_CODE (addr) == MEM)
2689 1.1 mrg addr = XEXP (addr, 0);
2690 1.1 mrg if (GET_CODE (addr) != UNSPEC)
2691 1.1 mrg return false;
2692 1.1 mrg if (XINT (addr, 1) != UNS_ES_ADDR)
2693 1.1 mrg return false;
2694 1.1 mrg return true;
2695 1.1 mrg }
2696 1.1 mrg
2697 1.1 mrg rtx
2698 1.1 mrg rl78_es_base (rtx addr)
2699 1.1 mrg {
2700 1.1 mrg if (GET_CODE (addr) == MEM)
2701 1.1 mrg addr = XEXP (addr, 0);
2702 1.1 mrg addr = XVECEXP (addr, 0, 1);
2703 1.1 mrg if (GET_CODE (addr) == CONST
2704 1.1 mrg && GET_CODE (XEXP (addr, 0)) == ZERO_EXTRACT)
2705 1.1 mrg addr = XEXP (XEXP (addr, 0), 0);
2706 1.1 mrg /* Mode doesn't matter here. */
2707 1.1 mrg return gen_rtx_MEM (HImode, addr);
2708 1.1 mrg }
2709 1.1 mrg
2710 1.1 mrg /* Rescans an insn to see if it's recognized again. This is done
2711 1.1 mrg carefully to ensure that all the constraint information is accurate
2712 1.1 mrg for the newly matched insn. */
2713 1.1 mrg static bool
2714 1.1 mrg insn_ok_now (rtx_insn * insn)
2715 1.1 mrg {
2716 1.1 mrg rtx pattern = PATTERN (insn);
2717 1.1 mrg int i;
2718 1.1 mrg
2719 1.1 mrg INSN_CODE (insn) = -1;
2720 1.1 mrg
2721 1.1 mrg if (recog (pattern, insn, 0) > -1)
2722 1.1 mrg {
2723 1.1 mrg extract_insn (insn);
2724 1.1 mrg if (constrain_operands (1, get_preferred_alternatives (insn)))
2725 1.1 mrg {
2726 1.1 mrg #if DEBUG_ALLOC
2727 1.1 mrg fprintf (stderr, "\033[32m");
2728 1.1 mrg debug_rtx (insn);
2729 1.1 mrg fprintf (stderr, "\033[0m");
2730 1.1 mrg #endif
2731 1.1 mrg if (SET_P (pattern))
2732 1.1 mrg record_content (SET_DEST (pattern), SET_SRC (pattern));
2733 1.1 mrg
2734 1.1 mrg /* We need to detect far addresses that haven't been
2735 1.1 mrg converted to es/lo16 format. */
2736 1.1 mrg for (i=0; i<recog_data.n_operands; i++)
2737 1.1 mrg if (GET_CODE (OP (i)) == MEM
2738 1.1 mrg && GET_MODE (XEXP (OP (i), 0)) == SImode
2739 1.1 mrg && GET_CODE (XEXP (OP (i), 0)) != UNSPEC)
2740 1.1 mrg goto not_ok;
2741 1.1 mrg
2742 1.1 mrg return true;
2743 1.1 mrg }
2744 1.1 mrg }
2745 1.1 mrg
2746 1.1 mrg /* INSN is not OK as-is. It may not be recognized in real mode or
2747 1.1 mrg it might not have satisfied its constraints in real mode. Either
2748 1.1 mrg way it will require fixups.
2749 1.1 mrg
2750 1.1 mrg It is vital we always re-recognize at this point as some insns
2751 1.1 mrg have fewer operands in real mode than virtual mode. If we do
2752 1.1 mrg not re-recognize, then the recog_data will refer to real mode
2753 1.1 mrg operands and we may read invalid data. Usually this isn't a
2754 1.1 mrg problem, but once in a while the data we read is bogus enough
2755 1.1 mrg to cause a segfault or other undesirable behavior. */
2756 1.1 mrg not_ok:
2757 1.1 mrg
2758 1.1 mrg /* We need to re-recog the insn with virtual registers to get
2759 1.1 mrg the operands. */
2760 1.1 mrg INSN_CODE (insn) = -1;
2761 1.1 mrg cfun->machine->virt_insns_ok = 1;
2762 1.1 mrg if (recog (pattern, insn, 0) > -1)
2763 1.1 mrg {
2764 1.1 mrg extract_insn (insn);
2765 1.1 mrg /* In theory this should always be true. */
2766 1.1 mrg if (constrain_operands (0, get_preferred_alternatives (insn)))
2767 1.1 mrg {
2768 1.1 mrg cfun->machine->virt_insns_ok = 0;
2769 1.1 mrg return false;
2770 1.1 mrg }
2771 1.1 mrg }
2772 1.1 mrg
2773 1.1 mrg #if DEBUG_ALLOC
2774 1.1 mrg fprintf (stderr, "\033[41;30m Unrecognized *virtual* insn \033[0m\n");
2775 1.1 mrg debug_rtx (insn);
2776 1.1 mrg #endif
2777 1.1 mrg gcc_unreachable ();
2778 1.1 mrg return false;
2779 1.1 mrg }
2780 1.1 mrg
2781 1.1 mrg #if DEBUG_ALLOC
2782 1.1 mrg #define WORKED fprintf (stderr, "\033[48;5;22m Worked at line %d \033[0m\n", __LINE__)
2783 1.1 mrg #define FAILEDSOFAR fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__)
2784 1.1 mrg #define FAILED fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__), gcc_unreachable ()
2785 1.1 mrg #define MAYBE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } else { FAILEDSOFAR; }
2786 1.1 mrg #define MUST_BE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } FAILED
2787 1.1 mrg #else
2788 1.1 mrg #define FAILED gcc_unreachable ()
2789 1.1 mrg #define MAYBE_OK(insn) if (insn_ok_now (insn)) return;
2790 1.1 mrg #define MUST_BE_OK(insn) if (insn_ok_now (insn)) return; FAILED
2791 1.1 mrg #endif
2792 1.1 mrg
2793 1.1 mrg /* Registers into which we move the contents of virtual registers. */
2794 1.1 mrg #define X gen_rtx_REG (QImode, X_REG)
2795 1.1 mrg #define A gen_rtx_REG (QImode, A_REG)
2796 1.1 mrg #define C gen_rtx_REG (QImode, C_REG)
2797 1.1 mrg #define B gen_rtx_REG (QImode, B_REG)
2798 1.1 mrg #define E gen_rtx_REG (QImode, E_REG)
2799 1.1 mrg #define D gen_rtx_REG (QImode, D_REG)
2800 1.1 mrg #define L gen_rtx_REG (QImode, L_REG)
2801 1.1 mrg #define H gen_rtx_REG (QImode, H_REG)
2802 1.1 mrg
2803 1.1 mrg #define AX gen_rtx_REG (HImode, AX_REG)
2804 1.1 mrg #define BC gen_rtx_REG (HImode, BC_REG)
2805 1.1 mrg #define DE gen_rtx_REG (HImode, DE_REG)
2806 1.1 mrg #define HL gen_rtx_REG (HImode, HL_REG)
2807 1.1 mrg
2808 1.1 mrg /* Returns TRUE if R is a virtual register. */
2809 1.1 mrg static inline bool
2810 1.1 mrg is_virtual_register (rtx r)
2811 1.1 mrg {
2812 1.1 mrg return (GET_CODE (r) == REG
2813 1.1 mrg && REGNO (r) >= 8
2814 1.1 mrg && REGNO (r) < 32);
2815 1.1 mrg }
2816 1.1 mrg
2817 1.1 mrg /* In all these alloc routines, we expect the following: the insn
2818 1.1 mrg pattern is unshared, the insn was previously recognized and failed
2819 1.1 mrg due to predicates or constraints, and the operand data is in
2820 1.1 mrg recog_data. */
2821 1.1 mrg
2822 1.1 mrg static int virt_insn_was_frame;
2823 1.1 mrg
2824 1.1 mrg /* Hook for all insns we emit. Re-mark them as FRAME_RELATED if
2825 1.1 mrg needed. */
2826 1.1 mrg static rtx
2827 1.1 mrg EM2 (int line ATTRIBUTE_UNUSED, rtx r)
2828 1.1 mrg {
2829 1.1 mrg #if DEBUG_ALLOC
2830 1.1 mrg fprintf (stderr, "\033[36m%d: ", line);
2831 1.1 mrg debug_rtx (r);
2832 1.1 mrg fprintf (stderr, "\033[0m");
2833 1.1 mrg #endif
2834 1.1 mrg /*SCHED_GROUP_P (r) = 1;*/
2835 1.1 mrg if (virt_insn_was_frame)
2836 1.1 mrg RTX_FRAME_RELATED_P (r) = 1;
2837 1.1 mrg return r;
2838 1.1 mrg }
2839 1.1 mrg
2840 1.1 mrg #define EM(x) EM2 (__LINE__, x)
2841 1.1 mrg
2842 1.1 mrg /* Return a suitable RTX for the low half of a __far address. */
2843 1.1 mrg static rtx
2844 1.1 mrg rl78_lo16 (rtx addr)
2845 1.1 mrg {
2846 1.1 mrg rtx r;
2847 1.1 mrg
2848 1.1 mrg if (GET_CODE (addr) == SYMBOL_REF
2849 1.1 mrg || GET_CODE (addr) == CONST)
2850 1.1 mrg {
2851 1.1 mrg r = gen_rtx_ZERO_EXTRACT (HImode, addr, GEN_INT (16), GEN_INT (0));
2852 1.1 mrg r = gen_rtx_CONST (HImode, r);
2853 1.1 mrg }
2854 1.1 mrg else
2855 1.1 mrg r = rl78_subreg (HImode, addr, SImode, 0);
2856 1.1 mrg
2857 1.1 mrg r = gen_es_addr (r);
2858 1.1 mrg cfun->machine->uses_es = true;
2859 1.1 mrg
2860 1.1 mrg return r;
2861 1.1 mrg }
2862 1.1 mrg
2863 1.1 mrg /* Return a suitable RTX for the high half's lower byte of a __far address. */
2864 1.1 mrg static rtx
2865 1.1 mrg rl78_hi8 (rtx addr)
2866 1.1 mrg {
2867 1.1 mrg if (GET_CODE (addr) == SYMBOL_REF
2868 1.1 mrg || GET_CODE (addr) == CONST)
2869 1.1 mrg {
2870 1.1 mrg rtx r = gen_rtx_ZERO_EXTRACT (QImode, addr, GEN_INT (8), GEN_INT (16));
2871 1.1 mrg r = gen_rtx_CONST (QImode, r);
2872 1.1 mrg return r;
2873 1.1 mrg }
2874 1.1 mrg return rl78_subreg (QImode, addr, SImode, 2);
2875 1.1 mrg }
2876 1.1 mrg
2877 1.1 mrg static void
2878 1.1 mrg add_postponed_content_update (rtx to, rtx value)
2879 1.1 mrg {
2880 1.1 mrg unsigned char index;
2881 1.1 mrg
2882 1.1 mrg if ((index = get_content_index (to)) == NOT_KNOWN)
2883 1.1 mrg return;
2884 1.1 mrg
2885 1.1 mrg gcc_assert (saved_update_index == NOT_KNOWN);
2886 1.1 mrg saved_update_index = index;
2887 1.1 mrg saved_update_value = get_content_index (value);
2888 1.1 mrg saved_update_mode = GET_MODE (to);
2889 1.1 mrg }
2890 1.1 mrg
2891 1.1 mrg static void
2892 1.1 mrg process_postponed_content_update (void)
2893 1.1 mrg {
2894 1.1 mrg if (saved_update_index != NOT_KNOWN)
2895 1.1 mrg {
2896 1.1 mrg update_content (saved_update_index, saved_update_value, saved_update_mode);
2897 1.1 mrg saved_update_index = NOT_KNOWN;
2898 1.1 mrg }
2899 1.1 mrg }
2900 1.1 mrg
2901 1.1 mrg /* Generate and emit a move of (register) FROM into TO. if WHERE is not NULL
2902 1.1 mrg then if BEFORE is true then emit the insn before WHERE, otherwise emit it
2903 1.1 mrg after WHERE. If TO already contains FROM then do nothing. Returns TO if
2904 1.1 mrg BEFORE is true, FROM otherwise. */
2905 1.1 mrg static rtx
2906 1.1 mrg gen_and_emit_move (rtx to, rtx from, rtx_insn *where, bool before)
2907 1.1 mrg {
2908 1.1 mrg machine_mode mode = GET_MODE (to);
2909 1.1 mrg
2910 1.1 mrg if (optimize && before && already_contains (to, from))
2911 1.1 mrg {
2912 1.1 mrg #if DEBUG_ALLOC
2913 1.1 mrg display_content_memory (stderr);
2914 1.1 mrg #endif
2915 1.1 mrg if (dump_file)
2916 1.1 mrg {
2917 1.1 mrg fprintf (dump_file, " Omit move of %s into ",
2918 1.1 mrg get_content_name (get_content_index (from), mode));
2919 1.1 mrg fprintf (dump_file, "%s as it already contains this value\n",
2920 1.1 mrg get_content_name (get_content_index (to), mode));
2921 1.1 mrg }
2922 1.1 mrg }
2923 1.1 mrg else
2924 1.1 mrg {
2925 1.1 mrg rtx move = mode == QImode ? gen_movqi (to, from) : gen_movhi (to, from);
2926 1.1 mrg
2927 1.1 mrg EM (move);
2928 1.1 mrg
2929 1.1 mrg if (where == NULL_RTX)
2930 1.1 mrg emit_insn (move);
2931 1.1 mrg else if (before)
2932 1.1 mrg emit_insn_before (move, where);
2933 1.1 mrg else
2934 1.1 mrg {
2935 1.1 mrg rtx note = find_reg_note (where, REG_EH_REGION, NULL_RTX);
2936 1.1 mrg
2937 1.1 mrg /* If necessary move REG_EH_REGION notes forward.
2938 1.1 mrg cf. compiling gcc.dg/pr44545.c. */
2939 1.1 mrg if (note != NULL_RTX)
2940 1.1 mrg {
2941 1.1 mrg add_reg_note (move, REG_EH_REGION, XEXP (note, 0));
2942 1.1 mrg remove_note (where, note);
2943 1.1 mrg }
2944 1.1 mrg
2945 1.1 mrg emit_insn_after (move, where);
2946 1.1 mrg }
2947 1.1 mrg
2948 1.1 mrg if (before)
2949 1.1 mrg record_content (to, from);
2950 1.1 mrg else
2951 1.1 mrg add_postponed_content_update (to, from);
2952 1.1 mrg }
2953 1.1 mrg
2954 1.1 mrg return before ? to : from;
2955 1.1 mrg }
2956 1.1 mrg
2957 1.1 mrg /* If M is MEM(REG) or MEM(PLUS(REG,INT)) and REG is virtual then
2958 1.1 mrg copy it into NEWBASE and return the updated MEM. Otherwise just
2959 1.1 mrg return M. Any needed insns are emitted before BEFORE. */
2960 1.1 mrg static rtx
2961 1.1 mrg transcode_memory_rtx (rtx m, rtx newbase, rtx_insn *before)
2962 1.1 mrg {
2963 1.1 mrg rtx base, index, addendr;
2964 1.1 mrg int addend = 0;
2965 1.1 mrg int need_es = 0;
2966 1.1 mrg
2967 1.1 mrg if (! MEM_P (m))
2968 1.1 mrg return m;
2969 1.1 mrg
2970 1.1 mrg if (GET_MODE (XEXP (m, 0)) == SImode)
2971 1.1 mrg {
2972 1.1 mrg rtx new_m;
2973 1.1 mrg rtx seg = rl78_hi8 (XEXP (m, 0));
2974 1.1 mrg
2975 1.1 mrg if (!TARGET_ES0)
2976 1.1 mrg {
2977 1.1 mrg emit_insn_before (EM (gen_movqi (A, seg)), before);
2978 1.1 mrg emit_insn_before (EM (gen_movqi_to_es (A)), before);
2979 1.1 mrg }
2980 1.1 mrg
2981 1.1 mrg record_content (A, NULL_RTX);
2982 1.1 mrg
2983 1.1 mrg new_m = gen_rtx_MEM (GET_MODE (m), rl78_lo16 (XEXP (m, 0)));
2984 1.1 mrg MEM_COPY_ATTRIBUTES (new_m, m);
2985 1.1 mrg m = new_m;
2986 1.1 mrg need_es = 1;
2987 1.1 mrg }
2988 1.1 mrg
2989 1.1 mrg characterize_address (XEXP (m, 0), & base, & index, & addendr);
2990 1.1 mrg gcc_assert (index == NULL_RTX);
2991 1.1 mrg
2992 1.1 mrg if (base == NULL_RTX)
2993 1.1 mrg return m;
2994 1.1 mrg
2995 1.1 mrg if (addendr && GET_CODE (addendr) == CONST_INT)
2996 1.1 mrg addend = INTVAL (addendr);
2997 1.1 mrg
2998 1.1 mrg gcc_assert (REG_P (base));
2999 1.1 mrg gcc_assert (REG_P (newbase));
3000 1.1 mrg
3001 1.1 mrg int limit = 256 - GET_MODE_SIZE (GET_MODE (m));
3002 1.1 mrg
3003 1.1 mrg if (REGNO (base) == SP_REG)
3004 1.1 mrg {
3005 1.1 mrg if (addend >= 0 && addend <= limit)
3006 1.1 mrg return m;
3007 1.1 mrg }
3008 1.1 mrg
3009 1.1 mrg /* BASE should be a virtual register. We copy it to NEWBASE. If
3010 1.1 mrg the addend is out of range for DE/HL, we use AX to compute the full
3011 1.1 mrg address. */
3012 1.1 mrg
3013 1.1 mrg if (addend < 0
3014 1.1 mrg || (addend > limit && REGNO (newbase) != BC_REG)
3015 1.1 mrg || (addendr
3016 1.1 mrg && (GET_CODE (addendr) != CONST_INT)
3017 1.1 mrg && ((REGNO (newbase) != BC_REG))
3018 1.1 mrg ))
3019 1.1 mrg {
3020 1.1 mrg /* mov ax, vreg
3021 1.1 mrg add ax, #imm
3022 1.1 mrg mov hl, ax */
3023 1.1 mrg EM (emit_insn_before (gen_movhi (AX, base), before));
3024 1.1 mrg EM (emit_insn_before (gen_addhi3 (AX, AX, addendr), before));
3025 1.1 mrg EM (emit_insn_before (gen_movhi (newbase, AX), before));
3026 1.1 mrg record_content (AX, NULL_RTX);
3027 1.1 mrg record_content (newbase, NULL_RTX);
3028 1.1 mrg
3029 1.1 mrg base = newbase;
3030 1.1 mrg addend = 0;
3031 1.1 mrg addendr = 0;
3032 1.1 mrg }
3033 1.1 mrg else
3034 1.1 mrg {
3035 1.1 mrg base = gen_and_emit_move (newbase, base, before, true);
3036 1.1 mrg }
3037 1.1 mrg
3038 1.1 mrg if (addend)
3039 1.1 mrg {
3040 1.1 mrg record_content (base, NULL_RTX);
3041 1.1 mrg base = gen_rtx_PLUS (HImode, base, GEN_INT (addend));
3042 1.1 mrg }
3043 1.1 mrg else if (addendr)
3044 1.1 mrg {
3045 1.1 mrg record_content (base, NULL_RTX);
3046 1.1 mrg base = gen_rtx_PLUS (HImode, base, addendr);
3047 1.1 mrg }
3048 1.1 mrg
3049 1.1 mrg if (need_es)
3050 1.1 mrg {
3051 1.1 mrg m = change_address (m, GET_MODE (m), gen_es_addr (base));
3052 1.1 mrg cfun->machine->uses_es = true;
3053 1.1 mrg }
3054 1.1 mrg else
3055 1.1 mrg m = change_address (m, GET_MODE (m), base);
3056 1.1 mrg return m;
3057 1.1 mrg }
3058 1.1 mrg
3059 1.1 mrg /* Copy SRC to accumulator (A or AX), placing any generated insns
3060 1.1 mrg before BEFORE. Returns accumulator RTX. */
3061 1.1 mrg static rtx
3062 1.1 mrg move_to_acc (int opno, rtx_insn *before)
3063 1.1 mrg {
3064 1.1 mrg rtx src = OP (opno);
3065 1.1 mrg machine_mode mode = GET_MODE (src);
3066 1.1 mrg
3067 1.1 mrg if (REG_P (src) && REGNO (src) < 2)
3068 1.1 mrg return src;
3069 1.1 mrg
3070 1.1 mrg if (mode == VOIDmode)
3071 1.1 mrg mode = recog_data.operand_mode[opno];
3072 1.1 mrg
3073 1.1 mrg return gen_and_emit_move (mode == QImode ? A : AX, src, before, true);
3074 1.1 mrg }
3075 1.1 mrg
3076 1.1 mrg static void
3077 1.1 mrg force_into_acc (rtx src, rtx_insn *before)
3078 1.1 mrg {
3079 1.1 mrg machine_mode mode = GET_MODE (src);
3080 1.1 mrg rtx move;
3081 1.1 mrg
3082 1.1 mrg if (REG_P (src) && REGNO (src) < 2)
3083 1.1 mrg return;
3084 1.1 mrg
3085 1.1 mrg move = mode == QImode ? gen_movqi (A, src) : gen_movhi (AX, src);
3086 1.1 mrg
3087 1.1 mrg EM (move);
3088 1.1 mrg
3089 1.1 mrg emit_insn_before (move, before);
3090 1.1 mrg record_content (AX, NULL_RTX);
3091 1.1 mrg }
3092 1.1 mrg
3093 1.1 mrg /* Copy accumulator (A or AX) to DEST, placing any generated insns
3094 1.1 mrg after AFTER. Returns accumulator RTX. */
3095 1.1 mrg static rtx
3096 1.1 mrg move_from_acc (unsigned int opno, rtx_insn *after)
3097 1.1 mrg {
3098 1.1 mrg rtx dest = OP (opno);
3099 1.1 mrg machine_mode mode = GET_MODE (dest);
3100 1.1 mrg
3101 1.1 mrg if (REG_P (dest) && REGNO (dest) < 2)
3102 1.1 mrg return dest;
3103 1.1 mrg
3104 1.1 mrg return gen_and_emit_move (dest, mode == QImode ? A : AX, after, false);
3105 1.1 mrg }
3106 1.1 mrg
3107 1.1 mrg /* Copy accumulator (A or AX) to REGNO, placing any generated insns
3108 1.1 mrg before BEFORE. Returns reg RTX. */
3109 1.1 mrg static rtx
3110 1.1 mrg move_acc_to_reg (rtx acc, int regno, rtx_insn *before)
3111 1.1 mrg {
3112 1.1 mrg machine_mode mode = GET_MODE (acc);
3113 1.1 mrg rtx reg;
3114 1.1 mrg
3115 1.1 mrg reg = gen_rtx_REG (mode, regno);
3116 1.1 mrg
3117 1.1 mrg return gen_and_emit_move (reg, acc, before, true);
3118 1.1 mrg }
3119 1.1 mrg
3120 1.1 mrg /* Copy SRC to X, placing any generated insns before BEFORE.
3121 1.1 mrg Returns X RTX. */
3122 1.1 mrg static rtx
3123 1.1 mrg move_to_x (int opno, rtx_insn *before)
3124 1.1 mrg {
3125 1.1 mrg rtx src = OP (opno);
3126 1.1 mrg machine_mode mode = GET_MODE (src);
3127 1.1 mrg rtx reg;
3128 1.1 mrg
3129 1.1 mrg if (mode == VOIDmode)
3130 1.1 mrg mode = recog_data.operand_mode[opno];
3131 1.1 mrg reg = (mode == QImode) ? X : AX;
3132 1.1 mrg
3133 1.1 mrg if (mode == QImode || ! is_virtual_register (OP (opno)))
3134 1.1 mrg {
3135 1.1 mrg OP (opno) = move_to_acc (opno, before);
3136 1.1 mrg OP (opno) = move_acc_to_reg (OP (opno), X_REG, before);
3137 1.1 mrg return reg;
3138 1.1 mrg }
3139 1.1 mrg
3140 1.1 mrg return gen_and_emit_move (reg, src, before, true);
3141 1.1 mrg }
3142 1.1 mrg
3143 1.1 mrg /* Copy OP (opno) to H or HL, placing any generated insns before BEFORE.
3144 1.1 mrg Returns H/HL RTX. */
3145 1.1 mrg static rtx
3146 1.1 mrg move_to_hl (int opno, rtx_insn *before)
3147 1.1 mrg {
3148 1.1 mrg rtx src = OP (opno);
3149 1.1 mrg machine_mode mode = GET_MODE (src);
3150 1.1 mrg rtx reg;
3151 1.1 mrg
3152 1.1 mrg if (mode == VOIDmode)
3153 1.1 mrg mode = recog_data.operand_mode[opno];
3154 1.1 mrg reg = (mode == QImode) ? L : HL;
3155 1.1 mrg
3156 1.1 mrg if (mode == QImode || ! is_virtual_register (OP (opno)))
3157 1.1 mrg {
3158 1.1 mrg OP (opno) = move_to_acc (opno, before);
3159 1.1 mrg OP (opno) = move_acc_to_reg (OP (opno), L_REG, before);
3160 1.1 mrg return reg;
3161 1.1 mrg }
3162 1.1 mrg
3163 1.1 mrg return gen_and_emit_move (reg, src, before, true);
3164 1.1 mrg }
3165 1.1 mrg
3166 1.1 mrg /* Copy OP (opno) to E or DE, placing any generated insns before BEFORE.
3167 1.1 mrg Returns E/DE RTX. */
3168 1.1 mrg static rtx
3169 1.1 mrg move_to_de (int opno, rtx_insn *before)
3170 1.1 mrg {
3171 1.1 mrg rtx src = OP (opno);
3172 1.1 mrg machine_mode mode = GET_MODE (src);
3173 1.1 mrg rtx reg;
3174 1.1 mrg
3175 1.1 mrg if (mode == VOIDmode)
3176 1.1 mrg mode = recog_data.operand_mode[opno];
3177 1.1 mrg
3178 1.1 mrg reg = (mode == QImode) ? E : DE;
3179 1.1 mrg
3180 1.1 mrg if (mode == QImode || ! is_virtual_register (OP (opno)))
3181 1.1 mrg {
3182 1.1 mrg OP (opno) = move_to_acc (opno, before);
3183 1.1 mrg OP (opno) = move_acc_to_reg (OP (opno), E_REG, before);
3184 1.1 mrg }
3185 1.1 mrg else
3186 1.1 mrg {
3187 1.1 mrg gen_and_emit_move (reg, src, before, true);
3188 1.1 mrg }
3189 1.1 mrg
3190 1.1 mrg return reg;
3191 1.1 mrg }
3192 1.1 mrg
3193 1.1 mrg /* Devirtualize an insn of the form (SET (op) (unop (op))). */
3194 1.1 mrg static void
3195 1.1 mrg rl78_alloc_physical_registers_op1 (rtx_insn * insn)
3196 1.1 mrg {
3197 1.1 mrg /* op[0] = func op[1] */
3198 1.1 mrg
3199 1.1 mrg /* We first try using A as the destination, then copying it
3200 1.1 mrg back. */
3201 1.1 mrg if (rtx_equal_p (OP (0), OP (1)))
3202 1.1 mrg {
3203 1.1 mrg OP (0) =
3204 1.1 mrg OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3205 1.1 mrg }
3206 1.1 mrg else
3207 1.1 mrg {
3208 1.1 mrg /* If necessary, load the operands into BC and HL.
3209 1.1 mrg Check to see if we already have OP (0) in HL
3210 1.1 mrg and if so, swap the order.
3211 1.1 mrg
3212 1.1 mrg It is tempting to perform this optimization when OP(0) does
3213 1.1 mrg not hold a MEM, but this leads to bigger code in general.
3214 1.1 mrg The problem is that if OP(1) holds a MEM then swapping it
3215 1.1 mrg into BC means a BC-relative load is used and these are 3
3216 1.1 mrg bytes long vs 1 byte for an HL load. */
3217 1.1 mrg if (MEM_P (OP (0))
3218 1.1 mrg && already_contains (HL, XEXP (OP (0), 0)))
3219 1.1 mrg {
3220 1.1 mrg OP (0) = transcode_memory_rtx (OP (0), HL, insn);
3221 1.1 mrg OP (1) = transcode_memory_rtx (OP (1), BC, insn);
3222 1.1 mrg }
3223 1.1 mrg else
3224 1.1 mrg {
3225 1.1 mrg OP (0) = transcode_memory_rtx (OP (0), BC, insn);
3226 1.1 mrg OP (1) = transcode_memory_rtx (OP (1), HL, insn);
3227 1.1 mrg }
3228 1.1 mrg }
3229 1.1 mrg
3230 1.1 mrg MAYBE_OK (insn);
3231 1.1 mrg
3232 1.1 mrg OP (0) = move_from_acc (0, insn);
3233 1.1 mrg
3234 1.1 mrg MAYBE_OK (insn);
3235 1.1 mrg
3236 1.1 mrg /* Try copying the src to acc first, then. This is for, for
3237 1.1 mrg example, ZERO_EXTEND or NOT. */
3238 1.1 mrg OP (1) = move_to_acc (1, insn);
3239 1.1 mrg
3240 1.1 mrg MUST_BE_OK (insn);
3241 1.1 mrg }
3242 1.1 mrg
3243 1.1 mrg /* Returns true if operand OPNUM contains a constraint of type CONSTRAINT.
3244 1.1 mrg Assumes that the current insn has already been recognised and hence the
3245 1.1 mrg constraint data has been filled in. */
3246 1.1 mrg static bool
3247 1.1 mrg has_constraint (unsigned int opnum, enum constraint_num constraint)
3248 1.1 mrg {
3249 1.1 mrg const char * p = recog_data.constraints[opnum];
3250 1.1 mrg
3251 1.1 mrg /* No constraints means anything is accepted. */
3252 1.1 mrg if (p == NULL || *p == 0 || *p == ',')
3253 1.1 mrg return true;
3254 1.1 mrg
3255 1.1 mrg do
3256 1.1 mrg {
3257 1.1 mrg char c;
3258 1.1 mrg unsigned int len;
3259 1.1 mrg
3260 1.1 mrg c = *p;
3261 1.1 mrg len = CONSTRAINT_LEN (c, p);
3262 1.1 mrg gcc_assert (len > 0);
3263 1.1 mrg
3264 1.1 mrg switch (c)
3265 1.1 mrg {
3266 1.1 mrg case 0:
3267 1.1 mrg case ',':
3268 1.1 mrg return false;
3269 1.1 mrg default:
3270 1.1 mrg if (lookup_constraint (p) == constraint)
3271 1.1 mrg return true;
3272 1.1 mrg }
3273 1.1 mrg p += len;
3274 1.1 mrg }
3275 1.1 mrg while (1);
3276 1.1 mrg }
3277 1.1 mrg
3278 1.1 mrg /* Devirtualize an insn of the form (SET (op) (binop (op) (op))). */
3279 1.1 mrg static void
3280 1.1 mrg rl78_alloc_physical_registers_op2 (rtx_insn * insn)
3281 1.1 mrg {
3282 1.1 mrg rtx_insn *prev;
3283 1.1 mrg rtx_insn *first;
3284 1.1 mrg bool hl_used;
3285 1.1 mrg int tmp_id;
3286 1.1 mrg rtx saved_op1;
3287 1.1 mrg
3288 1.1 mrg if (rtx_equal_p (OP (0), OP (1)))
3289 1.1 mrg {
3290 1.1 mrg if (MEM_P (OP (2)))
3291 1.1 mrg {
3292 1.1 mrg OP (0) =
3293 1.1 mrg OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3294 1.1 mrg OP (2) = transcode_memory_rtx (OP (2), HL, insn);
3295 1.1 mrg }
3296 1.1 mrg else
3297 1.1 mrg {
3298 1.1 mrg OP (0) =
3299 1.1 mrg OP (1) = transcode_memory_rtx (OP (1), HL, insn);
3300 1.1 mrg OP (2) = transcode_memory_rtx (OP (2), DE, insn);
3301 1.1 mrg }
3302 1.1 mrg }
3303 1.1 mrg else if (rtx_equal_p (OP (0), OP (2)))
3304 1.1 mrg {
3305 1.1 mrg OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3306 1.1 mrg OP (0) =
3307 1.1 mrg OP (2) = transcode_memory_rtx (OP (2), HL, insn);
3308 1.1 mrg }
3309 1.1 mrg else
3310 1.1 mrg {
3311 1.1 mrg OP (0) = transcode_memory_rtx (OP (0), BC, insn);
3312 1.1 mrg OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3313 1.1 mrg OP (2) = transcode_memory_rtx (OP (2), HL, insn);
3314 1.1 mrg }
3315 1.1 mrg
3316 1.1 mrg MAYBE_OK (insn);
3317 1.1 mrg
3318 1.1 mrg prev = prev_nonnote_nondebug_insn (insn);
3319 1.1 mrg if (recog_data.constraints[1][0] == '%'
3320 1.1 mrg && is_virtual_register (OP (1))
3321 1.1 mrg && ! is_virtual_register (OP (2))
3322 1.1 mrg && ! CONSTANT_P (OP (2)))
3323 1.1 mrg {
3324 1.1 mrg rtx tmp = OP (1);
3325 1.1 mrg OP (1) = OP (2);
3326 1.1 mrg OP (2) = tmp;
3327 1.1 mrg }
3328 1.1 mrg
3329 1.1 mrg /* Make a note of whether (H)L is being used. It matters
3330 1.1 mrg because if OP (2) also needs reloading, then we must take
3331 1.1 mrg care not to corrupt HL. */
3332 1.1 mrg hl_used = reg_mentioned_p (L, OP (0)) || reg_mentioned_p (L, OP (1));
3333 1.1 mrg
3334 1.1 mrg /* If HL is not currently being used and dest == op1 then there are
3335 1.1 mrg some possible optimizations available by reloading one of the
3336 1.1 mrg operands into HL, before trying to use the accumulator. */
3337 1.1 mrg if (optimize
3338 1.1 mrg && ! hl_used
3339 1.1 mrg && rtx_equal_p (OP (0), OP (1)))
3340 1.1 mrg {
3341 1.1 mrg /* If op0 is a Ws1 type memory address then switching the base
3342 1.1 mrg address register to HL might allow us to perform an in-memory
3343 1.1 mrg operation. (eg for the INCW instruction).
3344 1.1 mrg
3345 1.1 mrg FIXME: Adding the move into HL is costly if this optimization is not
3346 1.1 mrg going to work, so for now, make sure that we know that the new insn will
3347 1.1 mrg match the requirements of the addhi3_real pattern. Really we ought to
3348 1.1 mrg generate a candidate sequence, test that, and then install it if the
3349 1.1 mrg results are good. */
3350 1.1 mrg if (satisfies_constraint_Ws1 (OP (0))
3351 1.1 mrg && has_constraint (0, CONSTRAINT_Wh1)
3352 1.1 mrg && (satisfies_constraint_K (OP (2)) || satisfies_constraint_L (OP (2))))
3353 1.1 mrg {
3354 1.1 mrg rtx base, index, addend, newbase;
3355 1.1 mrg
3356 1.1 mrg characterize_address (XEXP (OP (0), 0), & base, & index, & addend);
3357 1.1 mrg gcc_assert (index == NULL_RTX);
3358 1.1 mrg gcc_assert (REG_P (base) && REGNO (base) == SP_REG);
3359 1.1 mrg
3360 1.1 mrg /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
3361 1.1 mrg if (addend != NULL_RTX)
3362 1.1 mrg {
3363 1.1 mrg newbase = gen_and_emit_move (HL, base, insn, true);
3364 1.1 mrg record_content (newbase, NULL_RTX);
3365 1.1 mrg newbase = gen_rtx_PLUS (HImode, newbase, addend);
3366 1.1 mrg
3367 1.1 mrg OP (0) = OP (1) = change_address (OP (0), VOIDmode, newbase);
3368 1.1 mrg
3369 1.1 mrg /* We do not want to fail here as this means that
3370 1.1 mrg we have inserted useless insns into the stream. */
3371 1.1 mrg MUST_BE_OK (insn);
3372 1.1 mrg }
3373 1.1 mrg }
3374 1.1 mrg else if (REG_P (OP (0))
3375 1.1 mrg && satisfies_constraint_Ws1 (OP (2))
3376 1.1 mrg && has_constraint (2, CONSTRAINT_Wh1))
3377 1.1 mrg {
3378 1.1 mrg rtx base, index, addend, newbase;
3379 1.1 mrg
3380 1.1 mrg characterize_address (XEXP (OP (2), 0), & base, & index, & addend);
3381 1.1 mrg gcc_assert (index == NULL_RTX);
3382 1.1 mrg gcc_assert (REG_P (base) && REGNO (base) == SP_REG);
3383 1.1 mrg
3384 1.1 mrg /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
3385 1.1 mrg if (addend != NULL_RTX)
3386 1.1 mrg {
3387 1.1 mrg gen_and_emit_move (HL, base, insn, true);
3388 1.1 mrg
3389 1.1 mrg if (REGNO (OP (0)) != X_REG)
3390 1.1 mrg {
3391 1.1 mrg OP (1) = move_to_acc (1, insn);
3392 1.1 mrg OP (0) = move_from_acc (0, insn);
3393 1.1 mrg }
3394 1.1 mrg
3395 1.1 mrg record_content (HL, NULL_RTX);
3396 1.1 mrg newbase = gen_rtx_PLUS (HImode, HL, addend);
3397 1.1 mrg
3398 1.1 mrg OP (2) = change_address (OP (2), VOIDmode, newbase);
3399 1.1 mrg
3400 1.1 mrg /* We do not want to fail here as this means that
3401 1.1 mrg we have inserted useless insns into the stream. */
3402 1.1 mrg MUST_BE_OK (insn);
3403 1.1 mrg }
3404 1.1 mrg }
3405 1.1 mrg }
3406 1.1 mrg
3407 1.1 mrg OP (0) = move_from_acc (0, insn);
3408 1.1 mrg
3409 1.1 mrg tmp_id = get_max_insn_count ();
3410 1.1 mrg saved_op1 = OP (1);
3411 1.1 mrg
3412 1.1 mrg if (rtx_equal_p (OP (1), OP (2)))
3413 1.1 mrg OP (2) = OP (1) = move_to_acc (1, insn);
3414 1.1 mrg else
3415 1.1 mrg OP (1) = move_to_acc (1, insn);
3416 1.1 mrg
3417 1.1 mrg MAYBE_OK (insn);
3418 1.1 mrg
3419 1.1 mrg /* If we omitted the move of OP1 into the accumulator (because
3420 1.1 mrg it was already there from a previous insn), then force the
3421 1.1 mrg generation of the move instruction now. We know that we
3422 1.1 mrg are about to emit a move into HL (or DE) via AX, and hence
3423 1.1 mrg our optimization to remove the load of OP1 is no longer valid. */
3424 1.1 mrg if (tmp_id == get_max_insn_count ())
3425 1.1 mrg force_into_acc (saved_op1, insn);
3426 1.1 mrg
3427 1.1 mrg /* We have to copy op2 to HL (or DE), but that involves AX, which
3428 1.1 mrg already has a live value. Emit it before those insns. */
3429 1.1 mrg
3430 1.1 mrg if (prev)
3431 1.1 mrg first = next_nonnote_nondebug_insn (prev);
3432 1.1 mrg else
3433 1.1 mrg for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
3434 1.1 mrg ;
3435 1.1 mrg
3436 1.1 mrg OP (2) = hl_used ? move_to_de (2, first) : move_to_hl (2, first);
3437 1.1 mrg
3438 1.1 mrg MUST_BE_OK (insn);
3439 1.1 mrg }
3440 1.1 mrg
3441 1.1 mrg /* Devirtualize an insn of the form SET (PC) (MEM/REG). */
3442 1.1 mrg static void
3443 1.1 mrg rl78_alloc_physical_registers_ro1 (rtx_insn * insn)
3444 1.1 mrg {
3445 1.1 mrg OP (0) = transcode_memory_rtx (OP (0), BC, insn);
3446 1.1 mrg
3447 1.1 mrg MAYBE_OK (insn);
3448 1.1 mrg
3449 1.1 mrg OP (0) = move_to_acc (0, insn);
3450 1.1 mrg
3451 1.1 mrg MUST_BE_OK (insn);
3452 1.1 mrg }
3453 1.1 mrg
3454 1.1 mrg /* Devirtualize a compare insn. */
3455 1.1 mrg static void
3456 1.1 mrg rl78_alloc_physical_registers_cmp (rtx_insn * insn)
3457 1.1 mrg {
3458 1.1 mrg int tmp_id;
3459 1.1 mrg rtx saved_op1;
3460 1.1 mrg rtx_insn *prev = prev_nonnote_nondebug_insn (insn);
3461 1.1 mrg rtx_insn *first;
3462 1.1 mrg
3463 1.1 mrg OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3464 1.1 mrg OP (2) = transcode_memory_rtx (OP (2), HL, insn);
3465 1.1 mrg
3466 1.1 mrg /* HI compares have to have OP (1) in AX, but QI
3467 1.1 mrg compares do not, so it is worth checking here. */
3468 1.1 mrg MAYBE_OK (insn);
3469 1.1 mrg
3470 1.1 mrg /* For an HImode compare, OP (1) must always be in AX.
3471 1.1 mrg But if OP (1) is a REG (and not AX), then we can avoid
3472 1.1 mrg a reload of OP (1) if we reload OP (2) into AX and invert
3473 1.1 mrg the comparison. */
3474 1.1 mrg if (REG_P (OP (1))
3475 1.1 mrg && REGNO (OP (1)) != AX_REG
3476 1.1 mrg && GET_MODE (OP (1)) == HImode
3477 1.1 mrg && MEM_P (OP (2)))
3478 1.1 mrg {
3479 1.1 mrg rtx cmp = XEXP (SET_SRC (PATTERN (insn)), 0);
3480 1.1 mrg
3481 1.1 mrg OP (2) = move_to_acc (2, insn);
3482 1.1 mrg
3483 1.1 mrg switch (GET_CODE (cmp))
3484 1.1 mrg {
3485 1.1 mrg case EQ:
3486 1.1 mrg case NE:
3487 1.1 mrg break;
3488 1.1 mrg case LTU: cmp = gen_rtx_GTU (HImode, OP (2), OP (1)); break;
3489 1.1 mrg case GTU: cmp = gen_rtx_LTU (HImode, OP (2), OP (1)); break;
3490 1.1 mrg case LEU: cmp = gen_rtx_GEU (HImode, OP (2), OP (1)); break;
3491 1.1 mrg case GEU: cmp = gen_rtx_LEU (HImode, OP (2), OP (1)); break;
3492 1.1 mrg
3493 1.1 mrg case LT:
3494 1.1 mrg case GT:
3495 1.1 mrg case LE:
3496 1.1 mrg case GE:
3497 1.1 mrg #if DEBUG_ALLOC
3498 1.1 mrg debug_rtx (insn);
3499 1.1 mrg #endif
3500 1.1 mrg default:
3501 1.1 mrg gcc_unreachable ();
3502 1.1 mrg }
3503 1.1 mrg
3504 1.1 mrg if (GET_CODE (cmp) == EQ || GET_CODE (cmp) == NE)
3505 1.1 mrg PATTERN (insn) = gen_cbranchhi4_real (cmp, OP (2), OP (1), OP (3));
3506 1.1 mrg else
3507 1.1 mrg PATTERN (insn) = gen_cbranchhi4_real_inverted (cmp, OP (2), OP (1), OP (3));
3508 1.1 mrg
3509 1.1 mrg MUST_BE_OK (insn);
3510 1.1 mrg }
3511 1.1 mrg
3512 1.1 mrg /* Surprisingly, gcc can generate a comparison of a register with itself, but this
3513 1.1 mrg should be handled by the second alternative of the cbranchhi_real pattern. */
3514 1.1 mrg if (rtx_equal_p (OP (1), OP (2)))
3515 1.1 mrg {
3516 1.1 mrg OP (1) = OP (2) = BC;
3517 1.1 mrg MUST_BE_OK (insn);
3518 1.1 mrg }
3519 1.1 mrg
3520 1.1 mrg tmp_id = get_max_insn_count ();
3521 1.1 mrg saved_op1 = OP (1);
3522 1.1 mrg
3523 1.1 mrg OP (1) = move_to_acc (1, insn);
3524 1.1 mrg
3525 1.1 mrg MAYBE_OK (insn);
3526 1.1 mrg
3527 1.1 mrg /* If we omitted the move of OP1 into the accumulator (because
3528 1.1 mrg it was already there from a previous insn), then force the
3529 1.1 mrg generation of the move instruction now. We know that we
3530 1.1 mrg are about to emit a move into HL via AX, and hence our
3531 1.1 mrg optimization to remove the load of OP1 is no longer valid. */
3532 1.1 mrg if (tmp_id == get_max_insn_count ())
3533 1.1 mrg force_into_acc (saved_op1, insn);
3534 1.1 mrg
3535 1.1 mrg /* We have to copy op2 to HL, but that involves the acc, which
3536 1.1 mrg already has a live value. Emit it before those insns. */
3537 1.1 mrg if (prev)
3538 1.1 mrg first = next_nonnote_nondebug_insn (prev);
3539 1.1 mrg else
3540 1.1 mrg for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
3541 1.1 mrg ;
3542 1.1 mrg OP (2) = move_to_hl (2, first);
3543 1.1 mrg
3544 1.1 mrg MUST_BE_OK (insn);
3545 1.1 mrg }
3546 1.1 mrg
3547 1.1 mrg /* Like op2, but AX = A * X. */
3548 1.1 mrg static void
3549 1.1 mrg rl78_alloc_physical_registers_umul (rtx_insn * insn)
3550 1.1 mrg {
3551 1.1 mrg rtx_insn *prev = prev_nonnote_nondebug_insn (insn);
3552 1.1 mrg rtx_insn *first;
3553 1.1 mrg int tmp_id;
3554 1.1 mrg rtx saved_op1;
3555 1.1 mrg
3556 1.1 mrg OP (0) = transcode_memory_rtx (OP (0), BC, insn);
3557 1.1 mrg OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3558 1.1 mrg OP (2) = transcode_memory_rtx (OP (2), HL, insn);
3559 1.1 mrg
3560 1.1 mrg MAYBE_OK (insn);
3561 1.1 mrg
3562 1.1 mrg if (recog_data.constraints[1][0] == '%'
3563 1.1 mrg && is_virtual_register (OP (1))
3564 1.1 mrg && !is_virtual_register (OP (2))
3565 1.1 mrg && !CONSTANT_P (OP (2)))
3566 1.1 mrg {
3567 1.1 mrg rtx tmp = OP (1);
3568 1.1 mrg OP (1) = OP (2);
3569 1.1 mrg OP (2) = tmp;
3570 1.1 mrg }
3571 1.1 mrg
3572 1.1 mrg OP (0) = move_from_acc (0, insn);
3573 1.1 mrg
3574 1.1 mrg tmp_id = get_max_insn_count ();
3575 1.1 mrg saved_op1 = OP (1);
3576 1.1 mrg
3577 1.1 mrg if (rtx_equal_p (OP (1), OP (2)))
3578 1.1 mrg {
3579 1.1 mrg gcc_assert (GET_MODE (OP (2)) == QImode);
3580 1.1 mrg /* The MULU instruction does not support duplicate arguments
3581 1.1 mrg but we know that if we copy OP (2) to X it will do so via
3582 1.1 mrg A and thus OP (1) will already be loaded into A. */
3583 1.1 mrg OP (2) = move_to_x (2, insn);
3584 1.1 mrg OP (1) = A;
3585 1.1 mrg }
3586 1.1 mrg else
3587 1.1 mrg OP (1) = move_to_acc (1, insn);
3588 1.1 mrg
3589 1.1 mrg MAYBE_OK (insn);
3590 1.1 mrg
3591 1.1 mrg /* If we omitted the move of OP1 into the accumulator (because
3592 1.1 mrg it was already there from a previous insn), then force the
3593 1.1 mrg generation of the move instruction now. We know that we
3594 1.1 mrg are about to emit a move into HL (or DE) via AX, and hence
3595 1.1 mrg our optimization to remove the load of OP1 is no longer valid. */
3596 1.1 mrg if (tmp_id == get_max_insn_count ())
3597 1.1 mrg force_into_acc (saved_op1, insn);
3598 1.1 mrg
3599 1.1 mrg /* We have to copy op2 to X, but that involves the acc, which
3600 1.1 mrg already has a live value. Emit it before those insns. */
3601 1.1 mrg
3602 1.1 mrg if (prev)
3603 1.1 mrg first = next_nonnote_nondebug_insn (prev);
3604 1.1 mrg else
3605 1.1 mrg for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
3606 1.1 mrg ;
3607 1.1 mrg OP (2) = move_to_x (2, first);
3608 1.1 mrg
3609 1.1 mrg MUST_BE_OK (insn);
3610 1.1 mrg }
3611 1.1 mrg
3612 1.1 mrg static void
3613 1.1 mrg rl78_alloc_address_registers_macax (rtx_insn * insn)
3614 1.1 mrg {
3615 1.1 mrg int which, op;
3616 1.1 mrg bool replace_in_op0 = false;
3617 1.1 mrg bool replace_in_op1 = false;
3618 1.1 mrg
3619 1.1 mrg MAYBE_OK (insn);
3620 1.1 mrg
3621 1.1 mrg /* Two different MEMs are not allowed. */
3622 1.1 mrg which = 0;
3623 1.1 mrg for (op = 2; op >= 0; op --)
3624 1.1 mrg {
3625 1.1 mrg if (MEM_P (OP (op)))
3626 1.1 mrg {
3627 1.1 mrg if (op == 0 && replace_in_op0)
3628 1.1 mrg continue;
3629 1.1 mrg if (op == 1 && replace_in_op1)
3630 1.1 mrg continue;
3631 1.1 mrg
3632 1.1 mrg switch (which)
3633 1.1 mrg {
3634 1.1 mrg case 0:
3635 1.1 mrg /* If we replace a MEM, make sure that we replace it for all
3636 1.1 mrg occurrences of the same MEM in the insn. */
3637 1.1 mrg replace_in_op0 = (op > 0 && rtx_equal_p (OP (op), OP (0)));
3638 1.1 mrg replace_in_op1 = (op > 1 && rtx_equal_p (OP (op), OP (1)));
3639 1.1 mrg
3640 1.1 mrg OP (op) = transcode_memory_rtx (OP (op), HL, insn);
3641 1.1 mrg if (op == 2
3642 1.1 mrg && MEM_P (OP (op))
3643 1.1 mrg && ((GET_CODE (XEXP (OP (op), 0)) == REG
3644 1.1 mrg && REGNO (XEXP (OP (op), 0)) == SP_REG)
3645 1.1 mrg || (GET_CODE (XEXP (OP (op), 0)) == PLUS
3646 1.1 mrg && REGNO (XEXP (XEXP (OP (op), 0), 0)) == SP_REG)))
3647 1.1 mrg {
3648 1.1 mrg emit_insn_before (gen_movhi (HL, gen_rtx_REG (HImode, SP_REG)), insn);
3649 1.1 mrg OP (op) = replace_rtx (OP (op), gen_rtx_REG (HImode, SP_REG), HL);
3650 1.1 mrg }
3651 1.1 mrg if (replace_in_op0)
3652 1.1 mrg OP (0) = OP (op);
3653 1.1 mrg if (replace_in_op1)
3654 1.1 mrg OP (1) = OP (op);
3655 1.1 mrg break;
3656 1.1 mrg case 1:
3657 1.1 mrg OP (op) = transcode_memory_rtx (OP (op), DE, insn);
3658 1.1 mrg break;
3659 1.1 mrg case 2:
3660 1.1 mrg OP (op) = transcode_memory_rtx (OP (op), BC, insn);
3661 1.1 mrg break;
3662 1.1 mrg }
3663 1.1 mrg which ++;
3664 1.1 mrg }
3665 1.1 mrg }
3666 1.1 mrg
3667 1.1 mrg MUST_BE_OK (insn);
3668 1.1 mrg }
3669 1.1 mrg
3670 1.1 mrg static void
3671 1.1 mrg rl78_alloc_address_registers_div (rtx_insn * insn)
3672 1.1 mrg {
3673 1.1 mrg MUST_BE_OK (insn);
3674 1.1 mrg }
3675 1.1 mrg
3676 1.1 mrg /* Scan all insns and devirtualize them. */
3677 1.1 mrg static void
3678 1.1 mrg rl78_alloc_physical_registers (void)
3679 1.1 mrg {
3680 1.1 mrg /* During most of the compile, gcc is dealing with virtual
3681 1.1 mrg registers. At this point, we need to assign physical registers
3682 1.1 mrg to the vitual ones, and copy in/out as needed. */
3683 1.1 mrg
3684 1.1 mrg rtx_insn *insn, *curr;
3685 1.1 mrg enum attr_valloc valloc_method;
3686 1.1 mrg
3687 1.1 mrg for (insn = get_insns (); insn; insn = curr)
3688 1.1 mrg {
3689 1.1 mrg int i;
3690 1.1 mrg
3691 1.1 mrg curr = next_nonnote_nondebug_insn (insn);
3692 1.1 mrg
3693 1.1 mrg if (INSN_P (insn)
3694 1.1 mrg && (GET_CODE (PATTERN (insn)) == SET
3695 1.1 mrg || GET_CODE (PATTERN (insn)) == CALL)
3696 1.1 mrg && INSN_CODE (insn) == -1)
3697 1.1 mrg {
3698 1.1 mrg if (GET_CODE (SET_SRC (PATTERN (insn))) == ASM_OPERANDS)
3699 1.1 mrg continue;
3700 1.1 mrg i = recog (PATTERN (insn), insn, 0);
3701 1.1 mrg if (i == -1)
3702 1.1 mrg {
3703 1.1 mrg debug_rtx (insn);
3704 1.1 mrg gcc_unreachable ();
3705 1.1 mrg }
3706 1.1 mrg INSN_CODE (insn) = i;
3707 1.1 mrg }
3708 1.1 mrg }
3709 1.1 mrg
3710 1.1 mrg cfun->machine->virt_insns_ok = 0;
3711 1.1 mrg cfun->machine->real_insns_ok = 1;
3712 1.1 mrg
3713 1.1 mrg clear_content_memory ();
3714 1.1 mrg
3715 1.1 mrg for (insn = get_insns (); insn; insn = curr)
3716 1.1 mrg {
3717 1.1 mrg rtx pattern;
3718 1.1 mrg
3719 1.1 mrg curr = insn ? next_nonnote_nondebug_insn (insn) : NULL;
3720 1.1 mrg
3721 1.1 mrg if (!INSN_P (insn))
3722 1.1 mrg {
3723 1.1 mrg if (LABEL_P (insn))
3724 1.1 mrg clear_content_memory ();
3725 1.1 mrg
3726 1.1 mrg continue;
3727 1.1 mrg }
3728 1.1 mrg
3729 1.1 mrg if (dump_file)
3730 1.1 mrg fprintf (dump_file, "Converting insn %d\n", INSN_UID (insn));
3731 1.1 mrg
3732 1.1 mrg pattern = PATTERN (insn);
3733 1.1 mrg if (GET_CODE (pattern) == PARALLEL)
3734 1.1 mrg pattern = XVECEXP (pattern, 0, 0);
3735 1.1 mrg if (JUMP_P (insn) || CALL_P (insn) || GET_CODE (pattern) == CALL)
3736 1.1 mrg clear_content_memory ();
3737 1.1 mrg if (GET_CODE (pattern) != SET
3738 1.1 mrg && GET_CODE (pattern) != CALL)
3739 1.1 mrg continue;
3740 1.1 mrg if (GET_CODE (pattern) == SET
3741 1.1 mrg && GET_CODE (SET_SRC (pattern)) == ASM_OPERANDS)
3742 1.1 mrg continue;
3743 1.1 mrg
3744 1.1 mrg valloc_method = get_attr_valloc (insn);
3745 1.1 mrg
3746 1.1 mrg PATTERN (insn) = copy_rtx_if_shared (PATTERN (insn));
3747 1.1 mrg
3748 1.1 mrg if (valloc_method == VALLOC_MACAX)
3749 1.1 mrg {
3750 1.1 mrg record_content (AX, NULL_RTX);
3751 1.1 mrg record_content (BC, NULL_RTX);
3752 1.1 mrg record_content (DE, NULL_RTX);
3753 1.1 mrg }
3754 1.1 mrg else if (valloc_method == VALLOC_DIVHI)
3755 1.1 mrg {
3756 1.1 mrg record_content (AX, NULL_RTX);
3757 1.1 mrg record_content (BC, NULL_RTX);
3758 1.1 mrg }
3759 1.1 mrg else if (valloc_method == VALLOC_DIVSI)
3760 1.1 mrg {
3761 1.1 mrg record_content (AX, NULL_RTX);
3762 1.1 mrg record_content (BC, NULL_RTX);
3763 1.1 mrg record_content (DE, NULL_RTX);
3764 1.1 mrg record_content (HL, NULL_RTX);
3765 1.1 mrg }
3766 1.1 mrg
3767 1.1 mrg if (insn_ok_now (insn))
3768 1.1 mrg continue;
3769 1.1 mrg
3770 1.1 mrg INSN_CODE (insn) = -1;
3771 1.1 mrg
3772 1.1 mrg if (RTX_FRAME_RELATED_P (insn))
3773 1.1 mrg virt_insn_was_frame = 1;
3774 1.1 mrg else
3775 1.1 mrg virt_insn_was_frame = 0;
3776 1.1 mrg
3777 1.1 mrg switch (valloc_method)
3778 1.1 mrg {
3779 1.1 mrg case VALLOC_OP1:
3780 1.1 mrg rl78_alloc_physical_registers_op1 (insn);
3781 1.1 mrg break;
3782 1.1 mrg case VALLOC_OP2:
3783 1.1 mrg rl78_alloc_physical_registers_op2 (insn);
3784 1.1 mrg break;
3785 1.1 mrg case VALLOC_RO1:
3786 1.1 mrg rl78_alloc_physical_registers_ro1 (insn);
3787 1.1 mrg break;
3788 1.1 mrg case VALLOC_CMP:
3789 1.1 mrg rl78_alloc_physical_registers_cmp (insn);
3790 1.1 mrg break;
3791 1.1 mrg case VALLOC_UMUL:
3792 1.1 mrg rl78_alloc_physical_registers_umul (insn);
3793 1.1 mrg record_content (AX, NULL_RTX);
3794 1.1 mrg break;
3795 1.1 mrg case VALLOC_MACAX:
3796 1.1 mrg /* Macro that clobbers AX. */
3797 1.1 mrg rl78_alloc_address_registers_macax (insn);
3798 1.1 mrg record_content (AX, NULL_RTX);
3799 1.1 mrg record_content (BC, NULL_RTX);
3800 1.1 mrg record_content (DE, NULL_RTX);
3801 1.1 mrg break;
3802 1.1 mrg case VALLOC_DIVSI:
3803 1.1 mrg rl78_alloc_address_registers_div (insn);
3804 1.1 mrg record_content (AX, NULL_RTX);
3805 1.1 mrg record_content (BC, NULL_RTX);
3806 1.1 mrg record_content (DE, NULL_RTX);
3807 1.1 mrg record_content (HL, NULL_RTX);
3808 1.1 mrg break;
3809 1.1 mrg case VALLOC_DIVHI:
3810 1.1 mrg rl78_alloc_address_registers_div (insn);
3811 1.1 mrg record_content (AX, NULL_RTX);
3812 1.1 mrg record_content (BC, NULL_RTX);
3813 1.1 mrg break;
3814 1.1 mrg default:
3815 1.1 mrg gcc_unreachable ();
3816 1.1 mrg }
3817 1.1 mrg
3818 1.1 mrg if (JUMP_P (insn) || CALL_P (insn) || GET_CODE (pattern) == CALL)
3819 1.1 mrg clear_content_memory ();
3820 1.1 mrg else
3821 1.1 mrg process_postponed_content_update ();
3822 1.1 mrg }
3823 1.1 mrg
3824 1.1 mrg #if DEBUG_ALLOC
3825 1.1 mrg fprintf (stderr, "\033[0m");
3826 1.1 mrg #endif
3827 1.1 mrg }
3828 1.1 mrg
3829 1.1 mrg /* Add REG_DEAD notes using DEAD[reg] for rtx S which is part of INSN.
3830 1.1 mrg This function scans for uses of registers; the last use (i.e. first
3831 1.1 mrg encounter when scanning backwards) triggers a REG_DEAD note if the
3832 1.1 mrg reg was previously in DEAD[]. */
3833 1.1 mrg static void
3834 1.1 mrg rl78_note_reg_uses (char *dead, rtx s, rtx insn)
3835 1.1 mrg {
3836 1.1 mrg const char *fmt;
3837 1.1 mrg int i, r;
3838 1.1 mrg enum rtx_code code;
3839 1.1 mrg
3840 1.1 mrg if (!s)
3841 1.1 mrg return;
3842 1.1 mrg
3843 1.1 mrg code = GET_CODE (s);
3844 1.1 mrg
3845 1.1 mrg switch (code)
3846 1.1 mrg {
3847 1.1 mrg /* Compare registers by number. */
3848 1.1 mrg case REG:
3849 1.1 mrg r = REGNO (s);
3850 1.1 mrg if (dump_file)
3851 1.1 mrg {
3852 1.1 mrg fprintf (dump_file, "note use reg %d size %d on insn %d\n",
3853 1.1 mrg r, GET_MODE_SIZE (GET_MODE (s)), INSN_UID (insn));
3854 1.1 mrg print_rtl_single (dump_file, s);
3855 1.1 mrg }
3856 1.1 mrg if (dead [r])
3857 1.1 mrg add_reg_note (insn, REG_DEAD, gen_rtx_REG (GET_MODE (s), r));
3858 1.1 mrg for (i = 0; i < GET_MODE_SIZE (GET_MODE (s)); i ++)
3859 1.1 mrg dead [r + i] = 0;
3860 1.1 mrg return;
3861 1.1 mrg
3862 1.1 mrg /* These codes have no constituent expressions
3863 1.1 mrg and are unique. */
3864 1.1 mrg case SCRATCH:
3865 1.1 mrg case PC:
3866 1.1 mrg return;
3867 1.1 mrg
3868 1.1 mrg case CONST_INT:
3869 1.1 mrg case CONST_VECTOR:
3870 1.1 mrg case CONST_DOUBLE:
3871 1.1 mrg case CONST_FIXED:
3872 1.1 mrg /* These are kept unique for a given value. */
3873 1.1 mrg return;
3874 1.1 mrg
3875 1.1 mrg default:
3876 1.1 mrg break;
3877 1.1 mrg }
3878 1.1 mrg
3879 1.1 mrg fmt = GET_RTX_FORMAT (code);
3880 1.1 mrg
3881 1.1 mrg for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
3882 1.1 mrg {
3883 1.1 mrg if (fmt[i] == 'E')
3884 1.1 mrg {
3885 1.1 mrg int j;
3886 1.1 mrg for (j = XVECLEN (s, i) - 1; j >= 0; j--)
3887 1.1 mrg rl78_note_reg_uses (dead, XVECEXP (s, i, j), insn);
3888 1.1 mrg }
3889 1.1 mrg else if (fmt[i] == 'e')
3890 1.1 mrg rl78_note_reg_uses (dead, XEXP (s, i), insn);
3891 1.1 mrg }
3892 1.1 mrg }
3893 1.1 mrg
3894 1.1 mrg /* Like the previous function, but scan for SETs instead. */
3895 1.1 mrg static void
3896 1.1 mrg rl78_note_reg_set (char *dead, rtx d, rtx insn)
3897 1.1 mrg {
3898 1.1 mrg int r, i;
3899 1.1 mrg bool is_dead;
3900 1.1 mrg if (GET_CODE (d) == MEM)
3901 1.1 mrg rl78_note_reg_uses (dead, XEXP (d, 0), insn);
3902 1.1 mrg
3903 1.1 mrg if (GET_CODE (d) != REG)
3904 1.1 mrg return;
3905 1.1 mrg
3906 1.1 mrg /* Do not mark the reg unused unless all QImode parts of it are dead. */
3907 1.1 mrg r = REGNO (d);
3908 1.1 mrg is_dead = true;
3909 1.1 mrg for (i = 0; i < GET_MODE_SIZE (GET_MODE (d)); i ++)
3910 1.1 mrg if (!dead [r + i])
3911 1.1 mrg is_dead = false;
3912 1.1 mrg if(is_dead)
3913 1.1 mrg add_reg_note (insn, REG_UNUSED, gen_rtx_REG (GET_MODE (d), r));
3914 1.1 mrg if (dump_file)
3915 1.1 mrg fprintf (dump_file, "note set reg %d size %d\n", r, GET_MODE_SIZE (GET_MODE (d)));
3916 1.1 mrg for (i = 0; i < GET_MODE_SIZE (GET_MODE (d)); i ++)
3917 1.1 mrg dead [r + i] = 1;
3918 1.1 mrg }
3919 1.1 mrg
3920 1.1 mrg /* This is a rather crude register death pass. Death status is reset
3921 1.1 mrg at every jump or call insn. */
3922 1.1 mrg static void
3923 1.1 mrg rl78_calculate_death_notes (void)
3924 1.1 mrg {
3925 1.1 mrg char dead[FIRST_PSEUDO_REGISTER];
3926 1.1 mrg rtx p, s, d;
3927 1.1 mrg rtx_insn *insn;
3928 1.1 mrg int i;
3929 1.1 mrg
3930 1.1 mrg memset (dead, 0, sizeof (dead));
3931 1.1 mrg
3932 1.1 mrg for (insn = get_last_insn ();
3933 1.1 mrg insn;
3934 1.1 mrg insn = prev_nonnote_nondebug_insn (insn))
3935 1.1 mrg {
3936 1.1 mrg if (dump_file)
3937 1.1 mrg {
3938 1.1 mrg fprintf (dump_file, "\n--------------------------------------------------");
3939 1.1 mrg fprintf (dump_file, "\nDead:");
3940 1.1 mrg for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
3941 1.1 mrg if (dead[i])
3942 1.1 mrg fprintf (dump_file, " %s", reg_names[i]);
3943 1.1 mrg fprintf (dump_file, "\n");
3944 1.1 mrg print_rtl_single (dump_file, insn);
3945 1.1 mrg }
3946 1.1 mrg
3947 1.1 mrg switch (GET_CODE (insn))
3948 1.1 mrg {
3949 1.1 mrg case INSN:
3950 1.1 mrg p = PATTERN (insn);
3951 1.1 mrg if (GET_CODE (p) == PARALLEL)
3952 1.1 mrg {
3953 1.1 mrg rtx q = XVECEXP (p, 0 ,1);
3954 1.1 mrg
3955 1.1 mrg /* This happens with the DIV patterns. */
3956 1.1 mrg if (GET_CODE (q) == SET)
3957 1.1 mrg {
3958 1.1 mrg s = SET_SRC (q);
3959 1.1 mrg d = SET_DEST (q);
3960 1.1 mrg rl78_note_reg_set (dead, d, insn);
3961 1.1 mrg rl78_note_reg_uses (dead, s, insn);
3962 1.1 mrg
3963 1.1 mrg }
3964 1.1 mrg p = XVECEXP (p, 0, 0);
3965 1.1 mrg }
3966 1.1 mrg
3967 1.1 mrg switch (GET_CODE (p))
3968 1.1 mrg {
3969 1.1 mrg case SET:
3970 1.1 mrg s = SET_SRC (p);
3971 1.1 mrg d = SET_DEST (p);
3972 1.1 mrg rl78_note_reg_set (dead, d, insn);
3973 1.1 mrg rl78_note_reg_uses (dead, s, insn);
3974 1.1 mrg break;
3975 1.1 mrg
3976 1.1 mrg case USE:
3977 1.1 mrg rl78_note_reg_uses (dead, p, insn);
3978 1.1 mrg break;
3979 1.1 mrg
3980 1.1 mrg default:
3981 1.1 mrg break;
3982 1.1 mrg }
3983 1.1 mrg break;
3984 1.1 mrg
3985 1.1 mrg case JUMP_INSN:
3986 1.1 mrg if (INSN_CODE (insn) == CODE_FOR_rl78_return)
3987 1.1 mrg {
3988 1.1 mrg memset (dead, 1, sizeof (dead));
3989 1.1 mrg /* We expect a USE just prior to this, which will mark
3990 1.1 mrg the actual return registers. The USE will have a
3991 1.1 mrg death note, but we aren't going to be modifying it
3992 1.1 mrg after this pass. */
3993 1.1 mrg break;
3994 1.1 mrg }
3995 1.1 mrg /* FALLTHRU */
3996 1.1 mrg case CALL_INSN:
3997 1.1 mrg memset (dead, 0, sizeof (dead));
3998 1.1 mrg break;
3999 1.1 mrg
4000 1.1 mrg default:
4001 1.1 mrg break;
4002 1.1 mrg }
4003 1.1 mrg if (dump_file)
4004 1.1 mrg print_rtl_single (dump_file, insn);
4005 1.1 mrg }
4006 1.1 mrg }
4007 1.1 mrg
4008 1.1 mrg /* Helper function to reset the origins in RP and the age in AGE for
4009 1.1 mrg all registers. */
4010 1.1 mrg static void
4011 1.1 mrg reset_origins (int *rp, int *age)
4012 1.1 mrg {
4013 1.1 mrg int i;
4014 1.1 mrg for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4015 1.1 mrg {
4016 1.1 mrg rp[i] = i;
4017 1.1 mrg age[i] = 0;
4018 1.1 mrg }
4019 1.1 mrg }
4020 1.1 mrg
4021 1.1 mrg static void
4022 1.1 mrg set_origin (rtx pat, rtx_insn * insn, int * origins, int * age)
4023 1.1 mrg {
4024 1.1 mrg rtx src = SET_SRC (pat);
4025 1.1 mrg rtx dest = SET_DEST (pat);
4026 1.1 mrg int mb = GET_MODE_SIZE (GET_MODE (dest));
4027 1.1 mrg int i;
4028 1.1 mrg
4029 1.1 mrg if (GET_CODE (dest) == REG)
4030 1.1 mrg {
4031 1.1 mrg int dr = REGNO (dest);
4032 1.1 mrg
4033 1.1 mrg if (GET_CODE (src) == REG)
4034 1.1 mrg {
4035 1.1 mrg int sr = REGNO (src);
4036 1.1 mrg bool same = true;
4037 1.1 mrg int best_age, best_reg;
4038 1.1 mrg
4039 1.1 mrg /* See if the copy is not needed. */
4040 1.1 mrg for (i = 0; i < mb; i ++)
4041 1.1 mrg if (origins[dr + i] != origins[sr + i])
4042 1.1 mrg same = false;
4043 1.1 mrg
4044 1.1 mrg if (same)
4045 1.1 mrg {
4046 1.1 mrg if (dump_file)
4047 1.1 mrg fprintf (dump_file, "deleting because dest already has correct value\n");
4048 1.1 mrg delete_insn (insn);
4049 1.1 mrg return;
4050 1.1 mrg }
4051 1.1 mrg
4052 1.1 mrg if (dr < 8 || sr >= 8)
4053 1.1 mrg {
4054 1.1 mrg int ar;
4055 1.1 mrg
4056 1.1 mrg best_age = -1;
4057 1.1 mrg best_reg = -1;
4058 1.1 mrg
4059 1.1 mrg /* See if the copy can be made from another
4060 1.1 mrg bank 0 register instead, instead of the
4061 1.1 mrg virtual src register. */
4062 1.1 mrg for (ar = 0; ar < 8; ar += mb)
4063 1.1 mrg {
4064 1.1 mrg same = true;
4065 1.1 mrg
4066 1.1 mrg for (i = 0; i < mb; i ++)
4067 1.1 mrg if (origins[ar + i] != origins[sr + i])
4068 1.1 mrg same = false;
4069 1.1 mrg
4070 1.1 mrg /* The chip has some reg-reg move limitations. */
4071 1.1 mrg if (mb == 1 && dr > 3)
4072 1.1 mrg same = false;
4073 1.1 mrg
4074 1.1 mrg if (same)
4075 1.1 mrg {
4076 1.1 mrg if (best_age == -1 || best_age > age[sr + i])
4077 1.1 mrg {
4078 1.1 mrg best_age = age[sr + i];
4079 1.1 mrg best_reg = sr;
4080 1.1 mrg }
4081 1.1 mrg }
4082 1.1 mrg }
4083 1.1 mrg
4084 1.1 mrg if (best_reg != -1)
4085 1.1 mrg {
4086 1.1 mrg /* FIXME: copy debug info too. */
4087 1.1 mrg SET_SRC (pat) = gen_rtx_REG (GET_MODE (src), best_reg);
4088 1.1 mrg sr = best_reg;
4089 1.1 mrg }
4090 1.1 mrg }
4091 1.1 mrg
4092 1.1 mrg for (i = 0; i < mb; i++)
4093 1.1 mrg {
4094 1.1 mrg origins[dr + i] = origins[sr + i];
4095 1.1 mrg age[dr + i] = age[sr + i] + 1;
4096 1.1 mrg }
4097 1.1 mrg }
4098 1.1 mrg else
4099 1.1 mrg {
4100 1.1 mrg /* The destination is computed, its origin is itself. */
4101 1.1 mrg if (dump_file)
4102 1.1 mrg fprintf (dump_file, "resetting origin of r%d for %d byte%s\n",
4103 1.1 mrg dr, mb, mb == 1 ? "" : "s");
4104 1.1 mrg
4105 1.1 mrg for (i = 0; i < mb; i ++)
4106 1.1 mrg {
4107 1.1 mrg origins[dr + i] = dr + i;
4108 1.1 mrg age[dr + i] = 0;
4109 1.1 mrg }
4110 1.1 mrg }
4111 1.1 mrg
4112 1.1 mrg /* Any registers marked with that reg as an origin are reset. */
4113 1.1 mrg for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4114 1.1 mrg if (origins[i] >= dr && origins[i] < dr + mb)
4115 1.1 mrg {
4116 1.1 mrg origins[i] = i;
4117 1.1 mrg age[i] = 0;
4118 1.1 mrg }
4119 1.1 mrg }
4120 1.1 mrg
4121 1.1 mrg /* Special case - our MUL patterns uses AX and sometimes BC. */
4122 1.1 mrg if (get_attr_valloc (insn) == VALLOC_MACAX)
4123 1.1 mrg {
4124 1.1 mrg if (dump_file)
4125 1.1 mrg fprintf (dump_file, "Resetting origin of AX/BC for MUL pattern.\n");
4126 1.1 mrg
4127 1.1 mrg for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4128 1.1 mrg if (i <= 3 || origins[i] <= 3)
4129 1.1 mrg {
4130 1.1 mrg origins[i] = i;
4131 1.1 mrg age[i] = 0;
4132 1.1 mrg }
4133 1.1 mrg }
4134 1.1 mrg else if (get_attr_valloc (insn) == VALLOC_DIVHI)
4135 1.1 mrg {
4136 1.1 mrg if (dump_file)
4137 1.1 mrg fprintf (dump_file, "Resetting origin of AX/DE for DIVHI pattern.\n");
4138 1.1 mrg
4139 1.1 mrg for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4140 1.1 mrg if (i == A_REG
4141 1.1 mrg || i == X_REG
4142 1.1 mrg || i == D_REG
4143 1.1 mrg || i == E_REG
4144 1.1 mrg || origins[i] == A_REG
4145 1.1 mrg || origins[i] == X_REG
4146 1.1 mrg || origins[i] == D_REG
4147 1.1 mrg || origins[i] == E_REG)
4148 1.1 mrg {
4149 1.1 mrg origins[i] = i;
4150 1.1 mrg age[i] = 0;
4151 1.1 mrg }
4152 1.1 mrg }
4153 1.1 mrg else if (get_attr_valloc (insn) == VALLOC_DIVSI)
4154 1.1 mrg {
4155 1.1 mrg if (dump_file)
4156 1.1 mrg fprintf (dump_file, "Resetting origin of AX/BC/DE/HL for DIVSI pattern.\n");
4157 1.1 mrg
4158 1.1 mrg for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4159 1.1 mrg if (i <= 7 || origins[i] <= 7)
4160 1.1 mrg {
4161 1.1 mrg origins[i] = i;
4162 1.1 mrg age[i] = 0;
4163 1.1 mrg }
4164 1.1 mrg }
4165 1.1 mrg
4166 1.1 mrg if (GET_CODE (src) == ASHIFT
4167 1.1 mrg || GET_CODE (src) == ASHIFTRT
4168 1.1 mrg || GET_CODE (src) == LSHIFTRT)
4169 1.1 mrg {
4170 1.1 mrg rtx count = XEXP (src, 1);
4171 1.1 mrg
4172 1.1 mrg if (GET_CODE (count) == REG)
4173 1.1 mrg {
4174 1.1 mrg /* Special case - our pattern clobbers the count register. */
4175 1.1 mrg int r = REGNO (count);
4176 1.1 mrg
4177 1.1 mrg if (dump_file)
4178 1.1 mrg fprintf (dump_file, "Resetting origin of r%d for shift.\n", r);
4179 1.1 mrg
4180 1.1 mrg for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4181 1.1 mrg if (i == r || origins[i] == r)
4182 1.1 mrg {
4183 1.1 mrg origins[i] = i;
4184 1.1 mrg age[i] = 0;
4185 1.1 mrg }
4186 1.1 mrg }
4187 1.1 mrg }
4188 1.1 mrg }
4189 1.1 mrg
4190 1.1 mrg /* The idea behind this optimization is to look for cases where we
4191 1.1 mrg move data from A to B to C, and instead move from A to B, and A to
4192 1.1 mrg C. If B is a virtual register or memory, this is a big win on its
4193 1.1 mrg own. If B turns out to be unneeded after this, it's a bigger win.
4194 1.1 mrg For each register, we try to determine where it's value originally
4195 1.1 mrg came from, if it's propogated purely through moves (and not
4196 1.1 mrg computes). The ORIGINS[] array has the regno for the "origin" of
4197 1.1 mrg the value in the [regno] it's indexed by. */
4198 1.1 mrg static void
4199 1.1 mrg rl78_propogate_register_origins (void)
4200 1.1 mrg {
4201 1.1 mrg int origins[FIRST_PSEUDO_REGISTER];
4202 1.1 mrg int age[FIRST_PSEUDO_REGISTER];
4203 1.1 mrg int i;
4204 1.1 mrg rtx_insn *insn, *ninsn = NULL;
4205 1.1 mrg rtx pat;
4206 1.1 mrg
4207 1.1 mrg reset_origins (origins, age);
4208 1.1 mrg
4209 1.1 mrg for (insn = get_insns (); insn; insn = ninsn)
4210 1.1 mrg {
4211 1.1 mrg ninsn = next_nonnote_nondebug_insn (insn);
4212 1.1 mrg
4213 1.1 mrg if (dump_file)
4214 1.1 mrg {
4215 1.1 mrg fprintf (dump_file, "\n");
4216 1.1 mrg fprintf (dump_file, "Origins:");
4217 1.1 mrg for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
4218 1.1 mrg if (origins[i] != i)
4219 1.1 mrg fprintf (dump_file, " r%d=r%d", i, origins[i]);
4220 1.1 mrg fprintf (dump_file, "\n");
4221 1.1 mrg print_rtl_single (dump_file, insn);
4222 1.1 mrg }
4223 1.1 mrg
4224 1.1 mrg switch (GET_CODE (insn))
4225 1.1 mrg {
4226 1.1 mrg case CODE_LABEL:
4227 1.1 mrg case BARRIER:
4228 1.1 mrg case CALL_INSN:
4229 1.1 mrg case JUMP_INSN:
4230 1.1 mrg reset_origins (origins, age);
4231 1.1 mrg break;
4232 1.1 mrg
4233 1.1 mrg default:
4234 1.1 mrg break;
4235 1.1 mrg
4236 1.1 mrg case INSN:
4237 1.1 mrg pat = PATTERN (insn);
4238 1.1 mrg
4239 1.1 mrg if (GET_CODE (pat) == PARALLEL)
4240 1.1 mrg {
4241 1.1 mrg rtx clobber = XVECEXP (pat, 0, 1);
4242 1.1 mrg pat = XVECEXP (pat, 0, 0);
4243 1.1 mrg if (GET_CODE (clobber) == CLOBBER
4244 1.1 mrg && GET_CODE (XEXP (clobber, 0)) == REG)
4245 1.1 mrg {
4246 1.1 mrg int cr = REGNO (XEXP (clobber, 0));
4247 1.1 mrg int mb = GET_MODE_SIZE (GET_MODE (XEXP (clobber, 0)));
4248 1.1 mrg if (dump_file)
4249 1.1 mrg fprintf (dump_file, "reset origins of %d regs at %d\n", mb, cr);
4250 1.1 mrg for (i = 0; i < mb; i++)
4251 1.1 mrg {
4252 1.1 mrg origins[cr + i] = cr + i;
4253 1.1 mrg age[cr + i] = 0;
4254 1.1 mrg }
4255 1.1 mrg }
4256 1.1 mrg /* This happens with the DIV patterns. */
4257 1.1 mrg else if (GET_CODE (clobber) == SET)
4258 1.1 mrg {
4259 1.1 mrg set_origin (clobber, insn, origins, age);
4260 1.1 mrg }
4261 1.1 mrg else
4262 1.1 mrg break;
4263 1.1 mrg }
4264 1.1 mrg
4265 1.1 mrg if (GET_CODE (pat) == SET)
4266 1.1 mrg {
4267 1.1 mrg set_origin (pat, insn, origins, age);
4268 1.1 mrg }
4269 1.1 mrg else if (GET_CODE (pat) == CLOBBER
4270 1.1 mrg && GET_CODE (XEXP (pat, 0)) == REG)
4271 1.1 mrg {
4272 1.1 mrg if (REG_P (XEXP (pat, 0)))
4273 1.1 mrg {
4274 1.1 mrg unsigned int reg = REGNO (XEXP (pat, 0));
4275 1.1 mrg
4276 1.1 mrg origins[reg] = reg;
4277 1.1 mrg age[reg] = 0;
4278 1.1 mrg }
4279 1.1 mrg }
4280 1.1 mrg }
4281 1.1 mrg }
4282 1.1 mrg }
4283 1.1 mrg
4284 1.1 mrg /* Remove any SETs where the destination is unneeded. */
4285 1.1 mrg static void
4286 1.1 mrg rl78_remove_unused_sets (void)
4287 1.1 mrg {
4288 1.1 mrg rtx_insn *insn, *ninsn = NULL;
4289 1.1 mrg rtx dest;
4290 1.1 mrg
4291 1.1 mrg for (insn = get_insns (); insn; insn = ninsn)
4292 1.1 mrg {
4293 1.1 mrg ninsn = next_nonnote_nondebug_insn (insn);
4294 1.1 mrg
4295 1.1 mrg rtx set = single_set (insn);
4296 1.1 mrg if (set == NULL)
4297 1.1 mrg continue;
4298 1.1 mrg
4299 1.1 mrg dest = SET_DEST (set);
4300 1.1 mrg
4301 1.1 mrg if (GET_CODE (dest) != REG || REGNO (dest) > 23)
4302 1.1 mrg continue;
4303 1.1 mrg
4304 1.1 mrg if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
4305 1.1 mrg {
4306 1.1 mrg if (dump_file)
4307 1.1 mrg fprintf (dump_file, "deleting because the set register is never used.\n");
4308 1.1 mrg delete_insn (insn);
4309 1.1 mrg }
4310 1.1 mrg }
4311 1.1 mrg }
4312 1.1 mrg
4313 1.1 mrg /* This is the top of the devritualization pass. */
4314 1.1 mrg static void
4315 1.1 mrg rl78_reorg (void)
4316 1.1 mrg {
4317 1.1 mrg /* split2 only happens when optimizing, but we need all movSIs to be
4318 1.1 mrg split now. */
4319 1.1 mrg if (optimize <= 0)
4320 1.1 mrg split_all_insns ();
4321 1.1 mrg
4322 1.1 mrg rl78_alloc_physical_registers ();
4323 1.1 mrg
4324 1.1 mrg if (dump_file)
4325 1.1 mrg {
4326 1.1 mrg fprintf (dump_file, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n");
4327 1.1 mrg print_rtl_with_bb (dump_file, get_insns (), TDF_NONE);
4328 1.1 mrg }
4329 1.1 mrg
4330 1.1 mrg rl78_propogate_register_origins ();
4331 1.1 mrg rl78_calculate_death_notes ();
4332 1.1 mrg
4333 1.1 mrg if (dump_file)
4334 1.1 mrg {
4335 1.1 mrg fprintf (dump_file, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n");
4336 1.1 mrg print_rtl_with_bb (dump_file, get_insns (), TDF_NONE);
4337 1.1 mrg fprintf (dump_file, "\n======================================================================\n");
4338 1.1 mrg }
4339 1.1 mrg
4340 1.1 mrg rl78_remove_unused_sets ();
4341 1.1 mrg
4342 1.1 mrg /* The code after devirtualizing has changed so much that at this point
4343 1.1 mrg we might as well just rescan everything. Note that
4344 1.1 mrg df_rescan_all_insns is not going to help here because it does not
4345 1.1 mrg touch the artificial uses and defs. */
4346 1.1 mrg df_finish_pass (true);
4347 1.1 mrg if (optimize > 1)
4348 1.1 mrg df_live_add_problem ();
4349 1.1 mrg df_scan_alloc (NULL);
4350 1.1 mrg df_scan_blocks ();
4351 1.1 mrg
4352 1.1 mrg if (optimize)
4353 1.1 mrg df_analyze ();
4354 1.1 mrg }
4355 1.1 mrg
4356 1.1 mrg #undef TARGET_RETURN_IN_MEMORY
4357 1.1 mrg #define TARGET_RETURN_IN_MEMORY rl78_return_in_memory
4358 1.1 mrg
4359 1.1 mrg static bool
4360 1.1 mrg rl78_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
4361 1.1 mrg {
4362 1.1 mrg const HOST_WIDE_INT size = int_size_in_bytes (type);
4363 1.1 mrg return (size == -1 || size > 8);
4364 1.1 mrg }
4365 1.1 mrg
4366 1.1 mrg
4367 1.1 mrg #undef TARGET_RTX_COSTS
4369 1.1 mrg #define TARGET_RTX_COSTS rl78_rtx_costs
4370 1.1 mrg
4371 1.1 mrg static bool
4372 1.1 mrg rl78_rtx_costs (rtx x,
4373 1.1 mrg machine_mode mode,
4374 1.1 mrg int outer_code ATTRIBUTE_UNUSED,
4375 1.1 mrg int opno ATTRIBUTE_UNUSED,
4376 1.1 mrg int * total,
4377 1.1 mrg bool speed ATTRIBUTE_UNUSED)
4378 1.1 mrg {
4379 1.1 mrg int code = GET_CODE (x);
4380 1.1 mrg
4381 1.1 mrg if (code == IF_THEN_ELSE)
4382 1.1 mrg {
4383 1.1 mrg *total = COSTS_N_INSNS (10);
4384 1.1 mrg return true;
4385 1.1 mrg }
4386 1.1 mrg
4387 1.1 mrg if (mode == HImode)
4388 1.1 mrg {
4389 1.1 mrg if (code == MULT && ! speed)
4390 1.1 mrg {
4391 1.1 mrg * total = COSTS_N_INSNS (8);
4392 1.1 mrg return true;
4393 1.1 mrg }
4394 1.1 mrg return false;
4395 1.1 mrg }
4396 1.1 mrg
4397 1.1 mrg if (mode == SImode)
4398 1.1 mrg {
4399 1.1 mrg switch (code)
4400 1.1 mrg {
4401 1.1 mrg case MULT:
4402 1.1 mrg if (! speed)
4403 1.1 mrg /* If we are compiling for space then we do not want to use the
4404 1.1 mrg inline SImode multiplication patterns or shift sequences.
4405 1.1 mrg The cost is not set to 1 or 5 however as we have to allow for
4406 1.1 mrg the possibility that we might be converting a leaf function
4407 1.1 mrg into a non-leaf function. (There is no way to tell here).
4408 1.1 mrg A value of 13 seems to be a reasonable compromise for the
4409 1.1 mrg moment. */
4410 1.1 mrg * total = COSTS_N_INSNS (13);
4411 1.1 mrg else if (RL78_MUL_G14)
4412 1.1 mrg *total = COSTS_N_INSNS (14);
4413 1.1 mrg else if (RL78_MUL_G13)
4414 1.1 mrg *total = COSTS_N_INSNS (29);
4415 1.1 mrg else
4416 1.1 mrg *total = COSTS_N_INSNS (500);
4417 1.1 mrg return true;
4418 1.1 mrg
4419 1.1 mrg case PLUS:
4420 1.1 mrg *total = COSTS_N_INSNS (8);
4421 1.1 mrg return true;
4422 1.1 mrg
4423 1.1 mrg case ASHIFT:
4424 1.1 mrg case ASHIFTRT:
4425 1.1 mrg case LSHIFTRT:
4426 1.1 mrg if (GET_CODE (XEXP (x, 1)) == CONST_INT)
4427 1.1 mrg {
4428 1.1 mrg switch (INTVAL (XEXP (x, 1)))
4429 1.1 mrg {
4430 1.1 mrg case 0: *total = COSTS_N_INSNS (0); break;
4431 1.1 mrg case 1: *total = COSTS_N_INSNS (6); break;
4432 1.1 mrg case 2: case 3: case 4: case 5: case 6: case 7:
4433 1.1 mrg *total = COSTS_N_INSNS (10); break;
4434 1.1 mrg case 8: *total = COSTS_N_INSNS (6); break;
4435 1.1 mrg case 9: case 10: case 11: case 12: case 13: case 14: case 15:
4436 1.1 mrg *total = COSTS_N_INSNS (10); break;
4437 1.1 mrg case 16: *total = COSTS_N_INSNS (3); break;
4438 1.1 mrg case 17: case 18: case 19: case 20: case 21: case 22: case 23:
4439 1.1 mrg *total = COSTS_N_INSNS (4); break;
4440 1.1 mrg case 24: *total = COSTS_N_INSNS (4); break;
4441 1.1 mrg case 25: case 26: case 27: case 28: case 29: case 30: case 31:
4442 1.1 mrg *total = COSTS_N_INSNS (5); break;
4443 1.1 mrg }
4444 1.1 mrg }
4445 1.1 mrg else
4446 1.1 mrg *total = COSTS_N_INSNS (10+4*16);
4447 1.1 mrg return true;
4448 1.1 mrg
4449 1.1 mrg default:
4450 1.1 mrg break;
4451 1.1 mrg }
4452 1.1 mrg }
4453 1.1 mrg return false;
4454 1.1 mrg }
4455 1.1 mrg
4456 1.1 mrg
4458 1.1 mrg static GTY(()) section * saddr_section;
4459 1.1 mrg static GTY(()) section * frodata_section;
4460 1.1 mrg
4461 1.1 mrg int
4462 1.1 mrg rl78_saddr_p (rtx x)
4463 1.1 mrg {
4464 1.1 mrg const char * c;
4465 1.1 mrg
4466 1.1 mrg if (MEM_P (x))
4467 1.1 mrg x = XEXP (x, 0);
4468 1.1 mrg if (GET_CODE (x) == PLUS)
4469 1.1 mrg x = XEXP (x, 0);
4470 1.1 mrg if (GET_CODE (x) != SYMBOL_REF)
4471 1.1 mrg return 0;
4472 1.1 mrg
4473 1.1 mrg c = XSTR (x, 0);
4474 1.1 mrg if (memcmp (c, "@s.", 3) == 0)
4475 1.1 mrg return 1;
4476 1.1 mrg
4477 1.1 mrg return 0;
4478 1.1 mrg }
4479 1.1 mrg
4480 1.1 mrg int
4481 1.1 mrg rl78_sfr_p (rtx x)
4482 1.1 mrg {
4483 1.1 mrg if (MEM_P (x))
4484 1.1 mrg x = XEXP (x, 0);
4485 1.1 mrg if (GET_CODE (x) != CONST_INT)
4486 1.1 mrg return 0;
4487 1.1 mrg
4488 1.1 mrg if ((INTVAL (x) & 0xFF00) != 0xFF00)
4489 1.1 mrg return 0;
4490 1.1 mrg
4491 1.1 mrg return 1;
4492 1.1 mrg }
4493 1.1 mrg
4494 1.1 mrg #undef TARGET_STRIP_NAME_ENCODING
4495 1.1 mrg #define TARGET_STRIP_NAME_ENCODING rl78_strip_name_encoding
4496 1.1 mrg
4497 1.1 mrg static const char *
4498 1.1 mrg rl78_strip_name_encoding (const char * sym)
4499 1.1 mrg {
4500 1.1 mrg while (1)
4501 1.1 mrg {
4502 1.1 mrg if (*sym == '*')
4503 1.1 mrg sym++;
4504 1.1 mrg else if (*sym == '@' && sym[2] == '.')
4505 1.1 mrg sym += 3;
4506 1.1 mrg else
4507 1.1 mrg return sym;
4508 1.1 mrg }
4509 1.1 mrg }
4510 1.1 mrg
4511 1.1 mrg /* Like rl78_strip_name_encoding, but does not strip leading asterisks. This
4512 1.1 mrg is important if the stripped name is going to be passed to assemble_name()
4513 1.1 mrg as that handles asterisk prefixed names in a special manner. */
4514 1.1 mrg
4515 1.1 mrg static const char *
4516 1.1 mrg rl78_strip_nonasm_name_encoding (const char * sym)
4517 1.1 mrg {
4518 1.1 mrg while (1)
4519 1.1 mrg {
4520 1.1 mrg if (*sym == '@' && sym[2] == '.')
4521 1.1 mrg sym += 3;
4522 1.1 mrg else
4523 1.1 mrg return sym;
4524 1.1 mrg }
4525 1.1 mrg }
4526 1.1 mrg
4527 1.1 mrg
4528 1.1 mrg static int
4529 1.1 mrg rl78_attrlist_to_encoding (tree list, tree decl ATTRIBUTE_UNUSED)
4530 1.1 mrg {
4531 1.1 mrg while (list)
4532 1.1 mrg {
4533 1.1 mrg if (is_attribute_p ("saddr", TREE_PURPOSE (list)))
4534 1.1 mrg return 's';
4535 1.1 mrg list = TREE_CHAIN (list);
4536 1.1 mrg }
4537 1.1 mrg
4538 1.1 mrg return 0;
4539 1.1 mrg }
4540 1.1 mrg
4541 1.1 mrg #define RL78_ATTRIBUTES(decl) \
4542 1.1 mrg (TYPE_P (decl)) ? TYPE_ATTRIBUTES (decl) \
4543 1.1 mrg : DECL_ATTRIBUTES (decl) \
4544 1.1 mrg ? (DECL_ATTRIBUTES (decl)) \
4545 1.1 mrg : TYPE_ATTRIBUTES (TREE_TYPE (decl))
4546 1.1 mrg
4547 1.1 mrg #undef TARGET_ENCODE_SECTION_INFO
4548 1.1 mrg #define TARGET_ENCODE_SECTION_INFO rl78_encode_section_info
4549 1.1 mrg
4550 1.1 mrg static void
4551 1.1 mrg rl78_encode_section_info (tree decl, rtx rtl, int first)
4552 1.1 mrg {
4553 1.1 mrg rtx rtlname;
4554 1.1 mrg const char * oldname;
4555 1.1 mrg char encoding;
4556 1.1 mrg char * newname;
4557 1.1 mrg tree idp;
4558 1.1 mrg tree type;
4559 1.1 mrg tree rl78_attributes;
4560 1.1 mrg
4561 1.1 mrg if (!first)
4562 1.1 mrg return;
4563 1.1 mrg
4564 1.1 mrg rtlname = XEXP (rtl, 0);
4565 1.1 mrg
4566 1.1 mrg if (GET_CODE (rtlname) == SYMBOL_REF)
4567 1.1 mrg oldname = XSTR (rtlname, 0);
4568 1.1 mrg else if (GET_CODE (rtlname) == MEM
4569 1.1 mrg && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
4570 1.1 mrg oldname = XSTR (XEXP (rtlname, 0), 0);
4571 1.1 mrg else
4572 1.1 mrg gcc_unreachable ();
4573 1.1 mrg
4574 1.1 mrg type = TREE_TYPE (decl);
4575 1.1 mrg if (type == error_mark_node)
4576 1.1 mrg return;
4577 1.1 mrg if (! DECL_P (decl))
4578 1.1 mrg return;
4579 1.1 mrg rl78_attributes = RL78_ATTRIBUTES (decl);
4580 1.1 mrg
4581 1.1 mrg encoding = rl78_attrlist_to_encoding (rl78_attributes, decl);
4582 1.1 mrg
4583 1.1 mrg if (encoding)
4584 1.1 mrg {
4585 1.1 mrg newname = (char *) alloca (strlen (oldname) + 4);
4586 1.1 mrg sprintf (newname, "@%c.%s", encoding, oldname);
4587 1.1 mrg idp = get_identifier (newname);
4588 1.1 mrg XEXP (rtl, 0) =
4589 1.1 mrg gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
4590 1.1 mrg SYMBOL_REF_WEAK (XEXP (rtl, 0)) = DECL_WEAK (decl);
4591 1.1 mrg SET_SYMBOL_REF_DECL (XEXP (rtl, 0), decl);
4592 1.1 mrg }
4593 1.1 mrg }
4594 1.1 mrg
4595 1.1 mrg #undef TARGET_ASM_INIT_SECTIONS
4596 1.1 mrg #define TARGET_ASM_INIT_SECTIONS rl78_asm_init_sections
4597 1.1 mrg
4598 1.1 mrg static void
4599 1.1 mrg rl78_asm_init_sections (void)
4600 1.1 mrg {
4601 1.1 mrg saddr_section
4602 1.1 mrg = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
4603 1.1 mrg "\t.section .saddr,\"aw\",@progbits");
4604 1.1 mrg frodata_section
4605 1.1 mrg = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
4606 1.1 mrg "\t.section .frodata,\"aw\",@progbits");
4607 1.1 mrg }
4608 1.1 mrg
4609 1.1 mrg #undef TARGET_ASM_SELECT_SECTION
4610 1.1 mrg #define TARGET_ASM_SELECT_SECTION rl78_select_section
4611 1.1 mrg
4612 1.1 mrg static section *
4613 1.1 mrg rl78_select_section (tree decl,
4614 1.1 mrg int reloc,
4615 1.1 mrg unsigned HOST_WIDE_INT align)
4616 1.1 mrg {
4617 1.1 mrg int readonly = 1;
4618 1.1 mrg
4619 1.1 mrg switch (TREE_CODE (decl))
4620 1.1 mrg {
4621 1.1 mrg case VAR_DECL:
4622 1.1 mrg if (!TREE_READONLY (decl)
4623 1.1 mrg || TREE_SIDE_EFFECTS (decl)
4624 1.1 mrg || !DECL_INITIAL (decl)
4625 1.1 mrg || (DECL_INITIAL (decl) != error_mark_node
4626 1.1 mrg && !TREE_CONSTANT (DECL_INITIAL (decl))))
4627 1.1 mrg readonly = 0;
4628 1.1 mrg break;
4629 1.1 mrg case CONSTRUCTOR:
4630 1.1 mrg if (! TREE_CONSTANT (decl))
4631 1.1 mrg readonly = 0;
4632 1.1 mrg break;
4633 1.1 mrg
4634 1.1 mrg default:
4635 1.1 mrg break;
4636 1.1 mrg }
4637 1.1 mrg
4638 1.1 mrg if (TREE_CODE (decl) == VAR_DECL)
4639 1.1 mrg {
4640 1.1 mrg const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
4641 1.1 mrg
4642 1.1 mrg if (name[0] == '@' && name[2] == '.')
4643 1.1 mrg switch (name[1])
4644 1.1 mrg {
4645 1.1 mrg case 's':
4646 1.1 mrg return saddr_section;
4647 1.1 mrg }
4648 1.1 mrg
4649 1.1 mrg if (TYPE_ADDR_SPACE (TREE_TYPE (decl)) == ADDR_SPACE_FAR
4650 1.1 mrg && readonly)
4651 1.1 mrg {
4652 1.1 mrg return frodata_section;
4653 1.1 mrg }
4654 1.1 mrg }
4655 1.1 mrg
4656 1.1 mrg if (readonly)
4657 1.1 mrg return TARGET_ES0 ? frodata_section : readonly_data_section;
4658 1.1 mrg
4659 1.1 mrg switch (categorize_decl_for_section (decl, reloc))
4660 1.1 mrg {
4661 1.1 mrg case SECCAT_TEXT: return text_section;
4662 1.1 mrg case SECCAT_DATA: return data_section;
4663 1.1 mrg case SECCAT_BSS: return bss_section;
4664 1.1 mrg case SECCAT_RODATA: return TARGET_ES0 ? frodata_section : readonly_data_section;
4665 1.1 mrg default:
4666 1.1 mrg return default_select_section (decl, reloc, align);
4667 1.1 mrg }
4668 1.1 mrg }
4669 1.1 mrg
4670 1.1 mrg void
4671 1.1 mrg rl78_output_labelref (FILE *file, const char *str)
4672 1.1 mrg {
4673 1.1 mrg const char *str2;
4674 1.1 mrg
4675 1.1 mrg str2 = targetm.strip_name_encoding (str);
4676 1.1 mrg if (str2[0] != '.')
4677 1.1 mrg fputs (user_label_prefix, file);
4678 1.1 mrg fputs (str2, file);
4679 1.1 mrg }
4680 1.1 mrg
4681 1.1 mrg void
4682 1.1 mrg rl78_output_aligned_common (FILE *stream,
4683 1.1 mrg tree decl ATTRIBUTE_UNUSED,
4684 1.1 mrg const char *name,
4685 1.1 mrg int size, int align, int global)
4686 1.1 mrg {
4687 1.1 mrg /* We intentionally don't use rl78_section_tag() here. */
4688 1.1 mrg if (name[0] == '@' && name[2] == '.')
4689 1.1 mrg {
4690 1.1 mrg const char *sec = 0;
4691 1.1 mrg switch (name[1])
4692 1.1 mrg {
4693 1.1 mrg case 's':
4694 1.1 mrg switch_to_section (saddr_section);
4695 1.1 mrg sec = ".saddr";
4696 1.1 mrg break;
4697 1.1 mrg }
4698 1.1 mrg if (sec)
4699 1.1 mrg {
4700 1.1 mrg const char *name2;
4701 1.1 mrg int p2align = 0;
4702 1.1 mrg
4703 1.1 mrg while (align > BITS_PER_UNIT)
4704 1.1 mrg {
4705 1.1 mrg align /= 2;
4706 1.1 mrg p2align ++;
4707 1.1 mrg }
4708 1.1 mrg name2 = targetm.strip_name_encoding (name);
4709 1.1 mrg if (global)
4710 1.1 mrg fprintf (stream, "\t.global\t_%s\n", name2);
4711 1.1 mrg fprintf (stream, "\t.p2align %d\n", p2align);
4712 1.1 mrg fprintf (stream, "\t.type\t_%s,@object\n", name2);
4713 1.1 mrg fprintf (stream, "\t.size\t_%s,%d\n", name2, size);
4714 1.1 mrg fprintf (stream, "_%s:\n\t.zero\t%d\n", name2, size);
4715 1.1 mrg return;
4716 1.1 mrg }
4717 1.1 mrg }
4718 1.1 mrg
4719 1.1 mrg if (!global)
4720 1.1 mrg {
4721 1.1 mrg fprintf (stream, "\t.local\t");
4722 1.1 mrg assemble_name (stream, name);
4723 1.1 mrg fprintf (stream, "\n");
4724 1.1 mrg }
4725 1.1 mrg fprintf (stream, "\t.comm\t");
4726 1.1 mrg assemble_name (stream, name);
4727 1.1 mrg fprintf (stream, ",%u,%u\n", size, align / BITS_PER_UNIT);
4728 1.1 mrg }
4729 1.1 mrg
4730 1.1 mrg #undef TARGET_INSERT_ATTRIBUTES
4731 1.1 mrg #define TARGET_INSERT_ATTRIBUTES rl78_insert_attributes
4732 1.1 mrg
4733 1.1 mrg static void
4734 1.1 mrg rl78_insert_attributes (tree decl, tree *attributes ATTRIBUTE_UNUSED)
4735 1.1 mrg {
4736 1.1 mrg if (TARGET_ES0
4737 1.1 mrg && TREE_CODE (decl) == VAR_DECL
4738 1.1 mrg && TREE_READONLY (decl)
4739 1.1 mrg && TREE_ADDRESSABLE (decl)
4740 1.1 mrg && TYPE_ADDR_SPACE (TREE_TYPE (decl)) == ADDR_SPACE_GENERIC)
4741 1.1 mrg {
4742 1.1 mrg tree type = TREE_TYPE (decl);
4743 1.1 mrg tree attr = TYPE_ATTRIBUTES (type);
4744 1.1 mrg int q = TYPE_QUALS_NO_ADDR_SPACE (type) | ENCODE_QUAL_ADDR_SPACE (ADDR_SPACE_FAR);
4745 1.1 mrg
4746 1.1 mrg TREE_TYPE (decl) = build_type_attribute_qual_variant (type, attr, q);
4747 1.1 mrg }
4748 1.1 mrg }
4749 1.1 mrg
4750 1.1 mrg #undef TARGET_ASM_INTEGER
4751 1.1 mrg #define TARGET_ASM_INTEGER rl78_asm_out_integer
4752 1.1 mrg
4753 1.1 mrg static bool
4754 1.1 mrg rl78_asm_out_integer (rtx x, unsigned int size, int aligned_p)
4755 1.1 mrg {
4756 1.1 mrg if (default_assemble_integer (x, size, aligned_p))
4757 1.1 mrg return true;
4758 1.1 mrg
4759 1.1 mrg if (size == 4)
4760 1.1 mrg {
4761 1.1 mrg assemble_integer_with_op (".long\t", x);
4762 1.1 mrg return true;
4763 1.1 mrg }
4764 1.1 mrg
4765 1.1 mrg return false;
4766 1.1 mrg }
4767 1.1 mrg
4768 1.1 mrg #undef TARGET_UNWIND_WORD_MODE
4770 1.1 mrg #define TARGET_UNWIND_WORD_MODE rl78_unwind_word_mode
4771 1.1 mrg
4772 1.1 mrg static scalar_int_mode
4773 1.1 mrg rl78_unwind_word_mode (void)
4774 1.1 mrg {
4775 1.1 mrg return HImode;
4776 1.1 mrg }
4777 1.1 mrg
4778 1.1 mrg #ifndef USE_COLLECT2
4779 1.1 mrg #undef TARGET_ASM_CONSTRUCTOR
4780 1.1 mrg #define TARGET_ASM_CONSTRUCTOR rl78_asm_constructor
4781 1.1 mrg #undef TARGET_ASM_DESTRUCTOR
4782 1.1 mrg #define TARGET_ASM_DESTRUCTOR rl78_asm_destructor
4783 1.1 mrg
4784 1.1 mrg static void
4785 1.1 mrg rl78_asm_ctor_dtor (rtx symbol, int priority, bool is_ctor)
4786 1.1 mrg {
4787 1.1 mrg section *sec;
4788 1.1 mrg
4789 1.1 mrg if (priority != DEFAULT_INIT_PRIORITY)
4790 1.1 mrg {
4791 1.1 mrg /* This section of the function is based upon code copied
4792 1.1 mrg from: gcc/varasm.cc:get_cdtor_priority_section(). */
4793 1.1 mrg char buf[18];
4794 1.1 mrg
4795 1.1 mrg sprintf (buf, "%s.%.5u", is_ctor ? ".ctors" : ".dtors",
4796 1.1 mrg MAX_INIT_PRIORITY - priority);
4797 1.1 mrg sec = get_section (buf, 0, NULL);
4798 1.1 mrg }
4799 1.1 mrg else
4800 1.1 mrg sec = is_ctor ? ctors_section : dtors_section;
4801 1.1 mrg
4802 1.1 mrg assemble_addr_to_section (symbol, sec);
4803 1.1 mrg }
4804 1.1 mrg
4805 1.1 mrg static void
4806 1.1 mrg rl78_asm_constructor (rtx symbol, int priority)
4807 1.1 mrg {
4808 1.1 mrg rl78_asm_ctor_dtor (symbol, priority, true);
4809 1.1 mrg }
4810 1.1 mrg
4811 1.1 mrg static void
4812 1.1 mrg rl78_asm_destructor (rtx symbol, int priority)
4813 1.1 mrg {
4814 1.1 mrg rl78_asm_ctor_dtor (symbol, priority, false);
4815 1.1 mrg }
4816 1.1 mrg #endif /* ! USE_COLLECT2 */
4817 1.1 mrg
4818 1.1 mrg /* Scan backwards through the insn chain looking to see if the flags
4819 1.1 mrg have been set for a comparison of OP against OPERAND. Start with
4820 1.1 mrg the insn *before* the current insn. */
4821 1.1 mrg
4822 1.1 mrg bool
4823 1.1 mrg rl78_flags_already_set (rtx op, rtx operand)
4824 1.1 mrg {
4825 1.1 mrg /* We only track the Z flag. */
4826 1.1 mrg if (GET_CODE (op) != EQ && GET_CODE (op) != NE)
4827 1.1 mrg return false;
4828 1.1 mrg
4829 1.1 mrg /* This should not happen, but let's be paranoid. */
4830 1.1 mrg if (current_output_insn == NULL_RTX)
4831 1.1 mrg return false;
4832 1.1 mrg
4833 1.1 mrg rtx_insn *insn;
4834 1.1 mrg bool res = false;
4835 1.1 mrg
4836 1.1 mrg for (insn = prev_nonnote_nondebug_insn (current_output_insn);
4837 1.1 mrg insn != NULL_RTX;
4838 1.1 mrg insn = prev_nonnote_nondebug_insn (insn))
4839 1.1 mrg {
4840 1.1 mrg if (LABEL_P (insn))
4841 1.1 mrg break;
4842 1.1 mrg
4843 1.1 mrg if (! INSN_P (insn))
4844 1.1 mrg continue;
4845 1.1 mrg
4846 1.1 mrg /* Make sure that the insn can be recognized. */
4847 1.1 mrg if (recog_memoized (insn) == -1)
4848 1.1 mrg continue;
4849 1.1 mrg
4850 1.1 mrg enum attr_update_Z updated = get_attr_update_Z (insn);
4851 1.1 mrg
4852 1.1 mrg rtx set = single_set (insn);
4853 1.1 mrg bool must_break = (set != NULL_RTX && rtx_equal_p (operand, SET_DEST (set)));
4854 1.1 mrg
4855 1.1 mrg switch (updated)
4856 1.1 mrg {
4857 1.1 mrg case UPDATE_Z_NO:
4858 1.1 mrg break;
4859 1.1 mrg case UPDATE_Z_CLOBBER:
4860 1.1 mrg must_break = true;
4861 1.1 mrg break;
4862 1.1 mrg case UPDATE_Z_UPDATE_Z:
4863 1.1 mrg res = must_break;
4864 1.1 mrg must_break = true;
4865 1.1 mrg break;
4866 1.1 mrg default:
4867 1.1 mrg gcc_unreachable ();
4868 1.1 mrg }
4869 1.1 mrg
4870 1.1 mrg if (must_break)
4871 1.1 mrg break;
4872 1.1 mrg }
4873 1.1 mrg
4874 1.1 mrg /* We have to re-recognize the current insn as the call(s) to
4875 1.1 mrg get_attr_update_Z() above will have overwritten the recog_data cache. */
4876 1.1 mrg recog_memoized (current_output_insn);
4877 1.1 mrg cleanup_subreg_operands (current_output_insn);
4878 1.1 mrg constrain_operands_cached (current_output_insn, 1);
4879 1.1 mrg
4880 1.1 mrg return res;
4881 1.1 mrg }
4882 1.1 mrg
4883 1.1 mrg const char *
4884 1.1 mrg rl78_addsi3_internal (rtx * operands, unsigned int alternative)
4885 1.1 mrg {
4886 1.1 mrg const char *addH2 = "addw ax, %H2\n\t";
4887 1.1 mrg
4888 1.1 mrg /* If we are adding in a constant symbolic address when -mes0
4889 1.1 mrg is active then we know that the address must be <64K and
4890 1.1 mrg that it is invalid to access anything above 64K relative to
4891 1.1 mrg this address. So we can skip adding in the high bytes. */
4892 1.1 mrg if (TARGET_ES0
4893 1.1 mrg && GET_CODE (operands[2]) == SYMBOL_REF
4894 1.1 mrg && TREE_CODE (SYMBOL_REF_DECL (operands[2])) == VAR_DECL
4895 1.1 mrg && TREE_READONLY (SYMBOL_REF_DECL (operands[2]))
4896 1.1 mrg && ! TREE_SIDE_EFFECTS (SYMBOL_REF_DECL (operands[2])))
4897 1.1 mrg return "movw ax, %h1\n\taddw ax, %h2\n\tmovw %h0, ax";
4898 1.1 mrg
4899 1.1 mrg if(CONST_INT_P(operands[2]))
4900 1.1 mrg {
4901 1.1 mrg if((INTVAL(operands[2]) & 0xFFFF0000) == 0)
4902 1.1 mrg {
4903 1.1 mrg addH2 = "";
4904 1.1 mrg }
4905 1.1 mrg else if((INTVAL(operands[2]) & 0xFFFF0000) == 0x00010000)
4906 1.1 mrg {
4907 1.1 mrg addH2 = "incw ax\n\t";
4908 1.1 mrg }
4909 1.1 mrg else if((INTVAL(operands[2]) & 0xFFFF0000) == 0xFFFF0000)
4910 1.1 mrg {
4911 1.1 mrg addH2 = "decw ax\n\t";
4912 1.1 mrg }
4913 1.1 mrg }
4914 1.1 mrg
4915 1.1 mrg switch (alternative)
4916 1.1 mrg {
4917 1.1 mrg case 0:
4918 1.1 mrg case 1:
4919 1.1 mrg snprintf(fmt_buffer, sizeof(fmt_buffer),
4920 1.1 mrg "movw ax, %%h1\n\taddw ax, %%h2\n\tmovw %%h0, ax\n\tmovw ax, %%H1\n\tsknc\n\tincw ax\n\t%smovw %%H0,ax", addH2);
4921 1.1 mrg break;
4922 1.1 mrg case 2:
4923 1.1 mrg snprintf(fmt_buffer, sizeof(fmt_buffer),
4924 1.1 mrg "movw ax, %%h1\n\taddw ax, %%h2\n\tmovw bc, ax\n\tmovw ax, %%H1\n\tsknc\n\tincw ax\n\t%smovw %%H0, ax\n\tmovw ax, bc\n\tmovw %%h0, ax", addH2);
4925 1.1 mrg break;
4926 1.1 mrg default:
4927 1.1 mrg gcc_unreachable ();
4928 1.1 mrg }
4929 1.1 mrg
4930 1.1 mrg return fmt_buffer;
4931 1.1 mrg }
4932 1.1 mrg
4933 1.1 mrg rtx
4934 1.1 mrg rl78_emit_libcall (const char *name, enum rtx_code code,
4935 1.1 mrg enum machine_mode dmode, enum machine_mode smode,
4936 1.1 mrg int noperands, rtx *operands)
4937 1.1 mrg {
4938 1.1 mrg rtx ret;
4939 1.1 mrg rtx_insn *insns;
4940 1.1 mrg rtx libcall;
4941 1.1 mrg rtx equiv;
4942 1.1 mrg
4943 1.1 mrg start_sequence ();
4944 1.1 mrg libcall = gen_rtx_SYMBOL_REF (Pmode, name);
4945 1.1 mrg
4946 1.1 mrg switch (noperands)
4947 1.1 mrg {
4948 1.1 mrg case 2:
4949 1.1 mrg ret = emit_library_call_value (libcall, NULL_RTX, LCT_CONST,
4950 1.1 mrg dmode, operands[1], smode);
4951 1.1 mrg equiv = gen_rtx_fmt_e (code, dmode, operands[1]);
4952 1.1 mrg break;
4953 1.1 mrg
4954 1.1 mrg case 3:
4955 1.1 mrg ret = emit_library_call_value (libcall, NULL_RTX,
4956 1.1 mrg LCT_CONST, dmode,
4957 1.1 mrg operands[1], smode, operands[2],
4958 1.1 mrg smode);
4959 1.1 mrg equiv = gen_rtx_fmt_ee (code, dmode, operands[1], operands[2]);
4960 1.1 mrg break;
4961 1.1 mrg
4962 1.1 mrg default:
4963 1.1 mrg gcc_unreachable ();
4964 1.1 mrg }
4965 1.1 mrg
4966 1.1 mrg insns = get_insns ();
4967 1.1 mrg end_sequence ();
4968 1.1 mrg emit_libcall_block (insns, operands[0], ret, equiv);
4969 1.1 mrg return ret;
4970 1.1 mrg }
4971 1.1 mrg
4972 1.1 mrg
4973 1.1 mrg #undef TARGET_PREFERRED_RELOAD_CLASS
4975 1.1 mrg #define TARGET_PREFERRED_RELOAD_CLASS rl78_preferred_reload_class
4976 1.1 mrg
4977 1.1 mrg static reg_class_t
4978 rl78_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, reg_class_t rclass)
4979 {
4980 if (rclass == NO_REGS)
4981 rclass = V_REGS;
4982
4983 return rclass;
4984 }
4985
4986
4987 struct gcc_target targetm = TARGET_INITIALIZER;
4989
4990 #include "gt-rl78.h"
4991