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