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 '/' for register prefix needed by longlong.h. 1493 1494 'b' for byte insn (no effect, on the Sun; this is for the ISI). 1495 'd' to force memory addressing to be absolute, not relative. 1496 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex) 1497 'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather 1498 than directly). Second part of 'y' below. 1499 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex), 1500 or print pair of registers as rx:ry. 1501 'y' for a FPA insn (print pair of registers as rx:ry). This also outputs 1502 CONST_DOUBLE's as SunFPA constant RAM registers if 1503 possible, so it should not be used except for the SunFPA. 1504 1505 */ 1506 1507 void 1508 print_operand (file, op, letter) 1509 FILE *file; /* file to write to */ 1510 rtx op; /* operand to print */ 1511 int letter; /* %<letter> or 0 */ 1512 { 1513 int i; 1514 1515 if (letter == '.') 1516 { 1517 #ifdef MOTOROLA 1518 asm_fprintf (file, "."); 1519 #endif 1520 } 1521 else if (letter == '#') 1522 { 1523 asm_fprintf (file, "%0I"); 1524 } 1525 else if (letter == '-') 1526 { 1527 #ifdef MOTOROLA 1528 asm_fprintf (file, "-(%Rsp)"); 1529 #else 1530 asm_fprintf (file, "%Rsp@-"); 1531 #endif 1532 } 1533 else if (letter == '+') 1534 { 1535 #ifdef MOTOROLA 1536 asm_fprintf (file, "(%Rsp)+"); 1537 #else 1538 asm_fprintf (file, "%Rsp@+"); 1539 #endif 1540 } 1541 else if (letter == '@') 1542 { 1543 #ifdef MOTOROLA 1544 asm_fprintf (file, "(%Rsp)"); 1545 #else 1546 asm_fprintf (file, "%Rsp@"); 1547 #endif 1548 } 1549 else if (letter == '!') 1550 { 1551 asm_fprintf (file, "%Rfpcr"); 1552 } 1553 else if (letter == '$') 1554 { 1555 if (TARGET_68040_ONLY) 1556 { 1557 fprintf (file, "s"); 1558 } 1559 } 1560 else if (letter == '&') 1561 { 1562 if (TARGET_68040_ONLY) 1563 { 1564 fprintf (file, "d"); 1565 } 1566 } 1567 else if (letter == '/') 1568 { 1569 asm_fprintf (file, "%R"); 1570 } 1571 else if (GET_CODE (op) == REG) 1572 { 1573 if (REGNO (op) < 16 1574 && (letter == 'y' || letter == 'x') 1575 && GET_MODE (op) == DFmode) 1576 { 1577 fprintf (file, "%s:%s", reg_names[REGNO (op)], 1578 reg_names[REGNO (op)+1]); 1579 } 1580 else 1581 { 1582 fprintf (file, "%s", reg_names[REGNO (op)]); 1583 } 1584 } 1585 else if (GET_CODE (op) == MEM) 1586 { 1587 output_address (XEXP (op, 0)); 1588 if (letter == 'd' && ! TARGET_68020 1589 && CONSTANT_ADDRESS_P (XEXP (op, 0)) 1590 && !(GET_CODE (XEXP (op, 0)) == CONST_INT 1591 && INTVAL (XEXP (op, 0)) < 0x8000 1592 && INTVAL (XEXP (op, 0)) >= -0x8000)) 1593 { 1594 fprintf (file, ":l"); 1595 } 1596 } 1597 #ifdef SUPPORT_SUN_FPA 1598 else if ((letter == 'y' || letter == 'w') 1599 && GET_CODE (op) == CONST_DOUBLE 1600 && (i = standard_sun_fpa_constant_p (op))) 1601 { 1602 fprintf (file, "%%%d", i & 0x1ff); 1603 } 1604 #endif 1605 else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode) 1606 { 1607 double d; 1608 union { float f; int i; } u1; 1609 REAL_VALUE_FROM_CONST_DOUBLE (d, op); 1610 u1.f = d; 1611 PRINT_OPERAND_PRINT_FLOAT (letter, file); 1612 } 1613 else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) != DImode) 1614 { 1615 double d; 1616 REAL_VALUE_FROM_CONST_DOUBLE (d, op); 1617 ASM_OUTPUT_DOUBLE_OPERAND (file, d); 1618 } 1619 else 1620 { 1621 asm_fprintf (file, "%0I"); output_addr_const (file, op); 1622 } 1623 } 1624 1625 1626 /* A C compound statement to output to stdio stream STREAM the 1627 assembler syntax for an instruction operand that is a memory 1628 reference whose address is ADDR. ADDR is an RTL expression. 1629 1630 Note that this contains a kludge that knows that the only reason 1631 we have an address (plus (label_ref...) (reg...)) when not generating 1632 PIC code is in the insn before a tablejump, and we know that m68k.md 1633 generates a label LInnn: on such an insn. 1634 1635 It is possible for PIC to generate a (plus (label_ref...) (reg...)) 1636 and we handle that just like we would a (plus (symbol_ref...) (reg...)). 1637 1638 Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)" 1639 fails to assemble. Luckily "Lnnn(pc,d0.l*2)" produces the results 1640 we want. This difference can be accommodated by using an assembler 1641 define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other 1642 string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END 1643 macro. See m68ksgs.h for an example; for versions without the bug. 1644 1645 They also do not like things like "pea 1.w", so we simple leave off 1646 the .w on small constants. 1647 1648 This routine is responsible for distinguishing between -fpic and -fPIC 1649 style relocations in an address. When generating -fpic code the 1650 offset is output in word mode (eg movel a5@(_foo:w), a0). When generating 1651 -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */ 1652 1653 void 1654 print_operand_address (file, addr) 1655 FILE *file; 1656 rtx addr; 1657 { 1658 register rtx reg1, reg2, breg, ireg; 1659 rtx offset; 1660 1661 switch (GET_CODE (addr)) 1662 { 1663 case REG: 1664 #ifdef MOTOROLA 1665 fprintf (file, "(%s)", reg_names[REGNO (addr)]); 1666 #else 1667 fprintf (file, "%s@", reg_names[REGNO (addr)]); 1668 #endif 1669 break; 1670 case PRE_DEC: 1671 #ifdef MOTOROLA 1672 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); 1673 #else 1674 fprintf (file, "%s@-", reg_names[REGNO (XEXP (addr, 0))]); 1675 #endif 1676 break; 1677 case POST_INC: 1678 #ifdef MOTOROLA 1679 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); 1680 #else 1681 fprintf (file, "%s@+", reg_names[REGNO (XEXP (addr, 0))]); 1682 #endif 1683 break; 1684 case PLUS: 1685 reg1 = reg2 = ireg = breg = offset = 0; 1686 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) 1687 { 1688 offset = XEXP (addr, 0); 1689 addr = XEXP (addr, 1); 1690 } 1691 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) 1692 { 1693 offset = XEXP (addr, 1); 1694 addr = XEXP (addr, 0); 1695 } 1696 if (GET_CODE (addr) != PLUS) 1697 { 1698 ; 1699 } 1700 else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) 1701 { 1702 reg1 = XEXP (addr, 0); 1703 addr = XEXP (addr, 1); 1704 } 1705 else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) 1706 { 1707 reg1 = XEXP (addr, 1); 1708 addr = XEXP (addr, 0); 1709 } 1710 else if (GET_CODE (XEXP (addr, 0)) == MULT) 1711 { 1712 reg1 = XEXP (addr, 0); 1713 addr = XEXP (addr, 1); 1714 } 1715 else if (GET_CODE (XEXP (addr, 1)) == MULT) 1716 { 1717 reg1 = XEXP (addr, 1); 1718 addr = XEXP (addr, 0); 1719 } 1720 else if (GET_CODE (XEXP (addr, 0)) == REG) 1721 { 1722 reg1 = XEXP (addr, 0); 1723 addr = XEXP (addr, 1); 1724 } 1725 else if (GET_CODE (XEXP (addr, 1)) == REG) 1726 { 1727 reg1 = XEXP (addr, 1); 1728 addr = XEXP (addr, 0); 1729 } 1730 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT 1731 || GET_CODE (addr) == SIGN_EXTEND) 1732 { 1733 if (reg1 == 0) 1734 { 1735 reg1 = addr; 1736 } 1737 else 1738 { 1739 reg2 = addr; 1740 } 1741 addr = 0; 1742 } 1743 #if 0 /* for OLD_INDEXING */ 1744 else if (GET_CODE (addr) == PLUS) 1745 { 1746 if (GET_CODE (XEXP (addr, 0)) == REG) 1747 { 1748 reg2 = XEXP (addr, 0); 1749 addr = XEXP (addr, 1); 1750 } 1751 else if (GET_CODE (XEXP (addr, 1)) == REG) 1752 { 1753 reg2 = XEXP (addr, 1); 1754 addr = XEXP (addr, 0); 1755 } 1756 } 1757 #endif 1758 if (offset != 0) 1759 { 1760 if (addr != 0) 1761 { 1762 abort (); 1763 } 1764 addr = offset; 1765 } 1766 if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND 1767 || GET_CODE (reg1) == MULT)) 1768 || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) 1769 { 1770 breg = reg2; 1771 ireg = reg1; 1772 } 1773 else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) 1774 { 1775 breg = reg1; 1776 ireg = reg2; 1777 } 1778 if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF 1779 && ! (flag_pic && ireg == pic_offset_table_rtx)) 1780 { 1781 int scale = 1; 1782 if (GET_CODE (ireg) == MULT) 1783 { 1784 scale = INTVAL (XEXP (ireg, 1)); 1785 ireg = XEXP (ireg, 0); 1786 } 1787 if (GET_CODE (ireg) == SIGN_EXTEND) 1788 { 1789 #ifdef MOTOROLA 1790 #ifdef SGS 1791 asm_fprintf (file, "%LLD%d(%Rpc,%s.w", 1792 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1793 reg_names[REGNO (XEXP (ireg, 0))]); 1794 #else 1795 asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.w", 1796 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1797 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1798 reg_names[REGNO (XEXP (ireg, 0))]); 1799 #endif 1800 #else 1801 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:w", 1802 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1803 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1804 reg_names[REGNO (XEXP (ireg, 0))]); 1805 #endif 1806 } 1807 else 1808 { 1809 #ifdef MOTOROLA 1810 #ifdef SGS 1811 asm_fprintf (file, "%LLD%d(%Rpc,%s.l", 1812 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1813 reg_names[REGNO (ireg)]); 1814 #else 1815 asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.l", 1816 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1817 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1818 reg_names[REGNO (ireg)]); 1819 #endif 1820 #else 1821 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l", 1822 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1823 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1824 reg_names[REGNO (ireg)]); 1825 #endif 1826 } 1827 if (scale != 1) 1828 { 1829 #ifdef MOTOROLA 1830 fprintf (file, "*%d", scale); 1831 #else 1832 fprintf (file, ":%d", scale); 1833 #endif 1834 } 1835 putc (')', file); 1836 break; 1837 } 1838 if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF 1839 && ! (flag_pic && breg == pic_offset_table_rtx)) 1840 { 1841 #ifdef MOTOROLA 1842 #ifdef SGS 1843 asm_fprintf (file, "%LLD%d(%Rpc,%s.l", 1844 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1845 reg_names[REGNO (breg)]); 1846 #else 1847 asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.l", 1848 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1849 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1850 reg_names[REGNO (breg)]); 1851 #endif 1852 #else 1853 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l", 1854 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1855 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1856 reg_names[REGNO (breg)]); 1857 #endif 1858 putc (')', file); 1859 break; 1860 } 1861 if (ireg != 0 || breg != 0) 1862 { 1863 int scale = 1; 1864 if (breg == 0) 1865 { 1866 abort (); 1867 } 1868 if (! flag_pic && addr && GET_CODE (addr) == LABEL_REF) 1869 { 1870 abort (); 1871 } 1872 #ifdef MOTOROLA 1873 if (addr != 0) 1874 { 1875 output_addr_const (file, addr); 1876 if ((flag_pic == 1) && (breg == pic_offset_table_rtx)) 1877 fprintf (file, ".w"); 1878 if ((flag_pic == 2) && (breg == pic_offset_table_rtx)) 1879 fprintf (file, ".l"); 1880 } 1881 fprintf (file, "(%s", reg_names[REGNO (breg)]); 1882 if (ireg != 0) 1883 { 1884 putc (',', file); 1885 } 1886 #else 1887 fprintf (file, "%s@(", reg_names[REGNO (breg)]); 1888 if (addr != 0) 1889 { 1890 output_addr_const (file, addr); 1891 if ((flag_pic == 1) && (breg == pic_offset_table_rtx)) 1892 fprintf (file, ":w"); 1893 if ((flag_pic == 2) && (breg == pic_offset_table_rtx)) 1894 fprintf (file, ":l"); 1895 } 1896 if (addr != 0 && ireg != 0) 1897 { 1898 putc (',', file); 1899 } 1900 #endif 1901 if (ireg != 0 && GET_CODE (ireg) == MULT) 1902 { 1903 scale = INTVAL (XEXP (ireg, 1)); 1904 ireg = XEXP (ireg, 0); 1905 } 1906 if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) 1907 { 1908 #ifdef MOTOROLA 1909 fprintf (file, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); 1910 #else 1911 fprintf (file, "%s:w", reg_names[REGNO (XEXP (ireg, 0))]); 1912 #endif 1913 } 1914 else if (ireg != 0) 1915 { 1916 #ifdef MOTOROLA 1917 fprintf (file, "%s.l", reg_names[REGNO (ireg)]); 1918 #else 1919 fprintf (file, "%s:l", reg_names[REGNO (ireg)]); 1920 #endif 1921 } 1922 if (scale != 1) 1923 { 1924 #ifdef MOTOROLA 1925 fprintf (file, "*%d", scale); 1926 #else 1927 fprintf (file, ":%d", scale); 1928 #endif 1929 } 1930 putc (')', file); 1931 break; 1932 } 1933 else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF 1934 && ! (flag_pic && reg1 == pic_offset_table_rtx)) 1935 { 1936 #ifdef MOTOROLA 1937 #ifdef SGS 1938 asm_fprintf (file, "%LLD%d(%Rpc,%s.l)", 1939 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1940 reg_names[REGNO (reg1)]); 1941 #else 1942 asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.l)", 1943 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1944 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1945 reg_names[REGNO (reg1)]); 1946 #endif 1947 #else 1948 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l)", 1949 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1950 CODE_LABEL_NUMBER (XEXP (addr, 0)), 1951 reg_names[REGNO (reg1)]); 1952 #endif 1953 break; 1954 } 1955 /* FALL-THROUGH (is this really what we want? */ 1956 default: 1957 if (GET_CODE (addr) == CONST_INT 1958 && INTVAL (addr) < 0x8000 1959 && INTVAL (addr) >= -0x8000) 1960 { 1961 #ifdef MOTOROLA 1962 #ifdef SGS 1963 /* Many SGS assemblers croak on size specifiers for constants. */ 1964 fprintf (file, "%d", INTVAL (addr)); 1965 #else 1966 fprintf (file, "%d.w", INTVAL (addr)); 1967 #endif 1968 #else 1969 fprintf (file, "%d:w", INTVAL (addr)); 1970 #endif 1971 } 1972 else 1973 { 1974 output_addr_const (file, addr); 1975 } 1976 break; 1977 } 1978 } 1979