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