1 /* Subroutines for insn-output.c for Motorola 68000 family. 2 Copyright (C) 1987 Free Software Foundation, Inc. 3 4 This file is part of GNU CC. 5 6 GNU CC is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 GNU CC is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GNU CC; see the file COPYING. If not, write to 18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ 19 20 21 /* Some output-actions in m68k.md need these. */ 22 #include <stdio.h> 23 #include "config.h" 24 #include "rtl.h" 25 #include "regs.h" 26 #include "hard-reg-set.h" 27 #include "real.h" 28 #include "insn-config.h" 29 #include "conditions.h" 30 #include "insn-flags.h" 31 #include "output.h" 32 #include "insn-attr.h" 33 34 /* Needed for use_return_insn. */ 35 #include "flags.h" 36 37 #ifdef SUPPORT_SUN_FPA 38 39 /* Index into this array by (register number >> 3) to find the 40 smallest class which contains that register. */ 41 enum reg_class regno_reg_class[] 42 = { DATA_REGS, ADDR_REGS, FP_REGS, 43 LO_FPA_REGS, LO_FPA_REGS, FPA_REGS, FPA_REGS }; 44 45 #endif /* defined SUPPORT_SUN_FPA */ 46 47 /* This flag is used to communicate between movhi and ASM_OUTPUT_CASE_END, 48 if SGS_SWITCH_TABLE. */ 49 int switch_table_difference_label_flag; 50 51 static rtx find_addr_reg (); 52 rtx legitimize_pic_address (); 53 54 55 /* Emit a (use pic_offset_table_rtx) if we used PIC relocation in the 56 function at any time during the compilation process. In the future 57 we should try and eliminate the USE if we can easily determine that 58 all PIC references were deleted from the current function. That would 59 save an address register */ 60 61 finalize_pic () 62 { 63 if (flag_pic && current_function_uses_pic_offset_table) 64 emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx)); 65 } 66 67 68 /* This function generates the assembly code for function entry. 69 STREAM is a stdio stream to output the code to. 70 SIZE is an int: how many units of temporary storage to allocate. 71 Refer to the array `regs_ever_live' to determine which registers 72 to save; `regs_ever_live[I]' is nonzero if register number I 73 is ever used in the function. This function is responsible for 74 knowing which registers should not be saved even if used. */ 75 76 77 /* Note that the order of the bit mask for fmovem is the opposite 78 of the order for movem! */ 79 80 81 void 82 output_function_prologue (stream, size) 83 FILE *stream; 84 int size; 85 { 86 register int regno; 87 register int mask = 0; 88 int num_saved_regs = 0; 89 extern char call_used_regs[]; 90 int fsize = (size + 3) & -4; 91 92 93 if (frame_pointer_needed) 94 { 95 /* Adding negative number is faster on the 68040. */ 96 if (fsize < 0x8000 && !TARGET_68040) 97 { 98 #ifdef MOTOROLA 99 asm_fprintf (stream, "\tlink.w %s,%0I%d\n", 100 reg_names[FRAME_POINTER_REGNUM], -fsize); 101 #else 102 asm_fprintf (stream, "\tlink %s,%0I%d\n", 103 reg_names[FRAME_POINTER_REGNUM], -fsize); 104 #endif 105 } 106 else if (TARGET_68020) 107 { 108 #ifdef MOTOROLA 109 asm_fprintf (stream, "\tlink.l %s,%0I%d\n", 110 reg_names[FRAME_POINTER_REGNUM], -fsize); 111 #else 112 asm_fprintf (stream, "\tlink %s,%0I%d\n", 113 reg_names[FRAME_POINTER_REGNUM], -fsize); 114 #endif 115 } 116 else 117 { 118 #ifdef MOTOROLA 119 asm_fprintf (stream, "\tlink.w %s,%0I0\n\tadd.l %0I%d,%Rsp\n", 120 reg_names[FRAME_POINTER_REGNUM], -fsize); 121 #else 122 asm_fprintf (stream, "\tlink %s,%0I0\n\taddl %0I%d,%Rsp\n", 123 reg_names[FRAME_POINTER_REGNUM], -fsize); 124 #endif 125 } 126 } 127 else if (fsize) 128 { 129 /* Adding negative number is faster on the 68040. */ 130 if (fsize + 4 < 0x8000) 131 { 132 #ifdef MOTOROLA 133 asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", - (fsize + 4)); 134 #else 135 asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", - (fsize + 4)); 136 #endif 137 } 138 else 139 { 140 #ifdef MOTOROLA 141 asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", - (fsize + 4)); 142 #else 143 asm_fprintf (stream, "\taddl %0I%d,%Rsp\n", - (fsize + 4)); 144 #endif 145 } 146 } 147 #ifdef SUPPORT_SUN_FPA 148 for (regno = 24; regno < 56; regno++) 149 if (regs_ever_live[regno] && ! call_used_regs[regno]) 150 { 151 #ifdef MOTOROLA 152 asm_fprintf (stream, "\tfpmovd %s,-(%Rsp)\n", 153 reg_names[regno]); 154 #else 155 asm_fprintf (stream, "\tfpmoved %s,%Rsp@-\n", 156 reg_names[regno]); 157 #endif 158 } 159 #endif 160 for (regno = 16; regno < 24; regno++) 161 if (regs_ever_live[regno] && ! call_used_regs[regno]) 162 mask |= 1 << (regno - 16); 163 if ((mask & 0xff) != 0) 164 { 165 #ifdef MOTOROLA 166 asm_fprintf (stream, "\tfmovm %0I0x%x,-(%Rsp)\n", mask & 0xff); 167 #else 168 asm_fprintf (stream, "\tfmovem %0I0x%x,%Rsp@-\n", mask & 0xff); 169 #endif 170 } 171 mask = 0; 172 for (regno = 0; regno < 16; regno++) 173 if (regs_ever_live[regno] && ! call_used_regs[regno]) 174 { 175 mask |= 1 << (15 - regno); 176 num_saved_regs++; 177 } 178 if (frame_pointer_needed) 179 { 180 mask &= ~ (1 << (15 - FRAME_POINTER_REGNUM)); 181 num_saved_regs--; 182 } 183 184 #if NEED_PROBE 185 fprintf (stream, "\ttstl sp@(%d)\n", NEED_PROBE - num_saved_regs * 4); 186 #endif 187 188 if (num_saved_regs <= 2) 189 { 190 /* Store each separately in the same order moveml uses. 191 Using two movel instructions instead of a single moveml 192 is about 15% faster for the 68020 and 68030 at no expense 193 in code size */ 194 195 int i; 196 197 /* Undo the work from above. */ 198 for (i = 0; i< 16; i++) 199 if (mask & (1 << i)) 200 asm_fprintf (stream, 201 #ifdef MOTOROLA 202 "\t%Omove.l %s,-(%Rsp)\n", 203 #else 204 "\tmovel %s,%Rsp@-\n", 205 #endif 206 reg_names[15 - i]); 207 } 208 else if (mask) 209 { 210 #ifdef MOTOROLA 211 asm_fprintf (stream, "\tmovm.l %0I0x%x,-(%Rsp)\n", mask); 212 #else 213 asm_fprintf (stream, "\tmoveml %0I0x%x,%Rsp@-\n", mask); 214 #endif 215 } 216 if (flag_pic && current_function_uses_pic_offset_table) 217 { 218 #ifdef MOTOROLA 219 asm_fprintf (stream, "\t%Omove.l %0I__GLOBAL_OFFSET_TABLE_, %s\n", 220 reg_names[PIC_OFFSET_TABLE_REGNUM]); 221 asm_fprintf (stream, "\tlea.l (%Rpc,%s.l),%s\n", 222 reg_names[PIC_OFFSET_TABLE_REGNUM], 223 reg_names[PIC_OFFSET_TABLE_REGNUM]); 224 #else 225 asm_fprintf (stream, "\tmovel %0I__GLOBAL_OFFSET_TABLE_, %s\n", 226 reg_names[PIC_OFFSET_TABLE_REGNUM]); 227 asm_fprintf (stream, "\tlea %Rpc@(0,%s:l),%s\n", 228 reg_names[PIC_OFFSET_TABLE_REGNUM], 229 reg_names[PIC_OFFSET_TABLE_REGNUM]); 230 #endif 231 } 232 } 233 234 /* Return true if this function's epilogue can be output as RTL. */ 235 236 int 237 use_return_insn () 238 { 239 int regno; 240 241 if (!reload_completed || frame_pointer_needed || get_frame_size () != 0) 242 return 0; 243 244 /* Copied from output_function_epilogue (). We should probably create a 245 separate layout routine to perform the common work. */ 246 247 for (regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno++) 248 if (regs_ever_live[regno] && ! call_used_regs[regno]) 249 return 0; 250 251 return 1; 252 } 253 254 /* This function generates the assembly code for function exit, 255 on machines that need it. Args are same as for FUNCTION_PROLOGUE. 256 257 The function epilogue should not depend on the current stack pointer! 258 It should use the frame pointer only, if there is a frame pointer. 259 This is mandatory because of alloca; we also take advantage of it to 260 omit stack adjustments before returning. */ 261 262 void 263 output_function_epilogue (stream, size) 264 FILE *stream; 265 int size; 266 { 267 register int regno; 268 register int mask, fmask; 269 register int nregs; 270 int offset, foffset, fpoffset; 271 extern char call_used_regs[]; 272 int fsize = (size + 3) & -4; 273 int big = 0; 274 rtx insn = get_last_insn (); 275 276 /* If the last insn was a BARRIER, we don't have to write any code. */ 277 if (GET_CODE (insn) == NOTE) 278 insn = prev_nonnote_insn (insn); 279 if (insn && GET_CODE (insn) == BARRIER) 280 { 281 /* Output just a no-op so that debuggers don't get confused 282 about which function the pc is in at this address. */ 283 asm_fprintf (stream, "\tnop\n"); 284 return; 285 } 286 287 #ifdef FUNCTION_EXTRA_EPILOGUE 288 FUNCTION_EXTRA_EPILOGUE (stream, size); 289 #endif 290 nregs = 0; fmask = 0; fpoffset = 0; 291 #ifdef SUPPORT_SUN_FPA 292 for (regno = 24 ; regno < 56 ; regno++) 293 if (regs_ever_live[regno] && ! call_used_regs[regno]) 294 nregs++; 295 fpoffset = nregs * 8; 296 #endif 297 nregs = 0; 298 for (regno = 16; regno < 24; regno++) 299 if (regs_ever_live[regno] && ! call_used_regs[regno]) 300 { 301 nregs++; 302 fmask |= 1 << (23 - regno); 303 } 304 foffset = fpoffset + nregs * 12; 305 nregs = 0; mask = 0; 306 if (frame_pointer_needed) 307 regs_ever_live[FRAME_POINTER_REGNUM] = 0; 308 for (regno = 0; regno < 16; regno++) 309 if (regs_ever_live[regno] && ! call_used_regs[regno]) 310 { 311 nregs++; 312 mask |= 1 << regno; 313 } 314 offset = foffset + nregs * 4; 315 if (offset + fsize >= 0x8000 316 && frame_pointer_needed 317 && (mask || fmask || fpoffset)) 318 { 319 #ifdef MOTOROLA 320 asm_fprintf (stream, "\t%Omove.l %0I%d,%Ra0\n", -fsize); 321 #else 322 asm_fprintf (stream, "\tmovel %0I%d,%Ra0\n", -fsize); 323 #endif 324 fsize = 0, big = 1; 325 } 326 if (nregs <= 2) 327 { 328 /* Restore each separately in the same order moveml does. 329 Using two movel instructions instead of a single moveml 330 is about 15% faster for the 68020 and 68030 at no expense 331 in code size. */ 332 333 int i; 334 335 /* Undo the work from above. */ 336 for (i = 0; i< 16; i++) 337 if (mask & (1 << i)) 338 { 339 if (big) 340 { 341 #ifdef MOTOROLA 342 asm_fprintf (stream, "\t%Omove.l -%d(%s,%Ra0.l),%s\n", 343 offset + fsize, 344 reg_names[FRAME_POINTER_REGNUM], 345 reg_names[i]); 346 #else 347 asm_fprintf (stream, "\tmovel %s@(-%d,%Ra0:l),%s\n", 348 reg_names[FRAME_POINTER_REGNUM], 349 offset + fsize, reg_names[i]); 350 #endif 351 } 352 else if (! frame_pointer_needed) 353 { 354 #ifdef MOTOROLA 355 asm_fprintf (stream, "\t%Omove.l (%Rsp)+,%s\n", 356 reg_names[i]); 357 #else 358 asm_fprintf (stream, "\tmovel %Rsp@+,%s\n", 359 reg_names[i]); 360 #endif 361 } 362 else 363 { 364 #ifdef MOTOROLA 365 asm_fprintf (stream, "\t%Omove.l -%d(%s),%s\n", 366 offset + fsize, 367 reg_names[FRAME_POINTER_REGNUM], 368 reg_names[i]); 369 #else 370 asm_fprintf (stream, "\tmovel %s@(-%d),%s\n", 371 reg_names[FRAME_POINTER_REGNUM], 372 offset + fsize, reg_names[i]); 373 #endif 374 } 375 offset = offset - 4; 376 } 377 } 378 else if (mask) 379 { 380 if (big) 381 { 382 #ifdef MOTOROLA 383 asm_fprintf (stream, "\tmovm.l -%d(%s,%Ra0.l),%0I0x%x\n", 384 offset + fsize, 385 reg_names[FRAME_POINTER_REGNUM], 386 mask); 387 #else 388 asm_fprintf (stream, "\tmoveml %s@(-%d,%Ra0:l),%0I0x%x\n", 389 reg_names[FRAME_POINTER_REGNUM], 390 offset + fsize, mask); 391 #endif 392 } 393 else if (! frame_pointer_needed) 394 { 395 #ifdef MOTOROLA 396 asm_fprintf (stream, "\tmovm.l (%Rsp)+,%0I0x%x\n", mask); 397 #else 398 asm_fprintf (stream, "\tmoveml %Rsp@+,%0I0x%x\n", mask); 399 #endif 400 } 401 else 402 { 403 #ifdef MOTOROLA 404 asm_fprintf (stream, "\tmovm.l -%d(%s),%0I0x%x\n", 405 offset + fsize, 406 reg_names[FRAME_POINTER_REGNUM], 407 mask); 408 #else 409 asm_fprintf (stream, "\tmoveml %s@(-%d),%0I0x%x\n", 410 reg_names[FRAME_POINTER_REGNUM], 411 offset + fsize, mask); 412 #endif 413 } 414 } 415 if (fmask) 416 { 417 if (big) 418 { 419 #ifdef MOTOROLA 420 asm_fprintf (stream, "\tfmovm -%d(%s,%Ra0.l),%0I0x%x\n", 421 foffset + fsize, 422 reg_names[FRAME_POINTER_REGNUM], 423 fmask); 424 #else 425 asm_fprintf (stream, "\tfmovem %s@(-%d,%Ra0:l),%0I0x%x\n", 426 reg_names[FRAME_POINTER_REGNUM], 427 foffset + fsize, fmask); 428 #endif 429 } 430 else if (! frame_pointer_needed) 431 { 432 #ifdef MOTOROLA 433 asm_fprintf (stream, "\tfmovm (%Rsp)+,%0I0x%x\n", fmask); 434 #else 435 asm_fprintf (stream, "\tfmovem %Rsp@+,%0I0x%x\n", fmask); 436 #endif 437 } 438 else 439 { 440 #ifdef MOTOROLA 441 asm_fprintf (stream, "\tfmovm -%d(%s),%0I0x%x\n", 442 foffset + fsize, 443 reg_names[FRAME_POINTER_REGNUM], 444 fmask); 445 #else 446 asm_fprintf (stream, "\tfmovem %s@(-%d),%0I0x%x\n", 447 reg_names[FRAME_POINTER_REGNUM], 448 foffset + fsize, fmask); 449 #endif 450 } 451 } 452 if (fpoffset != 0) 453 for (regno = 55; regno >= 24; regno--) 454 if (regs_ever_live[regno] && ! call_used_regs[regno]) 455 { 456 if (big) 457 { 458 #ifdef MOTOROLA 459 asm_fprintf (stream, "\tfpmovd -%d(%s,%Ra0.l), %s\n", 460 fpoffset + fsize, 461 reg_names[FRAME_POINTER_REGNUM], 462 reg_names[regno]); 463 #else 464 asm_fprintf (stream, "\tfpmoved %s@(-%d,%Ra0:l), %s\n", 465 reg_names[FRAME_POINTER_REGNUM], 466 fpoffset + fsize, reg_names[regno]); 467 #endif 468 } 469 else if (! frame_pointer_needed) 470 { 471 #ifdef MOTOROLA 472 asm_fprintf (stream, "\tfpmovd (%Rsp)+,%s\n", 473 reg_names[regno]); 474 #else 475 asm_fprintf (stream, "\tfpmoved %Rsp@+, %s\n", 476 reg_names[regno]); 477 #endif 478 } 479 else 480 { 481 #ifdef MOTOROLA 482 asm_fprintf (stream, "\tfpmovd -%d(%s), %s\n", 483 fpoffset + fsize, 484 reg_names[FRAME_POINTER_REGNUM], 485 reg_names[regno]); 486 #else 487 asm_fprintf (stream, "\tfpmoved %s@(-%d), %s\n", 488 reg_names[FRAME_POINTER_REGNUM], 489 fpoffset + fsize, reg_names[regno]); 490 #endif 491 } 492 fpoffset -= 8; 493 } 494 if (frame_pointer_needed) 495 fprintf (stream, "\tunlk %s\n", 496 reg_names[FRAME_POINTER_REGNUM]); 497 else if (fsize) 498 { 499 if (fsize + 4 < 0x8000) 500 { 501 #ifdef MOTOROLA 502 asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", fsize + 4); 503 #else 504 asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", fsize + 4); 505 #endif 506 } 507 else 508 { 509 #ifdef MOTOROLA 510 asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", fsize + 4); 511 #else 512 asm_fprintf (stream, "\taddl %0I%d,%Rsp\n", fsize + 4); 513 #endif 514 } 515 } 516 if (current_function_pops_args) 517 asm_fprintf (stream, "\trtd %0I%d\n", current_function_pops_args); 518 else 519 fprintf (stream, "\trts\n"); 520 } 521 522 /* Similar to general_operand, but exclude stack_pointer_rtx. */ 523 524 int 525 not_sp_operand (op, mode) 526 register rtx op; 527 enum machine_mode mode; 528 { 529 return op != stack_pointer_rtx && general_operand (op, mode); 530 } 531 532 /* Return TRUE if X is a valid comparison operator for the dbcc 533 instruction. 534 535 Note it rejects floating point comparison operators. 536 (In the future we could use Fdbcc). 537 538 It also rejects some comparisons when CC_NO_OVERFLOW is set. */ 539 540 int 541 valid_dbcc_comparison_p (x, mode) 542 rtx x; 543 enum machine_mode mode; 544 { 545 /* We could add support for these in the future */ 546 if (cc_prev_status.flags & CC_IN_68881) 547 return 0; 548 549 switch (GET_CODE (x)) 550 { 551 552 case EQ: case NE: case GTU: case LTU: 553 case GEU: case LEU: 554 return 1; 555 556 /* Reject some when CC_NO_OVERFLOW is set. This may be over 557 conservative */ 558 case GT: case LT: case GE: case LE: 559 return ! (cc_prev_status.flags & CC_NO_OVERFLOW); 560 default: 561 return 0; 562 } 563 } 564 565 /* Output a dbCC; jCC sequence. Note we do not handle the 566 floating point version of this sequence (Fdbcc). We also 567 do not handle alternative conditions when CC_NO_OVERFLOW is 568 set. It is assumed that valid_dbcc_comparison_p will kick 569 those out before we get here. */ 570 571 output_dbcc_and_branch (operands) 572 rtx *operands; 573 { 574 575 switch (GET_CODE (operands[3])) 576 { 577 case EQ: 578 #ifdef MOTOROLA 579 output_asm_insn ("dbeq %0,%l1\n\tjbeq %l2", operands); 580 #else 581 output_asm_insn ("dbeq %0,%l1\n\tjeq %l2", operands); 582 #endif 583 break; 584 585 case NE: 586 #ifdef MOTOROLA 587 output_asm_insn ("dbne %0,%l1\n\tjbne %l2", operands); 588 #else 589 output_asm_insn ("dbne %0,%l1\n\tjne %l2", operands); 590 #endif 591 break; 592 593 case GT: 594 #ifdef MOTOROLA 595 output_asm_insn ("dbgt %0,%l1\n\tjbgt %l2", operands); 596 #else 597 output_asm_insn ("dbgt %0,%l1\n\tjgt %l2", operands); 598 #endif 599 break; 600 601 case GTU: 602 #ifdef MOTOROLA 603 output_asm_insn ("dbhi %0,%l1\n\tjbhi %l2", operands); 604 #else 605 output_asm_insn ("dbhi %0,%l1\n\tjhi %l2", operands); 606 #endif 607 break; 608 609 case LT: 610 #ifdef MOTOROLA 611 output_asm_insn ("dblt %0,%l1\n\tjblt %l2", operands); 612 #else 613 output_asm_insn ("dblt %0,%l1\n\tjlt %l2", operands); 614 #endif 615 break; 616 617 case LTU: 618 #ifdef MOTOROLA 619 output_asm_insn ("dbcs %0,%l1\n\tjbcs %l2", operands); 620 #else 621 output_asm_insn ("dbcs %0,%l1\n\tjcs %l2", operands); 622 #endif 623 break; 624 625 case GE: 626 #ifdef MOTOROLA 627 output_asm_insn ("dbge %0,%l1\n\tjbge %l2", operands); 628 #else 629 output_asm_insn ("dbge %0,%l1\n\tjge %l2", operands); 630 #endif 631 break; 632 633 case GEU: 634 #ifdef MOTOROLA 635 output_asm_insn ("dbcc %0,%l1\n\tjbcc %l2", operands); 636 #else 637 output_asm_insn ("dbcc %0,%l1\n\tjcc %l2", operands); 638 #endif 639 break; 640 641 case LE: 642 #ifdef MOTOROLA 643 output_asm_insn ("dble %0,%l1\n\tjble %l2", operands); 644 #else 645 output_asm_insn ("dble %0,%l1\n\tjle %l2", operands); 646 #endif 647 break; 648 649 case LEU: 650 #ifdef MOTOROLA 651 output_asm_insn ("dbls %0,%l1\n\tjbls %l2", operands); 652 #else 653 output_asm_insn ("dbls %0,%l1\n\tjls %l2", operands); 654 #endif 655 break; 656 657 default: 658 abort (); 659 } 660 661 /* If the decrement is to be done in SImode, then we have 662 to compensate for the fact that dbcc decrements in HImode. */ 663 switch (GET_MODE (operands[0])) 664 { 665 case SImode: 666 #ifdef MOTOROLA 667 output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjbpl %l1", operands); 668 #else 669 output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjpl %l1", operands); 670 #endif 671 break; 672 673 case HImode: 674 break; 675 676 default: 677 abort (); 678 } 679 } 680 681 char * 682 output_btst (operands, countop, dataop, insn, signpos) 683 rtx *operands; 684 rtx countop, dataop; 685 rtx insn; 686 int signpos; 687 { 688 operands[0] = countop; 689 operands[1] = dataop; 690 691 if (GET_CODE (countop) == CONST_INT) 692 { 693 register int count = INTVAL (countop); 694 /* If COUNT is bigger than size of storage unit in use, 695 advance to the containing unit of same size. */ 696 if (count > signpos) 697 { 698 int offset = (count & ~signpos) / 8; 699 count = count & signpos; 700 operands[1] = dataop = adj_offsettable_operand (dataop, offset); 701 } 702 if (count == signpos) 703 cc_status.flags = CC_NOT_POSITIVE | CC_Z_IN_NOT_N; 704 else 705 cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N; 706 707 /* These three statements used to use next_insns_test_no... 708 but it appears that this should do the same job. */ 709 if (count == 31 710 && next_insn_tests_no_inequality (insn)) 711 return "tst%.l %1"; 712 if (count == 15 713 && next_insn_tests_no_inequality (insn)) 714 return "tst%.w %1"; 715 if (count == 7 716 && next_insn_tests_no_inequality (insn)) 717 return "tst%.b %1"; 718 719 cc_status.flags = CC_NOT_NEGATIVE; 720 } 721 return "btst %0,%1"; 722 } 723 724 /* Returns 1 if OP is either a symbol reference or a sum of a symbol 725 reference and a constant. */ 726 727 int 728 symbolic_operand (op, mode) 729 register rtx op; 730 enum machine_mode mode; 731 { 732 switch (GET_CODE (op)) 733 { 734 case SYMBOL_REF: 735 case LABEL_REF: 736 return 1; 737 738 case CONST: 739 op = XEXP (op, 0); 740 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF 741 || GET_CODE (XEXP (op, 0)) == LABEL_REF) 742 && GET_CODE (XEXP (op, 1)) == CONST_INT); 743 744 #if 0 /* Deleted, with corresponding change in m68k.h, 745 so as to fit the specs. No CONST_DOUBLE is ever symbolic. */ 746 case CONST_DOUBLE: 747 return GET_MODE (op) == mode; 748 #endif 749 750 default: 751 return 0; 752 } 753 } 754 755 756 /* Legitimize PIC addresses. If the address is already 757 position-independent, we return ORIG. Newly generated 758 position-independent addresses go to REG. If we need more 759 than one register, we lose. 760 761 An address is legitimized by making an indirect reference 762 through the Global Offset Table with the name of the symbol 763 used as an offset. 764 765 The assembler and linker are responsible for placing the 766 address of the symbol in the GOT. The function prologue 767 is responsible for initializing a5 to the starting address 768 of the GOT. 769 770 The assembler is also responsible for translating a symbol name 771 into a constant displacement from the start of the GOT. 772 773 A quick example may make things a little clearer: 774 775 When not generating PIC code to store the value 12345 into _foo 776 we would generate the following code: 777 778 movel #12345, _foo 779 780 When generating PIC two transformations are made. First, the compiler 781 loads the address of foo into a register. So the first transformation makes: 782 783 lea _foo, a0 784 movel #12345, a0@ 785 786 The code in movsi will intercept the lea instruction and call this 787 routine which will transform the instructions into: 788 789 movel a5@(_foo:w), a0 790 movel #12345, a0@ 791 792 793 That (in a nutshell) is how *all* symbol and label references are 794 handled. */ 795 796 rtx 797 legitimize_pic_address (orig, mode, reg) 798 rtx orig, reg; 799 enum machine_mode mode; 800 { 801 rtx pic_ref = orig; 802 803 /* First handle a simple SYMBOL_REF or LABEL_REF */ 804 if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF) 805 { 806 if (reg == 0) 807 abort (); 808 809 pic_ref = gen_rtx (MEM, Pmode, 810 gen_rtx (PLUS, Pmode, 811 pic_offset_table_rtx, orig)); 812 current_function_uses_pic_offset_table = 1; 813 RTX_UNCHANGING_P (pic_ref) = 1; 814 emit_move_insn (reg, pic_ref); 815 return reg; 816 } 817 else if (GET_CODE (orig) == CONST) 818 { 819 rtx base, offset; 820 821 /* Make sure this is CONST has not already been legitimized */ 822 if (GET_CODE (XEXP (orig, 0)) == PLUS 823 && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx) 824 return orig; 825 826 if (reg == 0) 827 abort (); 828 829 /* legitimize both operands of the PLUS */ 830 if (GET_CODE (XEXP (orig, 0)) == PLUS) 831 { 832 base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg); 833 orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode, 834 base == reg ? 0 : reg); 835 } 836 else abort (); 837 838 if (GET_CODE (orig) == CONST_INT) 839 return plus_constant_for_output (base, INTVAL (orig)); 840 pic_ref = gen_rtx (PLUS, Pmode, base, orig); 841 /* Likewise, should we set special REG_NOTEs here? */ 842 } 843 return pic_ref; 844 } 845 846 847 /* Return the best assembler insn template 848 for moving operands[1] into operands[0] as a fullword. */ 849 850 static char * 851 singlemove_string (operands) 852 rtx *operands; 853 { 854 #ifdef SUPPORT_SUN_FPA 855 if (FPA_REG_P (operands[0]) || FPA_REG_P (operands[1])) 856 return "fpmoves %1,%0"; 857 #endif 858 if (DATA_REG_P (operands[0]) 859 && GET_CODE (operands[1]) == CONST_INT 860 && INTVAL (operands[1]) < 128 861 && INTVAL (operands[1]) >= -128) 862 { 863 #if defined (MOTOROLA) && !defined (CRDS) 864 return "moveq%.l %1,%0"; 865 #else 866 return "moveq %1,%0"; 867 #endif 868 } 869 if (operands[1] != const0_rtx) 870 return "move%.l %1,%0"; 871 if (! ADDRESS_REG_P (operands[0])) 872 return "clr%.l %0"; 873 return "sub%.l %0,%0"; 874 } 875 876 /* Output assembler code to perform a doubleword move insn 877 with operands OPERANDS. */ 878 879 char * 880 output_move_double (operands) 881 rtx *operands; 882 { 883 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1; 884 rtx latehalf[2]; 885 rtx addreg0 = 0, addreg1 = 0; 886 887 /* First classify both operands. */ 888 889 if (REG_P (operands[0])) 890 optype0 = REGOP; 891 else if (offsettable_memref_p (operands[0])) 892 optype0 = OFFSOP; 893 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC) 894 optype0 = POPOP; 895 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) 896 optype0 = PUSHOP; 897 else if (GET_CODE (operands[0]) == MEM) 898 optype0 = MEMOP; 899 else 900 optype0 = RNDOP; 901 902 if (REG_P (operands[1])) 903 optype1 = REGOP; 904 else if (CONSTANT_P (operands[1])) 905 optype1 = CNSTOP; 906 else if (offsettable_memref_p (operands[1])) 907 optype1 = OFFSOP; 908 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC) 909 optype1 = POPOP; 910 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC) 911 optype1 = PUSHOP; 912 else if (GET_CODE (operands[1]) == MEM) 913 optype1 = MEMOP; 914 else 915 optype1 = RNDOP; 916 917 /* Check for the cases that the operand constraints are not 918 supposed to allow to happen. Abort if we get one, 919 because generating code for these cases is painful. */ 920 921 if (optype0 == RNDOP || optype1 == RNDOP) 922 abort (); 923 924 /* If one operand is decrementing and one is incrementing 925 decrement the former register explicitly 926 and change that operand into ordinary indexing. */ 927 928 if (optype0 == PUSHOP && optype1 == POPOP) 929 { 930 operands[0] = XEXP (XEXP (operands[0], 0), 0); 931 output_asm_insn ("subq%.l %#8,%0", operands); 932 operands[0] = gen_rtx (MEM, DImode, operands[0]); 933 optype0 = OFFSOP; 934 } 935 if (optype0 == POPOP && optype1 == PUSHOP) 936 { 937 operands[1] = XEXP (XEXP (operands[1], 0), 0); 938 output_asm_insn ("subq%.l %#8,%1", operands); 939 operands[1] = gen_rtx (MEM, DImode, operands[1]); 940 optype1 = OFFSOP; 941 } 942 943 /* If an operand is an unoffsettable memory ref, find a register 944 we can increment temporarily to make it refer to the second word. */ 945 946 if (optype0 == MEMOP) 947 addreg0 = find_addr_reg (XEXP (operands[0], 0)); 948 949 if (optype1 == MEMOP) 950 addreg1 = find_addr_reg (XEXP (operands[1], 0)); 951 952 /* Ok, we can do one word at a time. 953 Normally we do the low-numbered word first, 954 but if either operand is autodecrementing then we 955 do the high-numbered word first. 956 957 In either case, set up in LATEHALF the operands to use 958 for the high-numbered word and in some cases alter the 959 operands in OPERANDS to be suitable for the low-numbered word. */ 960 961 if (optype0 == REGOP) 962 latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); 963 else if (optype0 == OFFSOP) 964 latehalf[0] = adj_offsettable_operand (operands[0], 4); 965 else 966 latehalf[0] = operands[0]; 967 968 if (optype1 == REGOP) 969 latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); 970 else if (optype1 == OFFSOP) 971 latehalf[1] = adj_offsettable_operand (operands[1], 4); 972 else if (optype1 == CNSTOP) 973 split_double (operands[1], &operands[1], &latehalf[1]); 974 else 975 latehalf[1] = operands[1]; 976 977 /* If insn is effectively movd N(sp),-(sp) then we will do the 978 high word first. We should use the adjusted operand 1 (which is N+4(sp)) 979 for the low word as well, to compensate for the first decrement of sp. */ 980 if (optype0 == PUSHOP 981 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM 982 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1])) 983 operands[1] = latehalf[1]; 984 985 /* If one or both operands autodecrementing, 986 do the two words, high-numbered first. */ 987 988 /* Likewise, the first move would clobber the source of the second one, 989 do them in the other order. This happens only for registers; 990 such overlap can't happen in memory unless the user explicitly 991 sets it up, and that is an undefined circumstance. */ 992 993 if (optype0 == PUSHOP || optype1 == PUSHOP 994 || (optype0 == REGOP && optype1 == REGOP 995 && REGNO (operands[0]) == REGNO (latehalf[1]))) 996 { 997 /* Make any unoffsettable addresses point at high-numbered word. */ 998 if (addreg0) 999 output_asm_insn ("addql %#4,%0", &addreg0); 1000 if (addreg1) 1001 output_asm_insn ("addql %#4,%0", &addreg1); 1002 1003 /* Do that word. */ 1004 output_asm_insn (singlemove_string (latehalf), latehalf); 1005 1006 /* Undo the adds we just did. */ 1007 if (addreg0) 1008 output_asm_insn ("subql %#4,%0", &addreg0); 1009 if (addreg1) 1010 output_asm_insn ("subql %#4,%0", &addreg1); 1011 1012 /* Do low-numbered word. */ 1013 return singlemove_string (operands); 1014 } 1015 1016 /* Normal case: do the two words, low-numbered first. */ 1017 1018 output_asm_insn (singlemove_string (operands), operands); 1019 1020 /* Make any unoffsettable addresses point at high-numbered word. */ 1021 if (addreg0) 1022 output_asm_insn ("addql %#4,%0", &addreg0); 1023 if (addreg1) 1024 output_asm_insn ("addql %#4,%0", &addreg1); 1025 1026 /* Do that word. */ 1027 output_asm_insn (singlemove_string (latehalf), latehalf); 1028 1029 /* Undo the adds we just did. */ 1030 if (addreg0) 1031 output_asm_insn ("subql %#4,%0", &addreg0); 1032 if (addreg1) 1033 output_asm_insn ("subql %#4,%0", &addreg1); 1034 1035 return ""; 1036 } 1037 1038 /* Return a REG that occurs in ADDR with coefficient 1. 1039 ADDR can be effectively incremented by incrementing REG. */ 1040 1041 static rtx 1042 find_addr_reg (addr) 1043 rtx addr; 1044 { 1045 while (GET_CODE (addr) == PLUS) 1046 { 1047 if (GET_CODE (XEXP (addr, 0)) == REG) 1048 addr = XEXP (addr, 0); 1049 else if (GET_CODE (XEXP (addr, 1)) == REG) 1050 addr = XEXP (addr, 1); 1051 else if (CONSTANT_P (XEXP (addr, 0))) 1052 addr = XEXP (addr, 1); 1053 else if (CONSTANT_P (XEXP (addr, 1))) 1054 addr = XEXP (addr, 0); 1055 else 1056 abort (); 1057 } 1058 if (GET_CODE (addr) == REG) 1059 return addr; 1060 abort (); 1061 } 1062 1063 /* Store in cc_status the expressions that the condition codes will 1064 describe after execution of an instruction whose pattern is EXP. 1065 Do not alter them if the instruction would not alter the cc's. */ 1066 1067 /* On the 68000, all the insns to store in an address register fail to 1068 set the cc's. However, in some cases these instructions can make it 1069 possibly invalid to use the saved cc's. In those cases we clear out 1070 some or all of the saved cc's so they won't be used. */ 1071 1072 notice_update_cc (exp, insn) 1073 rtx exp; 1074 rtx insn; 1075 { 1076 /* If the cc is being set from the fpa and the expression is not an 1077 explicit floating point test instruction (which has code to deal with 1078 this), reinit the CC. */ 1079 if (((cc_status.value1 && FPA_REG_P (cc_status.value1)) 1080 || (cc_status.value2 && FPA_REG_P (cc_status.value2))) 1081 && !(GET_CODE (exp) == PARALLEL 1082 && GET_CODE (XVECEXP (exp, 0, 0)) == SET 1083 && XEXP (XVECEXP (exp, 0, 0), 0) == cc0_rtx)) 1084 { 1085 CC_STATUS_INIT; 1086 } 1087 else if (GET_CODE (exp) == SET) 1088 { 1089 if (GET_CODE (SET_SRC (exp)) == CALL) 1090 { 1091 CC_STATUS_INIT; 1092 } 1093 else if (ADDRESS_REG_P (SET_DEST (exp))) 1094 { 1095 if (cc_status.value1 1096 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)) 1097 cc_status.value1 = 0; 1098 if (cc_status.value2 1099 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)) 1100 cc_status.value2 = 0; 1101 } 1102 else if (!FP_REG_P (SET_DEST (exp)) 1103 && SET_DEST (exp) != cc0_rtx 1104 && (FP_REG_P (SET_SRC (exp)) 1105 || GET_CODE (SET_SRC (exp)) == FIX 1106 || GET_CODE (SET_SRC (exp)) == FLOAT_TRUNCATE 1107 || GET_CODE (SET_SRC (exp)) == FLOAT_EXTEND)) 1108 { 1109 CC_STATUS_INIT; 1110 } 1111 /* A pair of move insns doesn't produce a useful overall cc. */ 1112 else if (!FP_REG_P (SET_DEST (exp)) 1113 && !FP_REG_P (SET_SRC (exp)) 1114 && GET_MODE_SIZE (GET_MODE (SET_SRC (exp))) > 4 1115 && (GET_CODE (SET_SRC (exp)) == REG 1116 || GET_CODE (SET_SRC (exp)) == MEM 1117 || GET_CODE (SET_SRC (exp)) == CONST_DOUBLE)) 1118 { 1119 CC_STATUS_INIT; 1120 } 1121 else if (GET_CODE (SET_SRC (exp)) == CALL) 1122 { 1123 CC_STATUS_INIT; 1124 } 1125 else if (XEXP (exp, 0) != pc_rtx) 1126 { 1127 cc_status.flags = 0; 1128 cc_status.value1 = XEXP (exp, 0); 1129 cc_status.value2 = XEXP (exp, 1); 1130 } 1131 } 1132 else if (GET_CODE (exp) == PARALLEL 1133 && GET_CODE (XVECEXP (exp, 0, 0)) == SET) 1134 { 1135 if (ADDRESS_REG_P (XEXP (XVECEXP (exp, 0, 0), 0))) 1136 CC_STATUS_INIT; 1137 else if (XEXP (XVECEXP (exp, 0, 0), 0) != pc_rtx) 1138 { 1139 cc_status.flags = 0; 1140 cc_status.value1 = XEXP (XVECEXP (exp, 0, 0), 0); 1141 cc_status.value2 = XEXP (XVECEXP (exp, 0, 0), 1); 1142 } 1143 } 1144 else 1145 CC_STATUS_INIT; 1146 if (cc_status.value2 != 0 1147 && ADDRESS_REG_P (cc_status.value2) 1148 && GET_MODE (cc_status.value2) == QImode) 1149 CC_STATUS_INIT; 1150 if (cc_status.value2 != 0 1151 && !(cc_status.value1 && FPA_REG_P (cc_status.value1))) 1152 switch (GET_CODE (cc_status.value2)) 1153 { 1154 case PLUS: case MINUS: case MULT: 1155 case DIV: case UDIV: case MOD: case UMOD: case NEG: 1156 case ASHIFT: case LSHIFT: case ASHIFTRT: case LSHIFTRT: 1157 case ROTATE: case ROTATERT: 1158 if (GET_MODE (cc_status.value2) != VOIDmode) 1159 cc_status.flags |= CC_NO_OVERFLOW; 1160 break; 1161 case ZERO_EXTEND: 1162 /* (SET r1 (ZERO_EXTEND r2)) on this machine 1163 ends with a move insn moving r2 in r2's mode. 1164 Thus, the cc's are set for r2. 1165 This can set N bit spuriously. */ 1166 cc_status.flags |= CC_NOT_NEGATIVE; 1167 } 1168 if (cc_status.value1 && GET_CODE (cc_status.value1) == REG 1169 && cc_status.value2 1170 && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2)) 1171 cc_status.value2 = 0; 1172 if (((cc_status.value1 && FP_REG_P (cc_status.value1)) 1173 || (cc_status.value2 && FP_REG_P (cc_status.value2))) 1174 && !((cc_status.value1 && FPA_REG_P (cc_status.value1)) 1175 || (cc_status.value2 && FPA_REG_P (cc_status.value2)))) 1176 cc_status.flags = CC_IN_68881; 1177 } 1178 1179 char * 1180 output_move_const_double (operands) 1181 rtx *operands; 1182 { 1183 #ifdef SUPPORT_SUN_FPA 1184 if (TARGET_FPA && FPA_REG_P (operands[0])) 1185 { 1186 int code = standard_sun_fpa_constant_p (operands[1]); 1187 1188 if (code != 0) 1189 { 1190 static char buf[40]; 1191 1192 sprintf (buf, "fpmove%%.d %%%%%d,%%0", code & 0x1ff); 1193 return buf; 1194 } 1195 return "fpmove%.d %1,%0"; 1196 } 1197 else 1198 #endif 1199 { 1200 int code = standard_68881_constant_p (operands[1]); 1201 1202 if (code != 0) 1203 { 1204 static char buf[40]; 1205 1206 sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff); 1207 return buf; 1208 } 1209 return "fmove%.d %1,%0"; 1210 } 1211 } 1212 1213 char * 1214 output_move_const_single (operands) 1215 rtx *operands; 1216 { 1217 #ifdef SUPPORT_SUN_FPA 1218 if (TARGET_FPA) 1219 { 1220 int code = standard_sun_fpa_constant_p (operands[1]); 1221 1222 if (code != 0) 1223 { 1224 static char buf[40]; 1225 1226 sprintf (buf, "fpmove%%.s %%%%%d,%%0", code & 0x1ff); 1227 return buf; 1228 } 1229 return "fpmove%.s %1,%0"; 1230 } 1231 else 1232 #endif /* defined SUPPORT_SUN_FPA */ 1233 { 1234 int code = standard_68881_constant_p (operands[1]); 1235 1236 if (code != 0) 1237 { 1238 static char buf[40]; 1239 1240 sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff); 1241 return buf; 1242 } 1243 return "fmove%.s %f1,%0"; 1244 } 1245 } 1246 1247 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get 1248 from the "fmovecr" instruction. 1249 The value, anded with 0xff, gives the code to use in fmovecr 1250 to get the desired constant. */ 1251 1252 /* ??? This code should be fixed for cross-compilation. */ 1253 1254 int 1255 standard_68881_constant_p (x) 1256 rtx x; 1257 { 1258 register double d; 1259 1260 /* fmovecr must be emulated on the 68040, so it shouldn't be used at all. */ 1261 if (TARGET_68040) 1262 return 0; 1263 1264 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT 1265 if (! flag_pretend_float) 1266 return 0; 1267 #endif 1268 1269 REAL_VALUE_FROM_CONST_DOUBLE (d, x); 1270 1271 if (d == 0) 1272 return 0x0f; 1273 /* Note: there are various other constants available 1274 but it is a nuisance to put in their values here. */ 1275 if (d == 1) 1276 return 0x32; 1277 if (d == 10) 1278 return 0x33; 1279 if (d == 100) 1280 return 0x34; 1281 if (d == 10000) 1282 return 0x35; 1283 if (d == 1e8) 1284 return 0x36; 1285 if (GET_MODE (x) == SFmode) 1286 return 0; 1287 if (d == 1e16) 1288 return 0x37; 1289 /* larger powers of ten in the constants ram are not used 1290 because they are not equal to a `double' C constant. */ 1291 return 0; 1292 } 1293 1294 /* If X is a floating-point constant, return the logarithm of X base 2, 1295 or 0 if X is not a power of 2. */ 1296 1297 int 1298 floating_exact_log2 (x) 1299 rtx x; 1300 { 1301 register double d, d1; 1302 int i; 1303 1304 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT 1305 if (! flag_pretend_float) 1306 return 0; 1307 #endif 1308 1309 REAL_VALUE_FROM_CONST_DOUBLE (d, x); 1310 1311 if (! (d > 0)) 1312 return 0; 1313 1314 for (d1 = 1.0, i = 0; d1 < d; d1 *= 2.0, i++) 1315 ; 1316 1317 if (d == d1) 1318 return i; 1319 1320 return 0; 1321 } 1322 1323 #ifdef SUPPORT_SUN_FPA 1324 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get 1325 from the Sun FPA's constant RAM. 1326 The value returned, anded with 0x1ff, gives the code to use in fpmove 1327 to get the desired constant. */ 1328 #define S_E (2.718281745910644531) 1329 #define D_E (2.718281828459045091) 1330 #define S_PI (3.141592741012573242) 1331 #define D_PI (3.141592653589793116) 1332 #define S_SQRT2 (1.414213538169860840) 1333 #define D_SQRT2 (1.414213562373095145) 1334 #define S_LOG2ofE (1.442695021629333496) 1335 #define D_LOG2ofE (1.442695040888963387) 1336 #define S_LOG2of10 (3.321928024291992188) 1337 #define D_LOG2of10 (3.321928024887362182) 1338 #define S_LOGEof2 (0.6931471824645996094) 1339 #define D_LOGEof2 (0.6931471805599452862) 1340 #define S_LOGEof10 (2.302585124969482442) 1341 #define D_LOGEof10 (2.302585092994045901) 1342 #define S_LOG10of2 (0.3010300099849700928) 1343 #define D_LOG10of2 (0.3010299956639811980) 1344 #define S_LOG10ofE (0.4342944920063018799) 1345 #define D_LOG10ofE (0.4342944819032518167) 1346 1347 /* This code should be fixed for cross-compilation. */ 1348 1349 int 1350 standard_sun_fpa_constant_p (x) 1351 rtx x; 1352 { 1353 register double d; 1354 1355 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT 1356 if (! flag_pretend_float) 1357 return 0; 1358 #endif 1359 1360 REAL_VALUE_FROM_CONST_DOUBLE (d, x); 1361 1362 if (d == 0.0) 1363 return 0x200; /* 0 once 0x1ff is anded with it */ 1364 if (d == 1.0) 1365 return 0xe; 1366 if (d == 0.5) 1367 return 0xf; 1368 if (d == -1.0) 1369 return 0x10; 1370 if (d == 2.0) 1371 return 0x11; 1372 if (d == 3.0) 1373 return 0xB1; 1374 if (d == 4.0) 1375 return 0x12; 1376 if (d == 8.0) 1377 return 0x13; 1378 if (d == 0.25) 1379 return 0x15; 1380 if (d == 0.125) 1381 return 0x16; 1382 if (d == 10.0) 1383 return 0x17; 1384 if (d == -(1.0/2.0)) 1385 return 0x2E; 1386 1387 /* 1388 * Stuff that looks different if it's single or double 1389 */ 1390 if (GET_MODE (x) == SFmode) 1391 { 1392 if (d == S_E) 1393 return 0x8; 1394 if (d == (2*S_PI)) 1395 return 0x9; 1396 if (d == S_PI) 1397 return 0xA; 1398 if (d == (S_PI / 2.0)) 1399 return 0xB; 1400 if (d == S_SQRT2) 1401 return 0xC; 1402 if (d == (1.0 / S_SQRT2)) 1403 return 0xD; 1404 /* Large powers of 10 in the constant 1405 ram are not used because they are 1406 not equal to a C double constant */ 1407 if (d == -(S_PI / 2.0)) 1408 return 0x27; 1409 if (d == S_LOG2ofE) 1410 return 0x28; 1411 if (d == S_LOG2of10) 1412 return 0x29; 1413 if (d == S_LOGEof2) 1414 return 0x2A; 1415 if (d == S_LOGEof10) 1416 return 0x2B; 1417 if (d == S_LOG10of2) 1418 return 0x2C; 1419 if (d == S_LOG10ofE) 1420 return 0x2D; 1421 } 1422 else 1423 { 1424 if (d == D_E) 1425 return 0x8; 1426 if (d == (2*D_PI)) 1427 return 0x9; 1428 if (d == D_PI) 1429 return 0xA; 1430 if (d == (D_PI / 2.0)) 1431 return 0xB; 1432 if (d == D_SQRT2) 1433 return 0xC; 1434 if (d == (1.0 / D_SQRT2)) 1435 return 0xD; 1436 /* Large powers of 10 in the constant 1437 ram are not used because they are 1438 not equal to a C double constant */ 1439 if (d == -(D_PI / 2.0)) 1440 return 0x27; 1441 if (d == D_LOG2ofE) 1442 return 0x28; 1443 if (d == D_LOG2of10) 1444 return 0x29; 1445 if (d == D_LOGEof2) 1446 return 0x2A; 1447 if (d == D_LOGEof10) 1448 return 0x2B; 1449 if (d == D_LOG10of2) 1450 return 0x2C; 1451 if (d == D_LOG10ofE) 1452 return 0x2D; 1453 } 1454 return 0x0; 1455 } 1456 #endif /* define SUPPORT_SUN_FPA */ 1457 1458 /* A C compound statement to output to stdio stream STREAM the 1459 assembler syntax for an instruction operand X. X is an RTL 1460 expression. 1461 1462 CODE is a value that can be used to specify one of several ways 1463 of printing the operand. It is used when identical operands 1464 must be printed differently depending on the context. CODE 1465 comes from the `%' specification that was used to request 1466 printing of the operand. If the specification was just `%DIGIT' 1467 then CODE is 0; if the specification was `%LTR DIGIT' then CODE 1468 is the ASCII code for LTR. 1469 1470 If X is a register, this macro should print the register's name. 1471 The names can be found in an array `reg_names' whose type is 1472 `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'. 1473 1474 When the machine description has a specification `%PUNCT' (a `%' 1475 followed by a punctuation character), this macro is called with 1476 a null pointer for X and the punctuation character for CODE. 1477 1478 The m68k specific codes are: 1479 1480 '.' for dot needed in Motorola-style opcode names. 1481 '-' for an operand pushing on the stack: 1482 sp@-, -(sp) or -(%sp) depending on the style of syntax. 1483 '+' for an operand pushing on the stack: 1484 sp@+, (sp)+ or (%sp)+ depending on the style of syntax. 1485 '@' for a reference to the top word on the stack: 1486 sp@, (sp) or (%sp) depending on the style of syntax. 1487 '#' for an immediate operand prefix (# in MIT and Motorola syntax 1488 but & in SGS syntax). 1489 '!' for the cc register (used in an `and to cc' insn). 1490 '$' for the letter `s' in an op code, but only on the 68040. 1491 '&' for the letter `d' in an op code, but only on the 68040. 1492 1493 'b' for byte insn (no effect, on the Sun; this is for the ISI). 1494 'd' to force memory addressing to be absolute, not relative. 1495 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex) 1496 'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather 1497 than directly). Second part of 'y' below. 1498 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex), 1499 or print pair of registers as rx:ry. 1500 'y' for a FPA insn (print pair of registers as rx:ry). This also outputs 1501 CONST_DOUBLE's as SunFPA constant RAM registers if 1502 possible, so it should not be used except for the SunFPA. 1503 1504 */ 1505 1506 void 1507 print_operand (file, op, letter) 1508 FILE *file; /* file to write to */ 1509 rtx op; /* operand to print */ 1510 int letter; /* %<letter> or 0 */ 1511 { 1512 int i; 1513 1514 if (letter == '.') 1515 { 1516 #ifdef MOTOROLA 1517 asm_fprintf (file, "."); 1518 #endif 1519 } 1520 else if (letter == '#') 1521 { 1522 asm_fprintf (file, "%0I"); 1523 } 1524 else if (letter == '-') 1525 { 1526 #ifdef MOTOROLA 1527 asm_fprintf (file, "-(%Rsp)"); 1528 #else 1529 asm_fprintf (file, "%Rsp@-"); 1530 #endif 1531 } 1532 else if (letter == '+') 1533 { 1534 #ifdef MOTOROLA 1535 asm_fprintf (file, "(%Rsp)+"); 1536 #else 1537 asm_fprintf (file, "%Rsp@+"); 1538 #endif 1539 } 1540 else if (letter == '@') 1541 { 1542 #ifdef MOTOROLA 1543 asm_fprintf (file, "(%Rsp)"); 1544 #else 1545 asm_fprintf (file, "%Rsp@"); 1546 #endif 1547 } 1548 else if (letter == '!') 1549 { 1550 asm_fprintf (file, "%Rfpcr"); 1551 } 1552 else if (letter == '$') 1553 { 1554 if (TARGET_68040_ONLY) 1555 { 1556 fprintf (file, "s"); 1557 } 1558 } 1559 else if (letter == '&') 1560 { 1561 if (TARGET_68040_ONLY) 1562 { 1563 fprintf (file, "d"); 1564 } 1565 } 1566 else if (GET_CODE (op) == REG) 1567 { 1568 if (REGNO (op) < 16 1569 && (letter == 'y' || letter == 'x') 1570 && GET_MODE (op) == DFmode) 1571 { 1572 fprintf (file, "%s:%s", reg_names[REGNO (op)], 1573 reg_names[REGNO (op)+1]); 1574 } 1575 else 1576 { 1577 fprintf (file, "%s", reg_names[REGNO (op)]); 1578 } 1579 } 1580 else if (GET_CODE (op) == MEM) 1581 { 1582 output_address (XEXP (op, 0)); 1583 if (letter == 'd' && ! TARGET_68020 1584 && CONSTANT_ADDRESS_P (XEXP (op, 0)) 1585 && !(GET_CODE (XEXP (op, 0)) == CONST_INT 1586 && INTVAL (XEXP (op, 0)) < 0x8000 1587 && INTVAL (XEXP (op, 0)) >= -0x8000)) 1588 { 1589 fprintf (file, ":l"); 1590 } 1591 } 1592 #ifdef SUPPORT_SUN_FPA 1593 else if ((letter == 'y' || letter == 'w') 1594 && GET_CODE (op) == CONST_DOUBLE 1595 && (i = standard_sun_fpa_constant_p (op))) 1596 { 1597 fprintf (file, "%%%d", i & 0x1ff); 1598 } 1599 #endif 1600 else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode) 1601 { 1602 double d; 1603 union { float f; int i; } u1; 1604 REAL_VALUE_FROM_CONST_DOUBLE (d, op); 1605 u1.f = d; 1606 PRINT_OPERAND_PRINT_FLOAT (letter, file); 1607 } 1608 else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) != DImode) 1609 { 1610 double d; 1611 REAL_VALUE_FROM_CONST_DOUBLE (d, op); 1612 ASM_OUTPUT_DOUBLE_OPERAND (file, d); 1613 } 1614 else 1615 { 1616 asm_fprintf (file, "%0I"); output_addr_const (file, op); 1617 } 1618 } 1619 1620 1621 /* A C compound statement to output to stdio stream STREAM the 1622 assembler syntax for an instruction operand that is a memory 1623 reference whose address is ADDR. ADDR is an RTL expression. 1624 1625 Note that this contains a kludge that knows that the only reason 1626 we have an address (plus (label_ref...) (reg...)) when not generating 1627 PIC code is in the insn before a tablejump, and we know that m68k.md 1628 generates a label LInnn: on such an insn. 1629 1630 It is possible for PIC to generate a (plus (label_ref...) (reg...)) 1631 and we handle that just like we would a (plus (symbol_ref...) (reg...)). 1632 1633 Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)" 1634 fails to assemble. Luckily "Lnnn(pc,d0.l*2)" produces the results 1635 we want. This difference can be accommodated by using an assembler 1636 define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other 1637 string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END 1638 macro. See m68ksgs.h for an example; for versions without the bug. 1639 1640 They also do not like things like "pea 1.w", so we simple leave off 1641 the .w on small constants. 1642 1643 This routine is responsible for distinguishing between -fpic and -fPIC 1644 style relocations in an address. When generating -fpic code the 1645 offset is output in word mode (eg movel a5@(_foo:w), a0). When generating 1646 -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */ 1647 1648 void 1649 print_operand_address (file, addr) 1650 FILE *file; 1651 rtx addr; 1652 { 1653 register rtx reg1, reg2, breg, ireg; 1654 rtx offset; 1655 1656 switch (GET_CODE (addr)) 1657 { 1658 case REG: 1659 #ifdef MOTOROLA 1660 fprintf (file, "(%s)", reg_names[REGNO (addr)]); 1661 #else 1662 fprintf (file, "%s@", reg_names[REGNO (addr)]); 1663 #endif 1664 break; 1665 case PRE_DEC: 1666 #ifdef MOTOROLA 1667 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); 1668 #else 1669 fprintf (file, "%s@-", reg_names[REGNO (XEXP (addr, 0))]); 1670 #endif 1671 break; 1672 case POST_INC: 1673 #ifdef MOTOROLA 1674 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); 1675 #else 1676 fprintf (file, "%s@+", reg_names[REGNO (XEXP (addr, 0))]); 1677 #endif 1678 break; 1679 case PLUS: 1680 reg1 = reg2 = ireg = breg = offset = 0; 1681 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) 1682 { 1683 offset = XEXP (addr, 0); 1684 addr = XEXP (addr, 1); 1685 } 1686 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) 1687 { 1688 offset = XEXP (addr, 1); 1689 addr = XEXP (addr, 0); 1690 } 1691 if (GET_CODE (addr) != PLUS) 1692 { 1693 ; 1694 } 1695 else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) 1696 { 1697 reg1 = XEXP (addr, 0); 1698 addr = XEXP (addr, 1); 1699 } 1700 else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) 1701 { 1702 reg1 = XEXP (addr, 1); 1703 addr = XEXP (addr, 0); 1704 } 1705 else if (GET_CODE (XEXP (addr, 0)) == MULT) 1706 { 1707 reg1 = XEXP (addr, 0); 1708 addr = XEXP (addr, 1); 1709 } 1710 else if (GET_CODE (XEXP (addr, 1)) == MULT) 1711 { 1712 reg1 = XEXP (addr, 1); 1713 addr = XEXP (addr, 0); 1714 } 1715 else if (GET_CODE (XEXP (addr, 0)) == REG) 1716 { 1717 reg1 = XEXP (addr, 0); 1718 addr = XEXP (addr, 1); 1719 } 1720 else if (GET_CODE (XEXP (addr, 1)) == REG) 1721 { 1722 reg1 = XEXP (addr, 1); 1723 addr = XEXP (addr, 0); 1724 } 1725 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT 1726 || GET_CODE (addr) == SIGN_EXTEND) 1727 { 1728 if (reg1 == 0) 1729 { 1730 reg1 = addr; 1731 } 1732 else 1733 { 1734 reg2 = addr; 1735 } 1736 addr = 0; 1737 } 1738 #if 0 /* for OLD_INDEXING */ 1739 else if (GET_CODE (addr) == PLUS) 1740 { 1741 if (GET_CODE (XEXP (addr, 0)) == REG) 1742 { 1743 reg2 = XEXP (addr, 0); 1744 addr = XEXP (addr, 1); 1745 } 1746 else if (GET_CODE (XEXP (addr, 1)) == REG) 1747 { 1748 reg2 = XEXP (addr, 1); 1749 addr = XEXP (addr, 0); 1750 } 1751 } 1752 #endif 1753 if (offset != 0) 1754 { 1755 if (addr != 0) 1756 { 1757 abort (); 1758 } 1759 addr = offset; 1760 } 1761 if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND 1762 || GET_CODE (reg1) == MULT)) 1763 || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) 1764 { 1765 breg = reg2; 1766 ireg = reg1; 1767 } 1768 else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) 1769 { 1770 breg = reg1; 1771 ireg = reg2; 1772 } 1773 if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF 1774 && ! (flag_pic && ireg == pic_offset_table_rtx)) 1775 { 1776 int scale = 1; 1777 if (GET_CODE (ireg) == MULT) 1778 { 1779 scale = INTVAL (XEXP (ireg, 1)); 1780 ireg = XEXP (ireg, 0); 1781 } 1782 if (GET_CODE (ireg) == SIGN_EXTEND) 1783 { 1784 #ifdef MOTOROLA 1785 #ifdef SGS 1786 asm_fprintf (file, "%LLD%d(%Rpc,%s.w", 1787 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1788 reg_names[REGNO (XEXP (ireg, 0))]); 1789 #else 1790 asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.w", 1791 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1792 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1793 reg_names[REGNO (XEXP (ireg, 0))]); 1794 #endif 1795 #else 1796 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:w", 1797 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1798 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1799 reg_names[REGNO (XEXP (ireg, 0))]); 1800 #endif 1801 } 1802 else 1803 { 1804 #ifdef MOTOROLA 1805 #ifdef SGS 1806 asm_fprintf (file, "%LLD%d(%Rpc,%s.l", 1807 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1808 reg_names[REGNO (ireg)]); 1809 #else 1810 asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.l", 1811 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1812 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1813 reg_names[REGNO (ireg)]); 1814 #endif 1815 #else 1816 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l", 1817 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1818 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1819 reg_names[REGNO (ireg)]); 1820 #endif 1821 } 1822 if (scale != 1) 1823 { 1824 #ifdef MOTOROLA 1825 fprintf (file, "*%d", scale); 1826 #else 1827 fprintf (file, ":%d", scale); 1828 #endif 1829 } 1830 putc (')', file); 1831 break; 1832 } 1833 if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF 1834 && ! (flag_pic && breg == pic_offset_table_rtx)) 1835 { 1836 #ifdef MOTOROLA 1837 #ifdef SGS 1838 asm_fprintf (file, "%LLD%d(%Rpc,%s.l", 1839 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1840 reg_names[REGNO (breg)]); 1841 #else 1842 asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.l", 1843 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1844 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1845 reg_names[REGNO (breg)]); 1846 #endif 1847 #else 1848 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l", 1849 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1850 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1851 reg_names[REGNO (breg)]); 1852 #endif 1853 putc (')', file); 1854 break; 1855 } 1856 if (ireg != 0 || breg != 0) 1857 { 1858 int scale = 1; 1859 if (breg == 0) 1860 { 1861 abort (); 1862 } 1863 if (! flag_pic && addr && GET_CODE (addr) == LABEL_REF) 1864 { 1865 abort (); 1866 } 1867 #ifdef MOTOROLA 1868 if (addr != 0) 1869 { 1870 output_addr_const (file, addr); 1871 if ((flag_pic == 1) && (breg == pic_offset_table_rtx)) 1872 fprintf (file, ".w"); 1873 if ((flag_pic == 2) && (breg == pic_offset_table_rtx)) 1874 fprintf (file, ".l"); 1875 } 1876 fprintf (file, "(%s", reg_names[REGNO (breg)]); 1877 if (ireg != 0) 1878 { 1879 putc (',', file); 1880 } 1881 #else 1882 fprintf (file, "%s@(", reg_names[REGNO (breg)]); 1883 if (addr != 0) 1884 { 1885 output_addr_const (file, addr); 1886 if ((flag_pic == 1) && (breg == pic_offset_table_rtx)) 1887 fprintf (file, ":w"); 1888 if ((flag_pic == 2) && (breg == pic_offset_table_rtx)) 1889 fprintf (file, ":l"); 1890 } 1891 if (addr != 0 && ireg != 0) 1892 { 1893 putc (',', file); 1894 } 1895 #endif 1896 if (ireg != 0 && GET_CODE (ireg) == MULT) 1897 { 1898 scale = INTVAL (XEXP (ireg, 1)); 1899 ireg = XEXP (ireg, 0); 1900 } 1901 if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) 1902 { 1903 #ifdef MOTOROLA 1904 fprintf (file, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); 1905 #else 1906 fprintf (file, "%s:w", reg_names[REGNO (XEXP (ireg, 0))]); 1907 #endif 1908 } 1909 else if (ireg != 0) 1910 { 1911 #ifdef MOTOROLA 1912 fprintf (file, "%s.l", reg_names[REGNO (ireg)]); 1913 #else 1914 fprintf (file, "%s:l", reg_names[REGNO (ireg)]); 1915 #endif 1916 } 1917 if (scale != 1) 1918 { 1919 #ifdef MOTOROLA 1920 fprintf (file, "*%d", scale); 1921 #else 1922 fprintf (file, ":%d", scale); 1923 #endif 1924 } 1925 putc (')', file); 1926 break; 1927 } 1928 else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF 1929 && ! (flag_pic && reg1 == pic_offset_table_rtx)) 1930 { 1931 #ifdef MOTOROLA 1932 #ifdef SGS 1933 asm_fprintf (file, "%LLD%d(%Rpc,%s.l)", 1934 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1935 reg_names[REGNO (reg1)]); 1936 #else 1937 asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.l)", 1938 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1939 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1940 reg_names[REGNO (reg1)]); 1941 #endif 1942 #else 1943 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l)", 1944 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1945 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1946 reg_names[REGNO (reg1)]); 1947 #endif 1948 break; 1949 } 1950 /* FALL-THROUGH (is this really what we want? */ 1951 default: 1952 if (GET_CODE (addr) == CONST_INT 1953 && INTVAL (addr) < 0x8000 1954 && INTVAL (addr) >= -0x8000) 1955 { 1956 #ifdef MOTOROLA 1957 #ifdef SGS 1958 /* Many SGS assemblers croak on size specifiers for constants. */ 1959 fprintf (file, "%d", INTVAL (addr)); 1960 #else 1961 fprintf (file, "%d.w", INTVAL (addr)); 1962 #endif 1963 #else 1964 fprintf (file, "%d:w", INTVAL (addr)); 1965 #endif 1966 } 1967 else 1968 { 1969 output_addr_const (file, addr); 1970 } 1971 break; 1972 } 1973 } 1974