1/* Definitions of target machine for GNU compiler, for MMIX. 2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 3 Free Software Foundation, Inc. 4 Contributed by Hans-Peter Nilsson (hp@bitrange.com) 5 6This file is part of GCC. 7 8GCC is free software; you can redistribute it and/or modify 9it under the terms of the GNU General Public License as published by 10the Free Software Foundation; either version 3, or (at your option) 11any later version. 12 13GCC is distributed in the hope that it will be useful, 14but WITHOUT ANY WARRANTY; without even the implied warranty of 15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16GNU General Public License for more details. 17 18You should have received a copy of the GNU General Public License 19along with GCC; see the file COPYING3. If not see 20<http://www.gnu.org/licenses/>. */ 21 22#include "config.h" 23#include "system.h" 24#include "coretypes.h" 25#include "tm.h" 26#include "rtl.h" 27#include "regs.h" 28#include "hard-reg-set.h" 29#include "hashtab.h" 30#include "insn-config.h" 31#include "output.h" 32#include "flags.h" 33#include "tree.h" 34#include "function.h" 35#include "expr.h" 36#include "toplev.h" 37#include "recog.h" 38#include "ggc.h" 39#include "dwarf2.h" 40#include "debug.h" 41#include "tm_p.h" 42#include "integrate.h" 43#include "target.h" 44#include "target-def.h" 45#include "real.h" 46 47/* First some local helper definitions. */ 48#define MMIX_FIRST_GLOBAL_REGNUM 32 49 50/* We'd need a current_function_has_landing_pad. It's marked as such when 51 a nonlocal_goto_receiver is expanded. Not just a C++ thing, but 52 mostly. */ 53#define MMIX_CFUN_HAS_LANDING_PAD (cfun->machine->has_landing_pad != 0) 54 55/* We have no means to tell DWARF 2 about the register stack, so we need 56 to store the return address on the stack if an exception can get into 57 this function. FIXME: Narrow condition. Before any whole-function 58 analysis, df_regs_ever_live_p () isn't initialized. We know it's up-to-date 59 after reload_completed; it may contain incorrect information some time 60 before that. Within a RTL sequence (after a call to start_sequence, 61 such as in RTL expanders), leaf_function_p doesn't see all insns 62 (perhaps any insn). But regs_ever_live is up-to-date when 63 leaf_function_p () isn't, so we "or" them together to get accurate 64 information. FIXME: Some tweak to leaf_function_p might be 65 preferable. */ 66#define MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS \ 67 (flag_exceptions \ 68 && ((reload_completed && df_regs_ever_live_p (MMIX_rJ_REGNUM)) \ 69 || !leaf_function_p ())) 70 71#define IS_MMIX_EH_RETURN_DATA_REG(REGNO) \ 72 (crtl->calls_eh_return \ 73 && (EH_RETURN_DATA_REGNO (0) == REGNO \ 74 || EH_RETURN_DATA_REGNO (1) == REGNO \ 75 || EH_RETURN_DATA_REGNO (2) == REGNO \ 76 || EH_RETURN_DATA_REGNO (3) == REGNO)) 77 78/* For the default ABI, we rename registers at output-time to fill the gap 79 between the (statically partitioned) saved registers and call-clobbered 80 registers. In effect this makes unused call-saved registers to be used 81 as call-clobbered registers. The benefit comes from keeping the number 82 of local registers (value of rL) low, since there's a cost of 83 increasing rL and clearing unused (unset) registers with lower numbers. 84 Don't translate while outputting the prologue. */ 85#define MMIX_OUTPUT_REGNO(N) \ 86 (TARGET_ABI_GNU \ 87 || (int) (N) < MMIX_RETURN_VALUE_REGNUM \ 88 || (int) (N) > MMIX_LAST_STACK_REGISTER_REGNUM \ 89 || cfun == NULL \ 90 || cfun->machine == NULL \ 91 || cfun->machine->in_prologue \ 92 ? (N) : ((N) - MMIX_RETURN_VALUE_REGNUM \ 93 + cfun->machine->highest_saved_stack_register + 1)) 94 95/* The %d in "POP %d,0". */ 96#define MMIX_POP_ARGUMENT() \ 97 ((! TARGET_ABI_GNU \ 98 && crtl->return_rtx != NULL \ 99 && ! cfun->returns_struct) \ 100 ? (GET_CODE (crtl->return_rtx) == PARALLEL \ 101 ? GET_NUM_ELEM (XVEC (crtl->return_rtx, 0)) : 1) \ 102 : 0) 103 104/* The canonical saved comparison operands for non-cc0 machines, set in 105 the compare expander. */ 106rtx mmix_compare_op0; 107rtx mmix_compare_op1; 108 109/* Declarations of locals. */ 110 111/* Intermediate for insn output. */ 112static int mmix_output_destination_register; 113 114static void mmix_output_shiftvalue_op_from_str 115 (FILE *, const char *, HOST_WIDEST_INT); 116static void mmix_output_shifted_value (FILE *, HOST_WIDEST_INT); 117static void mmix_output_condition (FILE *, rtx, int); 118static HOST_WIDEST_INT mmix_intval (rtx); 119static void mmix_output_octa (FILE *, HOST_WIDEST_INT, int); 120static bool mmix_assemble_integer (rtx, unsigned int, int); 121static struct machine_function *mmix_init_machine_status (void); 122static void mmix_encode_section_info (tree, rtx, int); 123static const char *mmix_strip_name_encoding (const char *); 124static void mmix_emit_sp_add (HOST_WIDE_INT offset); 125static void mmix_target_asm_function_prologue (FILE *, HOST_WIDE_INT); 126static void mmix_target_asm_function_end_prologue (FILE *); 127static void mmix_target_asm_function_epilogue (FILE *, HOST_WIDE_INT); 128static bool mmix_legitimate_address_p (enum machine_mode, rtx, bool); 129static void mmix_reorg (void); 130static void mmix_asm_output_mi_thunk 131 (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree); 132static void mmix_setup_incoming_varargs 133 (CUMULATIVE_ARGS *, enum machine_mode, tree, int *, int); 134static void mmix_file_start (void); 135static void mmix_file_end (void); 136static bool mmix_rtx_costs (rtx, int, int, int *, bool); 137static rtx mmix_struct_value_rtx (tree, int); 138static enum machine_mode mmix_promote_function_mode (const_tree, 139 enum machine_mode, 140 int *, const_tree, int); 141static bool mmix_pass_by_reference (CUMULATIVE_ARGS *, 142 enum machine_mode, const_tree, bool); 143static bool mmix_frame_pointer_required (void); 144static void mmix_asm_trampoline_template (FILE *); 145static void mmix_trampoline_init (rtx, tree, rtx); 146 147/* Target structure macros. Listed by node. See `Using and Porting GCC' 148 for a general description. */ 149 150/* Node: Function Entry */ 151 152#undef TARGET_ASM_BYTE_OP 153#define TARGET_ASM_BYTE_OP NULL 154#undef TARGET_ASM_ALIGNED_HI_OP 155#define TARGET_ASM_ALIGNED_HI_OP NULL 156#undef TARGET_ASM_ALIGNED_SI_OP 157#define TARGET_ASM_ALIGNED_SI_OP NULL 158#undef TARGET_ASM_ALIGNED_DI_OP 159#define TARGET_ASM_ALIGNED_DI_OP NULL 160#undef TARGET_ASM_INTEGER 161#define TARGET_ASM_INTEGER mmix_assemble_integer 162 163#undef TARGET_ASM_FUNCTION_PROLOGUE 164#define TARGET_ASM_FUNCTION_PROLOGUE mmix_target_asm_function_prologue 165 166#undef TARGET_ASM_FUNCTION_END_PROLOGUE 167#define TARGET_ASM_FUNCTION_END_PROLOGUE mmix_target_asm_function_end_prologue 168 169#undef TARGET_ASM_FUNCTION_EPILOGUE 170#define TARGET_ASM_FUNCTION_EPILOGUE mmix_target_asm_function_epilogue 171 172#undef TARGET_ENCODE_SECTION_INFO 173#define TARGET_ENCODE_SECTION_INFO mmix_encode_section_info 174#undef TARGET_STRIP_NAME_ENCODING 175#define TARGET_STRIP_NAME_ENCODING mmix_strip_name_encoding 176 177#undef TARGET_ASM_OUTPUT_MI_THUNK 178#define TARGET_ASM_OUTPUT_MI_THUNK mmix_asm_output_mi_thunk 179#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK 180#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall 181#undef TARGET_ASM_FILE_START 182#define TARGET_ASM_FILE_START mmix_file_start 183#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE 184#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true 185#undef TARGET_ASM_FILE_END 186#define TARGET_ASM_FILE_END mmix_file_end 187 188#undef TARGET_RTX_COSTS 189#define TARGET_RTX_COSTS mmix_rtx_costs 190#undef TARGET_ADDRESS_COST 191#define TARGET_ADDRESS_COST hook_int_rtx_bool_0 192 193#undef TARGET_MACHINE_DEPENDENT_REORG 194#define TARGET_MACHINE_DEPENDENT_REORG mmix_reorg 195 196#undef TARGET_PROMOTE_FUNCTION_MODE 197#define TARGET_PROMOTE_FUNCTION_MODE mmix_promote_function_mode 198 199 200#undef TARGET_STRUCT_VALUE_RTX 201#define TARGET_STRUCT_VALUE_RTX mmix_struct_value_rtx 202#undef TARGET_SETUP_INCOMING_VARARGS 203#define TARGET_SETUP_INCOMING_VARARGS mmix_setup_incoming_varargs 204#undef TARGET_PASS_BY_REFERENCE 205#define TARGET_PASS_BY_REFERENCE mmix_pass_by_reference 206#undef TARGET_CALLEE_COPIES 207#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true 208#undef TARGET_DEFAULT_TARGET_FLAGS 209#define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT 210 211#undef TARGET_LEGITIMATE_ADDRESS_P 212#define TARGET_LEGITIMATE_ADDRESS_P mmix_legitimate_address_p 213 214#undef TARGET_FRAME_POINTER_REQUIRED 215#define TARGET_FRAME_POINTER_REQUIRED mmix_frame_pointer_required 216 217#undef TARGET_ASM_TRAMPOLINE_TEMPLATE 218#define TARGET_ASM_TRAMPOLINE_TEMPLATE mmix_asm_trampoline_template 219#undef TARGET_TRAMPOLINE_INIT 220#define TARGET_TRAMPOLINE_INIT mmix_trampoline_init 221 222struct gcc_target targetm = TARGET_INITIALIZER; 223 224/* Functions that are expansions for target macros. 225 See Target Macros in `Using and Porting GCC'. */ 226 227/* OVERRIDE_OPTIONS. */ 228 229void 230mmix_override_options (void) 231{ 232 /* Should we err or should we warn? Hmm. At least we must neutralize 233 it. For example the wrong kind of case-tables will be generated with 234 PIC; we use absolute address items for mmixal compatibility. FIXME: 235 They could be relative if we just elide them to after all pertinent 236 labels. */ 237 if (flag_pic) 238 { 239 warning (0, "-f%s not supported: ignored", (flag_pic > 1) ? "PIC" : "pic"); 240 flag_pic = 0; 241 } 242} 243 244/* INIT_EXPANDERS. */ 245 246void 247mmix_init_expanders (void) 248{ 249 init_machine_status = mmix_init_machine_status; 250} 251 252/* Set the per-function data. */ 253 254static struct machine_function * 255mmix_init_machine_status (void) 256{ 257 return GGC_CNEW (struct machine_function); 258} 259 260/* DATA_ALIGNMENT. 261 We have trouble getting the address of stuff that is located at other 262 than 32-bit alignments (GETA requirements), so try to give everything 263 at least 32-bit alignment. */ 264 265int 266mmix_data_alignment (tree type ATTRIBUTE_UNUSED, int basic_align) 267{ 268 if (basic_align < 32) 269 return 32; 270 271 return basic_align; 272} 273 274/* CONSTANT_ALIGNMENT. */ 275 276int 277mmix_constant_alignment (tree constant ATTRIBUTE_UNUSED, int basic_align) 278{ 279 if (basic_align < 32) 280 return 32; 281 282 return basic_align; 283} 284 285/* LOCAL_ALIGNMENT. */ 286 287int 288mmix_local_alignment (tree type ATTRIBUTE_UNUSED, int basic_align) 289{ 290 if (basic_align < 32) 291 return 32; 292 293 return basic_align; 294} 295 296/* CONDITIONAL_REGISTER_USAGE. */ 297 298void 299mmix_conditional_register_usage (void) 300{ 301 int i; 302 303 if (TARGET_ABI_GNU) 304 { 305 static const int gnu_abi_reg_alloc_order[] 306 = MMIX_GNU_ABI_REG_ALLOC_ORDER; 307 308 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 309 reg_alloc_order[i] = gnu_abi_reg_alloc_order[i]; 310 311 /* Change the default from the mmixware ABI. For the GNU ABI, 312 $15..$30 are call-saved just as $0..$14. There must be one 313 call-clobbered local register for the "hole" that holds the 314 number of saved local registers saved by PUSHJ/PUSHGO during the 315 function call, receiving the return value at return. So best is 316 to use the highest, $31. It's already marked call-clobbered for 317 the mmixware ABI. */ 318 for (i = 15; i <= 30; i++) 319 call_used_regs[i] = 0; 320 321 /* "Unfix" the parameter registers. */ 322 for (i = MMIX_RESERVED_GNU_ARG_0_REGNUM; 323 i < MMIX_RESERVED_GNU_ARG_0_REGNUM + MMIX_MAX_ARGS_IN_REGS; 324 i++) 325 fixed_regs[i] = 0; 326 } 327 328 /* Step over the ":" in special register names. */ 329 if (! TARGET_TOPLEVEL_SYMBOLS) 330 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 331 if (reg_names[i][0] == ':') 332 reg_names[i]++; 333} 334 335/* INCOMING_REGNO and OUTGOING_REGNO worker function. 336 Those two macros must only be applied to function argument 337 registers. FIXME: for their current use in gcc, it'd be better 338 with an explicit specific additional FUNCTION_INCOMING_ARG_REGNO_P 339 a'la FUNCTION_ARG / FUNCTION_INCOMING_ARG instead of forcing the 340 target to commit to a fixed mapping and for any unspecified 341 register use. */ 342 343int 344mmix_opposite_regno (int regno, int incoming) 345{ 346 if (!mmix_function_arg_regno_p (regno, incoming)) 347 return regno; 348 349 return 350 regno - (incoming 351 ? MMIX_FIRST_INCOMING_ARG_REGNUM - MMIX_FIRST_ARG_REGNUM 352 : MMIX_FIRST_ARG_REGNUM - MMIX_FIRST_INCOMING_ARG_REGNUM); 353} 354 355/* LOCAL_REGNO. 356 All registers that are part of the register stack and that will be 357 saved are local. */ 358 359int 360mmix_local_regno (int regno) 361{ 362 return regno <= MMIX_LAST_STACK_REGISTER_REGNUM && !call_used_regs[regno]; 363} 364 365/* PREFERRED_RELOAD_CLASS. 366 We need to extend the reload class of REMAINDER_REG and HIMULT_REG. */ 367 368enum reg_class 369mmix_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, enum reg_class rclass) 370{ 371 /* FIXME: Revisit. */ 372 return GET_CODE (x) == MOD && GET_MODE (x) == DImode 373 ? REMAINDER_REG : rclass; 374} 375 376/* PREFERRED_OUTPUT_RELOAD_CLASS. 377 We need to extend the reload class of REMAINDER_REG and HIMULT_REG. */ 378 379enum reg_class 380mmix_preferred_output_reload_class (rtx x ATTRIBUTE_UNUSED, 381 enum reg_class rclass) 382{ 383 /* FIXME: Revisit. */ 384 return GET_CODE (x) == MOD && GET_MODE (x) == DImode 385 ? REMAINDER_REG : rclass; 386} 387 388/* SECONDARY_RELOAD_CLASS. 389 We need to reload regs of REMAINDER_REG and HIMULT_REG elsewhere. */ 390 391enum reg_class 392mmix_secondary_reload_class (enum reg_class rclass, 393 enum machine_mode mode ATTRIBUTE_UNUSED, 394 rtx x ATTRIBUTE_UNUSED, 395 int in_p ATTRIBUTE_UNUSED) 396{ 397 if (rclass == REMAINDER_REG 398 || rclass == HIMULT_REG 399 || rclass == SYSTEM_REGS) 400 return GENERAL_REGS; 401 402 return NO_REGS; 403} 404 405/* CONST_OK_FOR_LETTER_P. */ 406 407int 408mmix_const_ok_for_letter_p (HOST_WIDE_INT value, int c) 409{ 410 return 411 (c == 'I' ? value >= 0 && value <= 255 412 : c == 'J' ? value >= 0 && value <= 65535 413 : c == 'K' ? value <= 0 && value >= -255 414 : c == 'L' ? mmix_shiftable_wyde_value (value) 415 : c == 'M' ? value == 0 416 : c == 'N' ? mmix_shiftable_wyde_value (~value) 417 : c == 'O' ? (value == 3 || value == 5 || value == 9 418 || value == 17) 419 : 0); 420} 421 422/* CONST_DOUBLE_OK_FOR_LETTER_P. */ 423 424int 425mmix_const_double_ok_for_letter_p (rtx value, int c) 426{ 427 return 428 (c == 'G' ? value == CONST0_RTX (GET_MODE (value)) 429 : 0); 430} 431 432/* EXTRA_CONSTRAINT. 433 We need this since our constants are not always expressible as 434 CONST_INT:s, but rather often as CONST_DOUBLE:s. */ 435 436int 437mmix_extra_constraint (rtx x, int c, int strict) 438{ 439 HOST_WIDEST_INT value; 440 441 /* When checking for an address, we need to handle strict vs. non-strict 442 register checks. Don't use address_operand, but instead its 443 equivalent (its callee, which it is just a wrapper for), 444 memory_operand_p and the strict-equivalent strict_memory_address_p. */ 445 if (c == 'U') 446 return 447 strict 448 ? strict_memory_address_p (Pmode, x) 449 : memory_address_p (Pmode, x); 450 451 /* R asks whether x is to be loaded with GETA or something else. Right 452 now, only a SYMBOL_REF and LABEL_REF can fit for 453 TARGET_BASE_ADDRESSES. 454 455 Only constant symbolic addresses apply. With TARGET_BASE_ADDRESSES, 456 we just allow straight LABEL_REF or SYMBOL_REFs with SYMBOL_REF_FLAG 457 set right now; only function addresses and code labels. If we change 458 to let SYMBOL_REF_FLAG be set on other symbols, we have to check 459 inside CONST expressions. When TARGET_BASE_ADDRESSES is not in 460 effect, a "raw" constant check together with mmix_constant_address_p 461 is all that's needed; we want all constant addresses to be loaded 462 with GETA then. */ 463 if (c == 'R') 464 return 465 GET_CODE (x) != CONST_INT && GET_CODE (x) != CONST_DOUBLE 466 && mmix_constant_address_p (x) 467 && (! TARGET_BASE_ADDRESSES 468 || (GET_CODE (x) == LABEL_REF 469 || (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FLAG (x)))); 470 471 if (GET_CODE (x) != CONST_DOUBLE || GET_MODE (x) != VOIDmode) 472 return 0; 473 474 value = mmix_intval (x); 475 476 /* We used to map Q->J, R->K, S->L, T->N, U->O, but we don't have to any 477 more ('U' taken for address_operand, 'R' similarly). Some letters map 478 outside of CONST_INT, though; we still use 'S' and 'T'. */ 479 if (c == 'S') 480 return mmix_shiftable_wyde_value (value); 481 else if (c == 'T') 482 return mmix_shiftable_wyde_value (~value); 483 return 0; 484} 485 486/* DYNAMIC_CHAIN_ADDRESS. */ 487 488rtx 489mmix_dynamic_chain_address (rtx frame) 490{ 491 /* FIXME: the frame-pointer is stored at offset -8 from the current 492 frame-pointer. Unfortunately, the caller assumes that a 493 frame-pointer is present for *all* previous frames. There should be 494 a way to say that that cannot be done, like for RETURN_ADDR_RTX. */ 495 return plus_constant (frame, -8); 496} 497 498/* STARTING_FRAME_OFFSET. */ 499 500int 501mmix_starting_frame_offset (void) 502{ 503 /* The old frame pointer is in the slot below the new one, so 504 FIRST_PARM_OFFSET does not need to depend on whether the 505 frame-pointer is needed or not. We have to adjust for the register 506 stack pointer being located below the saved frame pointer. 507 Similarly, we store the return address on the stack too, for 508 exception handling, and always if we save the register stack pointer. */ 509 return 510 (-8 511 + (MMIX_CFUN_HAS_LANDING_PAD 512 ? -16 : (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS ? -8 : 0))); 513} 514 515/* RETURN_ADDR_RTX. */ 516 517rtx 518mmix_return_addr_rtx (int count, rtx frame ATTRIBUTE_UNUSED) 519{ 520 return count == 0 521 ? (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS 522 /* FIXME: Set frame_alias_set on the following. (Why?) 523 See mmix_initial_elimination_offset for the reason we can't use 524 get_hard_reg_initial_val for both. Always using a stack slot 525 and not a register would be suboptimal. */ 526 ? validize_mem (gen_rtx_MEM (Pmode, plus_constant (frame_pointer_rtx, -16))) 527 : get_hard_reg_initial_val (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM)) 528 : NULL_RTX; 529} 530 531/* SETUP_FRAME_ADDRESSES. */ 532 533void 534mmix_setup_frame_addresses (void) 535{ 536 /* Nothing needed at the moment. */ 537} 538 539/* The difference between the (imaginary) frame pointer and the stack 540 pointer. Used to eliminate the frame pointer. */ 541 542int 543mmix_initial_elimination_offset (int fromreg, int toreg) 544{ 545 int regno; 546 int fp_sp_offset 547 = (get_frame_size () + crtl->outgoing_args_size + 7) & ~7; 548 549 /* There is no actual offset between these two virtual values, but for 550 the frame-pointer, we have the old one in the stack position below 551 it, so the offset for the frame-pointer to the stack-pointer is one 552 octabyte larger. */ 553 if (fromreg == MMIX_ARG_POINTER_REGNUM 554 && toreg == MMIX_FRAME_POINTER_REGNUM) 555 return 0; 556 557 /* The difference is the size of local variables plus the size of 558 outgoing function arguments that would normally be passed as 559 registers but must be passed on stack because we're out of 560 function-argument registers. Only global saved registers are 561 counted; the others go on the register stack. 562 563 The frame-pointer is counted too if it is what is eliminated, as we 564 need to balance the offset for it from STARTING_FRAME_OFFSET. 565 566 Also add in the slot for the register stack pointer we save if we 567 have a landing pad. 568 569 Unfortunately, we can't access $0..$14, from unwinder code easily, so 570 store the return address in a frame slot too. FIXME: Only for 571 non-leaf functions. FIXME: Always with a landing pad, because it's 572 hard to know whether we need the other at the time we know we need 573 the offset for one (and have to state it). It's a kludge until we 574 can express the register stack in the EH frame info. 575 576 We have to do alignment here; get_frame_size will not return a 577 multiple of STACK_BOUNDARY. FIXME: Add note in manual. */ 578 579 for (regno = MMIX_FIRST_GLOBAL_REGNUM; 580 regno <= 255; 581 regno++) 582 if ((df_regs_ever_live_p (regno) && ! call_used_regs[regno]) 583 || IS_MMIX_EH_RETURN_DATA_REG (regno)) 584 fp_sp_offset += 8; 585 586 return fp_sp_offset 587 + (MMIX_CFUN_HAS_LANDING_PAD 588 ? 16 : (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS ? 8 : 0)) 589 + (fromreg == MMIX_ARG_POINTER_REGNUM ? 0 : 8); 590} 591 592/* Return an rtx for a function argument to go in a register, and 0 for 593 one that must go on stack. */ 594 595rtx 596mmix_function_arg (const CUMULATIVE_ARGS *argsp, 597 enum machine_mode mode, 598 tree type, 599 int named ATTRIBUTE_UNUSED, 600 int incoming) 601{ 602 /* Last-argument marker. */ 603 if (type == void_type_node) 604 return (argsp->regs < MMIX_MAX_ARGS_IN_REGS) 605 ? gen_rtx_REG (mode, 606 (incoming 607 ? MMIX_FIRST_INCOMING_ARG_REGNUM 608 : MMIX_FIRST_ARG_REGNUM) + argsp->regs) 609 : NULL_RTX; 610 611 return (argsp->regs < MMIX_MAX_ARGS_IN_REGS 612 && !targetm.calls.must_pass_in_stack (mode, type) 613 && (GET_MODE_BITSIZE (mode) <= 64 614 || argsp->lib 615 || TARGET_LIBFUNC)) 616 ? gen_rtx_REG (mode, 617 (incoming 618 ? MMIX_FIRST_INCOMING_ARG_REGNUM 619 : MMIX_FIRST_ARG_REGNUM) 620 + argsp->regs) 621 : NULL_RTX; 622} 623 624/* Returns nonzero for everything that goes by reference, 0 for 625 everything that goes by value. */ 626 627static bool 628mmix_pass_by_reference (CUMULATIVE_ARGS *argsp, enum machine_mode mode, 629 const_tree type, bool named ATTRIBUTE_UNUSED) 630{ 631 /* FIXME: Check: I'm not sure the must_pass_in_stack check is 632 necessary. */ 633 if (targetm.calls.must_pass_in_stack (mode, type)) 634 return true; 635 636 if (MMIX_FUNCTION_ARG_SIZE (mode, type) > 8 637 && !TARGET_LIBFUNC 638 && (!argsp || !argsp->lib)) 639 return true; 640 641 return false; 642} 643 644/* Return nonzero if regno is a register number where a parameter is 645 passed, and 0 otherwise. */ 646 647int 648mmix_function_arg_regno_p (int regno, int incoming) 649{ 650 int first_arg_regnum 651 = incoming ? MMIX_FIRST_INCOMING_ARG_REGNUM : MMIX_FIRST_ARG_REGNUM; 652 653 return regno >= first_arg_regnum 654 && regno < first_arg_regnum + MMIX_MAX_ARGS_IN_REGS; 655} 656 657/* FUNCTION_OUTGOING_VALUE. */ 658 659rtx 660mmix_function_outgoing_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED) 661{ 662 enum machine_mode mode = TYPE_MODE (valtype); 663 enum machine_mode cmode; 664 int first_val_regnum = MMIX_OUTGOING_RETURN_VALUE_REGNUM; 665 rtx vec[MMIX_MAX_REGS_FOR_VALUE]; 666 int i; 667 int nregs; 668 669 /* Return values that fit in a register need no special handling. 670 There's no register hole when parameters are passed in global 671 registers. */ 672 if (TARGET_ABI_GNU 673 || GET_MODE_BITSIZE (mode) <= BITS_PER_WORD) 674 return 675 gen_rtx_REG (mode, MMIX_OUTGOING_RETURN_VALUE_REGNUM); 676 677 if (COMPLEX_MODE_P (mode)) 678 /* A complex type, made up of components. */ 679 cmode = TYPE_MODE (TREE_TYPE (valtype)); 680 else 681 { 682 /* Of the other larger-than-register modes, we only support 683 scalar mode TImode. (At least, that's the only one that's 684 been rudimentally tested.) Make sure we're alerted for 685 unexpected cases. */ 686 if (mode != TImode) 687 sorry ("support for mode %qs", GET_MODE_NAME (mode)); 688 689 /* In any case, we will fill registers to the natural size. */ 690 cmode = DImode; 691 } 692 693 nregs = ((GET_MODE_BITSIZE (mode) + BITS_PER_WORD - 1) / BITS_PER_WORD); 694 695 /* We need to take care of the effect of the register hole on return 696 values of large sizes; the last register will appear as the first 697 register, with the rest shifted. (For complex modes, this is just 698 swapped registers.) */ 699 700 if (nregs > MMIX_MAX_REGS_FOR_VALUE) 701 internal_error ("too large function value type, needs %d registers,\ 702 have only %d registers for this", nregs, MMIX_MAX_REGS_FOR_VALUE); 703 704 /* FIXME: Maybe we should handle structure values like this too 705 (adjusted for BLKmode), perhaps for both ABI:s. */ 706 for (i = 0; i < nregs - 1; i++) 707 vec[i] 708 = gen_rtx_EXPR_LIST (VOIDmode, 709 gen_rtx_REG (cmode, first_val_regnum + i), 710 GEN_INT ((i + 1) * BITS_PER_UNIT)); 711 712 vec[nregs - 1] 713 = gen_rtx_EXPR_LIST (VOIDmode, 714 gen_rtx_REG (cmode, first_val_regnum + nregs - 1), 715 const0_rtx); 716 717 return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nregs, vec)); 718} 719 720/* FUNCTION_VALUE_REGNO_P. */ 721 722int 723mmix_function_value_regno_p (int regno) 724{ 725 return regno == MMIX_RETURN_VALUE_REGNUM; 726} 727 728/* EH_RETURN_DATA_REGNO. */ 729 730int 731mmix_eh_return_data_regno (int n) 732{ 733 if (n >= 0 && n < 4) 734 return MMIX_EH_RETURN_DATA_REGNO_START + n; 735 736 return INVALID_REGNUM; 737} 738 739/* EH_RETURN_STACKADJ_RTX. */ 740 741rtx 742mmix_eh_return_stackadj_rtx (void) 743{ 744 return gen_rtx_REG (Pmode, MMIX_EH_RETURN_STACKADJ_REGNUM); 745} 746 747/* EH_RETURN_HANDLER_RTX. */ 748 749rtx 750mmix_eh_return_handler_rtx (void) 751{ 752 return gen_rtx_REG (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM); 753} 754 755/* ASM_PREFERRED_EH_DATA_FORMAT. */ 756 757int 758mmix_asm_preferred_eh_data_format (int code ATTRIBUTE_UNUSED, 759 int global ATTRIBUTE_UNUSED) 760{ 761 /* This is the default (was at 2001-07-20). Revisit when needed. */ 762 return DW_EH_PE_absptr; 763} 764 765/* Make a note that we've seen the beginning of the prologue. This 766 matters to whether we'll translate register numbers as calculated by 767 mmix_reorg. */ 768 769static void 770mmix_target_asm_function_prologue (FILE *stream ATTRIBUTE_UNUSED, 771 HOST_WIDE_INT framesize ATTRIBUTE_UNUSED) 772{ 773 cfun->machine->in_prologue = 1; 774} 775 776/* Make a note that we've seen the end of the prologue. */ 777 778static void 779mmix_target_asm_function_end_prologue (FILE *stream ATTRIBUTE_UNUSED) 780{ 781 cfun->machine->in_prologue = 0; 782} 783 784/* Implement TARGET_MACHINE_DEPENDENT_REORG. No actual rearrangements 785 done here; just virtually by calculating the highest saved stack 786 register number used to modify the register numbers at output time. */ 787 788static void 789mmix_reorg (void) 790{ 791 int regno; 792 793 /* We put the number of the highest saved register-file register in a 794 location convenient for the call-patterns to output. Note that we 795 don't tell dwarf2 about these registers, since it can't restore them 796 anyway. */ 797 for (regno = MMIX_LAST_STACK_REGISTER_REGNUM; 798 regno >= 0; 799 regno--) 800 if ((df_regs_ever_live_p (regno) && !call_used_regs[regno]) 801 || (regno == MMIX_FRAME_POINTER_REGNUM && frame_pointer_needed)) 802 break; 803 804 /* Regardless of whether they're saved (they might be just read), we 805 mustn't include registers that carry parameters. We could scan the 806 insns to see whether they're actually used (and indeed do other less 807 trivial register usage analysis and transformations), but it seems 808 wasteful to optimize for unused parameter registers. As of 809 2002-04-30, df_regs_ever_live_p (n) seems to be set for only-reads too, but 810 that might change. */ 811 if (!TARGET_ABI_GNU && regno < crtl->args.info.regs - 1) 812 { 813 regno = crtl->args.info.regs - 1; 814 815 /* We don't want to let this cause us to go over the limit and make 816 incoming parameter registers be misnumbered and treating the last 817 parameter register and incoming return value register call-saved. 818 Stop things at the unmodified scheme. */ 819 if (regno > MMIX_RETURN_VALUE_REGNUM - 1) 820 regno = MMIX_RETURN_VALUE_REGNUM - 1; 821 } 822 823 cfun->machine->highest_saved_stack_register = regno; 824} 825 826/* TARGET_ASM_FUNCTION_EPILOGUE. */ 827 828static void 829mmix_target_asm_function_epilogue (FILE *stream, 830 HOST_WIDE_INT locals_size ATTRIBUTE_UNUSED) 831{ 832 /* Emit an \n for readability of the generated assembly. */ 833 fputc ('\n', stream); 834} 835 836/* TARGET_ASM_OUTPUT_MI_THUNK. */ 837 838static void 839mmix_asm_output_mi_thunk (FILE *stream, 840 tree fndecl ATTRIBUTE_UNUSED, 841 HOST_WIDE_INT delta, 842 HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED, 843 tree func) 844{ 845 /* If you define TARGET_STRUCT_VALUE_RTX that returns 0 (i.e. pass 846 location of structure to return as invisible first argument), you 847 need to tweak this code too. */ 848 const char *regname = reg_names[MMIX_FIRST_INCOMING_ARG_REGNUM]; 849 850 if (delta >= 0 && delta < 65536) 851 fprintf (stream, "\tINCL %s,%d\n", regname, (int)delta); 852 else if (delta < 0 && delta >= -255) 853 fprintf (stream, "\tSUBU %s,%s,%d\n", regname, regname, (int)-delta); 854 else 855 { 856 mmix_output_register_setting (stream, 255, delta, 1); 857 fprintf (stream, "\tADDU %s,%s,$255\n", regname, regname); 858 } 859 860 fprintf (stream, "\tJMP "); 861 assemble_name (stream, XSTR (XEXP (DECL_RTL (func), 0), 0)); 862 fprintf (stream, "\n"); 863} 864 865/* FUNCTION_PROFILER. */ 866 867void 868mmix_function_profiler (FILE *stream ATTRIBUTE_UNUSED, 869 int labelno ATTRIBUTE_UNUSED) 870{ 871 sorry ("function_profiler support for MMIX"); 872} 873 874/* Worker function for TARGET_SETUP_INCOMING_VARARGS. For the moment, 875 let's stick to pushing argument registers on the stack. Later, we 876 can parse all arguments in registers, to improve performance. */ 877 878static void 879mmix_setup_incoming_varargs (CUMULATIVE_ARGS *args_so_farp, 880 enum machine_mode mode, 881 tree vartype, 882 int *pretend_sizep, 883 int second_time ATTRIBUTE_UNUSED) 884{ 885 /* The last named variable has been handled, but 886 args_so_farp has not been advanced for it. */ 887 if (args_so_farp->regs + 1 < MMIX_MAX_ARGS_IN_REGS) 888 *pretend_sizep = (MMIX_MAX_ARGS_IN_REGS - (args_so_farp->regs + 1)) * 8; 889 890 /* We assume that one argument takes up one register here. That should 891 be true until we start messing with multi-reg parameters. */ 892 if ((7 + (MMIX_FUNCTION_ARG_SIZE (mode, vartype))) / 8 != 1) 893 internal_error ("MMIX Internal: Last named vararg would not fit in a register"); 894} 895 896/* TARGET_ASM_TRAMPOLINE_TEMPLATE. */ 897 898static void 899mmix_asm_trampoline_template (FILE *stream) 900{ 901 /* Read a value into the static-chain register and jump somewhere. The 902 static chain is stored at offset 16, and the function address is 903 stored at offset 24. */ 904 905 fprintf (stream, "\tGETA $255,1F\n\t"); 906 fprintf (stream, "LDOU %s,$255,0\n\t", reg_names[MMIX_STATIC_CHAIN_REGNUM]); 907 fprintf (stream, "LDOU $255,$255,8\n\t"); 908 fprintf (stream, "GO $255,$255,0\n"); 909 fprintf (stream, "1H\tOCTA 0\n\t"); 910 fprintf (stream, "OCTA 0\n"); 911} 912 913/* TARGET_TRAMPOLINE_INIT. */ 914/* Set the static chain and function pointer field in the trampoline. 915 We also SYNCID here to be sure (doesn't matter in the simulator, but 916 some day it will). */ 917 918static void 919mmix_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain) 920{ 921 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0); 922 rtx mem; 923 924 emit_block_move (m_tramp, assemble_trampoline_template (), 925 GEN_INT (2*UNITS_PER_WORD), BLOCK_OP_NORMAL); 926 927 mem = adjust_address (m_tramp, DImode, 2*UNITS_PER_WORD); 928 emit_move_insn (mem, static_chain); 929 mem = adjust_address (m_tramp, DImode, 3*UNITS_PER_WORD); 930 emit_move_insn (mem, fnaddr); 931 932 mem = adjust_address (m_tramp, DImode, 0); 933 emit_insn (gen_sync_icache (mem, GEN_INT (TRAMPOLINE_SIZE - 1))); 934} 935 936/* We must exclude constant addresses that have an increment that is not a 937 multiple of four bytes because of restrictions of the GETA 938 instruction, unless TARGET_BASE_ADDRESSES. */ 939 940int 941mmix_constant_address_p (rtx x) 942{ 943 RTX_CODE code = GET_CODE (x); 944 int addend = 0; 945 /* When using "base addresses", anything constant goes. */ 946 int constant_ok = TARGET_BASE_ADDRESSES != 0; 947 948 switch (code) 949 { 950 case LABEL_REF: 951 case SYMBOL_REF: 952 return 1; 953 954 case HIGH: 955 /* FIXME: Don't know how to dissect these. Avoid them for now, 956 except we know they're constants. */ 957 return constant_ok; 958 959 case CONST_INT: 960 addend = INTVAL (x); 961 break; 962 963 case CONST_DOUBLE: 964 if (GET_MODE (x) != VOIDmode) 965 /* Strange that we got here. FIXME: Check if we do. */ 966 return constant_ok; 967 addend = CONST_DOUBLE_LOW (x); 968 break; 969 970 case CONST: 971 /* Note that expressions with arithmetic on forward references don't 972 work in mmixal. People using gcc assembly code with mmixal might 973 need to move arrays and such to before the point of use. */ 974 if (GET_CODE (XEXP (x, 0)) == PLUS) 975 { 976 rtx x0 = XEXP (XEXP (x, 0), 0); 977 rtx x1 = XEXP (XEXP (x, 0), 1); 978 979 if ((GET_CODE (x0) == SYMBOL_REF 980 || GET_CODE (x0) == LABEL_REF) 981 && (GET_CODE (x1) == CONST_INT 982 || (GET_CODE (x1) == CONST_DOUBLE 983 && GET_MODE (x1) == VOIDmode))) 984 addend = mmix_intval (x1); 985 else 986 return constant_ok; 987 } 988 else 989 return constant_ok; 990 break; 991 992 default: 993 return 0; 994 } 995 996 return constant_ok || (addend & 3) == 0; 997} 998 999/* Return 1 if the address is OK, otherwise 0. */ 1000 1001bool 1002mmix_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, 1003 rtx x, 1004 bool strict_checking) 1005{ 1006#define MMIX_REG_OK(X) \ 1007 ((strict_checking \ 1008 && (REGNO (X) <= MMIX_LAST_GENERAL_REGISTER \ 1009 || (reg_renumber[REGNO (X)] > 0 \ 1010 && reg_renumber[REGNO (X)] <= MMIX_LAST_GENERAL_REGISTER))) \ 1011 || (!strict_checking \ 1012 && (REGNO (X) <= MMIX_LAST_GENERAL_REGISTER \ 1013 || REGNO (X) >= FIRST_PSEUDO_REGISTER \ 1014 || REGNO (X) == ARG_POINTER_REGNUM))) 1015 1016 /* We only accept: 1017 (mem reg) 1018 (mem (plus reg reg)) 1019 (mem (plus reg 0..255)). 1020 unless TARGET_BASE_ADDRESSES, in which case we accept all 1021 (mem constant_address) too. */ 1022 1023 1024 /* (mem reg) */ 1025 if (REG_P (x) && MMIX_REG_OK (x)) 1026 return 1; 1027 1028 if (GET_CODE(x) == PLUS) 1029 { 1030 rtx x1 = XEXP (x, 0); 1031 rtx x2 = XEXP (x, 1); 1032 1033 /* Try swapping the order. FIXME: Do we need this? */ 1034 if (! REG_P (x1)) 1035 { 1036 rtx tem = x1; 1037 x1 = x2; 1038 x2 = tem; 1039 } 1040 1041 /* (mem (plus (reg?) (?))) */ 1042 if (!REG_P (x1) || !MMIX_REG_OK (x1)) 1043 return TARGET_BASE_ADDRESSES && mmix_constant_address_p (x); 1044 1045 /* (mem (plus (reg) (reg?))) */ 1046 if (REG_P (x2) && MMIX_REG_OK (x2)) 1047 return 1; 1048 1049 /* (mem (plus (reg) (0..255?))) */ 1050 if (GET_CODE (x2) == CONST_INT 1051 && CONST_OK_FOR_LETTER_P (INTVAL (x2), 'I')) 1052 return 1; 1053 1054 return 0; 1055 } 1056 1057 return TARGET_BASE_ADDRESSES && mmix_constant_address_p (x); 1058} 1059 1060/* LEGITIMATE_CONSTANT_P. */ 1061 1062int 1063mmix_legitimate_constant_p (rtx x) 1064{ 1065 RTX_CODE code = GET_CODE (x); 1066 1067 /* We must allow any number due to the way the cse passes works; if we 1068 do not allow any number here, general_operand will fail, and insns 1069 will fatally fail recognition instead of "softly". */ 1070 if (code == CONST_INT || code == CONST_DOUBLE) 1071 return 1; 1072 1073 return CONSTANT_ADDRESS_P (x); 1074} 1075 1076/* SELECT_CC_MODE. */ 1077 1078enum machine_mode 1079mmix_select_cc_mode (RTX_CODE op, rtx x, rtx y ATTRIBUTE_UNUSED) 1080{ 1081 /* We use CCmode, CC_UNSmode, CC_FPmode, CC_FPEQmode and CC_FUNmode to 1082 output different compare insns. Note that we do not check the 1083 validity of the comparison here. */ 1084 1085 if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT) 1086 { 1087 if (op == ORDERED || op == UNORDERED || op == UNGE 1088 || op == UNGT || op == UNLE || op == UNLT) 1089 return CC_FUNmode; 1090 1091 if (op == EQ || op == NE) 1092 return CC_FPEQmode; 1093 1094 return CC_FPmode; 1095 } 1096 1097 if (op == GTU || op == LTU || op == GEU || op == LEU) 1098 return CC_UNSmode; 1099 1100 return CCmode; 1101} 1102 1103/* REVERSIBLE_CC_MODE. */ 1104 1105int 1106mmix_reversible_cc_mode (enum machine_mode mode) 1107{ 1108 /* That is, all integer and the EQ, NE, ORDERED and UNORDERED float 1109 compares. */ 1110 return mode != CC_FPmode; 1111} 1112 1113/* TARGET_RTX_COSTS. */ 1114 1115static bool 1116mmix_rtx_costs (rtx x ATTRIBUTE_UNUSED, 1117 int code ATTRIBUTE_UNUSED, 1118 int outer_code ATTRIBUTE_UNUSED, 1119 int *total ATTRIBUTE_UNUSED, 1120 bool speed ATTRIBUTE_UNUSED) 1121{ 1122 /* For the time being, this is just a stub and we'll accept the 1123 generic calculations, until we can do measurements, at least. 1124 Say we did not modify any calculated costs. */ 1125 return false; 1126} 1127 1128/* REGISTER_MOVE_COST. */ 1129 1130int 1131mmix_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED, 1132 enum reg_class from, 1133 enum reg_class to) 1134{ 1135 return (from == GENERAL_REGS && from == to) ? 2 : 3; 1136} 1137 1138/* Note that we don't have a TEXT_SECTION_ASM_OP, because it has to be a 1139 compile-time constant; it's used in an asm in crtstuff.c, compiled for 1140 the target. */ 1141 1142/* DATA_SECTION_ASM_OP. */ 1143 1144const char * 1145mmix_data_section_asm_op (void) 1146{ 1147 return "\t.data ! mmixal:= 8H LOC 9B"; 1148} 1149 1150static void 1151mmix_encode_section_info (tree decl, rtx rtl, int first) 1152{ 1153 /* Test for an external declaration, and do nothing if it is one. */ 1154 if ((TREE_CODE (decl) == VAR_DECL 1155 && (DECL_EXTERNAL (decl) || TREE_PUBLIC (decl))) 1156 || (TREE_CODE (decl) == FUNCTION_DECL && TREE_PUBLIC (decl))) 1157 ; 1158 else if (first && DECL_P (decl)) 1159 { 1160 /* For non-visible declarations, add a "@" prefix, which we skip 1161 when the label is output. If the label does not have this 1162 prefix, a ":" is output if -mtoplevel-symbols. 1163 1164 Note that this does not work for data that is declared extern and 1165 later defined as static. If there's code in between, that code 1166 will refer to the extern declaration, and vice versa. This just 1167 means that when -mtoplevel-symbols is in use, we can just handle 1168 well-behaved ISO-compliant code. */ 1169 1170 const char *str = XSTR (XEXP (rtl, 0), 0); 1171 int len = strlen (str); 1172 char *newstr = XALLOCAVEC (char, len + 2); 1173 newstr[0] = '@'; 1174 strcpy (newstr + 1, str); 1175 XSTR (XEXP (rtl, 0), 0) = ggc_alloc_string (newstr, len + 1); 1176 } 1177 1178 /* Set SYMBOL_REF_FLAG for things that we want to access with GETA. We 1179 may need different options to reach for different things with GETA. 1180 For now, functions and things we know or have been told are constant. */ 1181 if (TREE_CODE (decl) == FUNCTION_DECL 1182 || TREE_CONSTANT (decl) 1183 || (TREE_CODE (decl) == VAR_DECL 1184 && TREE_READONLY (decl) 1185 && !TREE_SIDE_EFFECTS (decl) 1186 && (!DECL_INITIAL (decl) 1187 || TREE_CONSTANT (DECL_INITIAL (decl))))) 1188 SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; 1189} 1190 1191static const char * 1192mmix_strip_name_encoding (const char *name) 1193{ 1194 for (; (*name == '@' || *name == '*'); name++) 1195 ; 1196 1197 return name; 1198} 1199 1200/* TARGET_ASM_FILE_START. 1201 We just emit a little comment for the time being. */ 1202 1203static void 1204mmix_file_start (void) 1205{ 1206 default_file_start (); 1207 1208 fputs ("! mmixal:= 8H LOC Data_Section\n", asm_out_file); 1209 1210 /* Make sure each file starts with the text section. */ 1211 switch_to_section (text_section); 1212} 1213 1214/* TARGET_ASM_FILE_END. */ 1215 1216static void 1217mmix_file_end (void) 1218{ 1219 /* Make sure each file ends with the data section. */ 1220 switch_to_section (data_section); 1221} 1222 1223/* ASM_OUTPUT_SOURCE_FILENAME. */ 1224 1225void 1226mmix_asm_output_source_filename (FILE *stream, const char *name) 1227{ 1228 fprintf (stream, "# 1 "); 1229 OUTPUT_QUOTED_STRING (stream, name); 1230 fprintf (stream, "\n"); 1231} 1232 1233/* OUTPUT_QUOTED_STRING. */ 1234 1235void 1236mmix_output_quoted_string (FILE *stream, const char *string, int length) 1237{ 1238 const char * string_end = string + length; 1239 static const char *const unwanted_chars = "\"[]\\"; 1240 1241 /* Output "any character except newline and double quote character". We 1242 play it safe and avoid all control characters too. We also do not 1243 want [] as characters, should input be passed through m4 with [] as 1244 quotes. Further, we avoid "\", because the GAS port handles it as a 1245 quoting character. */ 1246 while (string < string_end) 1247 { 1248 if (*string 1249 && (unsigned char) *string < 128 1250 && !ISCNTRL (*string) 1251 && strchr (unwanted_chars, *string) == NULL) 1252 { 1253 fputc ('"', stream); 1254 while (*string 1255 && (unsigned char) *string < 128 1256 && !ISCNTRL (*string) 1257 && strchr (unwanted_chars, *string) == NULL 1258 && string < string_end) 1259 { 1260 fputc (*string, stream); 1261 string++; 1262 } 1263 fputc ('"', stream); 1264 if (string < string_end) 1265 fprintf (stream, ","); 1266 } 1267 if (string < string_end) 1268 { 1269 fprintf (stream, "#%x", *string & 255); 1270 string++; 1271 if (string < string_end) 1272 fprintf (stream, ","); 1273 } 1274 } 1275} 1276 1277/* Target hook for assembling integer objects. Use mmix_print_operand 1278 for WYDE and TETRA. Use mmix_output_octa to output 8-byte 1279 CONST_DOUBLEs. */ 1280 1281static bool 1282mmix_assemble_integer (rtx x, unsigned int size, int aligned_p) 1283{ 1284 if (aligned_p) 1285 switch (size) 1286 { 1287 /* We handle a limited number of types of operands in here. But 1288 that's ok, because we can punt to generic functions. We then 1289 pretend that aligned data isn't needed, so the usual .<pseudo> 1290 syntax is used (which works for aligned data too). We actually 1291 *must* do that, since we say we don't have simple aligned 1292 pseudos, causing this function to be called. We just try and 1293 keep as much compatibility as possible with mmixal syntax for 1294 normal cases (i.e. without GNU extensions and C only). */ 1295 case 1: 1296 if (GET_CODE (x) != CONST_INT) 1297 { 1298 aligned_p = 0; 1299 break; 1300 } 1301 fputs ("\tBYTE\t", asm_out_file); 1302 mmix_print_operand (asm_out_file, x, 'B'); 1303 fputc ('\n', asm_out_file); 1304 return true; 1305 1306 case 2: 1307 if (GET_CODE (x) != CONST_INT) 1308 { 1309 aligned_p = 0; 1310 break; 1311 } 1312 fputs ("\tWYDE\t", asm_out_file); 1313 mmix_print_operand (asm_out_file, x, 'W'); 1314 fputc ('\n', asm_out_file); 1315 return true; 1316 1317 case 4: 1318 if (GET_CODE (x) != CONST_INT) 1319 { 1320 aligned_p = 0; 1321 break; 1322 } 1323 fputs ("\tTETRA\t", asm_out_file); 1324 mmix_print_operand (asm_out_file, x, 'L'); 1325 fputc ('\n', asm_out_file); 1326 return true; 1327 1328 case 8: 1329 /* We don't get here anymore for CONST_DOUBLE, because DImode 1330 isn't expressed as CONST_DOUBLE, and DFmode is handled 1331 elsewhere. */ 1332 gcc_assert (GET_CODE (x) != CONST_DOUBLE); 1333 assemble_integer_with_op ("\tOCTA\t", x); 1334 return true; 1335 } 1336 return default_assemble_integer (x, size, aligned_p); 1337} 1338 1339/* ASM_OUTPUT_ASCII. */ 1340 1341void 1342mmix_asm_output_ascii (FILE *stream, const char *string, int length) 1343{ 1344 while (length > 0) 1345 { 1346 int chunk_size = length > 60 ? 60 : length; 1347 fprintf (stream, "\tBYTE "); 1348 mmix_output_quoted_string (stream, string, chunk_size); 1349 string += chunk_size; 1350 length -= chunk_size; 1351 fprintf (stream, "\n"); 1352 } 1353} 1354 1355/* ASM_OUTPUT_ALIGNED_COMMON. */ 1356 1357void 1358mmix_asm_output_aligned_common (FILE *stream, 1359 const char *name, 1360 int size, 1361 int align) 1362{ 1363 /* This is mostly the elfos.h one. There doesn't seem to be a way to 1364 express this in a mmixal-compatible way. */ 1365 fprintf (stream, "\t.comm\t"); 1366 assemble_name (stream, name); 1367 fprintf (stream, ",%u,%u ! mmixal-incompatible COMMON\n", 1368 size, align / BITS_PER_UNIT); 1369} 1370 1371/* ASM_OUTPUT_ALIGNED_LOCAL. */ 1372 1373void 1374mmix_asm_output_aligned_local (FILE *stream, 1375 const char *name, 1376 int size, 1377 int align) 1378{ 1379 switch_to_section (data_section); 1380 1381 ASM_OUTPUT_ALIGN (stream, exact_log2 (align/BITS_PER_UNIT)); 1382 assemble_name (stream, name); 1383 fprintf (stream, "\tLOC @+%d\n", size); 1384} 1385 1386/* ASM_OUTPUT_LABEL. */ 1387 1388void 1389mmix_asm_output_label (FILE *stream, const char *name) 1390{ 1391 assemble_name (stream, name); 1392 fprintf (stream, "\tIS @\n"); 1393} 1394 1395/* ASM_OUTPUT_INTERNAL_LABEL. */ 1396 1397void 1398mmix_asm_output_internal_label (FILE *stream, const char *name) 1399{ 1400 assemble_name_raw (stream, name); 1401 fprintf (stream, "\tIS @\n"); 1402} 1403 1404/* ASM_DECLARE_REGISTER_GLOBAL. */ 1405 1406void 1407mmix_asm_declare_register_global (FILE *stream ATTRIBUTE_UNUSED, 1408 tree decl ATTRIBUTE_UNUSED, 1409 int regno ATTRIBUTE_UNUSED, 1410 const char *name ATTRIBUTE_UNUSED) 1411{ 1412 /* Nothing to do here, but there *will* be, therefore the framework is 1413 here. */ 1414} 1415 1416/* ASM_WEAKEN_LABEL. */ 1417 1418void 1419mmix_asm_weaken_label (FILE *stream ATTRIBUTE_UNUSED, 1420 const char *name ATTRIBUTE_UNUSED) 1421{ 1422 fprintf (stream, "\t.weak "); 1423 assemble_name (stream, name); 1424 fprintf (stream, " ! mmixal-incompatible\n"); 1425} 1426 1427/* MAKE_DECL_ONE_ONLY. */ 1428 1429void 1430mmix_make_decl_one_only (tree decl) 1431{ 1432 DECL_WEAK (decl) = 1; 1433} 1434 1435/* ASM_OUTPUT_LABELREF. 1436 Strip GCC's '*' and our own '@'. No order is assumed. */ 1437 1438void 1439mmix_asm_output_labelref (FILE *stream, const char *name) 1440{ 1441 int is_extern = 1; 1442 1443 for (; (*name == '@' || *name == '*'); name++) 1444 if (*name == '@') 1445 is_extern = 0; 1446 1447 asm_fprintf (stream, "%s%U%s", 1448 is_extern && TARGET_TOPLEVEL_SYMBOLS ? ":" : "", 1449 name); 1450} 1451 1452/* ASM_OUTPUT_DEF. */ 1453 1454void 1455mmix_asm_output_def (FILE *stream, const char *name, const char *value) 1456{ 1457 assemble_name (stream, name); 1458 fprintf (stream, "\tIS "); 1459 assemble_name (stream, value); 1460 fputc ('\n', stream); 1461} 1462 1463/* PRINT_OPERAND. */ 1464 1465void 1466mmix_print_operand (FILE *stream, rtx x, int code) 1467{ 1468 /* When we add support for different codes later, we can, when needed, 1469 drop through to the main handler with a modified operand. */ 1470 rtx modified_x = x; 1471 int regno = x != NULL_RTX && REG_P (x) ? REGNO (x) : 0; 1472 1473 switch (code) 1474 { 1475 /* Unrelated codes are in alphabetic order. */ 1476 1477 case '+': 1478 /* For conditional branches, output "P" for a probable branch. */ 1479 if (TARGET_BRANCH_PREDICT) 1480 { 1481 x = find_reg_note (current_output_insn, REG_BR_PROB, 0); 1482 if (x && INTVAL (XEXP (x, 0)) > REG_BR_PROB_BASE / 2) 1483 putc ('P', stream); 1484 } 1485 return; 1486 1487 case '.': 1488 /* For the %d in POP %d,0. */ 1489 fprintf (stream, "%d", MMIX_POP_ARGUMENT ()); 1490 return; 1491 1492 case 'B': 1493 if (GET_CODE (x) != CONST_INT) 1494 fatal_insn ("MMIX Internal: Expected a CONST_INT, not this", x); 1495 fprintf (stream, "%d", (int) (INTVAL (x) & 0xff)); 1496 return; 1497 1498 case 'H': 1499 /* Highpart. Must be general register, and not the last one, as 1500 that one cannot be part of a consecutive register pair. */ 1501 if (regno > MMIX_LAST_GENERAL_REGISTER - 1) 1502 internal_error ("MMIX Internal: Bad register: %d", regno); 1503 1504 /* This is big-endian, so the high-part is the first one. */ 1505 fprintf (stream, "%s", reg_names[MMIX_OUTPUT_REGNO (regno)]); 1506 return; 1507 1508 case 'L': 1509 /* Lowpart. Must be CONST_INT or general register, and not the last 1510 one, as that one cannot be part of a consecutive register pair. */ 1511 if (GET_CODE (x) == CONST_INT) 1512 { 1513 fprintf (stream, "#%lx", 1514 (unsigned long) (INTVAL (x) 1515 & ((unsigned int) 0x7fffffff * 2 + 1))); 1516 return; 1517 } 1518 1519 if (GET_CODE (x) == SYMBOL_REF) 1520 { 1521 output_addr_const (stream, x); 1522 return; 1523 } 1524 1525 if (regno > MMIX_LAST_GENERAL_REGISTER - 1) 1526 internal_error ("MMIX Internal: Bad register: %d", regno); 1527 1528 /* This is big-endian, so the low-part is + 1. */ 1529 fprintf (stream, "%s", reg_names[MMIX_OUTPUT_REGNO (regno) + 1]); 1530 return; 1531 1532 /* Can't use 'a' because that's a generic modifier for address 1533 output. */ 1534 case 'A': 1535 mmix_output_shiftvalue_op_from_str (stream, "ANDN", 1536 ~(unsigned HOST_WIDEST_INT) 1537 mmix_intval (x)); 1538 return; 1539 1540 case 'i': 1541 mmix_output_shiftvalue_op_from_str (stream, "INC", 1542 (unsigned HOST_WIDEST_INT) 1543 mmix_intval (x)); 1544 return; 1545 1546 case 'o': 1547 mmix_output_shiftvalue_op_from_str (stream, "OR", 1548 (unsigned HOST_WIDEST_INT) 1549 mmix_intval (x)); 1550 return; 1551 1552 case 's': 1553 mmix_output_shiftvalue_op_from_str (stream, "SET", 1554 (unsigned HOST_WIDEST_INT) 1555 mmix_intval (x)); 1556 return; 1557 1558 case 'd': 1559 case 'D': 1560 mmix_output_condition (stream, x, (code == 'D')); 1561 return; 1562 1563 case 'e': 1564 /* Output an extra "e" to make fcmpe, fune. */ 1565 if (TARGET_FCMP_EPSILON) 1566 fprintf (stream, "e"); 1567 return; 1568 1569 case 'm': 1570 /* Output the number minus 1. */ 1571 if (GET_CODE (x) != CONST_INT) 1572 { 1573 fatal_insn ("MMIX Internal: Bad value for 'm', not a CONST_INT", 1574 x); 1575 } 1576 fprintf (stream, HOST_WIDEST_INT_PRINT_DEC, 1577 (HOST_WIDEST_INT) (mmix_intval (x) - 1)); 1578 return; 1579 1580 case 'p': 1581 /* Store the number of registers we want to save. This was setup 1582 by the prologue. The actual operand contains the number of 1583 registers to pass, but we don't use it currently. Anyway, we 1584 need to output the number of saved registers here. */ 1585 fprintf (stream, "%d", 1586 cfun->machine->highest_saved_stack_register + 1); 1587 return; 1588 1589 case 'r': 1590 /* Store the register to output a constant to. */ 1591 if (! REG_P (x)) 1592 fatal_insn ("MMIX Internal: Expected a register, not this", x); 1593 mmix_output_destination_register = MMIX_OUTPUT_REGNO (regno); 1594 return; 1595 1596 case 'I': 1597 /* Output the constant. Note that we use this for floats as well. */ 1598 if (GET_CODE (x) != CONST_INT 1599 && (GET_CODE (x) != CONST_DOUBLE 1600 || (GET_MODE (x) != VOIDmode && GET_MODE (x) != DFmode 1601 && GET_MODE (x) != SFmode))) 1602 fatal_insn ("MMIX Internal: Expected a constant, not this", x); 1603 mmix_output_register_setting (stream, 1604 mmix_output_destination_register, 1605 mmix_intval (x), 0); 1606 return; 1607 1608 case 'U': 1609 /* An U for unsigned, if TARGET_ZERO_EXTEND. Ignore the operand. */ 1610 if (TARGET_ZERO_EXTEND) 1611 putc ('U', stream); 1612 return; 1613 1614 case 'v': 1615 mmix_output_shifted_value (stream, (HOST_WIDEST_INT) mmix_intval (x)); 1616 return; 1617 1618 case 'V': 1619 mmix_output_shifted_value (stream, (HOST_WIDEST_INT) ~mmix_intval (x)); 1620 return; 1621 1622 case 'W': 1623 if (GET_CODE (x) != CONST_INT) 1624 fatal_insn ("MMIX Internal: Expected a CONST_INT, not this", x); 1625 fprintf (stream, "#%x", (int) (INTVAL (x) & 0xffff)); 1626 return; 1627 1628 case 0: 1629 /* Nothing to do. */ 1630 break; 1631 1632 default: 1633 /* Presumably there's a missing case above if we get here. */ 1634 internal_error ("MMIX Internal: Missing %qc case in mmix_print_operand", code); 1635 } 1636 1637 switch (GET_CODE (modified_x)) 1638 { 1639 case REG: 1640 regno = REGNO (modified_x); 1641 if (regno >= FIRST_PSEUDO_REGISTER) 1642 internal_error ("MMIX Internal: Bad register: %d", regno); 1643 fprintf (stream, "%s", reg_names[MMIX_OUTPUT_REGNO (regno)]); 1644 return; 1645 1646 case MEM: 1647 output_address (XEXP (modified_x, 0)); 1648 return; 1649 1650 case CONST_INT: 1651 /* For -2147483648, mmixal complains that the constant does not fit 1652 in 4 bytes, so let's output it as hex. Take care to handle hosts 1653 where HOST_WIDE_INT is longer than an int. 1654 1655 Print small constants +-255 using decimal. */ 1656 1657 if (INTVAL (modified_x) > -256 && INTVAL (modified_x) < 256) 1658 fprintf (stream, "%d", (int) (INTVAL (modified_x))); 1659 else 1660 fprintf (stream, "#%x", 1661 (int) (INTVAL (modified_x)) & (unsigned int) ~0); 1662 return; 1663 1664 case CONST_DOUBLE: 1665 /* Do somewhat as CONST_INT. */ 1666 mmix_output_octa (stream, mmix_intval (modified_x), 0); 1667 return; 1668 1669 case CONST: 1670 output_addr_const (stream, modified_x); 1671 return; 1672 1673 default: 1674 /* No need to test for all strange things. Let output_addr_const do 1675 it for us. */ 1676 if (CONSTANT_P (modified_x) 1677 /* Strangely enough, this is not included in CONSTANT_P. 1678 FIXME: Ask/check about sanity here. */ 1679 || GET_CODE (modified_x) == CODE_LABEL) 1680 { 1681 output_addr_const (stream, modified_x); 1682 return; 1683 } 1684 1685 /* We need the original here. */ 1686 fatal_insn ("MMIX Internal: Cannot decode this operand", x); 1687 } 1688} 1689 1690/* PRINT_OPERAND_PUNCT_VALID_P. */ 1691 1692int 1693mmix_print_operand_punct_valid_p (int code ATTRIBUTE_UNUSED) 1694{ 1695 /* A '+' is used for branch prediction, similar to other ports. */ 1696 return code == '+' 1697 /* A '.' is used for the %d in the POP %d,0 return insn. */ 1698 || code == '.'; 1699} 1700 1701/* PRINT_OPERAND_ADDRESS. */ 1702 1703void 1704mmix_print_operand_address (FILE *stream, rtx x) 1705{ 1706 if (REG_P (x)) 1707 { 1708 /* I find the generated assembly code harder to read without 1709 the ",0". */ 1710 fprintf (stream, "%s,0", reg_names[MMIX_OUTPUT_REGNO (REGNO (x))]); 1711 return; 1712 } 1713 else if (GET_CODE (x) == PLUS) 1714 { 1715 rtx x1 = XEXP (x, 0); 1716 rtx x2 = XEXP (x, 1); 1717 1718 if (REG_P (x1)) 1719 { 1720 fprintf (stream, "%s,", reg_names[MMIX_OUTPUT_REGNO (REGNO (x1))]); 1721 1722 if (REG_P (x2)) 1723 { 1724 fprintf (stream, "%s", 1725 reg_names[MMIX_OUTPUT_REGNO (REGNO (x2))]); 1726 return; 1727 } 1728 else if (GET_CODE (x2) == CONST_INT 1729 && CONST_OK_FOR_LETTER_P (INTVAL (x2), 'I')) 1730 { 1731 output_addr_const (stream, x2); 1732 return; 1733 } 1734 } 1735 } 1736 1737 if (TARGET_BASE_ADDRESSES && mmix_legitimate_constant_p (x)) 1738 { 1739 output_addr_const (stream, x); 1740 return; 1741 } 1742 1743 fatal_insn ("MMIX Internal: This is not a recognized address", x); 1744} 1745 1746/* ASM_OUTPUT_REG_PUSH. */ 1747 1748void 1749mmix_asm_output_reg_push (FILE *stream, int regno) 1750{ 1751 fprintf (stream, "\tSUBU %s,%s,8\n\tSTOU %s,%s,0\n", 1752 reg_names[MMIX_STACK_POINTER_REGNUM], 1753 reg_names[MMIX_STACK_POINTER_REGNUM], 1754 reg_names[MMIX_OUTPUT_REGNO (regno)], 1755 reg_names[MMIX_STACK_POINTER_REGNUM]); 1756} 1757 1758/* ASM_OUTPUT_REG_POP. */ 1759 1760void 1761mmix_asm_output_reg_pop (FILE *stream, int regno) 1762{ 1763 fprintf (stream, "\tLDOU %s,%s,0\n\tINCL %s,8\n", 1764 reg_names[MMIX_OUTPUT_REGNO (regno)], 1765 reg_names[MMIX_STACK_POINTER_REGNUM], 1766 reg_names[MMIX_STACK_POINTER_REGNUM]); 1767} 1768 1769/* ASM_OUTPUT_ADDR_DIFF_ELT. */ 1770 1771void 1772mmix_asm_output_addr_diff_elt (FILE *stream, 1773 rtx body ATTRIBUTE_UNUSED, 1774 int value, 1775 int rel) 1776{ 1777 fprintf (stream, "\tTETRA L%d-L%d\n", value, rel); 1778} 1779 1780/* ASM_OUTPUT_ADDR_VEC_ELT. */ 1781 1782void 1783mmix_asm_output_addr_vec_elt (FILE *stream, int value) 1784{ 1785 fprintf (stream, "\tOCTA L:%d\n", value); 1786} 1787 1788/* ASM_OUTPUT_SKIP. */ 1789 1790void 1791mmix_asm_output_skip (FILE *stream, int nbytes) 1792{ 1793 fprintf (stream, "\tLOC @+%d\n", nbytes); 1794} 1795 1796/* ASM_OUTPUT_ALIGN. */ 1797 1798void 1799mmix_asm_output_align (FILE *stream, int power) 1800{ 1801 /* We need to record the needed alignment of this section in the object, 1802 so we have to output an alignment directive. Use a .p2align (not 1803 .align) so people will never have to wonder about whether the 1804 argument is in number of bytes or the log2 thereof. We do it in 1805 addition to the LOC directive, so nothing needs tweaking when 1806 copy-pasting assembly into mmixal. */ 1807 fprintf (stream, "\t.p2align %d\n", power); 1808 fprintf (stream, "\tLOC @+(%d-@)&%d\n", 1 << power, (1 << power) - 1); 1809} 1810 1811/* DBX_REGISTER_NUMBER. */ 1812 1813int 1814mmix_dbx_register_number (int regno) 1815{ 1816 /* Adjust the register number to the one it will be output as, dammit. 1817 It'd be nice if we could check the assumption that we're filling a 1818 gap, but every register between the last saved register and parameter 1819 registers might be a valid parameter register. */ 1820 regno = MMIX_OUTPUT_REGNO (regno); 1821 1822 /* We need to renumber registers to get the number of the return address 1823 register in the range 0..255. It is also space-saving if registers 1824 mentioned in the call-frame information (which uses this function by 1825 defaulting DWARF_FRAME_REGNUM to DBX_REGISTER_NUMBER) are numbered 1826 0 .. 63. So map 224 .. 256+15 -> 0 .. 47 and 0 .. 223 -> 48..223+48. */ 1827 return regno >= 224 ? (regno - 224) : (regno + 48); 1828} 1829 1830/* End of target macro support functions. 1831 1832 Now the MMIX port's own functions. First the exported ones. */ 1833 1834/* Wrapper for get_hard_reg_initial_val since integrate.h isn't included 1835 from insn-emit.c. */ 1836 1837rtx 1838mmix_get_hard_reg_initial_val (enum machine_mode mode, int regno) 1839{ 1840 return get_hard_reg_initial_val (mode, regno); 1841} 1842 1843/* Nonzero when the function epilogue is simple enough that a single 1844 "POP %d,0" should be used even within the function. */ 1845 1846int 1847mmix_use_simple_return (void) 1848{ 1849 int regno; 1850 1851 int stack_space_to_allocate 1852 = (crtl->outgoing_args_size 1853 + crtl->args.pretend_args_size 1854 + get_frame_size () + 7) & ~7; 1855 1856 if (!TARGET_USE_RETURN_INSN || !reload_completed) 1857 return 0; 1858 1859 for (regno = 255; 1860 regno >= MMIX_FIRST_GLOBAL_REGNUM; 1861 regno--) 1862 /* Note that we assume that the frame-pointer-register is one of these 1863 registers, in which case we don't count it here. */ 1864 if ((((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed) 1865 && df_regs_ever_live_p (regno) && !call_used_regs[regno])) 1866 || IS_MMIX_EH_RETURN_DATA_REG (regno)) 1867 return 0; 1868 1869 if (frame_pointer_needed) 1870 stack_space_to_allocate += 8; 1871 1872 if (MMIX_CFUN_HAS_LANDING_PAD) 1873 stack_space_to_allocate += 16; 1874 else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS) 1875 stack_space_to_allocate += 8; 1876 1877 return stack_space_to_allocate == 0; 1878} 1879 1880 1881/* Expands the function prologue into RTX. */ 1882 1883void 1884mmix_expand_prologue (void) 1885{ 1886 HOST_WIDE_INT locals_size = get_frame_size (); 1887 int regno; 1888 HOST_WIDE_INT stack_space_to_allocate 1889 = (crtl->outgoing_args_size 1890 + crtl->args.pretend_args_size 1891 + locals_size + 7) & ~7; 1892 HOST_WIDE_INT offset = -8; 1893 1894 /* Add room needed to save global non-register-stack registers. */ 1895 for (regno = 255; 1896 regno >= MMIX_FIRST_GLOBAL_REGNUM; 1897 regno--) 1898 /* Note that we assume that the frame-pointer-register is one of these 1899 registers, in which case we don't count it here. */ 1900 if ((((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed) 1901 && df_regs_ever_live_p (regno) && !call_used_regs[regno])) 1902 || IS_MMIX_EH_RETURN_DATA_REG (regno)) 1903 stack_space_to_allocate += 8; 1904 1905 /* If we do have a frame-pointer, add room for it. */ 1906 if (frame_pointer_needed) 1907 stack_space_to_allocate += 8; 1908 1909 /* If we have a non-local label, we need to be able to unwind to it, so 1910 store the current register stack pointer. Also store the return 1911 address if we do that. */ 1912 if (MMIX_CFUN_HAS_LANDING_PAD) 1913 stack_space_to_allocate += 16; 1914 else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS) 1915 /* If we do have a saved return-address slot, add room for it. */ 1916 stack_space_to_allocate += 8; 1917 1918 /* Make sure we don't get an unaligned stack. */ 1919 if ((stack_space_to_allocate % 8) != 0) 1920 internal_error ("stack frame not a multiple of 8 bytes: %wd", 1921 stack_space_to_allocate); 1922 1923 if (crtl->args.pretend_args_size) 1924 { 1925 int mmix_first_vararg_reg 1926 = (MMIX_FIRST_INCOMING_ARG_REGNUM 1927 + (MMIX_MAX_ARGS_IN_REGS 1928 - crtl->args.pretend_args_size / 8)); 1929 1930 for (regno 1931 = MMIX_FIRST_INCOMING_ARG_REGNUM + MMIX_MAX_ARGS_IN_REGS - 1; 1932 regno >= mmix_first_vararg_reg; 1933 regno--) 1934 { 1935 if (offset < 0) 1936 { 1937 HOST_WIDE_INT stack_chunk 1938 = stack_space_to_allocate > (256 - 8) 1939 ? (256 - 8) : stack_space_to_allocate; 1940 1941 mmix_emit_sp_add (-stack_chunk); 1942 offset += stack_chunk; 1943 stack_space_to_allocate -= stack_chunk; 1944 } 1945 1946 /* These registers aren't actually saved (as in "will be 1947 restored"), so don't tell DWARF2 they're saved. */ 1948 emit_move_insn (gen_rtx_MEM (DImode, 1949 plus_constant (stack_pointer_rtx, 1950 offset)), 1951 gen_rtx_REG (DImode, regno)); 1952 offset -= 8; 1953 } 1954 } 1955 1956 /* Store the frame-pointer. */ 1957 1958 if (frame_pointer_needed) 1959 { 1960 rtx insn; 1961 1962 if (offset < 0) 1963 { 1964 /* Get 8 less than otherwise, since we need to reach offset + 8. */ 1965 HOST_WIDE_INT stack_chunk 1966 = stack_space_to_allocate > (256 - 8 - 8) 1967 ? (256 - 8 - 8) : stack_space_to_allocate; 1968 1969 mmix_emit_sp_add (-stack_chunk); 1970 1971 offset += stack_chunk; 1972 stack_space_to_allocate -= stack_chunk; 1973 } 1974 1975 insn = emit_move_insn (gen_rtx_MEM (DImode, 1976 plus_constant (stack_pointer_rtx, 1977 offset)), 1978 hard_frame_pointer_rtx); 1979 RTX_FRAME_RELATED_P (insn) = 1; 1980 insn = emit_insn (gen_adddi3 (hard_frame_pointer_rtx, 1981 stack_pointer_rtx, 1982 GEN_INT (offset + 8))); 1983 RTX_FRAME_RELATED_P (insn) = 1; 1984 offset -= 8; 1985 } 1986 1987 if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS) 1988 { 1989 rtx tmpreg, retreg; 1990 rtx insn; 1991 1992 /* Store the return-address, if one is needed on the stack. We 1993 usually store it in a register when needed, but that doesn't work 1994 with -fexceptions. */ 1995 1996 if (offset < 0) 1997 { 1998 /* Get 8 less than otherwise, since we need to reach offset + 8. */ 1999 HOST_WIDE_INT stack_chunk 2000 = stack_space_to_allocate > (256 - 8 - 8) 2001 ? (256 - 8 - 8) : stack_space_to_allocate; 2002 2003 mmix_emit_sp_add (-stack_chunk); 2004 2005 offset += stack_chunk; 2006 stack_space_to_allocate -= stack_chunk; 2007 } 2008 2009 tmpreg = gen_rtx_REG (DImode, 255); 2010 retreg = gen_rtx_REG (DImode, MMIX_rJ_REGNUM); 2011 2012 /* Dwarf2 code is confused by the use of a temporary register for 2013 storing the return address, so we have to express it as a note, 2014 which we attach to the actual store insn. */ 2015 emit_move_insn (tmpreg, retreg); 2016 2017 insn = emit_move_insn (gen_rtx_MEM (DImode, 2018 plus_constant (stack_pointer_rtx, 2019 offset)), 2020 tmpreg); 2021 RTX_FRAME_RELATED_P (insn) = 1; 2022 REG_NOTES (insn) 2023 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, 2024 gen_rtx_SET (VOIDmode, 2025 gen_rtx_MEM (DImode, 2026 plus_constant (stack_pointer_rtx, 2027 offset)), 2028 retreg), 2029 REG_NOTES (insn)); 2030 2031 offset -= 8; 2032 } 2033 else if (MMIX_CFUN_HAS_LANDING_PAD) 2034 offset -= 8; 2035 2036 if (MMIX_CFUN_HAS_LANDING_PAD) 2037 { 2038 /* Store the register defining the numbering of local registers, so 2039 we know how long to unwind the register stack. */ 2040 2041 if (offset < 0) 2042 { 2043 /* Get 8 less than otherwise, since we need to reach offset + 8. */ 2044 HOST_WIDE_INT stack_chunk 2045 = stack_space_to_allocate > (256 - 8 - 8) 2046 ? (256 - 8 - 8) : stack_space_to_allocate; 2047 2048 mmix_emit_sp_add (-stack_chunk); 2049 2050 offset += stack_chunk; 2051 stack_space_to_allocate -= stack_chunk; 2052 } 2053 2054 /* We don't tell dwarf2 about this one; we just have it to unwind 2055 the register stack at landing pads. FIXME: It's a kludge because 2056 we can't describe the effect of the PUSHJ and PUSHGO insns on the 2057 register stack at the moment. Best thing would be to handle it 2058 like stack-pointer offsets. Better: some hook into dwarf2out.c 2059 to produce DW_CFA_expression:s that specify the increment of rO, 2060 and unwind it at eh_return (preferred) or at the landing pad. 2061 Then saves to $0..$G-1 could be specified through that register. */ 2062 2063 emit_move_insn (gen_rtx_REG (DImode, 255), 2064 gen_rtx_REG (DImode, 2065 MMIX_rO_REGNUM)); 2066 emit_move_insn (gen_rtx_MEM (DImode, 2067 plus_constant (stack_pointer_rtx, offset)), 2068 gen_rtx_REG (DImode, 255)); 2069 offset -= 8; 2070 } 2071 2072 /* After the return-address and the frame-pointer, we have the local 2073 variables. They're the ones that may have an "unaligned" size. */ 2074 offset -= (locals_size + 7) & ~7; 2075 2076 /* Now store all registers that are global, i.e. not saved by the 2077 register file machinery. 2078 2079 It is assumed that the frame-pointer is one of these registers, so it 2080 is explicitly excluded in the count. */ 2081 2082 for (regno = 255; 2083 regno >= MMIX_FIRST_GLOBAL_REGNUM; 2084 regno--) 2085 if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed) 2086 && df_regs_ever_live_p (regno) && ! call_used_regs[regno]) 2087 || IS_MMIX_EH_RETURN_DATA_REG (regno)) 2088 { 2089 rtx insn; 2090 2091 if (offset < 0) 2092 { 2093 HOST_WIDE_INT stack_chunk 2094 = (stack_space_to_allocate > (256 - offset - 8) 2095 ? (256 - offset - 8) : stack_space_to_allocate); 2096 2097 mmix_emit_sp_add (-stack_chunk); 2098 offset += stack_chunk; 2099 stack_space_to_allocate -= stack_chunk; 2100 } 2101 2102 insn = emit_move_insn (gen_rtx_MEM (DImode, 2103 plus_constant (stack_pointer_rtx, 2104 offset)), 2105 gen_rtx_REG (DImode, regno)); 2106 RTX_FRAME_RELATED_P (insn) = 1; 2107 offset -= 8; 2108 } 2109 2110 /* Finally, allocate room for outgoing args and local vars if room 2111 wasn't allocated above. */ 2112 if (stack_space_to_allocate) 2113 mmix_emit_sp_add (-stack_space_to_allocate); 2114} 2115 2116/* Expands the function epilogue into RTX. */ 2117 2118void 2119mmix_expand_epilogue (void) 2120{ 2121 HOST_WIDE_INT locals_size = get_frame_size (); 2122 int regno; 2123 HOST_WIDE_INT stack_space_to_deallocate 2124 = (crtl->outgoing_args_size 2125 + crtl->args.pretend_args_size 2126 + locals_size + 7) & ~7; 2127 2128 /* The first address to access is beyond the outgoing_args area. */ 2129 HOST_WIDE_INT offset = crtl->outgoing_args_size; 2130 2131 /* Add the space for global non-register-stack registers. 2132 It is assumed that the frame-pointer register can be one of these 2133 registers, in which case it is excluded from the count when needed. */ 2134 for (regno = 255; 2135 regno >= MMIX_FIRST_GLOBAL_REGNUM; 2136 regno--) 2137 if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed) 2138 && df_regs_ever_live_p (regno) && !call_used_regs[regno]) 2139 || IS_MMIX_EH_RETURN_DATA_REG (regno)) 2140 stack_space_to_deallocate += 8; 2141 2142 /* Add in the space for register stack-pointer. If so, always add room 2143 for the saved PC. */ 2144 if (MMIX_CFUN_HAS_LANDING_PAD) 2145 stack_space_to_deallocate += 16; 2146 else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS) 2147 /* If we have a saved return-address slot, add it in. */ 2148 stack_space_to_deallocate += 8; 2149 2150 /* Add in the frame-pointer. */ 2151 if (frame_pointer_needed) 2152 stack_space_to_deallocate += 8; 2153 2154 /* Make sure we don't get an unaligned stack. */ 2155 if ((stack_space_to_deallocate % 8) != 0) 2156 internal_error ("stack frame not a multiple of octabyte: %wd", 2157 stack_space_to_deallocate); 2158 2159 /* We will add back small offsets to the stack pointer as we go. 2160 First, we restore all registers that are global, i.e. not saved by 2161 the register file machinery. */ 2162 2163 for (regno = MMIX_FIRST_GLOBAL_REGNUM; 2164 regno <= 255; 2165 regno++) 2166 if (((regno != MMIX_FRAME_POINTER_REGNUM || !frame_pointer_needed) 2167 && df_regs_ever_live_p (regno) && !call_used_regs[regno]) 2168 || IS_MMIX_EH_RETURN_DATA_REG (regno)) 2169 { 2170 if (offset > 255) 2171 { 2172 mmix_emit_sp_add (offset); 2173 stack_space_to_deallocate -= offset; 2174 offset = 0; 2175 } 2176 2177 emit_move_insn (gen_rtx_REG (DImode, regno), 2178 gen_rtx_MEM (DImode, 2179 plus_constant (stack_pointer_rtx, 2180 offset))); 2181 offset += 8; 2182 } 2183 2184 /* Here is where the local variables were. As in the prologue, they 2185 might be of an unaligned size. */ 2186 offset += (locals_size + 7) & ~7; 2187 2188 /* The saved register stack pointer is just below the frame-pointer 2189 register. We don't need to restore it "manually"; the POP 2190 instruction does that. */ 2191 if (MMIX_CFUN_HAS_LANDING_PAD) 2192 offset += 16; 2193 else if (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS) 2194 /* The return-address slot is just below the frame-pointer register. 2195 We don't need to restore it because we don't really use it. */ 2196 offset += 8; 2197 2198 /* Get back the old frame-pointer-value. */ 2199 if (frame_pointer_needed) 2200 { 2201 if (offset > 255) 2202 { 2203 mmix_emit_sp_add (offset); 2204 2205 stack_space_to_deallocate -= offset; 2206 offset = 0; 2207 } 2208 2209 emit_move_insn (hard_frame_pointer_rtx, 2210 gen_rtx_MEM (DImode, 2211 plus_constant (stack_pointer_rtx, 2212 offset))); 2213 offset += 8; 2214 } 2215 2216 /* We do not need to restore pretended incoming args, just add back 2217 offset to sp. */ 2218 if (stack_space_to_deallocate != 0) 2219 mmix_emit_sp_add (stack_space_to_deallocate); 2220 2221 if (crtl->calls_eh_return) 2222 /* Adjust the (normal) stack-pointer to that of the receiver. 2223 FIXME: It would be nice if we could also adjust the register stack 2224 here, but we need to express it through DWARF 2 too. */ 2225 emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx, 2226 gen_rtx_REG (DImode, 2227 MMIX_EH_RETURN_STACKADJ_REGNUM))); 2228} 2229 2230/* Output an optimal sequence for setting a register to a specific 2231 constant. Used in an alternative for const_ints in movdi, and when 2232 using large stack-frame offsets. 2233 2234 Use do_begin_end to say if a line-starting TAB and newline before the 2235 first insn and after the last insn is wanted. */ 2236 2237void 2238mmix_output_register_setting (FILE *stream, 2239 int regno, 2240 HOST_WIDEST_INT value, 2241 int do_begin_end) 2242{ 2243 if (do_begin_end) 2244 fprintf (stream, "\t"); 2245 2246 if (mmix_shiftable_wyde_value ((unsigned HOST_WIDEST_INT) value)) 2247 { 2248 /* First, the one-insn cases. */ 2249 mmix_output_shiftvalue_op_from_str (stream, "SET", 2250 (unsigned HOST_WIDEST_INT) 2251 value); 2252 fprintf (stream, " %s,", reg_names[regno]); 2253 mmix_output_shifted_value (stream, (unsigned HOST_WIDEST_INT) value); 2254 } 2255 else if (mmix_shiftable_wyde_value (-(unsigned HOST_WIDEST_INT) value)) 2256 { 2257 /* We do this to get a bit more legible assembly code. The next 2258 alternative is mostly redundant with this. */ 2259 2260 mmix_output_shiftvalue_op_from_str (stream, "SET", 2261 -(unsigned HOST_WIDEST_INT) 2262 value); 2263 fprintf (stream, " %s,", reg_names[regno]); 2264 mmix_output_shifted_value (stream, -(unsigned HOST_WIDEST_INT) value); 2265 fprintf (stream, "\n\tNEGU %s,0,%s", reg_names[regno], 2266 reg_names[regno]); 2267 } 2268 else if (mmix_shiftable_wyde_value (~(unsigned HOST_WIDEST_INT) value)) 2269 { 2270 /* Slightly more expensive, the two-insn cases. */ 2271 2272 /* FIXME: We could of course also test if 0..255-N or ~(N | 1..255) 2273 is shiftable, or any other one-insn transformation of the value. 2274 FIXME: Check first if the value is "shiftable" by two loading 2275 with two insns, since it makes more readable assembly code (if 2276 anyone else cares). */ 2277 2278 mmix_output_shiftvalue_op_from_str (stream, "SET", 2279 ~(unsigned HOST_WIDEST_INT) 2280 value); 2281 fprintf (stream, " %s,", reg_names[regno]); 2282 mmix_output_shifted_value (stream, ~(unsigned HOST_WIDEST_INT) value); 2283 fprintf (stream, "\n\tNOR %s,%s,0", reg_names[regno], 2284 reg_names[regno]); 2285 } 2286 else 2287 { 2288 /* The generic case. 2..4 insns. */ 2289 static const char *const higher_parts[] = {"L", "ML", "MH", "H"}; 2290 const char *op = "SET"; 2291 const char *line_begin = ""; 2292 int insns = 0; 2293 int i; 2294 HOST_WIDEST_INT tmpvalue = value; 2295 2296 /* Compute the number of insns needed to output this constant. */ 2297 for (i = 0; i < 4 && tmpvalue != 0; i++) 2298 { 2299 if (tmpvalue & 65535) 2300 insns++; 2301 tmpvalue >>= 16; 2302 } 2303 if (TARGET_BASE_ADDRESSES && insns == 3) 2304 { 2305 /* The number three is based on a static observation on 2306 ghostscript-6.52. Two and four are excluded because there 2307 are too many such constants, and each unique constant (maybe 2308 offset by 1..255) were used few times compared to other uses, 2309 e.g. addresses. 2310 2311 We use base-plus-offset addressing to force it into a global 2312 register; we just use a "LDA reg,VALUE", which will cause the 2313 assembler and linker to DTRT (for constants as well as 2314 addresses). */ 2315 fprintf (stream, "LDA %s,", reg_names[regno]); 2316 mmix_output_octa (stream, value, 0); 2317 } 2318 else 2319 { 2320 /* Output pertinent parts of the 4-wyde sequence. 2321 Still more to do if we want this to be optimal, but hey... 2322 Note that the zero case has been handled above. */ 2323 for (i = 0; i < 4 && value != 0; i++) 2324 { 2325 if (value & 65535) 2326 { 2327 fprintf (stream, "%s%s%s %s,#%x", line_begin, op, 2328 higher_parts[i], reg_names[regno], 2329 (int) (value & 65535)); 2330 /* The first one sets the rest of the bits to 0, the next 2331 ones add set bits. */ 2332 op = "INC"; 2333 line_begin = "\n\t"; 2334 } 2335 2336 value >>= 16; 2337 } 2338 } 2339 } 2340 2341 if (do_begin_end) 2342 fprintf (stream, "\n"); 2343} 2344 2345/* Return 1 if value is 0..65535*2**(16*N) for N=0..3. 2346 else return 0. */ 2347 2348int 2349mmix_shiftable_wyde_value (unsigned HOST_WIDEST_INT value) 2350{ 2351 /* Shift by 16 bits per group, stop when we've found two groups with 2352 nonzero bits. */ 2353 int i; 2354 int has_candidate = 0; 2355 2356 for (i = 0; i < 4; i++) 2357 { 2358 if (value & 65535) 2359 { 2360 if (has_candidate) 2361 return 0; 2362 else 2363 has_candidate = 1; 2364 } 2365 2366 value >>= 16; 2367 } 2368 2369 return 1; 2370} 2371 2372/* X and Y are two things to compare using CODE. Return the rtx for 2373 the cc-reg in the proper mode. */ 2374 2375rtx 2376mmix_gen_compare_reg (RTX_CODE code, rtx x, rtx y) 2377{ 2378 enum machine_mode ccmode = SELECT_CC_MODE (code, x, y); 2379 return gen_reg_rtx (ccmode); 2380} 2381 2382/* Local (static) helper functions. */ 2383 2384static void 2385mmix_emit_sp_add (HOST_WIDE_INT offset) 2386{ 2387 rtx insn; 2388 2389 if (offset < 0) 2390 { 2391 /* Negative stack-pointer adjustments are allocations and appear in 2392 the prologue only. We mark them as frame-related so unwind and 2393 debug info is properly emitted for them. */ 2394 if (offset > -255) 2395 insn = emit_insn (gen_adddi3 (stack_pointer_rtx, 2396 stack_pointer_rtx, 2397 GEN_INT (offset))); 2398 else 2399 { 2400 rtx tmpr = gen_rtx_REG (DImode, 255); 2401 RTX_FRAME_RELATED_P (emit_move_insn (tmpr, GEN_INT (offset))) = 1; 2402 insn = emit_insn (gen_adddi3 (stack_pointer_rtx, 2403 stack_pointer_rtx, tmpr)); 2404 } 2405 RTX_FRAME_RELATED_P (insn) = 1; 2406 } 2407 else 2408 { 2409 /* Positive adjustments are in the epilogue only. Don't mark them 2410 as "frame-related" for unwind info. */ 2411 if (CONST_OK_FOR_LETTER_P (offset, 'L')) 2412 emit_insn (gen_adddi3 (stack_pointer_rtx, 2413 stack_pointer_rtx, 2414 GEN_INT (offset))); 2415 else 2416 { 2417 rtx tmpr = gen_rtx_REG (DImode, 255); 2418 emit_move_insn (tmpr, GEN_INT (offset)); 2419 insn = emit_insn (gen_adddi3 (stack_pointer_rtx, 2420 stack_pointer_rtx, tmpr)); 2421 } 2422 } 2423} 2424 2425/* Print operator suitable for doing something with a shiftable 2426 wyde. The type of operator is passed as an asm output modifier. */ 2427 2428static void 2429mmix_output_shiftvalue_op_from_str (FILE *stream, 2430 const char *mainop, 2431 HOST_WIDEST_INT value) 2432{ 2433 static const char *const op_part[] = {"L", "ML", "MH", "H"}; 2434 int i; 2435 2436 if (! mmix_shiftable_wyde_value (value)) 2437 { 2438 char s[sizeof ("0xffffffffffffffff")]; 2439 sprintf (s, HOST_WIDEST_INT_PRINT_HEX, value); 2440 internal_error ("MMIX Internal: %s is not a shiftable int", s); 2441 } 2442 2443 for (i = 0; i < 4; i++) 2444 { 2445 /* We know we're through when we find one-bits in the low 2446 16 bits. */ 2447 if (value & 0xffff) 2448 { 2449 fprintf (stream, "%s%s", mainop, op_part[i]); 2450 return; 2451 } 2452 value >>= 16; 2453 } 2454 2455 /* No bits set? Then it must have been zero. */ 2456 fprintf (stream, "%sL", mainop); 2457} 2458 2459/* Print a 64-bit value, optionally prefixed by assembly pseudo. */ 2460 2461static void 2462mmix_output_octa (FILE *stream, HOST_WIDEST_INT value, int do_begin_end) 2463{ 2464 /* Snipped from final.c:output_addr_const. We need to avoid the 2465 presumed universal "0x" prefix. We can do it by replacing "0x" with 2466 "#0" here; we must avoid a space in the operands and no, the zero 2467 won't cause the number to be assumed in octal format. */ 2468 char hex_format[sizeof (HOST_WIDEST_INT_PRINT_HEX)]; 2469 2470 if (do_begin_end) 2471 fprintf (stream, "\tOCTA "); 2472 2473 strcpy (hex_format, HOST_WIDEST_INT_PRINT_HEX); 2474 hex_format[0] = '#'; 2475 hex_format[1] = '0'; 2476 2477 /* Provide a few alternative output formats depending on the number, to 2478 improve legibility of assembler output. */ 2479 if ((value < (HOST_WIDEST_INT) 0 && value > (HOST_WIDEST_INT) -10000) 2480 || (value >= (HOST_WIDEST_INT) 0 && value <= (HOST_WIDEST_INT) 16384)) 2481 fprintf (stream, "%d", (int) value); 2482 else if (value > (HOST_WIDEST_INT) 0 2483 && value < ((HOST_WIDEST_INT) 1 << 31) * 2) 2484 fprintf (stream, "#%x", (unsigned int) value); 2485 else 2486 fprintf (stream, hex_format, value); 2487 2488 if (do_begin_end) 2489 fprintf (stream, "\n"); 2490} 2491 2492/* Print the presumed shiftable wyde argument shifted into place (to 2493 be output with an operand). */ 2494 2495static void 2496mmix_output_shifted_value (FILE *stream, HOST_WIDEST_INT value) 2497{ 2498 int i; 2499 2500 if (! mmix_shiftable_wyde_value (value)) 2501 { 2502 char s[16+2+1]; 2503 sprintf (s, HOST_WIDEST_INT_PRINT_HEX, value); 2504 internal_error ("MMIX Internal: %s is not a shiftable int", s); 2505 } 2506 2507 for (i = 0; i < 4; i++) 2508 { 2509 /* We know we're through when we find one-bits in the low 16 bits. */ 2510 if (value & 0xffff) 2511 { 2512 fprintf (stream, "#%x", (int) (value & 0xffff)); 2513 return; 2514 } 2515 2516 value >>= 16; 2517 } 2518 2519 /* No bits set? Then it must have been zero. */ 2520 fprintf (stream, "0"); 2521} 2522 2523/* Output an MMIX condition name corresponding to an operator 2524 and operands: 2525 (comparison_operator [(comparison_operator ...) (const_int 0)]) 2526 which means we have to look at *two* operators. 2527 2528 The argument "reversed" refers to reversal of the condition (not the 2529 same as swapping the arguments). */ 2530 2531static void 2532mmix_output_condition (FILE *stream, rtx x, int reversed) 2533{ 2534 struct cc_conv 2535 { 2536 RTX_CODE cc; 2537 2538 /* The normal output cc-code. */ 2539 const char *const normal; 2540 2541 /* The reversed cc-code, or NULL if invalid. */ 2542 const char *const reversed; 2543 }; 2544 2545 struct cc_type_conv 2546 { 2547 enum machine_mode cc_mode; 2548 2549 /* Terminated with {UNKNOWN, NULL, NULL} */ 2550 const struct cc_conv *const convs; 2551 }; 2552 2553#undef CCEND 2554#define CCEND {UNKNOWN, NULL, NULL} 2555 2556 static const struct cc_conv cc_fun_convs[] 2557 = {{ORDERED, "Z", "P"}, 2558 {UNORDERED, "P", "Z"}, 2559 CCEND}; 2560 static const struct cc_conv cc_fp_convs[] 2561 = {{GT, "P", NULL}, 2562 {LT, "N", NULL}, 2563 CCEND}; 2564 static const struct cc_conv cc_fpeq_convs[] 2565 = {{NE, "Z", "P"}, 2566 {EQ, "P", "Z"}, 2567 CCEND}; 2568 static const struct cc_conv cc_uns_convs[] 2569 = {{GEU, "NN", "N"}, 2570 {GTU, "P", "NP"}, 2571 {LEU, "NP", "P"}, 2572 {LTU, "N", "NN"}, 2573 CCEND}; 2574 static const struct cc_conv cc_signed_convs[] 2575 = {{NE, "NZ", "Z"}, 2576 {EQ, "Z", "NZ"}, 2577 {GE, "NN", "N"}, 2578 {GT, "P", "NP"}, 2579 {LE, "NP", "P"}, 2580 {LT, "N", "NN"}, 2581 CCEND}; 2582 static const struct cc_conv cc_di_convs[] 2583 = {{NE, "NZ", "Z"}, 2584 {EQ, "Z", "NZ"}, 2585 {GE, "NN", "N"}, 2586 {GT, "P", "NP"}, 2587 {LE, "NP", "P"}, 2588 {LT, "N", "NN"}, 2589 {GTU, "NZ", "Z"}, 2590 {LEU, "Z", "NZ"}, 2591 CCEND}; 2592#undef CCEND 2593 2594 static const struct cc_type_conv cc_convs[] 2595 = {{CC_FUNmode, cc_fun_convs}, 2596 {CC_FPmode, cc_fp_convs}, 2597 {CC_FPEQmode, cc_fpeq_convs}, 2598 {CC_UNSmode, cc_uns_convs}, 2599 {CCmode, cc_signed_convs}, 2600 {DImode, cc_di_convs}}; 2601 2602 size_t i; 2603 int j; 2604 2605 enum machine_mode mode = GET_MODE (XEXP (x, 0)); 2606 RTX_CODE cc = GET_CODE (x); 2607 2608 for (i = 0; i < ARRAY_SIZE (cc_convs); i++) 2609 { 2610 if (mode == cc_convs[i].cc_mode) 2611 { 2612 for (j = 0; cc_convs[i].convs[j].cc != UNKNOWN; j++) 2613 if (cc == cc_convs[i].convs[j].cc) 2614 { 2615 const char *mmix_cc 2616 = (reversed ? cc_convs[i].convs[j].reversed 2617 : cc_convs[i].convs[j].normal); 2618 2619 if (mmix_cc == NULL) 2620 fatal_insn ("MMIX Internal: Trying to output invalidly\ 2621 reversed condition:", x); 2622 2623 fprintf (stream, "%s", mmix_cc); 2624 return; 2625 } 2626 2627 fatal_insn ("MMIX Internal: What's the CC of this?", x); 2628 } 2629 } 2630 2631 fatal_insn ("MMIX Internal: What is the CC of this?", x); 2632} 2633 2634/* Return the bit-value for a const_int or const_double. */ 2635 2636static HOST_WIDEST_INT 2637mmix_intval (rtx x) 2638{ 2639 unsigned HOST_WIDEST_INT retval; 2640 2641 if (GET_CODE (x) == CONST_INT) 2642 return INTVAL (x); 2643 2644 /* We make a little song and dance because converting to long long in 2645 gcc-2.7.2 is broken. I still want people to be able to use it for 2646 cross-compilation to MMIX. */ 2647 if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == VOIDmode) 2648 { 2649 if (sizeof (HOST_WIDE_INT) < sizeof (HOST_WIDEST_INT)) 2650 { 2651 retval = (unsigned) CONST_DOUBLE_LOW (x) / 2; 2652 retval *= 2; 2653 retval |= CONST_DOUBLE_LOW (x) & 1; 2654 2655 retval |= 2656 (unsigned HOST_WIDEST_INT) CONST_DOUBLE_HIGH (x) 2657 << (HOST_BITS_PER_LONG); 2658 } 2659 else 2660 retval = CONST_DOUBLE_HIGH (x); 2661 2662 return retval; 2663 } 2664 2665 if (GET_CODE (x) == CONST_DOUBLE) 2666 { 2667 REAL_VALUE_TYPE value; 2668 2669 /* FIXME: This macro is not in the manual but should be. */ 2670 REAL_VALUE_FROM_CONST_DOUBLE (value, x); 2671 2672 if (GET_MODE (x) == DFmode) 2673 { 2674 long bits[2]; 2675 2676 REAL_VALUE_TO_TARGET_DOUBLE (value, bits); 2677 2678 /* The double cast is necessary to avoid getting the long 2679 sign-extended to unsigned long long(!) when they're of 2680 different size (usually 32-bit hosts). */ 2681 return 2682 ((unsigned HOST_WIDEST_INT) (unsigned long) bits[0] 2683 << (unsigned HOST_WIDEST_INT) 32U) 2684 | (unsigned HOST_WIDEST_INT) (unsigned long) bits[1]; 2685 } 2686 else if (GET_MODE (x) == SFmode) 2687 { 2688 long bits; 2689 REAL_VALUE_TO_TARGET_SINGLE (value, bits); 2690 2691 return (unsigned long) bits; 2692 } 2693 } 2694 2695 fatal_insn ("MMIX Internal: This is not a constant:", x); 2696} 2697 2698/* Worker function for TARGET_PROMOTE_FUNCTION_MODE. */ 2699 2700enum machine_mode 2701mmix_promote_function_mode (const_tree type ATTRIBUTE_UNUSED, 2702 enum machine_mode mode, 2703 int *punsignedp ATTRIBUTE_UNUSED, 2704 const_tree fntype ATTRIBUTE_UNUSED, 2705 int for_return) 2706{ 2707 /* Apparently not doing TRT if int < register-size. FIXME: Perhaps 2708 FUNCTION_VALUE and LIBCALL_VALUE needs tweaking as some ports say. */ 2709 if (for_return == 1) 2710 return mode; 2711 2712 /* Promotion of modes currently generates slow code, extending before 2713 operation, so we do it only for arguments. */ 2714 if (GET_MODE_CLASS (mode) == MODE_INT 2715 && GET_MODE_SIZE (mode) < 8) 2716 return DImode; 2717 else 2718 return mode; 2719} 2720/* Worker function for TARGET_STRUCT_VALUE_RTX. */ 2721 2722static rtx 2723mmix_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED, 2724 int incoming ATTRIBUTE_UNUSED) 2725{ 2726 return gen_rtx_REG (Pmode, MMIX_STRUCT_VALUE_REGNUM); 2727} 2728 2729/* Worker function for TARGET_FRAME_POINTER_REQUIRED. 2730 2731 FIXME: Is this requirement built-in? Anyway, we should try to get rid 2732 of it; we can deduce the value. */ 2733 2734bool 2735mmix_frame_pointer_required (void) 2736{ 2737 return (cfun->has_nonlocal_label); 2738} 2739 2740/* 2741 * Local variables: 2742 * eval: (c-set-style "gnu") 2743 * indent-tabs-mode: t 2744 * End: 2745 */ 2746