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