1 /* Subroutines for insn-output.c for Motorola 88000. 2 Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 3 2001, 2002 Free Software Foundation, Inc. 4 Contributed by Michael Tiemann (tiemann@mcc.com) 5 Currently maintained by (gcc@dg-rtp.dg.com) 6 7 This file is part of GNU CC. 8 9 GNU CC is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2, or (at your option) 12 any later version. 13 14 GNU CC is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with GNU CC; see the file COPYING. If not, write to 21 the Free Software Foundation, 59 Temple Place - Suite 330, 22 Boston, MA 02111-1307, USA. */ 23 24 #include "config.h" 25 #include "system.h" 26 #include "rtl.h" 27 #include "regs.h" 28 #include "hard-reg-set.h" 29 #include "real.h" 30 #include "insn-config.h" 31 #include "conditions.h" 32 #include "output.h" 33 #include "insn-attr.h" 34 #include "tree.h" 35 #include "function.h" 36 #include "expr.h" 37 #include "libfuncs.h" 38 #include "c-tree.h" 39 #include "flags.h" 40 #include "recog.h" 41 #include "toplev.h" 42 #include "tm_p.h" 43 #include "target.h" 44 #include "target-def.h" 45 46 #ifdef REGISTER_PREFIX 47 const char *m88k_register_prefix = REGISTER_PREFIX; 48 #else 49 const char *m88k_register_prefix = ""; 50 #endif 51 char m88k_volatile_code; 52 53 int m88k_fp_offset = 0; /* offset of frame pointer if used */ 54 int m88k_stack_size = 0; /* size of allocated stack (including frame) */ 55 int m88k_case_index; 56 57 rtx m88k_compare_reg; /* cmp output pseudo register */ 58 rtx m88k_compare_op0; /* cmpsi operand 0 */ 59 rtx m88k_compare_op1; /* cmpsi operand 1 */ 60 61 enum processor_type m88k_cpu; /* target cpu */ 62 63 static void m88k_frame_related PARAMS ((rtx, rtx, HOST_WIDE_INT)); 64 static void m88k_maybe_dead PARAMS ((rtx)); 65 static void m88k_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT)); 66 static int m88k_adjust_cost PARAMS ((rtx, rtx, rtx, int)); 67 68 /* Initialize the GCC target structure. */ 69 #if !defined(OBJECT_FORMAT_ELF) 70 #undef TARGET_ASM_BYTE_OP 71 #define TARGET_ASM_BYTE_OP "\tbyte\t" 72 #undef TARGET_ASM_ALIGNED_HI_OP 73 #define TARGET_ASM_ALIGNED_HI_OP "\thalf\t" 74 #undef TARGET_ASM_ALIGNED_SI_OP 75 #define TARGET_ASM_ALIGNED_SI_OP "\tword\t" 76 #undef TARGET_ASM_UNALIGNED_HI_OP 77 #define TARGET_ASM_UNALIGNED_HI_OP "\tuahalf\t" 78 #undef TARGET_ASM_UNALIGNED_SI_OP 79 #define TARGET_ASM_UNALIGNED_SI_OP "\tuaword\t" 80 #endif 81 82 #undef TARGET_ASM_FUNCTION_EPILOGUE 83 #define TARGET_ASM_FUNCTION_EPILOGUE m88k_output_function_epilogue 84 85 #undef TARGET_SCHED_ADJUST_COST 86 #define TARGET_SCHED_ADJUST_COST m88k_adjust_cost 87 88 struct gcc_target targetm = TARGET_INITIALIZER; 89 90 /* Determine what instructions are needed to manufacture the integer VALUE 91 in the given MODE. */ 92 93 enum m88k_instruction 94 classify_integer (mode, value) 95 enum machine_mode mode; 96 register int value; 97 { 98 if (value == 0) 99 return m88k_zero; 100 else if (SMALL_INTVAL (value)) 101 return m88k_or; 102 else if (SMALL_INTVAL (-value)) 103 return m88k_subu; 104 else if (mode == HImode) 105 return m88k_or_lo16; 106 else if (mode == QImode) 107 return m88k_or_lo8; 108 else if (integer_ok_for_set (value)) 109 return m88k_set; 110 else if ((value & 0xffff) == 0) 111 return m88k_oru_hi16; 112 else 113 return m88k_oru_or; 114 } 115 116 /* Return the bit number in a compare word corresponding to CONDITION. */ 117 118 int 119 condition_value (condition) 120 rtx condition; 121 { 122 switch (GET_CODE (condition)) 123 { 124 case UNORDERED: 125 return 0; 126 case ORDERED: 127 return 1; 128 case EQ: 129 return 2; 130 case NE: 131 return 3; 132 case GT: 133 return 4; 134 case LE: 135 return 5; 136 case LT: 137 return 6; 138 case GE: 139 return 7; 140 case GTU: 141 return 8; 142 case LEU: 143 return 9; 144 case LTU: 145 return 10; 146 case GEU: 147 return 11; 148 default: 149 abort (); 150 } 151 } 152 153 int 154 integer_ok_for_set (value) 155 register unsigned value; 156 { 157 /* All the "one" bits must be contiguous. If so, MASK + 1 will be 158 a power of two or zero. */ 159 register unsigned mask = (value | (value - 1)); 160 return (value && POWER_OF_2_or_0 (mask + 1)); 161 } 162 163 const char * 164 output_load_const_int (mode, operands) 165 enum machine_mode mode; 166 rtx *operands; 167 { 168 static const char *const patterns[] = 169 { "or %0,%#r0,0", 170 "or %0,%#r0,%1", 171 "subu %0,%#r0,%n1", 172 "or %0,%#r0,%h1", 173 "or %0,%#r0,%q1", 174 "set %0,%#r0,%s1", 175 "or.u %0,%#r0,%X1", 176 "or.u %0,%#r0,%X1\n\tor %0,%0,%x1", 177 }; 178 179 if (! REG_P (operands[0]) 180 || GET_CODE (operands[1]) != CONST_INT) 181 abort (); 182 return patterns[classify_integer (mode, INTVAL (operands[1]))]; 183 } 184 185 /* These next two routines assume that floating point numbers are represented 186 in a manner which is consistent between host and target machines. */ 187 188 const char * 189 output_load_const_float (operands) 190 rtx *operands; 191 { 192 /* These can return 0 under some circumstances when cross-compiling. */ 193 operands[0] = operand_subword (operands[0], 0, 0, SFmode); 194 operands[1] = operand_subword (operands[1], 0, 0, SFmode); 195 196 return output_load_const_int (SImode, operands); 197 } 198 199 const char * 200 output_load_const_double (operands) 201 rtx *operands; 202 { 203 rtx latehalf[2]; 204 205 /* These can return zero on some cross-compilers, but there's nothing 206 we can do about it. */ 207 latehalf[0] = operand_subword (operands[0], 1, 0, DFmode); 208 latehalf[1] = operand_subword (operands[1], 1, 0, DFmode); 209 210 operands[0] = operand_subword (operands[0], 0, 0, DFmode); 211 operands[1] = operand_subword (operands[1], 0, 0, DFmode); 212 213 output_asm_insn (output_load_const_int (SImode, operands), operands); 214 215 operands[0] = latehalf[0]; 216 operands[1] = latehalf[1]; 217 218 return output_load_const_int (SImode, operands); 219 } 220 221 const char * 222 output_load_const_dimode (operands) 223 rtx *operands; 224 { 225 rtx latehalf[2]; 226 227 latehalf[0] = operand_subword (operands[0], 1, 0, DImode); 228 latehalf[1] = operand_subword (operands[1], 1, 0, DImode); 229 230 operands[0] = operand_subword (operands[0], 0, 0, DImode); 231 operands[1] = operand_subword (operands[1], 0, 0, DImode); 232 233 output_asm_insn (output_load_const_int (SImode, operands), operands); 234 235 operands[0] = latehalf[0]; 236 operands[1] = latehalf[1]; 237 238 return output_load_const_int (SImode, operands); 239 } 240 241 /* Emit insns to move operands[1] into operands[0]. 242 243 Return 1 if we have written out everything that needs to be done to 244 do the move. Otherwise, return 0 and the caller will emit the move 245 normally. 246 247 SCRATCH if nonzero can be used as a scratch register for the move 248 operation. It is provided by a SECONDARY_RELOAD_* macro if needed. */ 249 250 int 251 emit_move_sequence (operands, mode, scratch) 252 rtx *operands; 253 enum machine_mode mode; 254 rtx scratch; 255 { 256 register rtx operand0 = operands[0]; 257 register rtx operand1 = operands[1]; 258 259 if (CONSTANT_P (operand1) && flag_pic 260 && pic_address_needs_scratch (operand1)) 261 operands[1] = operand1 = legitimize_address (1, operand1, 0, 0); 262 263 /* Handle most common case first: storing into a register. */ 264 if (register_operand (operand0, mode)) 265 { 266 if (register_operand (operand1, mode) 267 || (GET_CODE (operand1) == CONST_INT && SMALL_INT (operand1)) 268 || GET_CODE (operand1) == HIGH 269 /* Only `general_operands' can come here, so MEM is ok. */ 270 || GET_CODE (operand1) == MEM) 271 { 272 /* Run this case quickly. */ 273 emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1)); 274 return 1; 275 } 276 } 277 else if (GET_CODE (operand0) == MEM) 278 { 279 if (register_operand (operand1, mode) 280 || (operand1 == const0_rtx && GET_MODE_SIZE (mode) <= UNITS_PER_WORD)) 281 { 282 /* Run this case quickly. */ 283 emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1)); 284 return 1; 285 } 286 if (! reload_in_progress && ! reload_completed) 287 { 288 operands[0] = validize_mem (operand0); 289 operands[1] = operand1 = force_reg (mode, operand1); 290 } 291 } 292 293 /* Simplify the source if we need to. */ 294 if (GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode)) 295 { 296 if (GET_CODE (operand1) != CONST_INT 297 && GET_CODE (operand1) != CONST_DOUBLE) 298 { 299 rtx temp = ((reload_in_progress || reload_completed) 300 ? operand0 : 0); 301 operands[1] = legitimize_address (flag_pic 302 && symbolic_address_p (operand1), 303 operand1, temp, scratch); 304 if (mode != SImode) 305 operands[1] = gen_rtx_SUBREG (mode, operands[1], 0); 306 } 307 } 308 309 /* Now have insn-emit do whatever it normally does. */ 310 return 0; 311 } 312 313 /* Return a legitimate reference for ORIG (either an address or a MEM) 314 using the register REG. If PIC and the address is already 315 position-independent, use ORIG. Newly generated position-independent 316 addresses go into a reg. This is REG if nonzero, otherwise we 317 allocate register(s) as necessary. If this is called during reload, 318 and we need a second temp register, then we use SCRATCH, which is 319 provided via the SECONDARY_INPUT_RELOAD_CLASS mechanism. */ 320 321 struct rtx_def * 322 legitimize_address (pic, orig, reg, scratch) 323 int pic; 324 rtx orig; 325 rtx reg; 326 rtx scratch; 327 { 328 rtx addr = (GET_CODE (orig) == MEM ? XEXP (orig, 0) : orig); 329 rtx new = orig; 330 rtx temp, insn; 331 332 if (pic) 333 { 334 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF) 335 { 336 if (reg == 0) 337 { 338 if (reload_in_progress || reload_completed) 339 abort (); 340 else 341 reg = gen_reg_rtx (Pmode); 342 } 343 344 if (flag_pic == 2) 345 { 346 /* If not during reload, allocate another temp reg here for 347 loading in the address, so that these instructions can be 348 optimized properly. */ 349 temp = ((reload_in_progress || reload_completed) 350 ? reg : gen_reg_rtx (Pmode)); 351 352 /* Must put the SYMBOL_REF inside an UNSPEC here so that cse 353 won't get confused into thinking that these two instructions 354 are loading in the true address of the symbol. If in the 355 future a PIC rtx exists, that should be used instead. */ 356 emit_insn (gen_movsi_high_pic (temp, addr)); 357 emit_insn (gen_movsi_lo_sum_pic (temp, temp, addr)); 358 addr = temp; 359 } 360 361 new = gen_rtx_MEM (Pmode, 362 gen_rtx_PLUS (SImode, 363 pic_offset_table_rtx, addr)); 364 365 current_function_uses_pic_offset_table = 1; 366 RTX_UNCHANGING_P (new) = 1; 367 insn = emit_move_insn (reg, new); 368 /* Put a REG_EQUAL note on this insn, so that it can be optimized 369 by loop. */ 370 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig, 371 REG_NOTES (insn)); 372 new = reg; 373 } 374 else if (GET_CODE (addr) == CONST) 375 { 376 rtx base; 377 378 if (GET_CODE (XEXP (addr, 0)) == PLUS 379 && XEXP (XEXP (addr, 0), 0) == pic_offset_table_rtx) 380 return orig; 381 382 if (reg == 0) 383 { 384 if (reload_in_progress || reload_completed) 385 abort (); 386 else 387 reg = gen_reg_rtx (Pmode); 388 } 389 390 if (GET_CODE (XEXP (addr, 0)) != PLUS) abort (); 391 392 base = legitimize_address (1, XEXP (XEXP (addr, 0), 0), reg, 0); 393 addr = legitimize_address (1, XEXP (XEXP (addr, 0), 1), 394 base == reg ? 0 : reg, 0); 395 396 if (GET_CODE (addr) == CONST_INT) 397 { 398 if (ADD_INT (addr)) 399 return plus_constant (base, INTVAL (addr)); 400 else if (! reload_in_progress && ! reload_completed) 401 addr = force_reg (Pmode, addr); 402 /* We can't create any new registers during reload, so use the 403 SCRATCH reg provided by the reload_insi pattern. */ 404 else if (scratch) 405 { 406 emit_move_insn (scratch, addr); 407 addr = scratch; 408 } 409 else 410 /* If we reach here, then the SECONDARY_INPUT_RELOAD_CLASS 411 macro needs to be adjusted so that a scratch reg is provided 412 for this address. */ 413 abort (); 414 } 415 new = gen_rtx_PLUS (SImode, base, addr); 416 /* Should we set special REG_NOTEs here? */ 417 } 418 } 419 else 420 { 421 if (reg == 0) 422 { 423 if (reload_in_progress || reload_completed) 424 abort (); 425 else 426 reg = gen_reg_rtx (Pmode); 427 } 428 429 emit_insn (gen_rtx_SET (VOIDmode, 430 reg, gen_rtx_HIGH (SImode, addr))); 431 new = gen_rtx_LO_SUM (SImode, reg, addr); 432 } 433 434 if (GET_CODE (orig) == MEM) 435 { 436 new = gen_rtx_MEM (GET_MODE (orig), new); 437 MEM_COPY_ATTRIBUTES (new, orig); 438 } 439 return new; 440 } 441 442 /* Support functions for code to emit a block move. There are four methods 443 used to perform the block move: 444 + call memcpy 445 + call the looping library function, e.g. __movstrSI64n8 446 + call a non-looping library function, e.g. __movstrHI15x11 447 + produce an inline sequence of ld/st instructions 448 449 The parameters below describe the library functions produced by 450 movstr-m88k.sh. */ 451 452 #define MOVSTR_LOOP 64 /* __movstrSI64n68 .. __movstrSI64n8 */ 453 #define MOVSTR_QI 16 /* __movstrQI16x16 .. __movstrQI16x2 */ 454 #define MOVSTR_HI 48 /* __movstrHI48x48 .. __movstrHI48x4 */ 455 #define MOVSTR_SI 96 /* __movstrSI96x96 .. __movstrSI96x8 */ 456 #define MOVSTR_DI 96 /* __movstrDI96x96 .. __movstrDI96x16 */ 457 #define MOVSTR_ODD_HI 16 /* __movstrHI15x15 .. __movstrHI15x5 */ 458 #define MOVSTR_ODD_SI 48 /* __movstrSI47x47 .. __movstrSI47x11, 459 __movstrSI46x46 .. __movstrSI46x10, 460 __movstrSI45x45 .. __movstrSI45x9 */ 461 #define MOVSTR_ODD_DI 48 /* __movstrDI47x47 .. __movstrDI47x23, 462 __movstrDI46x46 .. __movstrDI46x22, 463 __movstrDI45x45 .. __movstrDI45x21, 464 __movstrDI44x44 .. __movstrDI44x20, 465 __movstrDI43x43 .. __movstrDI43x19, 466 __movstrDI42x42 .. __movstrDI42x18, 467 __movstrDI41x41 .. __movstrDI41x17 */ 468 469 /* Limits for using the non-looping movstr functions. For the m88100 470 processor, we assume the source and destination are word aligned. 471 The QImode and HImode limits are the break even points where memcpy 472 does just as well and beyond which memcpy does better. For the 473 m88110, we tend to assume double word alignment, but also analyze 474 the word aligned cases. The analysis is complicated because memcpy 475 may use the cache control instructions for better performance. */ 476 477 #define MOVSTR_QI_LIMIT_88100 13 478 #define MOVSTR_HI_LIMIT_88100 38 479 #define MOVSTR_SI_LIMIT_88100 MOVSTR_SI 480 #define MOVSTR_DI_LIMIT_88100 MOVSTR_SI 481 482 #define MOVSTR_QI_LIMIT_88000 16 483 #define MOVSTR_HI_LIMIT_88000 38 484 #define MOVSTR_SI_LIMIT_88000 72 485 #define MOVSTR_DI_LIMIT_88000 72 486 487 #define MOVSTR_QI_LIMIT_88110 16 488 #define MOVSTR_HI_LIMIT_88110 38 489 #define MOVSTR_SI_LIMIT_88110 72 490 #define MOVSTR_DI_LIMIT_88110 72 491 492 static const enum machine_mode mode_from_align[] = 493 {VOIDmode, QImode, HImode, VOIDmode, SImode, 494 VOIDmode, VOIDmode, VOIDmode, DImode}; 495 static const int max_from_align[] = {0, MOVSTR_QI, MOVSTR_HI, 0, MOVSTR_SI, 496 0, 0, 0, MOVSTR_DI}; 497 static const int all_from_align[] = {0, MOVSTR_QI, MOVSTR_ODD_HI, 0, 498 MOVSTR_ODD_SI, 0, 0, 0, MOVSTR_ODD_DI}; 499 500 static const int best_from_align[3][9] = { 501 {0, MOVSTR_QI_LIMIT_88100, MOVSTR_HI_LIMIT_88100, 0, MOVSTR_SI_LIMIT_88100, 502 0, 0, 0, MOVSTR_DI_LIMIT_88100}, 503 {0, MOVSTR_QI_LIMIT_88110, MOVSTR_HI_LIMIT_88110, 0, MOVSTR_SI_LIMIT_88110, 504 0, 0, 0, MOVSTR_DI_LIMIT_88110}, 505 {0, MOVSTR_QI_LIMIT_88000, MOVSTR_HI_LIMIT_88000, 0, MOVSTR_SI_LIMIT_88000, 506 0, 0, 0, MOVSTR_DI_LIMIT_88000} 507 }; 508 509 #if 0 510 static void block_move_loop PARAMS ((rtx, rtx, rtx, rtx, int, int)); 511 static void block_move_no_loop PARAMS ((rtx, rtx, rtx, rtx, int, int)); 512 #endif 513 static void block_move_sequence PARAMS ((rtx, rtx, rtx, rtx, int, int, int)); 514 static void output_short_branch_defs PARAMS ((FILE *)); 515 516 /* Emit code to perform a block move. Choose the best method. 517 518 OPERANDS[0] is the destination. 519 OPERANDS[1] is the source. 520 OPERANDS[2] is the size. 521 OPERANDS[3] is the alignment safe to use. */ 522 523 void 524 expand_block_move (dest_mem, src_mem, operands) 525 rtx dest_mem; 526 rtx src_mem; 527 rtx *operands; 528 { 529 int align = INTVAL (operands[3]); 530 int constp = (GET_CODE (operands[2]) == CONST_INT); 531 int bytes = (constp ? INTVAL (operands[2]) : 0); 532 #if 0 533 int target = (int) m88k_cpu; 534 #endif 535 536 if (constp && bytes <= 0) 537 return; 538 539 /* Determine machine mode to do move with. */ 540 if (align > 4 && !TARGET_88110) 541 align = 4; 542 else if (align <= 0 || align == 3) 543 abort (); /* block move invalid alignment. */ 544 545 if (constp && bytes <= 3 * align) 546 block_move_sequence (operands[0], dest_mem, operands[1], src_mem, 547 bytes, align, 0); 548 549 #if 0 550 else if (constp && bytes <= best_from_align[target][align] && !TARGET_MEMCPY) 551 block_move_no_loop (operands[0], dest_mem, operands[1], src_mem, 552 bytes, align); 553 554 else if (constp && align == 4 && TARGET_88100 && !TARGET_MEMCPY) 555 block_move_loop (operands[0], dest_mem, operands[1], src_mem, 556 bytes, align); 557 #endif 558 559 else 560 { 561 #ifdef TARGET_MEM_FUNCTIONS 562 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "memcpy"), 0, 563 VOIDmode, 3, 564 operands[0], Pmode, 565 operands[1], Pmode, 566 convert_to_mode (TYPE_MODE (sizetype), operands[2], 567 TREE_UNSIGNED (sizetype)), 568 TYPE_MODE (sizetype)); 569 #else 570 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "bcopy"), 0, 571 VOIDmode, 3, 572 operands[1], Pmode, 573 operands[0], Pmode, 574 convert_to_mode (TYPE_MODE (integer_type_node), 575 operands[2], 576 TREE_UNSIGNED (integer_type_node)), 577 TYPE_MODE (integer_type_node)); 578 #endif 579 } 580 } 581 582 #if 0 583 /* Emit code to perform a block move by calling a looping movstr library 584 function. SIZE and ALIGN are known constants. DEST and SRC are 585 registers. */ 586 587 static void 588 block_move_loop (dest, dest_mem, src, src_mem, size, align) 589 rtx dest, dest_mem; 590 rtx src, src_mem; 591 int size; 592 int align; 593 { 594 enum machine_mode mode; 595 int count; 596 int units; 597 int remainder; 598 rtx offset_rtx; 599 rtx value_rtx; 600 char entry[30]; 601 tree entry_name; 602 603 /* Determine machine mode to do move with. */ 604 if (align != 4) 605 abort (); 606 607 /* Determine the structure of the loop. */ 608 count = size / MOVSTR_LOOP; 609 units = (size - count * MOVSTR_LOOP) / align; 610 611 if (units < 2) 612 { 613 count--; 614 units += MOVSTR_LOOP / align; 615 } 616 617 if (count <= 0) 618 { 619 block_move_no_loop (dest, dest_mem, src, src_mem, size, align); 620 return; 621 } 622 623 remainder = size - count * MOVSTR_LOOP - units * align; 624 625 mode = mode_from_align[align]; 626 sprintf (entry, "__movstr%s%dn%d", 627 GET_MODE_NAME (mode), MOVSTR_LOOP, units * align); 628 entry_name = get_identifier (entry); 629 630 offset_rtx = GEN_INT (MOVSTR_LOOP + (1 - units) * align); 631 632 value_rtx = gen_rtx_MEM (MEM_IN_STRUCT_P (src_mem) ? mode : BLKmode, 633 gen_rtx_PLUS (Pmode, 634 gen_rtx_REG (Pmode, 3), 635 offset_rtx)); 636 MEM_COPY_ATTRIBUTES (value_rtx, src_mem); 637 638 emit_insn (gen_call_movstrsi_loop 639 (gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (entry_name)), 640 dest, src, offset_rtx, value_rtx, 641 gen_rtx_REG (mode, ((units & 1) ? 4 : 5)), 642 GEN_INT (count))); 643 644 if (remainder) 645 block_move_sequence (gen_rtx_REG (Pmode, 2), dest_mem, 646 gen_rtx_REG (Pmode, 3), src_mem, 647 remainder, align, MOVSTR_LOOP + align); 648 } 649 650 /* Emit code to perform a block move by calling a non-looping library 651 function. SIZE and ALIGN are known constants. DEST and SRC are 652 registers. OFFSET is the known starting point for the output pattern. */ 653 654 static void 655 block_move_no_loop (dest, dest_mem, src, src_mem, size, align) 656 rtx dest, dest_mem; 657 rtx src, src_mem; 658 int size; 659 int align; 660 { 661 enum machine_mode mode = mode_from_align[align]; 662 int units = size / align; 663 int remainder = size - units * align; 664 int most; 665 int value_reg; 666 rtx offset_rtx; 667 rtx value_rtx; 668 char entry[30]; 669 tree entry_name; 670 671 if (remainder && size <= all_from_align[align]) 672 { 673 most = all_from_align[align] - (align - remainder); 674 remainder = 0; 675 } 676 else 677 { 678 most = max_from_align[align]; 679 } 680 681 sprintf (entry, "__movstr%s%dx%d", 682 GET_MODE_NAME (mode), most, size - remainder); 683 entry_name = get_identifier (entry); 684 685 offset_rtx = GEN_INT (most - (size - remainder)); 686 687 value_rtx = gen_rtx_MEM (MEM_IN_STRUCT_P (src_mem) ? mode : BLKmode, 688 gen_rtx_PLUS (Pmode, 689 gen_rtx_REG (Pmode, 3), 690 offset_rtx)); 691 692 MEM_COPY_ATTRIBUTES (value_rtx, src_mem); 693 694 value_reg = ((((most - (size - remainder)) / align) & 1) == 0 695 ? (mode == DImode ? 6 : 5) : 4); 696 697 if (mode == DImode) 698 { 699 emit_insn (gen_call_block_move_DI 700 (gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (entry_name)), 701 dest, src, offset_rtx, value_rtx, 702 gen_rtx_REG (mode, value_reg))); 703 } 704 else 705 { 706 emit_insn (gen_call_block_move 707 (gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (entry_name)), 708 dest, src, offset_rtx, value_rtx, 709 gen_rtx_REG (mode, value_reg))); 710 } 711 712 if (remainder) 713 block_move_sequence (gen_rtx_REG (Pmode, 2), dest_mem, 714 gen_rtx_REG (Pmode, 3), src_mem, 715 remainder, align, most); 716 } 717 #endif 718 719 /* Emit code to perform a block move with an offset sequence of ld/st 720 instructions (..., ld 0, st 1, ld 1, st 0, ...). SIZE and ALIGN are 721 known constants. DEST and SRC are registers. OFFSET is the known 722 starting point for the output pattern. */ 723 724 static void 725 block_move_sequence (dest, dest_mem, src, src_mem, size, align, offset) 726 rtx dest, dest_mem; 727 rtx src, src_mem; 728 int size; 729 int align; 730 int offset; 731 { 732 rtx temp[2]; 733 enum machine_mode mode[2]; 734 int amount[2]; 735 int active[2]; 736 int phase = 0; 737 int next; 738 int offset_ld = offset; 739 int offset_st = offset; 740 741 active[0] = active[1] = FALSE; 742 743 /* Establish parameters for the first load and for the second load if 744 it is known to be the same mode as the first. */ 745 amount[0] = amount[1] = align; 746 mode[0] = mode_from_align[align]; 747 temp[0] = gen_reg_rtx (mode[0]); 748 if (size >= 2 * align) 749 { 750 mode[1] = mode[0]; 751 temp[1] = gen_reg_rtx (mode[1]); 752 } 753 754 do 755 { 756 next = phase; 757 phase = !phase; 758 759 if (size > 0) 760 { 761 /* Change modes as the sequence tails off. */ 762 if (size < amount[next]) 763 { 764 amount[next] = (size >= 4 ? 4 : (size >= 2 ? 2 : 1)); 765 mode[next] = mode_from_align[amount[next]]; 766 temp[next] = gen_reg_rtx (mode[next]); 767 } 768 size -= amount[next]; 769 emit_move_insn (temp[next], 770 adjust_address (src_mem, mode[next], offset_ld)); 771 offset_ld += amount[next]; 772 active[next] = TRUE; 773 } 774 775 if (active[phase]) 776 { 777 active[phase] = FALSE; 778 emit_move_insn (adjust_address (dest_mem, mode[phase], offset_st), 779 temp[phase]); 780 offset_st += amount[phase]; 781 } 782 } 783 while (active[next]); 784 } 785 786 /* Emit the code to do an AND operation. */ 787 788 const char * 789 output_and (operands) 790 rtx operands[]; 791 { 792 unsigned int value; 793 794 if (REG_P (operands[2])) 795 return "and %0,%1,%2"; 796 797 value = INTVAL (operands[2]); 798 if (SMALL_INTVAL (value)) 799 return "mask %0,%1,%2"; 800 else if ((value & 0xffff0000) == 0xffff0000) 801 return "and %0,%1,%x2"; 802 else if ((value & 0xffff) == 0xffff) 803 return "and.u %0,%1,%X2"; 804 else if ((value & 0xffff) == 0) 805 return "mask.u %0,%1,%X2"; 806 else if (integer_ok_for_set (~value)) 807 return "clr %0,%1,%S2"; 808 else 809 return "and.u %0,%1,%X2\n\tand %0,%0,%x2"; 810 } 811 812 /* Emit the code to do an inclusive OR operation. */ 813 814 const char * 815 output_ior (operands) 816 rtx operands[]; 817 { 818 unsigned int value; 819 820 if (REG_P (operands[2])) 821 return "or %0,%1,%2"; 822 823 value = INTVAL (operands[2]); 824 if (SMALL_INTVAL (value)) 825 return "or %0,%1,%2"; 826 else if ((value & 0xffff) == 0) 827 return "or.u %0,%1,%X2"; 828 else if (integer_ok_for_set (value)) 829 return "set %0,%1,%s2"; 830 else 831 return "or.u %0,%1,%X2\n\tor %0,%0,%x2"; 832 } 833 834 /* Emit the instructions for doing an XOR. */ 835 836 const char * 837 output_xor (operands) 838 rtx operands[]; 839 { 840 unsigned int value; 841 842 if (REG_P (operands[2])) 843 return "xor %0,%1,%2"; 844 845 value = INTVAL (operands[2]); 846 if (SMALL_INTVAL (value)) 847 return "xor %0,%1,%2"; 848 else if ((value & 0xffff) == 0) 849 return "xor.u %0,%1,%X2"; 850 else 851 return "xor.u %0,%1,%X2\n\txor %0,%0,%x2"; 852 } 853 854 /* Output a call. Normally this is just bsr or jsr, but this also deals with 855 accomplishing a branch after the call by incrementing r1. This requires 856 that various assembler bugs be accommodated. The 4.30 DG/UX assembler 857 requires that forward references not occur when computing the difference of 858 two labels. The [version?] Motorola assembler computes a word difference. 859 No doubt there's more to come! 860 861 It would seem the same idea could be used to tail call, but in this case, 862 the epilogue will be non-null. */ 863 864 static rtx sb_name = 0; 865 static rtx sb_high = 0; 866 static rtx sb_low = 0; 867 868 const char * 869 output_call (operands, addr) 870 rtx operands[]; 871 rtx addr; 872 { 873 operands[0] = addr; 874 if (final_sequence) 875 { 876 rtx jump; 877 rtx seq_insn; 878 879 /* This can be generalized, but there is currently no need. */ 880 if (XVECLEN (final_sequence, 0) != 2) 881 abort (); 882 883 /* The address of interior insns is not computed, so use the sequence. */ 884 seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0))); 885 jump = XVECEXP (final_sequence, 0, 1); 886 if (GET_CODE (jump) == JUMP_INSN) 887 { 888 #ifndef USE_GAS 889 rtx low, high; 890 #endif 891 const char *last; 892 rtx dest = XEXP (SET_SRC (PATTERN (jump)), 0); 893 int delta = 4 * (INSN_ADDRESSES (INSN_UID (dest)) 894 - INSN_ADDRESSES (INSN_UID (seq_insn)) 895 - 2); 896 897 /* Delete the jump. */ 898 PUT_CODE (jump, NOTE); 899 NOTE_LINE_NUMBER (jump) = NOTE_INSN_DELETED; 900 NOTE_SOURCE_FILE (jump) = 0; 901 902 /* We only do this optimization if -O2, modifying the value of 903 r1 in the delay slot confuses debuggers and profilers on some 904 systems. 905 906 If we loose, we must use the non-delay form. This is unlikely 907 to ever happen. If it becomes a problem, claim that a call 908 has two delay slots and only the second can be filled with 909 a jump. 910 911 The 88110 can lose when a jsr.n r1 is issued and a page fault 912 occurs accessing the delay slot. So don't use jsr.n form when 913 jumping thru r1. 914 */ 915 if (optimize < 2 916 || ! ADD_INTVAL (delta) 917 || (REG_P (addr) && REGNO (addr) == 1)) 918 { 919 operands[1] = dest; 920 return (REG_P (addr) 921 ? "jsr %0\n\tbr %l1" 922 : (flag_pic 923 ? "bsr %0#plt\n\tbr %l1" 924 : "bsr %0\n\tbr %l1")); 925 } 926 927 /* Output the short branch form. */ 928 output_asm_insn ((REG_P (addr) 929 ? "jsr.n %0" 930 : (flag_pic ? "bsr.n %0#plt" : "bsr.n %0")), 931 operands); 932 933 #ifdef USE_GAS 934 last = (delta < 0 935 ? "subu %#r1,%#r1,.-%l0+4" 936 : "addu %#r1,%#r1,%l0-.-4"); 937 operands[0] = dest; 938 #else 939 operands[0] = gen_label_rtx (); 940 operands[1] = gen_label_rtx (); 941 if (delta < 0) 942 { 943 low = dest; 944 high = operands[1]; 945 last = "subu %#r1,%#r1,%l0\n%l1:"; 946 } 947 else 948 { 949 low = operands[1]; 950 high = dest; 951 last = "addu %#r1,%#r1,%l0\n%l1:"; 952 } 953 954 /* Record the values to be computed later as "def name,high-low". */ 955 sb_name = gen_rtx_EXPR_LIST (VOIDmode, operands[0], sb_name); 956 sb_high = gen_rtx_EXPR_LIST (VOIDmode, high, sb_high); 957 sb_low = gen_rtx_EXPR_LIST (VOIDmode, low, sb_low); 958 #endif /* Don't USE_GAS */ 959 960 return last; 961 } 962 } 963 return (REG_P (addr) 964 ? "jsr%. %0" 965 : (flag_pic ? "bsr%. %0#plt" : "bsr%. %0")); 966 } 967 968 static void 969 output_short_branch_defs (stream) 970 FILE *stream; 971 { 972 char name[256], high[256], low[256]; 973 974 for (; sb_name && sb_high && sb_low; 975 sb_name = XEXP (sb_name, 1), 976 sb_high = XEXP (sb_high, 1), 977 sb_low = XEXP (sb_low, 1)) 978 { 979 ASM_GENERATE_INTERNAL_LABEL 980 (name, "L", CODE_LABEL_NUMBER (XEXP (sb_name, 0))); 981 ASM_GENERATE_INTERNAL_LABEL 982 (high, "L", CODE_LABEL_NUMBER (XEXP (sb_high, 0))); 983 ASM_GENERATE_INTERNAL_LABEL 984 (low, "L", CODE_LABEL_NUMBER (XEXP (sb_low, 0))); 985 /* This will change as the assembler requirements become known. */ 986 fprintf (stream, "%s%s,%s-%s\n", 987 SET_ASM_OP, &name[1], &high[1], &low[1]); 988 } 989 if (sb_name || sb_high || sb_low) 990 abort (); 991 } 992 993 /* Return truth value of the statement that this conditional branch is likely 994 to fall through. CONDITION, is the condition that JUMP_INSN is testing. */ 995 996 int 997 mostly_false_jump (jump_insn, condition) 998 rtx jump_insn, condition; 999 { 1000 rtx target_label = JUMP_LABEL (jump_insn); 1001 rtx insnt, insnj; 1002 1003 /* Much of this isn't computed unless we're optimizing. */ 1004 if (optimize == 0) 1005 return 0; 1006 1007 /* Determine if one path or the other leads to a return. */ 1008 for (insnt = NEXT_INSN (target_label); 1009 insnt; 1010 insnt = NEXT_INSN (insnt)) 1011 { 1012 if (GET_CODE (insnt) == JUMP_INSN) 1013 break; 1014 else if (GET_CODE (insnt) == INSN 1015 && GET_CODE (PATTERN (insnt)) == SEQUENCE 1016 && GET_CODE (XVECEXP (PATTERN (insnt), 0, 0)) == JUMP_INSN) 1017 { 1018 insnt = XVECEXP (PATTERN (insnt), 0, 0); 1019 break; 1020 } 1021 } 1022 if (insnt 1023 && (GET_CODE (PATTERN (insnt)) == RETURN 1024 || (GET_CODE (PATTERN (insnt)) == SET 1025 && GET_CODE (SET_SRC (PATTERN (insnt))) == REG 1026 && REGNO (SET_SRC (PATTERN (insnt))) == 1))) 1027 insnt = 0; 1028 1029 for (insnj = NEXT_INSN (jump_insn); 1030 insnj; 1031 insnj = NEXT_INSN (insnj)) 1032 { 1033 if (GET_CODE (insnj) == JUMP_INSN) 1034 break; 1035 else if (GET_CODE (insnj) == INSN 1036 && GET_CODE (PATTERN (insnj)) == SEQUENCE 1037 && GET_CODE (XVECEXP (PATTERN (insnj), 0, 0)) == JUMP_INSN) 1038 { 1039 insnj = XVECEXP (PATTERN (insnj), 0, 0); 1040 break; 1041 } 1042 } 1043 if (insnj 1044 && (GET_CODE (PATTERN (insnj)) == RETURN 1045 || (GET_CODE (PATTERN (insnj)) == SET 1046 && GET_CODE (SET_SRC (PATTERN (insnj))) == REG 1047 && REGNO (SET_SRC (PATTERN (insnj))) == 1))) 1048 insnj = 0; 1049 1050 /* Predict to not return. */ 1051 if ((insnt == 0) != (insnj == 0)) 1052 return (insnt == 0); 1053 1054 /* Predict loops to loop. */ 1055 for (insnt = PREV_INSN (target_label); 1056 insnt && GET_CODE (insnt) == NOTE; 1057 insnt = PREV_INSN (insnt)) 1058 if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_END) 1059 return 1; 1060 else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_BEG) 1061 return 0; 1062 else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_CONT) 1063 return 0; 1064 1065 /* Predict backward branches usually take. */ 1066 if (final_sequence) 1067 insnj = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0))); 1068 else 1069 insnj = jump_insn; 1070 if (INSN_ADDRESSES (INSN_UID (insnj)) 1071 > INSN_ADDRESSES (INSN_UID (target_label))) 1072 return 0; 1073 1074 /* EQ tests are usually false and NE tests are usually true. Also, 1075 most quantities are positive, so we can make the appropriate guesses 1076 about signed comparisons against zero. Consider unsigned comparisons 1077 to be a range check and assume quantities to be in range. */ 1078 switch (GET_CODE (condition)) 1079 { 1080 case CONST_INT: 1081 /* Unconditional branch. */ 1082 return 0; 1083 case EQ: 1084 return 1; 1085 case NE: 1086 return 0; 1087 case LE: 1088 case LT: 1089 case GEU: 1090 case GTU: /* Must get casesi right at least. */ 1091 if (XEXP (condition, 1) == const0_rtx) 1092 return 1; 1093 break; 1094 case GE: 1095 case GT: 1096 case LEU: 1097 case LTU: 1098 if (XEXP (condition, 1) == const0_rtx) 1099 return 0; 1100 break; 1101 default: 1102 break; 1103 } 1104 1105 return 0; 1106 } 1107 1108 /* Return true if the operand is a power of two and is a floating 1109 point type (to optimize division by power of two into multiplication). */ 1110 1111 int 1112 real_power_of_2_operand (op, mode) 1113 rtx op; 1114 enum machine_mode mode ATTRIBUTE_UNUSED; 1115 { 1116 REAL_VALUE_TYPE d; 1117 union { 1118 long l[2]; 1119 struct { /* IEEE double precision format */ 1120 unsigned sign : 1; 1121 unsigned exponent : 11; 1122 unsigned mantissa1 : 20; 1123 unsigned mantissa2; 1124 } s; 1125 struct { /* IEEE double format to quick check */ 1126 unsigned sign : 1; /* if it fits in a float */ 1127 unsigned exponent1 : 4; 1128 unsigned exponent2 : 7; 1129 unsigned mantissa1 : 20; 1130 unsigned mantissa2; 1131 } s2; 1132 } u; 1133 1134 if (GET_MODE (op) != DFmode && GET_MODE (op) != SFmode) 1135 return 0; 1136 1137 if (GET_CODE (op) != CONST_DOUBLE) 1138 return 0; 1139 1140 REAL_VALUE_FROM_CONST_DOUBLE (d, op); 1141 REAL_VALUE_TO_TARGET_DOUBLE (d, u.l); 1142 1143 if (u.s.mantissa1 != 0 || u.s.mantissa2 != 0 /* not a power of two */ 1144 || u.s.exponent == 0 /* constant 0.0 */ 1145 || u.s.exponent == 0x7ff /* NAN */ 1146 || (u.s2.exponent1 != 0x8 && u.s2.exponent1 != 0x7)) 1147 return 0; /* const won't fit in float */ 1148 1149 return 1; 1150 } 1151 1152 /* Make OP legitimate for mode MODE. Currently this only deals with DFmode 1153 operands, putting them in registers and making CONST_DOUBLE values 1154 SFmode where possible. */ 1155 1156 struct rtx_def * 1157 legitimize_operand (op, mode) 1158 rtx op; 1159 enum machine_mode mode; 1160 { 1161 rtx temp; 1162 REAL_VALUE_TYPE r; 1163 union { 1164 long l[2]; 1165 struct { /* IEEE double precision format */ 1166 unsigned sign : 1; 1167 unsigned exponent : 11; 1168 unsigned mantissa1 : 20; 1169 unsigned mantissa2; 1170 } d; 1171 struct { /* IEEE double format to quick check */ 1172 unsigned sign : 1; /* if it fits in a float */ 1173 unsigned exponent1 : 4; 1174 unsigned exponent2 : 7; 1175 unsigned mantissa1 : 20; 1176 unsigned mantissa2; 1177 } s; 1178 } u; 1179 1180 if (GET_CODE (op) == REG || mode != DFmode) 1181 return op; 1182 1183 if (GET_CODE (op) == CONST_DOUBLE) 1184 { 1185 REAL_VALUE_FROM_CONST_DOUBLE (r, op); 1186 REAL_VALUE_TO_TARGET_DOUBLE (r, u.l); 1187 if (u.d.exponent != 0x7ff /* NaN */ 1188 && u.d.mantissa2 == 0 /* Mantissa fits */ 1189 && (u.s.exponent1 == 0x8 || u.s.exponent1 == 0x7) /* Exponent fits */ 1190 && (temp = simplify_unary_operation (FLOAT_TRUNCATE, SFmode, 1191 op, mode)) != 0) 1192 return gen_rtx_FLOAT_EXTEND (mode, force_reg (SFmode, temp)); 1193 } 1194 else if (register_operand (op, mode)) 1195 return op; 1196 1197 return force_reg (mode, op); 1198 } 1199 1200 /* Return true if OP is a suitable input for a move insn. */ 1201 1202 int 1203 move_operand (op, mode) 1204 rtx op; 1205 enum machine_mode mode; 1206 { 1207 if (register_operand (op, mode)) 1208 return 1; 1209 if (GET_CODE (op) == CONST_INT) 1210 return (classify_integer (mode, INTVAL (op)) < m88k_oru_hi16); 1211 if (GET_MODE (op) != mode) 1212 return 0; 1213 if (GET_CODE (op) == SUBREG) 1214 op = SUBREG_REG (op); 1215 if (GET_CODE (op) != MEM) 1216 return 0; 1217 1218 op = XEXP (op, 0); 1219 if (GET_CODE (op) == LO_SUM) 1220 return (REG_P (XEXP (op, 0)) 1221 && symbolic_address_p (XEXP (op, 1))); 1222 return memory_address_p (mode, op); 1223 } 1224 1225 /* Return true if OP is suitable for a call insn. */ 1226 1227 int 1228 call_address_operand (op, mode) 1229 rtx op; 1230 enum machine_mode mode ATTRIBUTE_UNUSED; 1231 { 1232 return (REG_P (op) || symbolic_address_p (op)); 1233 } 1234 1235 /* Returns true if OP is either a symbol reference or a sum of a symbol 1236 reference and a constant. */ 1237 1238 int 1239 symbolic_address_p (op) 1240 register rtx op; 1241 { 1242 switch (GET_CODE (op)) 1243 { 1244 case SYMBOL_REF: 1245 case LABEL_REF: 1246 return 1; 1247 1248 case CONST: 1249 op = XEXP (op, 0); 1250 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF 1251 || GET_CODE (XEXP (op, 0)) == LABEL_REF) 1252 && GET_CODE (XEXP (op, 1)) == CONST_INT); 1253 1254 default: 1255 return 0; 1256 } 1257 } 1258 1259 /* Return true if OP is a register or const0_rtx. */ 1260 1261 int 1262 reg_or_0_operand (op, mode) 1263 rtx op; 1264 enum machine_mode mode; 1265 { 1266 return (op == const0_rtx || register_operand (op, mode)); 1267 } 1268 1269 /* Nonzero if OP is a valid second operand for an arithmetic insn. */ 1270 1271 int 1272 arith_operand (op, mode) 1273 rtx op; 1274 enum machine_mode mode; 1275 { 1276 return (register_operand (op, mode) 1277 || (GET_CODE (op) == CONST_INT && SMALL_INT (op))); 1278 } 1279 1280 /* Return true if OP is a register or 5 bit integer. */ 1281 1282 int 1283 arith5_operand (op, mode) 1284 rtx op; 1285 enum machine_mode mode; 1286 { 1287 return (register_operand (op, mode) 1288 || (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32)); 1289 } 1290 1291 int 1292 arith32_operand (op, mode) 1293 rtx op; 1294 enum machine_mode mode; 1295 { 1296 return (register_operand (op, mode) || GET_CODE (op) == CONST_INT); 1297 } 1298 1299 int 1300 arith64_operand (op, mode) 1301 rtx op; 1302 enum machine_mode mode; 1303 { 1304 return (register_operand (op, mode) 1305 || GET_CODE (op) == CONST_INT 1306 || (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode)); 1307 } 1308 1309 int 1310 int5_operand (op, mode) 1311 rtx op; 1312 enum machine_mode mode ATTRIBUTE_UNUSED; 1313 { 1314 return (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32); 1315 } 1316 1317 int 1318 int32_operand (op, mode) 1319 rtx op; 1320 enum machine_mode mode ATTRIBUTE_UNUSED; 1321 { 1322 return (GET_CODE (op) == CONST_INT); 1323 } 1324 1325 /* Return true if OP is a register or a valid immediate operand for 1326 addu or subu. */ 1327 1328 int 1329 add_operand (op, mode) 1330 rtx op; 1331 enum machine_mode mode; 1332 { 1333 return (register_operand (op, mode) 1334 || (GET_CODE (op) == CONST_INT && ADD_INT (op))); 1335 } 1336 1337 /* Nonzero if this is a bitmask filling the bottom bits, for optimizing and + 1338 shift left combinations into a single mak instruction. */ 1339 1340 int 1341 mak_mask_p (value) 1342 int value; 1343 { 1344 return (value && POWER_OF_2_or_0 (value + 1)); 1345 } 1346 1347 int 1348 reg_or_bbx_mask_operand (op, mode) 1349 rtx op; 1350 enum machine_mode mode; 1351 { 1352 int value; 1353 if (register_operand (op, mode)) 1354 return 1; 1355 if (GET_CODE (op) != CONST_INT) 1356 return 0; 1357 1358 value = INTVAL (op); 1359 if (POWER_OF_2 (value)) 1360 return 1; 1361 1362 return 0; 1363 } 1364 1365 /* Return true if OP is valid to use in the context of a floating 1366 point operation. Special case 0.0, since we can use r0. */ 1367 1368 int 1369 real_or_0_operand (op, mode) 1370 rtx op; 1371 enum machine_mode mode; 1372 { 1373 if (mode != SFmode && mode != DFmode) 1374 return 0; 1375 1376 return (register_operand (op, mode) 1377 || (GET_CODE (op) == CONST_DOUBLE 1378 && op == CONST0_RTX (mode))); 1379 } 1380 1381 /* Return true if OP is valid to use in the context of logic arithmetic 1382 on condition codes. */ 1383 1384 int 1385 partial_ccmode_register_operand (op, mode) 1386 rtx op; 1387 enum machine_mode mode ATTRIBUTE_UNUSED; 1388 { 1389 return register_operand (op, CCmode) || register_operand (op, CCEVENmode); 1390 } 1391 1392 /* Return true if OP is a relational operator. */ 1393 1394 int 1395 relop (op, mode) 1396 rtx op; 1397 enum machine_mode mode ATTRIBUTE_UNUSED; 1398 { 1399 switch (GET_CODE (op)) 1400 { 1401 case EQ: 1402 case NE: 1403 case LT: 1404 case LE: 1405 case GE: 1406 case GT: 1407 case LTU: 1408 case LEU: 1409 case GEU: 1410 case GTU: 1411 return 1; 1412 default: 1413 return 0; 1414 } 1415 } 1416 1417 int 1418 even_relop (op, mode) 1419 rtx op; 1420 enum machine_mode mode ATTRIBUTE_UNUSED; 1421 { 1422 switch (GET_CODE (op)) 1423 { 1424 case EQ: 1425 case LT: 1426 case GT: 1427 case LTU: 1428 case GTU: 1429 return 1; 1430 default: 1431 return 0; 1432 } 1433 } 1434 1435 int 1436 odd_relop (op, mode) 1437 rtx op; 1438 enum machine_mode mode ATTRIBUTE_UNUSED; 1439 { 1440 switch (GET_CODE (op)) 1441 { 1442 case NE: 1443 case LE: 1444 case GE: 1445 case LEU: 1446 case GEU: 1447 return 1; 1448 default: 1449 return 0; 1450 } 1451 } 1452 1453 /* Return true if OP is a relational operator, and is not an unsigned 1454 relational operator. */ 1455 1456 int 1457 relop_no_unsigned (op, mode) 1458 rtx op; 1459 enum machine_mode mode ATTRIBUTE_UNUSED; 1460 { 1461 switch (GET_CODE (op)) 1462 { 1463 case EQ: 1464 case NE: 1465 case LT: 1466 case LE: 1467 case GE: 1468 case GT: 1469 /* @@ What is this test doing? Why not use `mode'? */ 1470 if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT 1471 || GET_MODE (op) == DImode 1472 || GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_FLOAT 1473 || GET_MODE (XEXP (op, 0)) == DImode 1474 || GET_MODE_CLASS (GET_MODE (XEXP (op, 1))) == MODE_FLOAT 1475 || GET_MODE (XEXP (op, 1)) == DImode) 1476 return 0; 1477 return 1; 1478 default: 1479 return 0; 1480 } 1481 } 1482 1483 /* Return true if the code of this rtx pattern is EQ or NE. */ 1484 1485 int 1486 equality_op (op, mode) 1487 rtx op; 1488 enum machine_mode mode ATTRIBUTE_UNUSED; 1489 { 1490 return (GET_CODE (op) == EQ || GET_CODE (op) == NE); 1491 } 1492 1493 /* Return true if the code of this rtx pattern is pc or label_ref. */ 1494 1495 int 1496 pc_or_label_ref (op, mode) 1497 rtx op; 1498 enum machine_mode mode ATTRIBUTE_UNUSED; 1499 { 1500 return (GET_CODE (op) == PC || GET_CODE (op) == LABEL_REF); 1501 } 1502 1503 /* Output to FILE the start of the assembler file. */ 1504 1505 void 1506 output_file_start (file) 1507 FILE *file; 1508 { 1509 if (TARGET_88110) 1510 fprintf (file, "%s\n", REQUIRES_88110_ASM_OP); 1511 1512 output_file_directive (file, main_input_filename); 1513 } 1514 1515 #ifndef OBJECT_FORMAT_ELF 1516 /* Output an ascii string. */ 1517 1518 void 1519 output_ascii (file, opcode, max, p, size) 1520 FILE *file; 1521 const char *opcode; 1522 int max; 1523 const char *p; 1524 int size; 1525 { 1526 int i; 1527 int in_escape = 0; 1528 1529 register int num = 0; 1530 1531 fprintf (file, "%s\"", opcode); 1532 for (i = 0; i < size; i++) 1533 { 1534 register int c = (unsigned char) p[i]; 1535 1536 if (num > max) 1537 { 1538 fprintf (file, "\"\n%s\"", opcode); 1539 num = 0; 1540 } 1541 1542 if (c == '\"' || c == '\\') 1543 { 1544 escape: 1545 putc ('\\', file); 1546 putc (c, file); 1547 num += 2; 1548 in_escape = 0; 1549 } 1550 else if (in_escape && ISDIGIT (c)) 1551 { 1552 /* If a digit follows an octal-escape, the VAX assembler fails 1553 to stop reading the escape after three digits. Continue to 1554 output the values as an octal-escape until a non-digit is 1555 found. */ 1556 fprintf (file, "\\%03o", c); 1557 num += 4; 1558 } 1559 else if ((c >= ' ' && c < 0177) || (c == '\t')) 1560 { 1561 putc (c, file); 1562 num++; 1563 in_escape = 0; 1564 } 1565 else 1566 { 1567 switch (c) 1568 { 1569 /* Some assemblers can't handle \a, \v, or \?. */ 1570 case '\f': c = 'f'; goto escape; 1571 case '\b': c = 'b'; goto escape; 1572 case '\r': c = 'r'; goto escape; 1573 case '\n': c = 'n'; goto escape; 1574 } 1575 1576 fprintf (file, "\\%03o", c); 1577 num += 4; 1578 in_escape = 1; 1579 } 1580 } 1581 fprintf (file, "\"\n"); 1582 } 1583 #endif 1584 1585 /* Output a label (allows insn-output.c to be compiled without including 1586 m88k.c or needing to include stdio.h). */ 1587 1588 void 1589 output_label (label_number) 1590 int label_number; 1591 { 1592 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", label_number); 1593 } 1594 1595 /* Generate the assembly code for function entry. 1596 1597 The prologue is responsible for setting up the stack frame, 1598 initializing the frame pointer register, saving registers that must be 1599 saved, and allocating SIZE additional bytes of storage for the 1600 local variables. SIZE is an integer. FILE is a stdio 1601 stream to which the assembler code should be output. 1602 1603 The label for the beginning of the function need not be output by this 1604 macro. That has already been done when the macro is run. 1605 1606 To determine which registers to save, the macro can refer to the array 1607 `regs_ever_live': element R is nonzero if hard register 1608 R is used anywhere within the function. This implies the 1609 function prologue should save register R, but not if it is one 1610 of the call-used registers. 1611 1612 On machines where functions may or may not have frame-pointers, the 1613 function entry code must vary accordingly; it must set up the frame 1614 pointer if one is wanted, and not otherwise. To determine whether a 1615 frame pointer is in wanted, the macro can refer to the variable 1616 `frame_pointer_needed'. The variable's value will be 1 at run 1617 time in a function that needs a frame pointer. 1618 1619 On machines where an argument may be passed partly in registers and 1620 partly in memory, this macro must examine the variable 1621 `current_function_pretend_args_size', and allocate that many bytes 1622 of uninitialized space on the stack just underneath the first argument 1623 arriving on the stack. (This may not be at the very end of the stack, 1624 if the calling sequence has pushed anything else since pushing the stack 1625 arguments. But usually, on such machines, nothing else has been pushed 1626 yet, because the function prologue itself does all the pushing.) 1627 1628 If `ACCUMULATE_OUTGOING_ARGS' is defined, the variable 1629 `current_function_outgoing_args_size' contains the size in bytes 1630 required for the outgoing arguments. This macro must add that 1631 amount of uninitialized space to very bottom of the stack. 1632 1633 The stack frame we use looks like this: 1634 1635 caller callee 1636 |==============================================| 1637 | caller's frame | 1638 |==============================================| 1639 | [caller's outgoing memory arguments] | 1640 sp -> |==============================================| <- ap 1641 | [local variable space] | 1642 |----------------------------------------------| 1643 | [return address (r1)] | 1644 |----------------------------------------------| 1645 | [previous frame pointer (r30)] | 1646 |==============================================| <- fp 1647 | [preserved registers (r25..r14)] | 1648 |----------------------------------------------| 1649 | [preserved registers (x29..x22)] | 1650 |==============================================| 1651 | [dynamically allocated space (alloca)] | 1652 |==============================================| 1653 | [callee's outgoing memory arguments] | 1654 |==============================================| <- sp 1655 1656 Notes: 1657 1658 r1 and r30 must be saved if debugging. 1659 1660 fp (if present) is located two words down from the local 1661 variable space. 1662 */ 1663 1664 static rtx emit_add PARAMS ((rtx, rtx, int)); 1665 static void preserve_registers PARAMS ((int, int)); 1666 static void emit_ldst PARAMS ((int, int, enum machine_mode, int)); 1667 1668 static int nregs; 1669 static int nxregs; 1670 static char save_regs[FIRST_PSEUDO_REGISTER]; 1671 static int frame_laid_out; 1672 static int frame_size; 1673 1674 #define STACK_UNIT_BOUNDARY (STACK_BOUNDARY / BITS_PER_UNIT) 1675 #define ROUND_CALL_BLOCK_SIZE(BYTES) \ 1676 (((BYTES) + (STACK_UNIT_BOUNDARY - 1)) & ~(STACK_UNIT_BOUNDARY - 1)) 1677 1678 /* Establish the position of the FP relative to the SP. This is done 1679 either during output_function_prologue() or by 1680 INITIAL_ELIMINATION_OFFSET. */ 1681 1682 void 1683 m88k_layout_frame () 1684 { 1685 int regno, sp_size; 1686 1687 if (frame_laid_out && reload_completed) 1688 return; 1689 1690 frame_laid_out = 1; 1691 1692 memset ((char *) &save_regs[0], 0, sizeof (save_regs)); 1693 sp_size = nregs = nxregs = 0; 1694 frame_size = get_frame_size (); 1695 1696 /* Profiling requires a stack frame. */ 1697 if (current_function_profile) 1698 frame_pointer_needed = 1; 1699 1700 /* If we are producing debug information, store r1 and r30 where the 1701 debugger wants to find them (r30 at r30+0, r1 at r30+4). Space has 1702 already been reserved for r1/r30 in STARTING_FRAME_OFFSET. */ 1703 if (write_symbols != NO_DEBUG) 1704 save_regs[1] = 1; 1705 1706 /* If we are producing PIC, save the addressing base register and r1. */ 1707 if (flag_pic && current_function_uses_pic_offset_table) 1708 { 1709 save_regs[PIC_OFFSET_TABLE_REGNUM] = 1; 1710 nregs++; 1711 } 1712 1713 /* If a frame is requested, save the previous FP, and the return 1714 address (r1), so that a traceback can be done without using tdesc 1715 information. Otherwise, simply save the FP if it is used as 1716 a preserve register. */ 1717 if (frame_pointer_needed) 1718 save_regs[FRAME_POINTER_REGNUM] = save_regs[1] = 1; 1719 else 1720 { 1721 if (regs_ever_live[FRAME_POINTER_REGNUM]) 1722 save_regs[FRAME_POINTER_REGNUM] = 1; 1723 /* If there is a call, r1 needs to be saved as well. */ 1724 if (regs_ever_live[1]) 1725 save_regs[1] = 1; 1726 } 1727 1728 /* Figure out which extended register(s) needs to be saved. */ 1729 for (regno = FIRST_EXTENDED_REGISTER + 1; regno < FIRST_PSEUDO_REGISTER; 1730 regno++) 1731 if (regs_ever_live[regno] && ! call_used_regs[regno]) 1732 { 1733 save_regs[regno] = 1; 1734 nxregs++; 1735 } 1736 1737 /* Figure out which normal register(s) needs to be saved. */ 1738 for (regno = 2; regno < FRAME_POINTER_REGNUM; regno++) 1739 if (regs_ever_live[regno] && ! call_used_regs[regno]) 1740 { 1741 save_regs[regno] = 1; 1742 nregs++; 1743 } 1744 1745 /* Achieve greatest use of double memory ops. Either we end up saving 1746 r30 or we use that slot to align the registers we do save. */ 1747 if (nregs >= 2 && save_regs[1] && !save_regs[FRAME_POINTER_REGNUM]) 1748 sp_size += 4; 1749 1750 nregs += save_regs[1] + save_regs[FRAME_POINTER_REGNUM]; 1751 /* if we need to align extended registers, add a word */ 1752 if (nxregs > 0 && (nregs & 1) != 0) 1753 sp_size +=4; 1754 sp_size += 4 * nregs; 1755 sp_size += 8 * nxregs; 1756 sp_size += current_function_outgoing_args_size; 1757 1758 /* The first two saved registers are placed above the new frame pointer 1759 if any. In the only case this matters, they are r1 and r30. */ 1760 if (frame_pointer_needed || sp_size) 1761 m88k_fp_offset = ROUND_CALL_BLOCK_SIZE (sp_size - STARTING_FRAME_OFFSET); 1762 else 1763 m88k_fp_offset = -STARTING_FRAME_OFFSET; 1764 m88k_stack_size = m88k_fp_offset + STARTING_FRAME_OFFSET; 1765 1766 /* First, combine m88k_stack_size and size. If m88k_stack_size is 1767 nonzero, align the frame size to 8 mod 16; otherwise align the 1768 frame size to 0 mod 16. (If stacks are 8 byte aligned, this ends 1769 up as a NOP. */ 1770 { 1771 int need 1772 = ((m88k_stack_size ? STACK_UNIT_BOUNDARY - STARTING_FRAME_OFFSET : 0) 1773 - (frame_size % STACK_UNIT_BOUNDARY)); 1774 if (need < 0) 1775 need += STACK_UNIT_BOUNDARY; 1776 m88k_stack_size 1777 = ROUND_CALL_BLOCK_SIZE (m88k_stack_size + frame_size + need 1778 + current_function_pretend_args_size); 1779 } 1780 } 1781 1782 /* Return true if this function is known to have a null prologue. */ 1783 1784 int 1785 null_prologue () 1786 { 1787 if (! reload_completed) 1788 return 0; 1789 m88k_layout_frame (); 1790 return (! frame_pointer_needed 1791 && nregs == 0 1792 && nxregs == 0 1793 && m88k_stack_size == 0); 1794 } 1795 1796 /* Add to 'insn' a note which is PATTERN (INSN) but with REG replaced 1797 with (plus:P (reg 31) VAL). It would be nice if dwarf2out_frame_debug_expr 1798 could deduce these equivalences by itself so it wasn't necessary to hold 1799 its hand so much. */ 1800 1801 static void 1802 m88k_frame_related (insn, reg, val) 1803 rtx insn; 1804 rtx reg; 1805 HOST_WIDE_INT val; 1806 { 1807 rtx real, temp; 1808 1809 real = copy_rtx (PATTERN (insn)); 1810 1811 real = replace_rtx (real, reg, 1812 gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, 1813 STACK_POINTER_REGNUM), 1814 GEN_INT (val))); 1815 1816 /* We expect that 'real' is a SET. */ 1817 1818 if (GET_CODE (real) == SET) 1819 { 1820 rtx set = real; 1821 1822 temp = simplify_rtx (SET_SRC (set)); 1823 if (temp) 1824 SET_SRC (set) = temp; 1825 temp = simplify_rtx (SET_DEST (set)); 1826 if (temp) 1827 SET_DEST (set) = temp; 1828 if (GET_CODE (SET_DEST (set)) == MEM) 1829 { 1830 temp = simplify_rtx (XEXP (SET_DEST (set), 0)); 1831 if (temp) 1832 XEXP (SET_DEST (set), 0) = temp; 1833 } 1834 } 1835 else 1836 abort (); 1837 1838 RTX_FRAME_RELATED_P (insn) = 1; 1839 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, 1840 real, 1841 REG_NOTES (insn)); 1842 } 1843 1844 static void 1845 m88k_maybe_dead (insn) 1846 rtx insn; 1847 { 1848 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, 1849 const0_rtx, 1850 REG_NOTES (insn)); 1851 } 1852 1853 void 1854 m88k_expand_prologue () 1855 { 1856 rtx insn; 1857 1858 m88k_layout_frame (); 1859 1860 if (warn_stack_larger_than && m88k_stack_size > stack_larger_than_size) 1861 warning ("stack usage is %d bytes", m88k_stack_size); 1862 1863 if (m88k_stack_size) 1864 { 1865 insn = emit_add (stack_pointer_rtx, stack_pointer_rtx, -m88k_stack_size); 1866 RTX_FRAME_RELATED_P (insn) = 1; 1867 1868 /* If the stack pointer adjustment has required a temporary register, 1869 tell the DWARF code how to understand this sequence. */ 1870 if (! SMALL_INTVAL (m88k_stack_size)) 1871 REG_NOTES (insn) 1872 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, 1873 gen_rtx_SET (VOIDmode, stack_pointer_rtx, 1874 gen_rtx_PLUS (Pmode, stack_pointer_rtx, 1875 GEN_INT (-m88k_stack_size))), 1876 REG_NOTES(insn)); 1877 } 1878 1879 if (nregs || nxregs) 1880 preserve_registers (m88k_fp_offset + 4, 1); 1881 1882 if (frame_pointer_needed) 1883 { 1884 insn = emit_add (frame_pointer_rtx, stack_pointer_rtx, m88k_fp_offset); 1885 RTX_FRAME_RELATED_P (insn) = 1; 1886 } 1887 1888 if (flag_pic && save_regs[PIC_OFFSET_TABLE_REGNUM]) 1889 { 1890 rtx return_reg = gen_rtx_REG (SImode, 1); 1891 rtx label = gen_label_rtx (); 1892 #if 0 1893 rtx temp_reg = NULL_RTX; 1894 int save_r1 = regs_ever_live[1]; 1895 1896 if (save_r1) 1897 { 1898 temp_reg = gen_rtx_REG (SImode, TEMP_REGNUM); 1899 emit_move_insn (temp_reg, return_reg); 1900 } 1901 #endif 1902 1903 m88k_maybe_dead (emit_insn (gen_locate1 (pic_offset_table_rtx, label))); 1904 m88k_maybe_dead (emit_insn (gen_locate2 (pic_offset_table_rtx, label))); 1905 m88k_maybe_dead (emit_insn (gen_addsi3 (pic_offset_table_rtx, 1906 pic_offset_table_rtx, 1907 return_reg))); 1908 1909 #if 0 1910 if (save_r1) 1911 emit_move_insn (return_reg, temp_reg); 1912 #endif 1913 } 1914 if (current_function_profile) 1915 emit_insn (gen_blockage ()); 1916 } 1917 1918 /* This function generates the assembly code for function exit, 1919 on machines that need it. 1920 1921 The function epilogue should not depend on the current stack pointer! 1922 It should use the frame pointer only, if there is a frame pointer. 1923 This is mandatory because of alloca; we also take advantage of it to 1924 omit stack adjustments before returning. */ 1925 1926 static void 1927 m88k_output_function_epilogue (stream, size) 1928 FILE *stream; 1929 HOST_WIDE_INT size ATTRIBUTE_UNUSED; 1930 { 1931 rtx insn = get_last_insn (); 1932 1933 /* If the last insn isn't a BARRIER, we must write a return insn. This 1934 should only happen if the function has no prologue and no body. */ 1935 if (GET_CODE (insn) == NOTE) 1936 insn = prev_nonnote_insn (insn); 1937 if (insn == 0 || GET_CODE (insn) != BARRIER) 1938 asm_fprintf (stream, "\tjmp\t %R%s\n", reg_names[1]); 1939 1940 /* If the last insn is a barrier, and the insn before that is a call, 1941 then add a nop instruction so that tdesc can walk the stack correctly 1942 even though there is no epilogue. (Otherwise, the label for the 1943 end of the tdesc region ends up at the start of the next function. */ 1944 if (insn && GET_CODE (insn) == BARRIER) 1945 { 1946 insn = prev_nonnote_insn (insn); 1947 if (insn && GET_CODE (insn) == CALL_INSN) 1948 asm_fprintf (stream, "\tor\t %R%s,%R%s,%R%s\n", 1949 reg_names[0], reg_names[0], reg_names[0]); 1950 } 1951 1952 output_short_branch_defs (stream); 1953 1954 fprintf (stream, "\n"); 1955 1956 frame_laid_out = 0; 1957 } 1958 1959 void 1960 m88k_expand_epilogue () 1961 { 1962 if (frame_pointer_needed) 1963 emit_add (stack_pointer_rtx, frame_pointer_rtx, -m88k_fp_offset); 1964 1965 if (nregs || nxregs) 1966 preserve_registers (m88k_fp_offset + 4, 0); 1967 1968 if (m88k_stack_size) 1969 emit_add (stack_pointer_rtx, stack_pointer_rtx, m88k_stack_size); 1970 } 1971 1972 /* Emit insns to set DSTREG to SRCREG + AMOUNT during the prologue or 1973 epilogue. */ 1974 1975 static rtx 1976 emit_add (dstreg, srcreg, amount) 1977 rtx dstreg; 1978 rtx srcreg; 1979 int amount; 1980 { 1981 rtx incr = GEN_INT (abs (amount)); 1982 1983 if (! ADD_INTVAL (amount)) 1984 { 1985 rtx temp = gen_rtx_REG (SImode, TEMP_REGNUM); 1986 emit_move_insn (temp, incr); 1987 incr = temp; 1988 } 1989 return emit_insn ((amount < 0 ? gen_subsi3 : gen_addsi3) (dstreg, srcreg, 1990 incr)); 1991 } 1992 1993 /* Save/restore the preserve registers. base is the highest offset from 1994 r31 at which a register is stored. store_p is true if stores are to 1995 be done; otherwise loads. */ 1996 1997 static void 1998 preserve_registers (base, store_p) 1999 int base; 2000 int store_p; 2001 { 2002 int regno, offset; 2003 struct mem_op { 2004 int regno; 2005 int nregs; 2006 int offset; 2007 } mem_op[FIRST_PSEUDO_REGISTER]; 2008 struct mem_op *mo_ptr = mem_op; 2009 2010 /* The 88open OCS mandates that preserved registers be stored in 2011 increasing order. For compatibility with current practice, 2012 the order is r1, r30, then the preserve registers. */ 2013 2014 offset = base; 2015 if (save_regs[1]) 2016 { 2017 /* An extra word is given in this case to make best use of double 2018 memory ops. */ 2019 if (nregs > 2 && !save_regs[FRAME_POINTER_REGNUM]) 2020 offset -= 4; 2021 /* Do not reload r1 in the epilogue unless really necessary */ 2022 if (store_p || regs_ever_live[1] 2023 || (flag_pic && save_regs[PIC_OFFSET_TABLE_REGNUM])) 2024 emit_ldst (store_p, 1, SImode, offset); 2025 offset -= 4; 2026 base = offset; 2027 } 2028 2029 /* Walk the registers to save recording all single memory operations. */ 2030 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--) 2031 if (save_regs[regno]) 2032 { 2033 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1]) 2034 { 2035 mo_ptr->nregs = 1; 2036 mo_ptr->regno = regno; 2037 mo_ptr->offset = offset; 2038 mo_ptr++; 2039 offset -= 4; 2040 } 2041 else 2042 { 2043 regno--; 2044 offset -= 2*4; 2045 } 2046 } 2047 2048 /* Walk the registers to save recording all double memory operations. 2049 This avoids a delay in the epilogue (ld.d/ld). */ 2050 offset = base; 2051 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--) 2052 if (save_regs[regno]) 2053 { 2054 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1]) 2055 { 2056 offset -= 4; 2057 } 2058 else 2059 { 2060 mo_ptr->nregs = 2; 2061 mo_ptr->regno = regno-1; 2062 mo_ptr->offset = offset-4; 2063 mo_ptr++; 2064 regno--; 2065 offset -= 2*4; 2066 } 2067 } 2068 2069 /* Walk the extended registers to record all memory operations. */ 2070 /* Be sure the offset is double word aligned. */ 2071 offset = (offset - 1) & ~7; 2072 for (regno = FIRST_PSEUDO_REGISTER - 1; regno > FIRST_EXTENDED_REGISTER; 2073 regno--) 2074 if (save_regs[regno]) 2075 { 2076 mo_ptr->nregs = 2; 2077 mo_ptr->regno = regno; 2078 mo_ptr->offset = offset; 2079 mo_ptr++; 2080 offset -= 2*4; 2081 } 2082 2083 mo_ptr->regno = 0; 2084 2085 /* Output the memory operations. */ 2086 for (mo_ptr = mem_op; mo_ptr->regno; mo_ptr++) 2087 { 2088 if (mo_ptr->nregs) 2089 emit_ldst (store_p, mo_ptr->regno, 2090 (mo_ptr->nregs > 1 ? DImode : SImode), 2091 mo_ptr->offset); 2092 } 2093 } 2094 2095 static void 2096 emit_ldst (store_p, regno, mode, offset) 2097 int store_p; 2098 int regno; 2099 enum machine_mode mode; 2100 int offset; 2101 { 2102 rtx reg = gen_rtx_REG (mode, regno); 2103 rtx mem; 2104 rtx insn; 2105 2106 if (SMALL_INTVAL (offset)) 2107 { 2108 mem = gen_rtx_MEM (mode, plus_constant (stack_pointer_rtx, offset)); 2109 } 2110 else 2111 { 2112 /* offset is too large for immediate index must use register */ 2113 2114 rtx disp = GEN_INT (offset); 2115 rtx temp = gen_rtx_REG (SImode, TEMP_REGNUM); 2116 rtx regi = gen_rtx_PLUS (SImode, stack_pointer_rtx, temp); 2117 2118 emit_move_insn (temp, disp); 2119 mem = gen_rtx_MEM (mode, regi); 2120 } 2121 2122 if (store_p) 2123 { 2124 insn = emit_move_insn (mem, reg); 2125 m88k_frame_related (insn, stack_pointer_rtx, offset); 2126 } 2127 else 2128 emit_move_insn (reg, mem); 2129 } 2130 2131 /* Convert the address expression REG to a CFA offset. */ 2132 2133 int 2134 m88k_debugger_offset (reg, offset) 2135 register rtx reg; 2136 register int offset; 2137 { 2138 if (GET_CODE (reg) == PLUS) 2139 { 2140 offset = INTVAL (XEXP (reg, 1)); 2141 reg = XEXP (reg, 0); 2142 } 2143 2144 /* Put the offset in terms of the CFA (arg pointer). */ 2145 if (reg == frame_pointer_rtx) 2146 offset += m88k_fp_offset - m88k_stack_size; 2147 else if (reg == stack_pointer_rtx) 2148 offset -= m88k_stack_size; 2149 else if (reg != arg_pointer_rtx) 2150 return 0; 2151 2152 return offset; 2153 } 2154 2155 /* Output assembler code to FILE to increment profiler label # LABELNO 2156 for profiling a function entry. NAME is the mcount function name 2157 (varies). */ 2158 2159 void 2160 output_function_profiler (file, labelno, name) 2161 FILE *file; 2162 int labelno; 2163 const char *name; 2164 { 2165 char label[256]; 2166 2167 /* Remember to update FUNCTION_PROFILER_LENGTH. */ 2168 2169 asm_fprintf (file, "\tsubu\t %R%s,%R%s,32\n", reg_names[31], reg_names[31]); 2170 asm_fprintf (file, "\tst.d\t %R%s,%R%s,0\n", reg_names[2], reg_names[31]); 2171 asm_fprintf (file, "\tst.d\t %R%s,%R%s,8\n", reg_names[4], reg_names[31]); 2172 asm_fprintf (file, "\tst.d\t %R%s,%R%s,16\n", reg_names[6], reg_names[31]); 2173 asm_fprintf (file, "\tst.d\t %R%s,%R%s,24\n", reg_names[8], reg_names[31]); 2174 2175 ASM_GENERATE_INTERNAL_LABEL (label, "LP", labelno); 2176 if (flag_pic == 2) 2177 { 2178 asm_fprintf (file, "\tor.u\t %R%s,%R%s,%Rhi16(%s#got_rel)\n", 2179 reg_names[2], reg_names[0], &label[1]); 2180 asm_fprintf (file, "\tor\t %R%s,%R%s,%Rlo16(%s#got_rel)\n", 2181 reg_names[2], reg_names[2], &label[1]); 2182 asm_fprintf (file, "\tbsr.n\t %s#plt\n", name); 2183 asm_fprintf (file, "\t ld\t %R%s,%R%s,%R%s\n", reg_names[2], 2184 reg_names[PIC_OFFSET_TABLE_REGNUM], reg_names[2]); 2185 } 2186 else if (flag_pic) 2187 { 2188 asm_fprintf (file, "\tbsr.n\t %s#plt\n", name); 2189 asm_fprintf (file, "\t ld\t %R%s,%R%s,%s#got_rel\n", reg_names[2], 2190 reg_names[PIC_OFFSET_TABLE_REGNUM], &label[1]); 2191 } 2192 else 2193 { 2194 asm_fprintf (file, "\tor.u\t %R%s,%R%s,%Rhi16(%s)\n", 2195 reg_names[2], reg_names[0], &label[1]); 2196 asm_fprintf (file, "\tbsr.n\t %s\n", name); 2197 asm_fprintf (file, "\t or\t %R%s,%R%s,%Rlo16(%s)\n", 2198 reg_names[2], reg_names[2], &label[1]); 2199 } 2200 2201 asm_fprintf (file, "\tld.d\t %R%s,%R%s,0\n", reg_names[2], reg_names[31]); 2202 asm_fprintf (file, "\tld.d\t %R%s,%R%s,8\n", reg_names[4], reg_names[31]); 2203 asm_fprintf (file, "\tld.d\t %R%s,%R%s,16\n", reg_names[6], reg_names[31]); 2204 asm_fprintf (file, "\tld.d\t %R%s,%R%s,24\n", reg_names[8], reg_names[31]); 2205 asm_fprintf (file, "\taddu\t %R%s,%R%s,32\n", reg_names[31], reg_names[31]); 2206 } 2207 2208 /* Determine whether a function argument is passed in a register, and 2209 which register. 2210 2211 The arguments are CUM, which summarizes all the previous 2212 arguments; MODE, the machine mode of the argument; TYPE, 2213 the data type of the argument as a tree node or 0 if that is not known 2214 (which happens for C support library functions); and NAMED, 2215 which is 1 for an ordinary argument and 0 for nameless arguments that 2216 correspond to `...' in the called function's prototype. 2217 2218 The value of the expression should either be a `reg' RTX for the 2219 hard register in which to pass the argument, or zero to pass the 2220 argument on the stack. 2221 2222 On the m88000 the first eight words of args are normally in registers 2223 and the rest are pushed. Double precision floating point must be 2224 double word aligned (and if in a register, starting on an even 2225 register). Structures and unions which are not 4 byte, and word 2226 aligned are passed in memory rather than registers, even if they 2227 would fit completely in the registers under OCS rules. 2228 2229 Note that FUNCTION_ARG and FUNCTION_INCOMING_ARG were different. 2230 For structures that are passed in memory, but could have been 2231 passed in registers, we first load the structure into the 2232 register, and then when the last argument is passed, we store 2233 the registers into the stack locations. This fixes some bugs 2234 where GCC did not expect to have register arguments, followed 2235 by stack arguments, followed by register arguments. */ 2236 2237 struct rtx_def * 2238 m88k_function_arg (args_so_far, mode, type, named) 2239 CUMULATIVE_ARGS args_so_far; 2240 enum machine_mode mode; 2241 tree type; 2242 int named ATTRIBUTE_UNUSED; 2243 { 2244 int bytes, words; 2245 2246 if (type != 0 && AGGREGATE_TYPE_P (type)) /* undo putting struct in register */ 2247 mode = BLKmode; 2248 2249 if (type == 0 && mode == BLKmode) 2250 abort (); /* m88k_function_arg argument `type' is NULL for BLKmode. */ 2251 2252 bytes = (mode != BLKmode) ? GET_MODE_SIZE (mode) : int_size_in_bytes (type); 2253 2254 /* Variable-sized types get passed by reference, which can be passed 2255 in registers. */ 2256 if (bytes < 0) 2257 { 2258 if (args_so_far > 8 - (POINTER_SIZE / BITS_PER_WORD)) 2259 return (rtx) 0; 2260 2261 return gen_rtx_REG (Pmode, 2 + args_so_far); 2262 } 2263 2264 words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD; 2265 2266 if ((args_so_far & 1) != 0 2267 && (mode == DImode || mode == DFmode 2268 || (type != 0 && TYPE_ALIGN (type) > BITS_PER_WORD))) 2269 args_so_far++; 2270 2271 if (args_so_far + words > 8) 2272 return (rtx) 0; /* args have exhausted registers */ 2273 2274 else if (mode == BLKmode 2275 && (TYPE_ALIGN (type) != BITS_PER_WORD || bytes != UNITS_PER_WORD)) 2276 return (rtx) 0; 2277 2278 return gen_rtx_REG (((mode == BLKmode) ? TYPE_MODE (type) : mode), 2279 2 + args_so_far); 2280 } 2281 2282 /* Update the summarizer variable CUM to advance past an argument in 2283 the argument list. The values MODE, TYPE and NAMED describe that 2284 argument. Once this is done, the variable CUM is suitable for 2285 analyzing the *following* argument with `FUNCTION_ARG', etc. (TYPE 2286 is null for libcalls where that information may not be available.) */ 2287 void 2288 m88k_function_arg_advance (args_so_far, mode, type, named) 2289 CUMULATIVE_ARGS *args_so_far; 2290 enum machine_mode mode; 2291 tree type; 2292 int named ATTRIBUTE_UNUSED; 2293 { 2294 int bytes, words; 2295 int asf; 2296 2297 if (type != 0 && AGGREGATE_TYPE_P (type)) 2298 mode = BLKmode; 2299 2300 bytes = (mode != BLKmode) ? GET_MODE_SIZE (mode) : int_size_in_bytes (type); 2301 asf = *args_so_far; 2302 2303 /* Variable-sized types get passed by reference, which can be passed 2304 in registers. */ 2305 if (bytes < 0) 2306 { 2307 if (asf <= 8 - (POINTER_SIZE / BITS_PER_WORD)) 2308 *args_so_far += POINTER_SIZE / BITS_PER_WORD; 2309 2310 return; 2311 } 2312 2313 words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD; 2314 2315 /* Struct and unions which are not exactly the size of a register are to be 2316 passed on stack. */ 2317 if (mode == BLKmode 2318 && (TYPE_ALIGN (type) != BITS_PER_WORD || bytes != UNITS_PER_WORD)) 2319 return; 2320 2321 /* Align arguments requiring more than word alignment to a double-word 2322 boundary (or an even register number if the argument will get passed 2323 in registers). */ 2324 if ((asf & 1) != 0 2325 && (mode == DImode || mode == DFmode 2326 || (type != 0 && TYPE_ALIGN (type) > BITS_PER_WORD))) 2327 asf++; 2328 2329 if (asf + words > 8) 2330 return; 2331 2332 (*args_so_far) = asf + words; 2333 } 2334 2335 /* A C expression that indicates when an argument must be passed by 2336 reference. If nonzero for an argument, a copy of that argument is 2337 made in memory and a pointer to the argument is passed instead of 2338 the argument itself. The pointer is passed in whatever way is 2339 appropriate for passing a pointer to that type. 2340 2341 On m88k, only variable sized types are passed by reference. */ 2342 2343 int 2344 m88k_function_arg_pass_by_reference (cum, mode, type, named) 2345 CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED; 2346 enum machine_mode mode ATTRIBUTE_UNUSED; 2347 tree type; 2348 int named ATTRIBUTE_UNUSED; 2349 { 2350 return type != 0 && int_size_in_bytes (type) < 0; 2351 } 2352 2353 /* Perform any needed actions needed for a function that is receiving a 2354 variable number of arguments. 2355 2356 CUM is a variable of type CUMULATIVE_ARGS which gives info about 2357 the preceding args and about the function being called. 2358 2359 MODE and TYPE are the mode and type of the current parameter. 2360 2361 PRETEND_SIZE is a variable that should be set to the amount of stack 2362 that must be pushed by the prolog to pretend that our caller pushed 2363 it. 2364 2365 Normally, this macro will push all remaining incoming registers on the 2366 stack and set PRETEND_SIZE to the length of the registers pushed. */ 2367 2368 void 2369 m88k_setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl) 2370 CUMULATIVE_ARGS *cum; 2371 enum machine_mode mode; 2372 tree type; 2373 int *pretend_size; 2374 int no_rtl; 2375 { 2376 CUMULATIVE_ARGS next_cum; 2377 tree fntype; 2378 int stdarg_p; 2379 int regcnt, delta; 2380 2381 fntype = TREE_TYPE (current_function_decl); 2382 stdarg_p = (TYPE_ARG_TYPES (fntype) != 0 2383 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) 2384 != void_type_node)); 2385 2386 /* For varargs, we do not want to skip the dummy va_dcl argument. 2387 For stdargs, we do want to skip the last named argument. */ 2388 next_cum = *cum; 2389 if (stdarg_p) 2390 m88k_function_arg_advance(&next_cum, mode, type, 1); 2391 2392 regcnt = next_cum < 8 ? 8 - next_cum : 0; 2393 delta = regcnt & 1; 2394 2395 if (! no_rtl && regcnt != 0) 2396 { 2397 rtx mem, dst; 2398 int set, regno, offs; 2399 2400 set = get_varargs_alias_set (); 2401 mem = gen_rtx_MEM (BLKmode, 2402 plus_constant (virtual_incoming_args_rtx, 2403 - (regcnt + delta) * UNITS_PER_WORD)); 2404 set_mem_alias_set (mem, set); 2405 2406 /* Now store the incoming registers. */ 2407 /* The following is equivalent to 2408 move_block_from_reg (2 + next_cum, 2409 adjust_address (mem, Pmode, 2410 delta * UNITS_PER_WORD), 2411 regcnt, UNITS_PER_WORD * regcnt); 2412 but using double store instruction since the stack is properly 2413 aligned. */ 2414 regno = 2 + next_cum; 2415 dst = mem; 2416 2417 if (delta != 0) 2418 { 2419 dst = adjust_address (dst, Pmode, UNITS_PER_WORD); 2420 emit_move_insn (operand_subword (dst, 0, 1, BLKmode), 2421 gen_rtx_REG (SImode, regno)); 2422 regno++; 2423 } 2424 2425 offs = delta; 2426 while (regno < 10) 2427 { 2428 emit_move_insn (adjust_address (dst, DImode, offs * UNITS_PER_WORD), 2429 gen_rtx_REG (DImode, regno)); 2430 offs += 2; 2431 regno += 2; 2432 } 2433 2434 *pretend_size = (regcnt + delta) * UNITS_PER_WORD; 2435 } 2436 } 2437 2438 /* Define the `__builtin_va_list' type for the ABI. */ 2439 2440 tree 2441 m88k_build_va_list () 2442 { 2443 tree field_reg, field_stk, field_arg, int_ptr_type_node, record; 2444 2445 int_ptr_type_node = build_pointer_type (integer_type_node); 2446 2447 record = make_node (RECORD_TYPE); 2448 2449 field_arg = build_decl (FIELD_DECL, get_identifier ("__va_arg"), 2450 integer_type_node); 2451 field_stk = build_decl (FIELD_DECL, get_identifier ("__va_stk"), 2452 int_ptr_type_node); 2453 field_reg = build_decl (FIELD_DECL, get_identifier ("__va_reg"), 2454 int_ptr_type_node); 2455 2456 DECL_FIELD_CONTEXT (field_arg) = record; 2457 DECL_FIELD_CONTEXT (field_stk) = record; 2458 DECL_FIELD_CONTEXT (field_reg) = record; 2459 2460 TYPE_FIELDS (record) = field_arg; 2461 TREE_CHAIN (field_arg) = field_stk; 2462 TREE_CHAIN (field_stk) = field_reg; 2463 2464 layout_type (record); 2465 return record; 2466 } 2467 2468 /* Implement `va_start' for varargs and stdarg. */ 2469 2470 void 2471 m88k_va_start (valist, nextarg) 2472 tree valist; 2473 rtx nextarg ATTRIBUTE_UNUSED; 2474 { 2475 tree field_reg, field_stk, field_arg; 2476 tree reg, stk, arg, t; 2477 tree fntype; 2478 int stdarg_p; 2479 int offset; 2480 2481 if (! CONSTANT_P (current_function_arg_offset_rtx)) 2482 abort (); 2483 2484 field_arg = TYPE_FIELDS (va_list_type_node); 2485 field_stk = TREE_CHAIN (field_arg); 2486 field_reg = TREE_CHAIN (field_stk); 2487 2488 arg = build (COMPONENT_REF, TREE_TYPE (field_arg), valist, field_arg); 2489 stk = build (COMPONENT_REF, TREE_TYPE (field_stk), valist, field_stk); 2490 reg = build (COMPONENT_REF, TREE_TYPE (field_reg), valist, field_reg); 2491 2492 fntype = TREE_TYPE (current_function_decl); 2493 stdarg_p = (TYPE_ARG_TYPES (fntype) != 0 2494 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) 2495 != void_type_node)); 2496 2497 /* Fill in the __va_arg member. */ 2498 t = build (MODIFY_EXPR, TREE_TYPE (arg), arg, 2499 build_int_2 (current_function_args_info, 0)); 2500 TREE_SIDE_EFFECTS (t) = 1; 2501 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 2502 2503 /* Store the arg pointer in the __va_stk member. */ 2504 offset = XINT (current_function_arg_offset_rtx, 0); 2505 if (current_function_args_info >= 8 && ! stdarg_p) 2506 offset -= UNITS_PER_WORD; 2507 t = make_tree (TREE_TYPE (stk), virtual_incoming_args_rtx); 2508 t = build (PLUS_EXPR, TREE_TYPE (stk), t, build_int_2 (offset, 0)); 2509 t = build (MODIFY_EXPR, TREE_TYPE (stk), stk, t); 2510 TREE_SIDE_EFFECTS (t) = 1; 2511 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 2512 2513 /* Setup __va_reg */ 2514 t = make_tree (TREE_TYPE (reg), virtual_incoming_args_rtx); 2515 t = build (PLUS_EXPR, TREE_TYPE (reg), t, 2516 build_int_2 (-8 * UNITS_PER_WORD, -1)); 2517 t = build (MODIFY_EXPR, TREE_TYPE (reg), reg, t); 2518 TREE_SIDE_EFFECTS (t) = 1; 2519 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 2520 } 2521 2522 /* Implement `va_arg'. */ 2523 2524 rtx 2525 m88k_va_arg (valist, type) 2526 tree valist, type; 2527 { 2528 tree field_reg, field_stk, field_arg; 2529 int indirect_p, size, wsize, align, reg_p; 2530 rtx addr_rtx; 2531 rtx lab_done; 2532 2533 field_arg = TYPE_FIELDS (va_list_type_node); 2534 field_stk = TREE_CHAIN (field_arg); 2535 field_reg = TREE_CHAIN (field_stk); 2536 2537 size = int_size_in_bytes (type); 2538 /* Variable sized types are passed by reference. */ 2539 if (size < 0) 2540 { 2541 indirect_p = 1; 2542 wsize = POINTER_SIZE / BITS_PER_WORD; 2543 type = 0; 2544 reg_p = 1; 2545 } 2546 else 2547 { 2548 indirect_p = 0; 2549 wsize = (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD; 2550 reg_p = (AGGREGATE_TYPE_P (type) 2551 ? size == UNITS_PER_WORD && TYPE_ALIGN (type) == BITS_PER_WORD 2552 : size <= 2*UNITS_PER_WORD); 2553 } 2554 2555 addr_rtx = gen_reg_rtx (Pmode); 2556 lab_done = gen_label_rtx (); 2557 2558 /* Decide if we should read from stack or regs if the argument could have 2559 been passed in registers. */ 2560 if (reg_p) { 2561 tree arg, arg_align, reg; 2562 rtx lab_stack; 2563 tree t; 2564 rtx r; 2565 2566 lab_stack = gen_label_rtx (); 2567 2568 /* Align __va_arg to a doubleword boundary if necessary. */ 2569 arg = build (COMPONENT_REF, TREE_TYPE (field_arg), valist, field_arg); 2570 align = type == 0 ? 0 : TYPE_ALIGN (type) / BITS_PER_WORD; 2571 if (align > 1) 2572 { 2573 t = build (PLUS_EXPR, TREE_TYPE (arg), arg, build_int_2 (align - 1, 0)); 2574 arg_align = build (BIT_AND_EXPR, TREE_TYPE (t), t, 2575 build_int_2 (-align, -1)); 2576 arg_align = save_expr (arg_align); 2577 } 2578 else 2579 arg_align = arg; 2580 2581 /* Make sure the argument fits within the remainder of the saved 2582 register area, and branch to the stack logic if not. */ 2583 r = expand_expr (arg_align, NULL_RTX, TYPE_MODE (TREE_TYPE (arg_align)), 2584 EXPAND_NORMAL); 2585 /* if (arg_align > 8 - wsize) goto lab_stack */ 2586 emit_cmp_and_jump_insns (r, GEN_INT (8 - wsize), GTU, 2587 GEN_INT (UNITS_PER_WORD), GET_MODE (r), 1, 2588 lab_stack); 2589 2590 /* Compute the argument address. */ 2591 reg = build (COMPONENT_REF, TREE_TYPE (field_reg), valist, field_reg); 2592 t = build (MULT_EXPR, TREE_TYPE (reg), arg_align, 2593 build_int_2 (UNITS_PER_WORD, 0)); 2594 t = build (PLUS_EXPR, TREE_TYPE (reg), reg, t); 2595 TREE_SIDE_EFFECTS (t) = 1; 2596 2597 r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL); 2598 if (r != addr_rtx) 2599 emit_move_insn (addr_rtx, r); 2600 2601 /* Increment __va_arg. */ 2602 t = build (PLUS_EXPR, TREE_TYPE (arg), arg_align, build_int_2 (wsize, 0)); 2603 t = build (MODIFY_EXPR, TREE_TYPE (arg), arg, t); 2604 TREE_SIDE_EFFECTS (t) = 1; 2605 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 2606 2607 emit_jump_insn (gen_jump (lab_done)); 2608 emit_barrier (); 2609 2610 emit_label (lab_stack); 2611 } 2612 2613 { 2614 tree stk; 2615 tree t; 2616 rtx r; 2617 2618 stk = build (COMPONENT_REF, TREE_TYPE (field_stk), valist, field_stk); 2619 2620 /* Align __va_stk to the type boundary if necessary. */ 2621 align = type == 0 ? 0 : TYPE_ALIGN (type) / BITS_PER_UNIT; 2622 if (align > UNITS_PER_WORD) 2623 { 2624 t = build (PLUS_EXPR, TREE_TYPE (stk), stk, build_int_2 (align - 1, 0)); 2625 t = build (BIT_AND_EXPR, TREE_TYPE (t), t, build_int_2 (-align, -1)); 2626 TREE_SIDE_EFFECTS (t) = 1; 2627 } 2628 else 2629 t = stk; 2630 2631 /* Compute the argument address. */ 2632 r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL); 2633 if (r != addr_rtx) 2634 emit_move_insn (addr_rtx, r); 2635 2636 /* Increment __va_stk. */ 2637 t = build (PLUS_EXPR, TREE_TYPE (t), t, 2638 build_int_2 (wsize * UNITS_PER_WORD, 0)); 2639 t = build (MODIFY_EXPR, TREE_TYPE (stk), stk, t); 2640 TREE_SIDE_EFFECTS (t) = 1; 2641 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 2642 } 2643 2644 emit_label (lab_done); 2645 2646 if (indirect_p) 2647 { 2648 rtx r = gen_rtx_MEM (Pmode, addr_rtx); 2649 set_mem_alias_set (r, get_varargs_alias_set ()); 2650 emit_move_insn (addr_rtx, r); 2651 } 2652 2653 return addr_rtx; 2654 } 2655 2656 /* If cmpsi has not been generated, emit code to do the test. Return the 2657 expression describing the test of operator OP. */ 2658 2659 rtx 2660 emit_test (op, mode) 2661 enum rtx_code op; 2662 enum machine_mode mode; 2663 { 2664 if (m88k_compare_reg == 0) 2665 emit_insn (gen_test (m88k_compare_op0, m88k_compare_op1)); 2666 return (gen_rtx (op, mode, m88k_compare_reg, const0_rtx)); 2667 } 2668 2669 /* Determine how to best perform cmpsi/bxx, where cmpsi has a constant 2670 operand. All tests with zero (albeit swapped) and all equality tests 2671 with a constant are done with bcnd. The remaining cases are swapped 2672 as needed. */ 2673 2674 void 2675 emit_bcnd (op, label) 2676 enum rtx_code op; 2677 rtx label; 2678 { 2679 if (m88k_compare_op1 == const0_rtx) 2680 emit_jump_insn (gen_bcnd 2681 (gen_rtx (op, VOIDmode,m88k_compare_op0, const0_rtx), 2682 label)); 2683 else if (m88k_compare_op0 == const0_rtx) 2684 emit_jump_insn (gen_bcnd 2685 (gen_rtx (swap_condition (op), 2686 VOIDmode, m88k_compare_op1, const0_rtx), 2687 label)); 2688 else if (op != EQ && op != NE) 2689 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label)); 2690 else 2691 { 2692 rtx zero = gen_reg_rtx (SImode); 2693 rtx reg, constant; 2694 int value; 2695 2696 if (GET_CODE (m88k_compare_op1) == CONST_INT) 2697 { 2698 reg = force_reg (SImode, m88k_compare_op0); 2699 constant = m88k_compare_op1; 2700 } 2701 else 2702 { 2703 reg = force_reg (SImode, m88k_compare_op1); 2704 constant = m88k_compare_op0; 2705 } 2706 value = INTVAL (constant); 2707 2708 /* Perform an arithmetic computation to make the compared-to value 2709 zero, but avoid loosing if the bcnd is later changed into sxx. */ 2710 if (SMALL_INTVAL (value)) 2711 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label)); 2712 else 2713 { 2714 if (SMALL_INTVAL (-value)) 2715 emit_insn (gen_addsi3 (zero, reg, 2716 GEN_INT (-value))); 2717 else 2718 emit_insn (gen_xorsi3 (zero, reg, constant)); 2719 2720 emit_jump_insn (gen_bcnd (gen_rtx (op, VOIDmode, 2721 zero, const0_rtx), 2722 label)); 2723 } 2724 } 2725 } 2726 2727 /* Print an operand. Recognize special options, documented below. */ 2728 2729 void 2730 print_operand (file, x, code) 2731 FILE *file; 2732 rtx x; 2733 int code; 2734 { 2735 enum rtx_code xc = (x ? GET_CODE (x) : UNKNOWN); 2736 register int value = (xc == CONST_INT ? INTVAL (x) : 0); 2737 static int sequencep; 2738 static int reversep; 2739 2740 if (sequencep) 2741 { 2742 if (code < 'B' || code > 'E') 2743 output_operand_lossage ("%%R not followed by %%B/C/D/E"); 2744 if (reversep) 2745 xc = reverse_condition (xc); 2746 sequencep = 0; 2747 } 2748 2749 switch (code) 2750 { 2751 case '#': /* register prefix character (may be empty) */ 2752 fputs (m88k_register_prefix, file); 2753 return; 2754 2755 case 'V': /* Output a serializing instruction as needed if the operand 2756 (assumed to be a MEM) is a volatile load. */ 2757 case 'v': /* ditto for a volatile store. */ 2758 if (MEM_VOLATILE_P (x) && TARGET_SERIALIZE_VOLATILE) 2759 { 2760 /* The m88110 implements two FIFO queues, one for loads and 2761 one for stores. These queues mean that loads complete in 2762 their issue order as do stores. An interaction between the 2763 history buffer and the store reservation station ensures 2764 that a store will not bypass load. Finally, a load will not 2765 bypass store, but only when they reference the same address. 2766 2767 To avoid this reordering (a load bypassing a store) for 2768 volatile references, a serializing instruction is output. 2769 We choose the fldcr instruction as it does not serialize on 2770 the m88100 so that -m88000 code will not be degraded. 2771 2772 The mechanism below is completed by having CC_STATUS_INIT set 2773 the code to the unknown value. */ 2774 2775 /* 2776 hassey 6/30/93 2777 A problem with 88110 4.1 & 4.2 makes the use of fldcr for 2778 this purpose undesirable. Instead we will use tb1, this will 2779 cause serialization on the 88100 but such is life. 2780 */ 2781 2782 static rtx last_addr = 0; 2783 if (code == 'V' /* Only need to serialize before a load. */ 2784 && m88k_volatile_code != 'V' /* Loads complete in FIFO order. */ 2785 && !(m88k_volatile_code == 'v' 2786 && GET_CODE (XEXP (x, 0)) == LO_SUM 2787 && rtx_equal_p (XEXP (XEXP (x, 0), 1), last_addr))) 2788 asm_fprintf (file, 2789 #if 0 2790 #ifdef AS_BUG_FLDCR 2791 "fldcr\t %R%s,%Rcr63\n\t", 2792 #else 2793 "fldcr\t %R%s,%Rfcr63\n\t", 2794 #endif 2795 reg_names[0]); 2796 #else /* 0 */ 2797 "tb1\t 1,%R%s,0xff\n\t", reg_names[0]); 2798 #endif /* 0 */ 2799 m88k_volatile_code = code; 2800 last_addr = (GET_CODE (XEXP (x, 0)) == LO_SUM 2801 ? XEXP (XEXP (x, 0), 1) : 0); 2802 } 2803 return; 2804 2805 case 'X': /* print the upper 16 bits... */ 2806 value >>= 16; 2807 case 'x': /* print the lower 16 bits of the integer constant in hex */ 2808 if (xc != CONST_INT) 2809 output_operand_lossage ("invalid %%x/X value"); 2810 fprintf (file, "0x%x", value & 0xffff); return; 2811 2812 case 'H': /* print the low 16 bits of the negated integer constant */ 2813 if (xc != CONST_INT) 2814 output_operand_lossage ("invalid %%H value"); 2815 value = -value; 2816 case 'h': /* print the register or low 16 bits of the integer constant */ 2817 if (xc == REG) 2818 goto reg; 2819 if (xc != CONST_INT) 2820 output_operand_lossage ("invalid %%h value"); 2821 fprintf (file, "%d", value & 0xffff); 2822 return; 2823 2824 case 'Q': /* print the low 8 bits of the negated integer constant */ 2825 if (xc != CONST_INT) 2826 output_operand_lossage ("invalid %%Q value"); 2827 value = -value; 2828 case 'q': /* print the register or low 8 bits of the integer constant */ 2829 if (xc == REG) 2830 goto reg; 2831 if (xc != CONST_INT) 2832 output_operand_lossage ("invalid %%q value"); 2833 fprintf (file, "%d", value & 0xff); 2834 return; 2835 2836 case 'p': /* print the logarithm of the integer constant */ 2837 if (xc != CONST_INT 2838 || (value = exact_log2 (value)) < 0) 2839 output_operand_lossage ("invalid %%p value"); 2840 fprintf (file, "%d", value); 2841 return; 2842 2843 case 'S': /* complement the value and then... */ 2844 value = ~value; 2845 case 's': /* print the width and offset values forming the integer 2846 constant with a SET instruction. See integer_ok_for_set. */ 2847 { 2848 register unsigned mask, uval = value; 2849 register int top, bottom; 2850 2851 if (xc != CONST_INT) 2852 output_operand_lossage ("invalid %%s/S value"); 2853 /* All the "one" bits must be contiguous. If so, MASK will be 2854 a power of two or zero. */ 2855 mask = (uval | (uval - 1)) + 1; 2856 if (!(uval && POWER_OF_2_or_0 (mask))) 2857 output_operand_lossage ("invalid %%s/S value"); 2858 top = mask ? exact_log2 (mask) : 32; 2859 bottom = exact_log2 (uval & ~(uval - 1)); 2860 fprintf (file,"%d<%d>", top - bottom, bottom); 2861 return; 2862 } 2863 2864 case 'P': /* print nothing if pc_rtx; output label_ref */ 2865 if (xc == LABEL_REF) 2866 output_addr_const (file, x); 2867 else if (xc != PC) 2868 output_operand_lossage ("invalid %%P operand"); 2869 return; 2870 2871 case 'L': /* print 0 or 1 if operand is label_ref and then... */ 2872 fputc (xc == LABEL_REF ? '1' : '0', file); 2873 case '.': /* print .n if delay slot is used */ 2874 fputs ((final_sequence 2875 && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))) 2876 ? ".n\t" : "\t", file); 2877 return; 2878 2879 case '!': /* Reverse the following condition. */ 2880 sequencep++; 2881 reversep = 1; 2882 return; 2883 case 'R': /* reverse the condition of the next print_operand 2884 if operand is a label_ref. */ 2885 sequencep++; 2886 reversep = (xc == LABEL_REF); 2887 return; 2888 2889 case 'B': /* bcnd branch values */ 2890 if (0) /* SVR4 */ 2891 fputs (m88k_register_prefix, file); 2892 switch (xc) 2893 { 2894 case EQ: fputs ("eq0", file); return; 2895 case NE: fputs ("ne0", file); return; 2896 case GT: fputs ("gt0", file); return; 2897 case LE: fputs ("le0", file); return; 2898 case LT: fputs ("lt0", file); return; 2899 case GE: fputs ("ge0", file); return; 2900 default: output_operand_lossage ("invalid %%B value"); 2901 } 2902 2903 case 'C': /* bb0/bb1 branch values for comparisons */ 2904 if (0) /* SVR4 */ 2905 fputs (m88k_register_prefix, file); 2906 switch (xc) 2907 { 2908 case EQ: fputs ("eq", file); return; 2909 case NE: fputs ("ne", file); return; 2910 case GT: fputs ("gt", file); return; 2911 case LE: fputs ("le", file); return; 2912 case LT: fputs ("lt", file); return; 2913 case GE: fputs ("ge", file); return; 2914 case GTU: fputs ("hi", file); return; 2915 case LEU: fputs ("ls", file); return; 2916 case LTU: fputs ("lo", file); return; 2917 case GEU: fputs ("hs", file); return; 2918 default: output_operand_lossage ("invalid %%C value"); 2919 } 2920 2921 case 'D': /* bcnd branch values for float comparisons */ 2922 switch (xc) 2923 { 2924 case EQ: fputs ("0xa", file); return; 2925 case NE: fputs ("0x5", file); return; 2926 case GT: 2927 if (0) /* SVR4 */ 2928 fputs (m88k_register_prefix, file); 2929 fputs ("gt0", file); 2930 return; 2931 case LE: 2932 if (0) /* SVR4 */ 2933 fputs (m88k_register_prefix, file); 2934 fputs ("le0", file); 2935 return; 2936 case LT: fputs ("0x4", file); return; 2937 case GE: fputs ("0xb", file); return; 2938 default: output_operand_lossage ("invalid %%D value"); 2939 } 2940 2941 case 'E': /* bcnd branch values for special integers */ 2942 switch (xc) 2943 { 2944 case EQ: fputs ("0x8", file); return; 2945 case NE: fputs ("0x7", file); return; 2946 default: output_operand_lossage ("invalid %%E value"); 2947 } 2948 2949 case 'd': /* second register of a two register pair */ 2950 if (xc != REG) 2951 output_operand_lossage ("`%%d' operand isn't a register"); 2952 asm_fprintf (file, "%R%s", reg_names[REGNO (x) + 1]); 2953 return; 2954 2955 case 'r': /* an immediate 0 should be represented as `r0' */ 2956 if (x == const0_rtx) 2957 { 2958 asm_fprintf (file, "%R%s", reg_names[0]); 2959 return; 2960 } 2961 else if (xc != REG) 2962 output_operand_lossage ("invalid %%r value"); 2963 case 0: 2964 name: 2965 if (xc == REG) 2966 { 2967 reg: 2968 if (REGNO (x) == ARG_POINTER_REGNUM) 2969 output_operand_lossage ("operand is r0"); 2970 else 2971 asm_fprintf (file, "%R%s", reg_names[REGNO (x)]); 2972 } 2973 else if (xc == PLUS) 2974 output_address (x); 2975 else if (xc == MEM) 2976 output_address (XEXP (x, 0)); 2977 else if (flag_pic && xc == UNSPEC) 2978 { 2979 output_addr_const (file, XVECEXP (x, 0, 0)); 2980 fputs ("#got_rel", file); 2981 } 2982 else if (xc == CONST_DOUBLE) 2983 output_operand_lossage ("operand is const_double"); 2984 else 2985 output_addr_const (file, x); 2986 return; 2987 2988 case 'g': /* append #got_rel as needed */ 2989 if (flag_pic && (xc == SYMBOL_REF || xc == LABEL_REF)) 2990 { 2991 output_addr_const (file, x); 2992 fputs ("#got_rel", file); 2993 return; 2994 } 2995 goto name; 2996 2997 case 'a': /* (standard), assume operand is an address */ 2998 case 'c': /* (standard), assume operand is an immediate value */ 2999 case 'l': /* (standard), assume operand is a label_ref */ 3000 case 'n': /* (standard), like %c, except negate first */ 3001 default: 3002 output_operand_lossage ("invalid code"); 3003 } 3004 } 3005 3006 void 3007 print_operand_address (file, addr) 3008 FILE *file; 3009 rtx addr; 3010 { 3011 register rtx reg0, reg1; 3012 3013 switch (GET_CODE (addr)) 3014 { 3015 case REG: 3016 if (REGNO (addr) == ARG_POINTER_REGNUM) 3017 abort (); 3018 else 3019 asm_fprintf (file, "%R%s,%R%s", reg_names[0], reg_names [REGNO (addr)]); 3020 break; 3021 3022 case LO_SUM: 3023 asm_fprintf (file, "%R%s,%Rlo16(", 3024 reg_names[REGNO (XEXP (addr, 0))]); 3025 output_addr_const (file, XEXP (addr, 1)); 3026 fputc (')', file); 3027 break; 3028 3029 case PLUS: 3030 reg0 = XEXP (addr, 0); 3031 reg1 = XEXP (addr, 1); 3032 if (GET_CODE (reg0) == MULT || GET_CODE (reg0) == CONST_INT) 3033 { 3034 rtx tmp = reg0; 3035 reg0 = reg1; 3036 reg1 = tmp; 3037 } 3038 3039 if ((REG_P (reg0) && REGNO (reg0) == ARG_POINTER_REGNUM) 3040 || (REG_P (reg1) && REGNO (reg1) == ARG_POINTER_REGNUM)) 3041 abort (); 3042 3043 else if (REG_P (reg0)) 3044 { 3045 if (REG_P (reg1)) 3046 asm_fprintf (file, "%R%s,%R%s", 3047 reg_names [REGNO (reg0)], reg_names [REGNO (reg1)]); 3048 3049 else if (GET_CODE (reg1) == CONST_INT) 3050 asm_fprintf (file, "%R%s,%d", 3051 reg_names [REGNO (reg0)], INTVAL (reg1)); 3052 3053 else if (GET_CODE (reg1) == MULT) 3054 { 3055 rtx mreg = XEXP (reg1, 0); 3056 if (REGNO (mreg) == ARG_POINTER_REGNUM) 3057 abort (); 3058 3059 asm_fprintf (file, "%R%s[%R%s]", reg_names[REGNO (reg0)], 3060 reg_names[REGNO (mreg)]); 3061 } 3062 3063 else if (GET_CODE (reg1) == ZERO_EXTRACT) 3064 { 3065 asm_fprintf (file, "%R%s,%Rlo16(", 3066 reg_names[REGNO (reg0)]); 3067 output_addr_const (file, XEXP (reg1, 0)); 3068 fputc (')', file); 3069 } 3070 3071 else if (flag_pic) 3072 { 3073 asm_fprintf (file, "%R%s,", reg_names[REGNO (reg0)]); 3074 output_addr_const (file, reg1); 3075 fputs ("#got_rel", file); 3076 } 3077 else abort (); 3078 } 3079 3080 else 3081 abort (); 3082 break; 3083 3084 case MULT: 3085 if (REGNO (XEXP (addr, 0)) == ARG_POINTER_REGNUM) 3086 abort (); 3087 3088 asm_fprintf (file, "%R%s[%R%s]", 3089 reg_names[0], reg_names[REGNO (XEXP (addr, 0))]); 3090 break; 3091 3092 case CONST_INT: 3093 asm_fprintf (file, "%R%s,%d", reg_names[0], INTVAL (addr)); 3094 break; 3095 3096 default: 3097 asm_fprintf (file, "%R%s,", reg_names[0]); 3098 output_addr_const (file, addr); 3099 } 3100 } 3101 3102 /* Return true if X is an address which needs a temporary register when 3103 reloaded while generating PIC code. */ 3104 3105 int 3106 pic_address_needs_scratch (x) 3107 rtx x; 3108 { 3109 /* An address which is a symbolic plus a non SMALL_INT needs a temp reg. */ 3110 if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS 3111 && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF 3112 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT 3113 && ! ADD_INT (XEXP (XEXP (x, 0), 1))) 3114 return 1; 3115 3116 return 0; 3117 } 3118 3119 /* Returns 1 if OP is either a symbol reference or a sum of a symbol 3120 reference and a constant. */ 3121 3122 int 3123 symbolic_operand (op, mode) 3124 register rtx op; 3125 enum machine_mode mode; 3126 { 3127 switch (GET_CODE (op)) 3128 { 3129 case SYMBOL_REF: 3130 case LABEL_REF: 3131 return 1; 3132 3133 case CONST: 3134 op = XEXP (op, 0); 3135 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF 3136 || GET_CODE (XEXP (op, 0)) == LABEL_REF) 3137 && GET_CODE (XEXP (op, 1)) == CONST_INT); 3138 3139 /* ??? This clause seems to be irrelevant. */ 3140 case CONST_DOUBLE: 3141 return GET_MODE (op) == mode; 3142 3143 default: 3144 return 0; 3145 } 3146 } 3147 3148 /* Adjust the cost of INSN based on the relationship between INSN that 3149 is dependent on DEP_INSN through the dependence LINK. The default 3150 is to make no adjustment to COST. 3151 3152 On the m88k, ignore the cost of anti- and output-dependencies. On 3153 the m88100, a store can issue two cycles before the value (not the 3154 address) has finished computing. */ 3155 3156 static int 3157 m88k_adjust_cost (insn, link, dep, cost) 3158 rtx insn; 3159 rtx link; 3160 rtx dep; 3161 int cost; 3162 { 3163 if (REG_NOTE_KIND (link) != 0) 3164 return 0; /* Anti or output dependence. */ 3165 3166 if (! TARGET_88100 3167 && recog_memoized (insn) >= 0 3168 && get_attr_type (insn) == TYPE_STORE 3169 && SET_SRC (PATTERN (insn)) == SET_DEST (PATTERN (dep))) 3170 return cost - 4; /* 88110 store reservation station. */ 3171 3172 return cost; 3173 } 3174 3175 void 3176 m88k_override_options () 3177 { 3178 if ((target_flags & MASK_88000) == 0) 3179 target_flags |= CPU_DEFAULT; 3180 3181 if (TARGET_88110) 3182 { 3183 target_flags |= MASK_USE_DIV; 3184 target_flags &= ~MASK_CHECK_ZERO_DIV; 3185 } 3186 3187 m88k_cpu = (TARGET_88000 ? PROCESSOR_M88000 3188 : (TARGET_88100 ? PROCESSOR_M88100 : PROCESSOR_M88110)); 3189 3190 if ((target_flags & MASK_EITHER_LARGE_SHIFT) == MASK_EITHER_LARGE_SHIFT) 3191 error ("-mtrap-large-shift and -mhandle-large-shift are incompatible"); 3192 3193 if (TARGET_OMIT_LEAF_FRAME_POINTER) /* keep nonleaf frame pointers */ 3194 flag_omit_frame_pointer = 1; 3195 3196 /* On the m88100, it is desirable to align functions to a cache line. 3197 The m88110 cache is small, so align to an 8 byte boundary. */ 3198 if (align_functions == 0) 3199 align_functions = TARGET_88100 ? 16 : 8; 3200 } 3201