1/* Output routines for GCC for CRX. 2 Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 3 2002, 2003, 2004 Free Software Foundation, Inc. 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify it 8 under the terms of the GNU General Public License as published 9 by the Free Software Foundation; either version 2, or (at your 10 option) any later version. 11 12 GCC is distributed in the hope that it will be useful, but WITHOUT 13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 15 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 COPYING. If not, write to 19 the Free Software Foundation, 51 Franklin Street, Fifth Floor, 20 Boston, MA 02110-1301, USA. */ 21 22/*****************************************************************************/ 23/* HEADER INCLUDES */ 24/*****************************************************************************/ 25 26#include "config.h" 27#include "system.h" 28#include "coretypes.h" 29#include "tm.h" 30#include "rtl.h" 31#include "tree.h" 32#include "tm_p.h" 33#include "regs.h" 34#include "hard-reg-set.h" 35#include "real.h" 36#include "insn-config.h" 37#include "conditions.h" 38#include "output.h" 39#include "insn-codes.h" 40#include "insn-attr.h" 41#include "flags.h" 42#include "except.h" 43#include "function.h" 44#include "recog.h" 45#include "expr.h" 46#include "optabs.h" 47#include "toplev.h" 48#include "basic-block.h" 49#include "target.h" 50#include "target-def.h" 51 52/*****************************************************************************/ 53/* DEFINITIONS */ 54/*****************************************************************************/ 55 56/* Maximum number of register used for passing parameters. */ 57#define MAX_REG_FOR_PASSING_ARGS 6 58 59/* Minimum number register used for passing parameters. */ 60#define MIN_REG_FOR_PASSING_ARGS 2 61 62/* The maximum count of words supported in the assembly of the architecture in 63 * a push/pop instruction. */ 64#define MAX_COUNT 8 65 66/* Predicate is true if the current function is a 'noreturn' function, i.e. it 67 * is qualified as volatile. */ 68#define FUNC_IS_NORETURN_P(decl) (TREE_THIS_VOLATILE (decl)) 69 70/* The following macros are used in crx_decompose_address () */ 71 72/* Returns the factor of a scaled index address or -1 if invalid. */ 73#define SCALE_FOR_INDEX_P(X) \ 74 (GET_CODE (X) == CONST_INT ? \ 75 (INTVAL (X) == 1 ? 1 : \ 76 INTVAL (X) == 2 ? 2 : \ 77 INTVAL (X) == 4 ? 4 : \ 78 INTVAL (X) == 8 ? 8 : \ 79 -1) : \ 80 -1) 81 82/* Nonzero if the rtx X is a signed const int of n bits */ 83#define RTX_SIGNED_INT_FITS_N_BITS(X,n) \ 84 ((GET_CODE (X) == CONST_INT \ 85 && SIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0) 86 87/* Nonzero if the rtx X is an unsigned const int of n bits. */ 88#define RTX_UNSIGNED_INT_FITS_N_BITS(X, n) \ 89 ((GET_CODE (X) == CONST_INT \ 90 && UNSIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0) 91 92/*****************************************************************************/ 93/* STATIC VARIABLES */ 94/*****************************************************************************/ 95 96/* Nonzero if the last param processed is passed in a register. */ 97static int last_parm_in_reg; 98 99/* Will hold the number of the last register the prologue saves, -1 if no 100 * register is saved. */ 101static int last_reg_to_save; 102 103/* Each object in the array is a register number. Mark 1 for registers that 104 * need to be saved. */ 105static int save_regs[FIRST_PSEUDO_REGISTER]; 106 107/* Number of bytes saved on the stack for non-scratch registers */ 108static int sum_regs = 0; 109 110/* Number of bytes saved on the stack for local variables. */ 111static int local_vars_size; 112 113/* The sum of 2 sizes: locals vars and padding byte for saving the registers. 114 * Used in expand_prologue () and expand_epilogue (). */ 115static int size_for_adjusting_sp; 116 117/* In case of a POST_INC or POST_DEC memory reference, we must report the mode 118 * of the memory reference from PRINT_OPERAND to PRINT_OPERAND_ADDRESS. */ 119static enum machine_mode output_memory_reference_mode; 120 121/*****************************************************************************/ 122/* GLOBAL VARIABLES */ 123/*****************************************************************************/ 124 125/* Table of machine attributes. */ 126const struct attribute_spec crx_attribute_table[]; 127 128/* Test and compare insns use these globals to generate branch insns. */ 129rtx crx_compare_op0 = NULL_RTX; 130rtx crx_compare_op1 = NULL_RTX; 131 132/*****************************************************************************/ 133/* TARGETM FUNCTION PROTOTYPES */ 134/*****************************************************************************/ 135 136static bool crx_fixed_condition_code_regs (unsigned int *, unsigned int *); 137static rtx crx_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED, 138 int incoming ATTRIBUTE_UNUSED); 139static bool crx_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED); 140static int crx_address_cost (rtx); 141 142/*****************************************************************************/ 143/* STACK LAYOUT AND CALLING CONVENTIONS */ 144/*****************************************************************************/ 145 146#undef TARGET_FIXED_CONDITION_CODE_REGS 147#define TARGET_FIXED_CONDITION_CODE_REGS crx_fixed_condition_code_regs 148 149#undef TARGET_STRUCT_VALUE_RTX 150#define TARGET_STRUCT_VALUE_RTX crx_struct_value_rtx 151 152#undef TARGET_RETURN_IN_MEMORY 153#define TARGET_RETURN_IN_MEMORY crx_return_in_memory 154 155/*****************************************************************************/ 156/* RELATIVE COSTS OF OPERATIONS */ 157/*****************************************************************************/ 158 159#undef TARGET_ADDRESS_COST 160#define TARGET_ADDRESS_COST crx_address_cost 161 162/*****************************************************************************/ 163/* TARGET-SPECIFIC USES OF `__attribute__' */ 164/*****************************************************************************/ 165 166#undef TARGET_ATTRIBUTE_TABLE 167#define TARGET_ATTRIBUTE_TABLE crx_attribute_table 168 169const struct attribute_spec crx_attribute_table[] = { 170 /* ISRs have special prologue and epilogue requirements. */ 171 {"interrupt", 0, 0, false, true, true, NULL}, 172 {NULL, 0, 0, false, false, false, NULL} 173}; 174 175 176/* Initialize 'targetm' variable which contains pointers to functions and data 177 * relating to the target machine. */ 178 179struct gcc_target targetm = TARGET_INITIALIZER; 180 181 182/*****************************************************************************/ 183/* TARGET HOOK IMPLEMENTATIONS */ 184/*****************************************************************************/ 185 186/* Return the fixed registers used for condition codes. */ 187 188static bool 189crx_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2) 190{ 191 *p1 = CC_REGNUM; 192 *p2 = INVALID_REGNUM; 193 return true; 194} 195 196/* Implements hook TARGET_STRUCT_VALUE_RTX. */ 197 198static rtx 199crx_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED, 200 int incoming ATTRIBUTE_UNUSED) 201{ 202 return gen_rtx_REG (Pmode, CRX_STRUCT_VALUE_REGNUM); 203} 204 205/* Implements hook TARGET_RETURN_IN_MEMORY. */ 206 207static bool 208crx_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED) 209{ 210 if (TYPE_MODE (type) == BLKmode) 211 { 212 HOST_WIDE_INT size = int_size_in_bytes (type); 213 return (size == -1 || size > 8); 214 } 215 else 216 return false; 217} 218 219 220/*****************************************************************************/ 221/* MACRO IMPLEMENTATIONS */ 222/*****************************************************************************/ 223 224/* STACK LAYOUT AND CALLING CONVENTIONS ROUTINES */ 225/* --------------------------------------------- */ 226 227/* Return nonzero if the current function being compiled is an interrupt 228 * function as specified by the "interrupt" attribute. */ 229 230int 231crx_interrupt_function_p (void) 232{ 233 tree attributes; 234 235 attributes = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)); 236 return lookup_attribute ("interrupt", attributes) != NULL_TREE; 237} 238 239/* Compute values for the array save_regs and the variable sum_regs. The index 240 * of save_regs is numbers of register, each will get 1 if we need to save it 241 * in the current function, 0 if not. sum_regs is the total sum of the 242 * registers being saved. */ 243 244static void 245crx_compute_save_regs (void) 246{ 247 unsigned int regno; 248 249 /* initialize here so in case the function is no-return it will be -1. */ 250 last_reg_to_save = -1; 251 252 /* No need to save any registers if the function never returns. */ 253 if (FUNC_IS_NORETURN_P (current_function_decl)) 254 return; 255 256 /* Initialize the number of bytes to be saved. */ 257 sum_regs = 0; 258 259 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) 260 { 261 if (fixed_regs[regno]) 262 { 263 save_regs[regno] = 0; 264 continue; 265 } 266 267 /* If this reg is used and not call-used (except RA), save it. */ 268 if (crx_interrupt_function_p ()) 269 { 270 if (!current_function_is_leaf && call_used_regs[regno]) 271 /* this is a volatile reg in a non-leaf interrupt routine - save it 272 * for the sake of its sons. */ 273 save_regs[regno] = 1; 274 275 else if (regs_ever_live[regno]) 276 /* This reg is used - save it. */ 277 save_regs[regno] = 1; 278 else 279 /* This reg is not used, and is not a volatile - don't save. */ 280 save_regs[regno] = 0; 281 } 282 else 283 { 284 /* If this reg is used and not call-used (except RA), save it. */ 285 if (regs_ever_live[regno] 286 && (!call_used_regs[regno] || regno == RETURN_ADDRESS_REGNUM)) 287 save_regs[regno] = 1; 288 else 289 save_regs[regno] = 0; 290 } 291 } 292 293 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) 294 if (save_regs[regno] == 1) 295 { 296 last_reg_to_save = regno; 297 sum_regs += UNITS_PER_WORD; 298 } 299} 300 301/* Compute the size of the local area and the size to be adjusted by the 302 * prologue and epilogue. */ 303 304static void 305crx_compute_frame (void) 306{ 307 /* For aligning the local variables. */ 308 int stack_alignment = STACK_BOUNDARY / BITS_PER_UNIT; 309 int padding_locals; 310 311 /* Padding needed for each element of the frame. */ 312 local_vars_size = get_frame_size (); 313 314 /* Align to the stack alignment. */ 315 padding_locals = local_vars_size % stack_alignment; 316 if (padding_locals) 317 padding_locals = stack_alignment - padding_locals; 318 319 local_vars_size += padding_locals; 320 321 size_for_adjusting_sp = local_vars_size + (ACCUMULATE_OUTGOING_ARGS ? 322 current_function_outgoing_args_size : 0); 323} 324 325/* Implements the macro INITIAL_ELIMINATION_OFFSET, return the OFFSET. */ 326 327int 328crx_initial_elimination_offset (int from, int to) 329{ 330 /* Compute this since we need to use sum_regs. */ 331 crx_compute_save_regs (); 332 333 /* Compute this since we need to use local_vars_size. */ 334 crx_compute_frame (); 335 336 if ((from) == FRAME_POINTER_REGNUM && (to) == STACK_POINTER_REGNUM) 337 return (ACCUMULATE_OUTGOING_ARGS ? 338 current_function_outgoing_args_size : 0); 339 else if ((from) == ARG_POINTER_REGNUM && (to) == FRAME_POINTER_REGNUM) 340 return (sum_regs + local_vars_size); 341 else if ((from) == ARG_POINTER_REGNUM && (to) == STACK_POINTER_REGNUM) 342 return (sum_regs + local_vars_size + 343 (ACCUMULATE_OUTGOING_ARGS ? 344 current_function_outgoing_args_size : 0)); 345 else 346 abort (); 347} 348 349/* REGISTER USAGE */ 350/* -------------- */ 351 352/* Return the class number of the smallest class containing reg number REGNO. 353 * This could be a conditional expression or could index an array. */ 354 355enum reg_class 356crx_regno_reg_class (int regno) 357{ 358 if (regno >= 0 && regno < SP_REGNUM) 359 return NOSP_REGS; 360 361 if (regno == SP_REGNUM) 362 return GENERAL_REGS; 363 364 if (regno == LO_REGNUM) 365 return LO_REGS; 366 if (regno == HI_REGNUM) 367 return HI_REGS; 368 369 return NO_REGS; 370} 371 372/* Transfer between HILO_REGS and memory via secondary reloading. */ 373 374enum reg_class 375crx_secondary_reload_class (enum reg_class class, 376 enum machine_mode mode ATTRIBUTE_UNUSED, 377 rtx x ATTRIBUTE_UNUSED) 378{ 379 if (reg_classes_intersect_p (class, HILO_REGS) 380 && true_regnum (x) == -1) 381 return GENERAL_REGS; 382 383 return NO_REGS; 384} 385 386/* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */ 387 388int 389crx_hard_regno_mode_ok (int regno, enum machine_mode mode) 390{ 391 /* CC can only hold CCmode values. */ 392 if (regno == CC_REGNUM) 393 return GET_MODE_CLASS (mode) == MODE_CC; 394 if (GET_MODE_CLASS (mode) == MODE_CC) 395 return 0; 396 /* HILO registers can only hold SImode and DImode */ 397 if (HILO_REGNO_P (regno)) 398 return mode == SImode || mode == DImode; 399 return 1; 400} 401 402/* PASSING FUNCTION ARGUMENTS */ 403/* -------------------------- */ 404 405/* If enough param regs are available for passing the param of type TYPE return 406 * the number of registers needed else 0. */ 407 408static int 409enough_regs_for_param (CUMULATIVE_ARGS * cum, tree type, 410 enum machine_mode mode) 411{ 412 int type_size; 413 int remaining_size; 414 415 if (mode != BLKmode) 416 type_size = GET_MODE_BITSIZE (mode); 417 else 418 type_size = int_size_in_bytes (type) * BITS_PER_UNIT; 419 420 remaining_size = 421 BITS_PER_WORD * (MAX_REG_FOR_PASSING_ARGS - 422 (MIN_REG_FOR_PASSING_ARGS + cum->ints) + 1); 423 424 /* Any variable which is too big to pass in two registers, will pass on 425 * stack. */ 426 if ((remaining_size >= type_size) && (type_size <= 2 * BITS_PER_WORD)) 427 return (type_size + BITS_PER_WORD - 1) / BITS_PER_WORD; 428 429 return 0; 430} 431 432/* Implements the macro FUNCTION_ARG defined in crx.h. */ 433 434rtx 435crx_function_arg (CUMULATIVE_ARGS * cum, enum machine_mode mode, tree type, 436 int named ATTRIBUTE_UNUSED) 437{ 438 last_parm_in_reg = 0; 439 440 /* Function_arg () is called with this type just after all the args have had 441 * their registers assigned. The rtx that function_arg returns from this type 442 * is supposed to pass to 'gen_call' but currently it is not implemented (see 443 * macro GEN_CALL). */ 444 if (type == void_type_node) 445 return NULL_RTX; 446 447 if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0)) 448 return NULL_RTX; 449 450 if (mode == BLKmode) 451 { 452 /* Enable structures that need padding bytes at the end to pass to a 453 * function in registers. */ 454 if (enough_regs_for_param (cum, type, mode) != 0) 455 { 456 last_parm_in_reg = 1; 457 return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints); 458 } 459 } 460 461 if (MIN_REG_FOR_PASSING_ARGS + cum->ints > MAX_REG_FOR_PASSING_ARGS) 462 return NULL_RTX; 463 else 464 { 465 if (enough_regs_for_param (cum, type, mode) != 0) 466 { 467 last_parm_in_reg = 1; 468 return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints); 469 } 470 } 471 472 return NULL_RTX; 473} 474 475/* Implements the macro INIT_CUMULATIVE_ARGS defined in crx.h. */ 476 477void 478crx_init_cumulative_args (CUMULATIVE_ARGS * cum, tree fntype, 479 rtx libfunc ATTRIBUTE_UNUSED) 480{ 481 tree param, next_param; 482 483 cum->ints = 0; 484 485 /* Determine if this function has variable arguments. This is indicated by 486 * the last argument being 'void_type_mode' if there are no variable 487 * arguments. Change here for a different vararg. */ 488 for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0; 489 param != (tree) 0; param = next_param) 490 { 491 next_param = TREE_CHAIN (param); 492 if (next_param == (tree) 0 && TREE_VALUE (param) != void_type_node) 493 { 494 cum->ints = -1; 495 return; 496 } 497 } 498} 499 500/* Implements the macro FUNCTION_ARG_ADVANCE defined in crx.h. */ 501 502void 503crx_function_arg_advance (CUMULATIVE_ARGS * cum, enum machine_mode mode, 504 tree type, int named ATTRIBUTE_UNUSED) 505{ 506 /* l holds the number of registers required */ 507 int l = GET_MODE_BITSIZE (mode) / BITS_PER_WORD; 508 509 /* If the parameter isn't passed on a register don't advance cum. */ 510 if (!last_parm_in_reg) 511 return; 512 513 if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0)) 514 return; 515 516 if (mode == SImode || mode == HImode || mode == QImode || mode == DImode) 517 { 518 if (l <= 1) 519 cum->ints += 1; 520 else 521 cum->ints += l; 522 } 523 else if (mode == SFmode || mode == DFmode) 524 cum->ints += l; 525 else if ((mode) == BLKmode) 526 { 527 if ((l = enough_regs_for_param (cum, type, mode)) != 0) 528 cum->ints += l; 529 } 530 531} 532 533/* Implements the macro FUNCTION_ARG_REGNO_P defined in crx.h. Return nonzero 534 * if N is a register used for passing parameters. */ 535 536int 537crx_function_arg_regno_p (int n) 538{ 539 return (n <= MAX_REG_FOR_PASSING_ARGS && n >= MIN_REG_FOR_PASSING_ARGS); 540} 541 542/* ADDRESSING MODES */ 543/* ---------------- */ 544 545/* Implements the macro GO_IF_LEGITIMATE_ADDRESS defined in crx.h. 546 * The following addressing modes are supported on CRX: 547 * 548 * Relocations --> const | symbol_ref | label_ref 549 * Absolute address --> 32 bit absolute 550 * Post increment --> reg + 12 bit disp. 551 * Post modify --> reg + 12 bit disp. 552 * Register relative --> reg | 32 bit disp. + reg | 4 bit + reg 553 * Scaled index --> reg + reg | 22 bit disp. + reg + reg | 554 * 22 disp. + reg + reg + (2 | 4 | 8) */ 555 556static int crx_addr_reg_p (rtx addr_reg) 557{ 558 rtx reg; 559 560 if (REG_P (addr_reg)) 561 { 562 reg = addr_reg; 563 } 564 else if ((GET_CODE (addr_reg) == SUBREG 565 && REG_P (SUBREG_REG (addr_reg)) 566 && GET_MODE_SIZE (GET_MODE (SUBREG_REG (addr_reg))) 567 <= UNITS_PER_WORD)) 568 { 569 reg = SUBREG_REG (addr_reg); 570 } 571 else 572 return FALSE; 573 574 if (GET_MODE (addr_reg) != Pmode) 575 { 576 return FALSE; 577 } 578 579 return TRUE; 580} 581 582enum crx_addrtype 583crx_decompose_address (rtx addr, struct crx_address *out) 584{ 585 rtx base = NULL_RTX, index = NULL_RTX, disp = NULL_RTX; 586 rtx scale_rtx = NULL_RTX, side_effect = NULL_RTX; 587 int scale = -1; 588 589 enum crx_addrtype retval = CRX_INVALID; 590 591 switch (GET_CODE (addr)) 592 { 593 case CONST_INT: 594 /* Absolute address (known at compile time) */ 595 retval = CRX_ABSOLUTE; 596 disp = addr; 597 if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), GET_MODE_BITSIZE (Pmode))) 598 return CRX_INVALID; 599 break; 600 601 case CONST: 602 case SYMBOL_REF: 603 case LABEL_REF: 604 /* Absolute address (known at link time) */ 605 retval = CRX_ABSOLUTE; 606 disp = addr; 607 break; 608 609 case REG: 610 case SUBREG: 611 /* Register relative address */ 612 retval = CRX_REG_REL; 613 base = addr; 614 break; 615 616 case PLUS: 617 switch (GET_CODE (XEXP (addr, 0))) 618 { 619 case REG: 620 case SUBREG: 621 if (REG_P (XEXP (addr, 1))) 622 { 623 /* Scaled index with scale = 1 and disp. = 0 */ 624 retval = CRX_SCALED_INDX; 625 base = XEXP (addr, 1); 626 index = XEXP (addr, 0); 627 scale = 1; 628 } 629 else if (RTX_SIGNED_INT_FITS_N_BITS (XEXP (addr, 1), 28)) 630 { 631 /* Register relative address and <= 28-bit disp. */ 632 retval = CRX_REG_REL; 633 base = XEXP (addr, 0); 634 disp = XEXP (addr, 1); 635 } 636 else 637 return CRX_INVALID; 638 break; 639 640 case PLUS: 641 /* Scaled index and <= 22-bit disp. */ 642 retval = CRX_SCALED_INDX; 643 base = XEXP (XEXP (addr, 0), 1); 644 disp = XEXP (addr, 1); 645 if (!RTX_SIGNED_INT_FITS_N_BITS (disp, 22)) 646 return CRX_INVALID; 647 switch (GET_CODE (XEXP (XEXP (addr, 0), 0))) 648 { 649 case REG: 650 /* Scaled index with scale = 0 and <= 22-bit disp. */ 651 index = XEXP (XEXP (addr, 0), 0); 652 scale = 1; 653 break; 654 655 case MULT: 656 /* Scaled index with scale >= 0 and <= 22-bit disp. */ 657 index = XEXP (XEXP (XEXP (addr, 0), 0), 0); 658 scale_rtx = XEXP (XEXP (XEXP (addr, 0), 0), 1); 659 if ((scale = SCALE_FOR_INDEX_P (scale_rtx)) == -1) 660 return CRX_INVALID; 661 break; 662 663 default: 664 return CRX_INVALID; 665 } 666 break; 667 668 case MULT: 669 /* Scaled index with scale >= 0 */ 670 retval = CRX_SCALED_INDX; 671 base = XEXP (addr, 1); 672 index = XEXP (XEXP (addr, 0), 0); 673 scale_rtx = XEXP (XEXP (addr, 0), 1); 674 /* Scaled index with scale >= 0 and <= 22-bit disp. */ 675 if ((scale = SCALE_FOR_INDEX_P (scale_rtx)) == -1) 676 return CRX_INVALID; 677 break; 678 679 default: 680 return CRX_INVALID; 681 } 682 break; 683 684 case POST_INC: 685 case POST_DEC: 686 /* Simple post-increment */ 687 retval = CRX_POST_INC; 688 base = XEXP (addr, 0); 689 side_effect = addr; 690 break; 691 692 case POST_MODIFY: 693 /* Generic post-increment with <= 12-bit disp. */ 694 retval = CRX_POST_INC; 695 base = XEXP (addr, 0); 696 side_effect = XEXP (addr, 1); 697 if (base != XEXP (side_effect, 0)) 698 return CRX_INVALID; 699 switch (GET_CODE (side_effect)) 700 { 701 case PLUS: 702 case MINUS: 703 disp = XEXP (side_effect, 1); 704 if (!RTX_SIGNED_INT_FITS_N_BITS (disp, 12)) 705 return CRX_INVALID; 706 break; 707 708 default: 709 /* CRX only supports PLUS and MINUS */ 710 return CRX_INVALID; 711 } 712 break; 713 714 default: 715 return CRX_INVALID; 716 } 717 718 if (base && !crx_addr_reg_p (base)) return CRX_INVALID; 719 if (index && !crx_addr_reg_p (index)) return CRX_INVALID; 720 721 out->base = base; 722 out->index = index; 723 out->disp = disp; 724 out->scale = scale; 725 out->side_effect = side_effect; 726 727 return retval; 728} 729 730int 731crx_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, 732 rtx addr, int strict) 733{ 734 enum crx_addrtype addrtype; 735 struct crx_address address; 736 737 if (TARGET_DEBUG_ADDR) 738 { 739 fprintf (stderr, 740 "\n======\nGO_IF_LEGITIMATE_ADDRESS, mode = %s, strict = %d\n", 741 GET_MODE_NAME (mode), strict); 742 debug_rtx (addr); 743 } 744 745 addrtype = crx_decompose_address (addr, &address); 746 747 if (addrtype == CRX_POST_INC && GET_MODE_SIZE (mode) > UNITS_PER_WORD) 748 return FALSE; 749 750 if (TARGET_DEBUG_ADDR) 751 { 752 const char *typestr; 753 switch (addrtype) 754 { 755 case CRX_INVALID: 756 typestr = "Invalid"; 757 break; 758 case CRX_REG_REL: 759 typestr = "Register relative"; 760 break; 761 case CRX_POST_INC: 762 typestr = "Post-increment"; 763 break; 764 case CRX_SCALED_INDX: 765 typestr = "Scaled index"; 766 break; 767 case CRX_ABSOLUTE: 768 typestr = "Absolute"; 769 break; 770 default: 771 abort (); 772 } 773 fprintf (stderr, "CRX Address type: %s\n", typestr); 774 } 775 776 if (addrtype == CRX_INVALID) 777 return FALSE; 778 779 if (strict) 780 { 781 if (address.base && !REGNO_OK_FOR_BASE_P (REGNO (address.base))) 782 { 783 if (TARGET_DEBUG_ADDR) 784 fprintf (stderr, "Base register not strict\n"); 785 return FALSE; 786 } 787 if (address.index && !REGNO_OK_FOR_INDEX_P (REGNO (address.index))) 788 { 789 if (TARGET_DEBUG_ADDR) 790 fprintf (stderr, "Index register not strict\n"); 791 return FALSE; 792 } 793 } 794 795 return TRUE; 796} 797 798/* ROUTINES TO COMPUTE COSTS */ 799/* ------------------------- */ 800 801/* Return cost of the memory address x. */ 802 803static int 804crx_address_cost (rtx addr) 805{ 806 enum crx_addrtype addrtype; 807 struct crx_address address; 808 809 int cost = 2; 810 811 addrtype = crx_decompose_address (addr, &address); 812 813 gcc_assert (addrtype != CRX_INVALID); 814 815 /* An absolute address causes a 3-word instruction */ 816 if (addrtype == CRX_ABSOLUTE) 817 cost+=2; 818 819 /* Post-modifying addresses are more powerful. */ 820 if (addrtype == CRX_POST_INC) 821 cost-=2; 822 823 /* Attempt to minimize number of registers in the address. */ 824 if (address.base) 825 cost++; 826 827 if (address.index && address.scale == 1) 828 cost+=5; 829 830 if (address.disp && !INT_CST4 (INTVAL (address.disp))) 831 cost+=2; 832 833 if (TARGET_DEBUG_ADDR) 834 { 835 fprintf (stderr, "\n======\nTARGET_ADDRESS_COST = %d\n", cost); 836 debug_rtx (addr); 837 } 838 839 return cost; 840} 841 842/* Return the cost of moving data of mode MODE between a register of class 843 * CLASS and memory; IN is zero if the value is to be written to memory, 844 * nonzero if it is to be read in. This cost is relative to those in 845 * REGISTER_MOVE_COST. */ 846 847int 848crx_memory_move_cost (enum machine_mode mode, 849 enum reg_class class ATTRIBUTE_UNUSED, 850 int in ATTRIBUTE_UNUSED) 851{ 852 /* One LD or ST takes twice the time of a simple reg-reg move */ 853 if (reg_classes_intersect_p (class, GENERAL_REGS)) 854 { 855 /* printf ("GENERAL_REGS LD/ST = %d\n", 4 * HARD_REGNO_NREGS (0, mode));*/ 856 return 4 * HARD_REGNO_NREGS (0, mode); 857 } 858 else if (reg_classes_intersect_p (class, HILO_REGS)) 859 { 860 /* HILO to memory and vice versa */ 861 /* printf ("HILO_REGS %s = %d\n", in ? "LD" : "ST", 862 (REGISTER_MOVE_COST (mode, 863 in ? GENERAL_REGS : HILO_REGS, 864 in ? HILO_REGS : GENERAL_REGS) + 4) 865 * HARD_REGNO_NREGS (0, mode)); */ 866 return (REGISTER_MOVE_COST (mode, 867 in ? GENERAL_REGS : HILO_REGS, 868 in ? HILO_REGS : GENERAL_REGS) + 4) 869 * HARD_REGNO_NREGS (0, mode); 870 } 871 else /* default (like in i386) */ 872 { 873 /* printf ("ANYREGS = 100\n"); */ 874 return 100; 875 } 876} 877 878/* INSTRUCTION OUTPUT */ 879/* ------------------ */ 880 881/* Check if a const_double is ok for crx store-immediate instructions */ 882 883int 884crx_const_double_ok (rtx op) 885{ 886 if (GET_MODE (op) == DFmode) 887 { 888 REAL_VALUE_TYPE r; 889 long l[2]; 890 REAL_VALUE_FROM_CONST_DOUBLE (r, op); 891 REAL_VALUE_TO_TARGET_DOUBLE (r, l); 892 return (UNSIGNED_INT_FITS_N_BITS (l[0], 4) && 893 UNSIGNED_INT_FITS_N_BITS (l[1], 4)) ? 1 : 0; 894 } 895 896 if (GET_MODE (op) == SFmode) 897 { 898 REAL_VALUE_TYPE r; 899 long l; 900 REAL_VALUE_FROM_CONST_DOUBLE (r, op); 901 REAL_VALUE_TO_TARGET_SINGLE (r, l); 902 return UNSIGNED_INT_FITS_N_BITS (l, 4) ? 1 : 0; 903 } 904 905 return (UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_LOW (op), 4) && 906 UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_HIGH (op), 4)) ? 1 : 0; 907} 908 909/* Implements the macro PRINT_OPERAND defined in crx.h. */ 910 911void 912crx_print_operand (FILE * file, rtx x, int code) 913{ 914 switch (code) 915 { 916 case 'p' : 917 if (GET_CODE (x) == REG) { 918 if (GET_MODE (x) == DImode || GET_MODE (x) == DFmode) 919 { 920 int regno = REGNO (x); 921 if (regno + 1 >= SP_REGNUM) abort (); 922 fprintf (file, "{%s, %s}", reg_names[regno], reg_names[regno + 1]); 923 return; 924 } 925 else 926 { 927 if (REGNO (x) >= SP_REGNUM) abort (); 928 fprintf (file, "%s", reg_names[REGNO (x)]); 929 return; 930 } 931 } 932 933 case 'd' : 934 { 935 const char *crx_cmp_str; 936 switch (GET_CODE (x)) 937 { /* MD: compare (reg, reg or imm) but CRX: cmp (reg or imm, reg) 938 * -> swap all non symmetric ops */ 939 case EQ : crx_cmp_str = "eq"; break; 940 case NE : crx_cmp_str = "ne"; break; 941 case GT : crx_cmp_str = "lt"; break; 942 case GTU : crx_cmp_str = "lo"; break; 943 case LT : crx_cmp_str = "gt"; break; 944 case LTU : crx_cmp_str = "hi"; break; 945 case GE : crx_cmp_str = "le"; break; 946 case GEU : crx_cmp_str = "ls"; break; 947 case LE : crx_cmp_str = "ge"; break; 948 case LEU : crx_cmp_str = "hs"; break; 949 default : abort (); 950 } 951 fprintf (file, "%s", crx_cmp_str); 952 return; 953 } 954 955 case 'H': 956 /* Print high part of a double precision value. */ 957 switch (GET_CODE (x)) 958 { 959 case CONST_DOUBLE: 960 if (GET_MODE (x) == SFmode) abort (); 961 if (GET_MODE (x) == DFmode) 962 { 963 /* High part of a DF const. */ 964 REAL_VALUE_TYPE r; 965 long l[2]; 966 967 REAL_VALUE_FROM_CONST_DOUBLE (r, x); 968 REAL_VALUE_TO_TARGET_DOUBLE (r, l); 969 970 fprintf (file, "$0x%lx", l[1]); 971 return; 972 } 973 974 /* -- Fallthrough to handle DI consts -- */ 975 976 case CONST_INT: 977 { 978 rtx high, low; 979 split_double (x, &low, &high); 980 putc ('$', file); 981 output_addr_const (file, high); 982 return; 983 } 984 985 case REG: 986 if (REGNO (x) + 1 >= FIRST_PSEUDO_REGISTER) abort (); 987 fprintf (file, "%s", reg_names[REGNO (x) + 1]); 988 return; 989 990 case MEM: 991 /* Adjust memory address to high part. */ 992 { 993 rtx adj_mem = x; 994 adj_mem = adjust_address (adj_mem, GET_MODE (adj_mem), 4); 995 996 output_memory_reference_mode = GET_MODE (adj_mem); 997 output_address (XEXP (adj_mem, 0)); 998 return; 999 } 1000 1001 default: 1002 abort (); 1003 } 1004 1005 case 'L': 1006 /* Print low part of a double precision value. */ 1007 switch (GET_CODE (x)) 1008 { 1009 case CONST_DOUBLE: 1010 if (GET_MODE (x) == SFmode) abort (); 1011 if (GET_MODE (x) == DFmode) 1012 { 1013 /* High part of a DF const. */ 1014 REAL_VALUE_TYPE r; 1015 long l[2]; 1016 1017 REAL_VALUE_FROM_CONST_DOUBLE (r, x); 1018 REAL_VALUE_TO_TARGET_DOUBLE (r, l); 1019 1020 fprintf (file, "$0x%lx", l[0]); 1021 return; 1022 } 1023 1024 /* -- Fallthrough to handle DI consts -- */ 1025 1026 case CONST_INT: 1027 { 1028 rtx high, low; 1029 split_double (x, &low, &high); 1030 putc ('$', file); 1031 output_addr_const (file, low); 1032 return; 1033 } 1034 1035 case REG: 1036 fprintf (file, "%s", reg_names[REGNO (x)]); 1037 return; 1038 1039 case MEM: 1040 output_memory_reference_mode = GET_MODE (x); 1041 output_address (XEXP (x, 0)); 1042 return; 1043 1044 default: 1045 abort (); 1046 } 1047 1048 case 0 : /* default */ 1049 switch (GET_CODE (x)) 1050 { 1051 case REG: 1052 fprintf (file, "%s", reg_names[REGNO (x)]); 1053 return; 1054 1055 case MEM: 1056 output_memory_reference_mode = GET_MODE (x); 1057 output_address (XEXP (x, 0)); 1058 return; 1059 1060 case CONST_DOUBLE: 1061 { 1062 REAL_VALUE_TYPE r; 1063 long l; 1064 1065 /* Always use H and L for double precision - see above */ 1066 gcc_assert (GET_MODE (x) == SFmode); 1067 1068 REAL_VALUE_FROM_CONST_DOUBLE (r, x); 1069 REAL_VALUE_TO_TARGET_SINGLE (r, l); 1070 1071 fprintf (file, "$0x%lx", l); 1072 return; 1073 } 1074 1075 default: 1076 putc ('$', file); 1077 output_addr_const (file, x); 1078 return; 1079 } 1080 1081 default: 1082 output_operand_lossage ("invalid %%xn code"); 1083 } 1084 1085 abort (); 1086} 1087 1088/* Implements the macro PRINT_OPERAND_ADDRESS defined in crx.h. */ 1089 1090void 1091crx_print_operand_address (FILE * file, rtx addr) 1092{ 1093 enum crx_addrtype addrtype; 1094 struct crx_address address; 1095 1096 int offset; 1097 1098 addrtype = crx_decompose_address (addr, &address); 1099 1100 if (address.disp) 1101 offset = INTVAL (address.disp); 1102 else 1103 offset = 0; 1104 1105 switch (addrtype) 1106 { 1107 case CRX_REG_REL: 1108 fprintf (file, "%d(%s)", offset, reg_names[REGNO (address.base)]); 1109 return; 1110 1111 case CRX_POST_INC: 1112 switch (GET_CODE (address.side_effect)) 1113 { 1114 case PLUS: 1115 break; 1116 case MINUS: 1117 offset = -offset; 1118 break; 1119 case POST_INC: 1120 offset = GET_MODE_SIZE (output_memory_reference_mode); 1121 break; 1122 case POST_DEC: 1123 offset = -GET_MODE_SIZE (output_memory_reference_mode); 1124 break; 1125 default: 1126 abort (); 1127 } 1128 fprintf (file, "%d(%s)+", offset, reg_names[REGNO (address.base)]); 1129 return; 1130 1131 case CRX_SCALED_INDX: 1132 fprintf (file, "%d(%s, %s, %d)", offset, reg_names[REGNO (address.base)], 1133 reg_names[REGNO (address.index)], address.scale); 1134 return; 1135 1136 case CRX_ABSOLUTE: 1137 output_addr_const (file, address.disp); 1138 return; 1139 1140 default: 1141 abort (); 1142 } 1143} 1144 1145 1146/*****************************************************************************/ 1147/* MACHINE DESCRIPTION HELPER-FUNCTIONS */ 1148/*****************************************************************************/ 1149 1150void crx_expand_movmem_single (rtx src, rtx srcbase, rtx dst, rtx dstbase, 1151 rtx tmp_reg, unsigned HOST_WIDE_INT *offset_p) 1152{ 1153 rtx addr, mem; 1154 unsigned HOST_WIDE_INT offset = *offset_p; 1155 1156 /* Load */ 1157 addr = plus_constant (src, offset); 1158 mem = adjust_automodify_address (srcbase, SImode, addr, offset); 1159 emit_move_insn (tmp_reg, mem); 1160 1161 /* Store */ 1162 addr = plus_constant (dst, offset); 1163 mem = adjust_automodify_address (dstbase, SImode, addr, offset); 1164 emit_move_insn (mem, tmp_reg); 1165 1166 *offset_p = offset + 4; 1167} 1168 1169int 1170crx_expand_movmem (rtx dstbase, rtx srcbase, rtx count_exp, rtx align_exp) 1171{ 1172 unsigned HOST_WIDE_INT count = 0, offset, si_moves, i; 1173 HOST_WIDE_INT align = 0; 1174 1175 rtx src, dst; 1176 rtx tmp_reg; 1177 1178 if (GET_CODE (align_exp) == CONST_INT) 1179 { /* Only if aligned */ 1180 align = INTVAL (align_exp); 1181 if (align & 3) 1182 return 0; 1183 } 1184 1185 if (GET_CODE (count_exp) == CONST_INT) 1186 { /* No more than 16 SImode moves */ 1187 count = INTVAL (count_exp); 1188 if (count > 64) 1189 return 0; 1190 } 1191 1192 tmp_reg = gen_reg_rtx (SImode); 1193 1194 /* Create psrs for the src and dest pointers */ 1195 dst = copy_to_mode_reg (Pmode, XEXP (dstbase, 0)); 1196 if (dst != XEXP (dstbase, 0)) 1197 dstbase = replace_equiv_address_nv (dstbase, dst); 1198 src = copy_to_mode_reg (Pmode, XEXP (srcbase, 0)); 1199 if (src != XEXP (srcbase, 0)) 1200 srcbase = replace_equiv_address_nv (srcbase, src); 1201 1202 offset = 0; 1203 1204 /* Emit SImode moves */ 1205 si_moves = count >> 2; 1206 for (i = 0; i < si_moves; i++) 1207 crx_expand_movmem_single (src, srcbase, dst, dstbase, tmp_reg, &offset); 1208 1209 /* Special cases */ 1210 if (count & 3) 1211 { 1212 offset = count - 4; 1213 crx_expand_movmem_single (src, srcbase, dst, dstbase, tmp_reg, &offset); 1214 } 1215 1216 gcc_assert (offset == count); 1217 1218 return 1; 1219} 1220 1221rtx 1222crx_expand_compare (enum rtx_code code, enum machine_mode mode) 1223{ 1224 rtx op0, op1, cc_reg, ret; 1225 1226 op0 = crx_compare_op0; 1227 op1 = crx_compare_op1; 1228 1229 /* Emit the compare that writes into CC_REGNUM) */ 1230 cc_reg = gen_rtx_REG (CCmode, CC_REGNUM); 1231 ret = gen_rtx_COMPARE (CCmode, op0, op1); 1232 emit_insn (gen_rtx_SET (VOIDmode, cc_reg, ret)); 1233 /* debug_rtx (get_last_insn ()); */ 1234 1235 /* Return the rtx for using the result in CC_REGNUM */ 1236 return gen_rtx_fmt_ee (code, mode, cc_reg, const0_rtx); 1237} 1238 1239void 1240crx_expand_branch (enum rtx_code code, rtx label) 1241{ 1242 rtx tmp = crx_expand_compare (code, VOIDmode); 1243 tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, 1244 gen_rtx_LABEL_REF (VOIDmode, label), 1245 pc_rtx); 1246 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp)); 1247 /* debug_rtx (get_last_insn ()); */ 1248} 1249 1250void 1251crx_expand_scond (enum rtx_code code, rtx dest) 1252{ 1253 rtx tmp = crx_expand_compare (code, GET_MODE (dest)); 1254 emit_move_insn (dest, tmp); 1255 /* debug_rtx (get_last_insn ()); */ 1256} 1257 1258static void 1259mpushpop_str (char *stringbuffer, const char *mnemonic, char *mask) 1260{ 1261 if (strlen (mask) > 2 || crx_interrupt_function_p ()) /* needs 2-word instr. */ 1262 sprintf (stringbuffer, "\n\t%s\tsp, {%s}", mnemonic, mask); 1263 else /* single word instruction */ 1264 sprintf (stringbuffer, "\n\t%s\t%s", mnemonic, mask); 1265} 1266 1267/* Called from crx.md. The return value depends on the parameter push_or_pop: 1268 * When push_or_pop is zero -> string for push instructions of prologue. 1269 * When push_or_pop is nonzero -> string for pop/popret/retx in epilogue. 1270 * Relies on the assumptions: 1271 * 1. RA is the last register to be saved. 1272 * 2. The maximal value of the counter is MAX_COUNT. */ 1273 1274char * 1275crx_prepare_push_pop_string (int push_or_pop) 1276{ 1277 /* j is the number of registers being saved, takes care that there won't be 1278 * more than 8 in one push/pop instruction */ 1279 1280 /* For the register mask string */ 1281 static char mask_str[50]; 1282 1283 /* i is the index of save_regs[], going from 0 until last_reg_to_save */ 1284 int i = 0; 1285 1286 int ra_in_bitmask = 0; 1287 1288 char *return_str; 1289 1290 /* For reversing on the push instructions if there are more than one. */ 1291 char *temp_str; 1292 1293 return_str = (char *) xmalloc (120); 1294 temp_str = (char *) xmalloc (120); 1295 1296 /* Initialize */ 1297 memset (return_str, 0, 3); 1298 1299 while (i <= last_reg_to_save) 1300 { 1301 /* Prepare mask for one instruction. */ 1302 mask_str[0] = 0; 1303 1304 if (i <= SP_REGNUM) 1305 { /* Add regs unit full or SP register reached */ 1306 int j = 0; 1307 while (j < MAX_COUNT && i <= SP_REGNUM) 1308 { 1309 if (save_regs[i]) 1310 { 1311 /* TODO to use ra_in_bitmask for detecting last pop is not 1312 * smart it prevents things like: popret r5 */ 1313 if (i == RETURN_ADDRESS_REGNUM) ra_in_bitmask = 1; 1314 if (j > 0) strcat (mask_str, ", "); 1315 strcat (mask_str, reg_names[i]); 1316 ++j; 1317 } 1318 ++i; 1319 } 1320 } 1321 else 1322 { 1323 /* Handle hi/lo savings */ 1324 while (i <= last_reg_to_save) 1325 { 1326 if (save_regs[i]) 1327 { 1328 strcat (mask_str, "lo, hi"); 1329 i = last_reg_to_save + 1; 1330 break; 1331 } 1332 ++i; 1333 } 1334 } 1335 1336 if (strlen (mask_str) == 0) continue; 1337 1338 if (push_or_pop == 1) 1339 { 1340 if (crx_interrupt_function_p ()) 1341 mpushpop_str (temp_str, "popx", mask_str); 1342 else 1343 { 1344 if (ra_in_bitmask) 1345 { 1346 mpushpop_str (temp_str, "popret", mask_str); 1347 ra_in_bitmask = 0; 1348 } 1349 else mpushpop_str (temp_str, "pop", mask_str); 1350 } 1351 1352 strcat (return_str, temp_str); 1353 } 1354 else 1355 { 1356 /* push - We need to reverse the order of the instructions if there 1357 * are more than one. (since the pop will not be reversed in the 1358 * epilogue */ 1359 if (crx_interrupt_function_p ()) 1360 mpushpop_str (temp_str, "pushx", mask_str); 1361 else 1362 mpushpop_str (temp_str, "push", mask_str); 1363 strcat (temp_str, return_str); 1364 strcpy (strcat (return_str, "\t"), temp_str); 1365 } 1366 1367 } 1368 1369 if (push_or_pop == 1) 1370 { 1371 /* pop */ 1372 if (crx_interrupt_function_p ()) 1373 strcat (return_str, "\n\tretx\n"); 1374 1375 else if (!FUNC_IS_NORETURN_P (current_function_decl) 1376 && !save_regs[RETURN_ADDRESS_REGNUM]) 1377 strcat (return_str, "\n\tjump\tra\n"); 1378 } 1379 1380 /* Skip the newline and the tab in the start of return_str. */ 1381 return_str += 2; 1382 return return_str; 1383} 1384 1385/* CompactRISC CRX Architecture stack layout: 1386 1387 0 +--------------------- 1388 | 1389 . 1390 . 1391 | 1392 +==================== Sp(x)=Ap(x+1) 1393 A | Args for functions 1394 | | called by X and Dynamically 1395 | | Dynamic allocations allocated and 1396 | | (alloca, variable deallocated 1397 Stack | length arrays). 1398 grows +-------------------- Fp(x) 1399 down| | Local variables of X 1400 ward| +-------------------- 1401 | | Regs saved for X-1 1402 | +==================== Sp(x-1)=Ap(x) 1403 | Args for func X 1404 | pushed by X-1 1405 +-------------------- Fp(x-1) 1406 | 1407 | 1408 V 1409 1410*/ 1411 1412void 1413crx_expand_prologue (void) 1414{ 1415 crx_compute_frame (); 1416 crx_compute_save_regs (); 1417 1418 /* If there is no need in push and adjustment to sp, return. */ 1419 if (size_for_adjusting_sp + sum_regs == 0) 1420 return; 1421 1422 if (last_reg_to_save != -1) 1423 /* If there are registers to push. */ 1424 emit_insn (gen_push_for_prologue (GEN_INT (sum_regs))); 1425 1426 if (size_for_adjusting_sp > 0) 1427 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, 1428 GEN_INT (-size_for_adjusting_sp))); 1429 1430 if (frame_pointer_needed) 1431 /* Initialize the frame pointer with the value of the stack pointer 1432 * pointing now to the locals. */ 1433 emit_move_insn (frame_pointer_rtx, stack_pointer_rtx); 1434} 1435 1436/* Generate insn that updates the stack for local variables and padding for 1437 * registers we save. - Generate the appropriate return insn. */ 1438 1439void 1440crx_expand_epilogue (void) 1441{ 1442 rtx return_reg; 1443 1444 /* Nonzero if we need to return and pop only RA. This will generate a 1445 * different insn. This differentiate is for the peepholes for call as last 1446 * statement in function. */ 1447 int only_popret_RA = (save_regs[RETURN_ADDRESS_REGNUM] 1448 && (sum_regs == UNITS_PER_WORD)); 1449 1450 /* Return register. */ 1451 return_reg = gen_rtx_REG (Pmode, RETURN_ADDRESS_REGNUM); 1452 1453 if (frame_pointer_needed) 1454 /* Restore the stack pointer with the frame pointers value */ 1455 emit_move_insn (stack_pointer_rtx, frame_pointer_rtx); 1456 1457 if (size_for_adjusting_sp > 0) 1458 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, 1459 GEN_INT (size_for_adjusting_sp))); 1460 1461 if (crx_interrupt_function_p ()) 1462 emit_jump_insn (gen_interrupt_return ()); 1463 else if (last_reg_to_save == -1) 1464 /* Nothing to pop */ 1465 /* Don't output jump for interrupt routine, only retx. */ 1466 emit_jump_insn (gen_indirect_jump_return ()); 1467 else if (only_popret_RA) 1468 emit_jump_insn (gen_popret_RA_return ()); 1469 else 1470 emit_jump_insn (gen_pop_and_popret_return (GEN_INT (sum_regs))); 1471} 1472 1473