1 /* Subroutines for insn-output.c for VAX. 2 Copyright (C) 1987, 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002 3 Free Software Foundation, Inc. 4 5 This file is part of GNU CC. 6 7 GNU CC is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2, or (at your option) 10 any later version. 11 12 GNU CC is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GNU CC; see the file COPYING. If not, write to 19 the Free Software Foundation, 59 Temple Place - Suite 330, 20 Boston, MA 02111-1307, USA. */ 21 22 #include "config.h" 23 #include "system.h" 24 #include "rtl.h" 25 #include "tree.h" 26 #include "regs.h" 27 #include "hard-reg-set.h" 28 #include "real.h" 29 #include "insn-config.h" 30 #include "conditions.h" 31 #include "function.h" 32 #include "output.h" 33 #include "insn-attr.h" 34 #include "recog.h" 35 #include "expr.h" 36 #include "flags.h" 37 #include "debug.h" 38 #include "tm_p.h" 39 #include "target.h" 40 #include "target-def.h" 41 42 static int follows_p PARAMS ((rtx, rtx)); 43 static void vax_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT)); 44 #if VMS_TARGET 45 static void vms_asm_out_constructor PARAMS ((rtx, int)); 46 static void vms_asm_out_destructor PARAMS ((rtx, int)); 47 static void vms_select_section PARAMS ((tree, int, unsigned HOST_WIDE_INT)); 48 static void vms_encode_section_info PARAMS ((tree, int)); 49 static void vms_globalize_label PARAMS ((FILE *, const char *)); 50 #endif 51 static void vax_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT, 52 HOST_WIDE_INT, tree)); 53 54 /* Initialize the GCC target structure. */ 55 #undef TARGET_ASM_ALIGNED_HI_OP 56 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t" 57 58 #undef TARGET_ASM_FUNCTION_PROLOGUE 59 #define TARGET_ASM_FUNCTION_PROLOGUE vax_output_function_prologue 60 61 #if VMS_TARGET 62 #undef TARGET_ASM_SELECT_SECTION 63 #define TARGET_ASM_SELECT_SECTION vms_select_section 64 #undef TARGET_ENCODE_SECTION_INFO 65 #define TARGET_ENCODE_SECTION_INFO vms_encode_section_info 66 #undef TARGET_ASM_GLOBALIZE_LABEL 67 #define TARGET_ASM_GLOBALIZE_LABEL vms_globalize_label 68 #endif 69 70 #undef TARGET_ASM_OUTPUT_MI_THUNK 71 #define TARGET_ASM_OUTPUT_MI_THUNK vax_output_mi_thunk 72 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK 73 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall 74 75 struct gcc_target targetm = TARGET_INITIALIZER; 76 77 /* Set global variables as needed for the options enabled. */ 78 79 void 80 override_options () 81 { 82 /* We're VAX floating point, not IEEE floating point. */ 83 memset (real_format_for_mode, 0, sizeof real_format_for_mode); 84 real_format_for_mode[SFmode - QFmode] = &vax_f_format; 85 real_format_for_mode[DFmode - QFmode] 86 = (TARGET_G_FLOAT ? &vax_g_format : &vax_d_format); 87 88 #if defined(OPENBSD_NATIVE) || defined(OPENBSD_CROSS) 89 flag_gcse = 0; 90 #endif 91 } 92 93 /* Generate the assembly code for function entry. FILE is a stdio 94 stream to output the code to. SIZE is an int: how many units of 95 temporary storage to allocate. 96 97 Refer to the array `regs_ever_live' to determine which registers to 98 save; `regs_ever_live[I]' is nonzero if register number I is ever 99 used in the function. This function is responsible for knowing 100 which registers should not be saved even if used. */ 101 102 static void 103 vax_output_function_prologue (file, size) 104 FILE * file; 105 HOST_WIDE_INT size; 106 { 107 register int regno; 108 register int mask = 0; 109 110 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) 111 if (regs_ever_live[regno] && !call_used_regs[regno]) 112 mask |= 1 << regno; 113 114 fprintf (file, "\t.word 0x%x\n", mask); 115 116 if (dwarf2out_do_frame ()) 117 { 118 const char *label = dwarf2out_cfi_label (); 119 int offset = 0; 120 121 for (regno = FIRST_PSEUDO_REGISTER-1; regno >= 0; --regno) 122 if (regs_ever_live[regno] && !call_used_regs[regno]) 123 dwarf2out_reg_save (label, regno, offset -= 4); 124 125 dwarf2out_reg_save (label, PC_REGNUM, offset -= 4); 126 dwarf2out_reg_save (label, FRAME_POINTER_REGNUM, offset -= 4); 127 dwarf2out_reg_save (label, ARG_POINTER_REGNUM, offset -= 4); 128 dwarf2out_def_cfa (label, FRAME_POINTER_REGNUM, -(offset - 4)); 129 } 130 131 if (VMS_TARGET) 132 { 133 /* Adjusting the stack pointer by 4 before calling C$MAIN_ARGS 134 is required when linking with the VMS POSIX version of the C 135 run-time library; using `subl2 $4,r0' is adequate but we use 136 `clrl -(sp)' instead. The extra 4 bytes could be removed 137 after the call because STARTING_FRAME_OFFSET's setting of -4 138 will end up adding them right back again, but don't bother. */ 139 140 if (MAIN_NAME_P (DECL_NAME (current_function_decl))) 141 asm_fprintf (file, "\tclrl -(%Rsp)\n\tjsb _C$MAIN_ARGS\n"); 142 } 143 144 size -= STARTING_FRAME_OFFSET; 145 146 if (warn_stack_larger_than && size > stack_larger_than_size) 147 warning ("stack usage is %d bytes", size); 148 149 if (size >= 64) 150 asm_fprintf (file, "\tmovab %d(%Rsp),%Rsp\n", -size); 151 else if (size) 152 asm_fprintf (file, "\tsubl2 $%d,%Rsp\n", size); 153 } 154 155 /* This is like nonimmediate_operand with a restriction on the type of MEM. */ 156 157 void 158 split_quadword_operands (operands, low, n) 159 rtx *operands, *low; 160 int n ATTRIBUTE_UNUSED; 161 { 162 int i; 163 /* Split operands. */ 164 165 low[0] = low[1] = low[2] = 0; 166 for (i = 0; i < 3; i++) 167 { 168 if (low[i]) 169 /* it's already been figured out */; 170 else if (GET_CODE (operands[i]) == MEM 171 && (GET_CODE (XEXP (operands[i], 0)) == POST_INC)) 172 { 173 rtx addr = XEXP (operands[i], 0); 174 operands[i] = low[i] = gen_rtx_MEM (SImode, addr); 175 if (which_alternative == 0 && i == 0) 176 { 177 addr = XEXP (operands[i], 0); 178 operands[i+1] = low[i+1] = gen_rtx_MEM (SImode, addr); 179 } 180 } 181 else 182 { 183 low[i] = operand_subword (operands[i], 0, 0, DImode); 184 operands[i] = operand_subword (operands[i], 1, 0, DImode); 185 } 186 } 187 } 188 189 void 190 print_operand_address (file, addr) 191 FILE *file; 192 register rtx addr; 193 { 194 register rtx reg1, breg, ireg; 195 rtx offset; 196 197 retry: 198 switch (GET_CODE (addr)) 199 { 200 case MEM: 201 fprintf (file, "*"); 202 addr = XEXP (addr, 0); 203 goto retry; 204 205 case REG: 206 fprintf (file, "(%s)", reg_names[REGNO (addr)]); 207 break; 208 209 case PRE_DEC: 210 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); 211 break; 212 213 case POST_INC: 214 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); 215 break; 216 217 case PLUS: 218 /* There can be either two or three things added here. One must be a 219 REG. One can be either a REG or a MULT of a REG and an appropriate 220 constant, and the third can only be a constant or a MEM. 221 222 We get these two or three things and put the constant or MEM in 223 OFFSET, the MULT or REG in IREG, and the REG in BREG. If we have 224 a register and can't tell yet if it is a base or index register, 225 put it into REG1. */ 226 227 reg1 = 0; ireg = 0; breg = 0; offset = 0; 228 229 if (CONSTANT_ADDRESS_P (XEXP (addr, 0)) 230 || GET_CODE (XEXP (addr, 0)) == MEM) 231 { 232 offset = XEXP (addr, 0); 233 addr = XEXP (addr, 1); 234 } 235 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)) 236 || GET_CODE (XEXP (addr, 1)) == MEM) 237 { 238 offset = XEXP (addr, 1); 239 addr = XEXP (addr, 0); 240 } 241 else if (GET_CODE (XEXP (addr, 1)) == MULT) 242 { 243 ireg = XEXP (addr, 1); 244 addr = XEXP (addr, 0); 245 } 246 else if (GET_CODE (XEXP (addr, 0)) == MULT) 247 { 248 ireg = XEXP (addr, 0); 249 addr = XEXP (addr, 1); 250 } 251 else if (GET_CODE (XEXP (addr, 1)) == REG) 252 { 253 reg1 = XEXP (addr, 1); 254 addr = XEXP (addr, 0); 255 } 256 else if (GET_CODE (XEXP (addr, 0)) == REG) 257 { 258 reg1 = XEXP (addr, 0); 259 addr = XEXP (addr, 1); 260 } 261 else 262 abort (); 263 264 if (GET_CODE (addr) == REG) 265 { 266 if (reg1) 267 ireg = addr; 268 else 269 reg1 = addr; 270 } 271 else if (GET_CODE (addr) == MULT) 272 ireg = addr; 273 else if (GET_CODE (addr) == PLUS) 274 { 275 if (CONSTANT_ADDRESS_P (XEXP (addr, 0)) 276 || GET_CODE (XEXP (addr, 0)) == MEM) 277 { 278 if (offset) 279 { 280 if (GET_CODE (offset) == CONST_INT) 281 offset = plus_constant (XEXP (addr, 0), INTVAL (offset)); 282 else if (GET_CODE (XEXP (addr, 0)) == CONST_INT) 283 offset = plus_constant (offset, INTVAL (XEXP (addr, 0))); 284 else 285 abort (); 286 } 287 offset = XEXP (addr, 0); 288 } 289 else if (GET_CODE (XEXP (addr, 0)) == REG) 290 { 291 if (reg1) 292 ireg = reg1, breg = XEXP (addr, 0), reg1 = 0; 293 else 294 reg1 = XEXP (addr, 0); 295 } 296 else if (GET_CODE (XEXP (addr, 0)) == MULT) 297 { 298 if (ireg) 299 abort (); 300 ireg = XEXP (addr, 0); 301 } 302 else 303 abort (); 304 305 if (CONSTANT_ADDRESS_P (XEXP (addr, 1)) 306 || GET_CODE (XEXP (addr, 1)) == MEM) 307 { 308 if (offset) 309 { 310 if (GET_CODE (offset) == CONST_INT) 311 offset = plus_constant (XEXP (addr, 1), INTVAL (offset)); 312 else if (GET_CODE (XEXP (addr, 1)) == CONST_INT) 313 offset = plus_constant (offset, INTVAL (XEXP (addr, 1))); 314 else 315 abort (); 316 } 317 offset = XEXP (addr, 1); 318 } 319 else if (GET_CODE (XEXP (addr, 1)) == REG) 320 { 321 if (reg1) 322 ireg = reg1, breg = XEXP (addr, 1), reg1 = 0; 323 else 324 reg1 = XEXP (addr, 1); 325 } 326 else if (GET_CODE (XEXP (addr, 1)) == MULT) 327 { 328 if (ireg) 329 abort (); 330 ireg = XEXP (addr, 1); 331 } 332 else 333 abort (); 334 } 335 else 336 abort (); 337 338 /* If REG1 is nonzero, figure out if it is a base or index register. */ 339 if (reg1) 340 { 341 if (breg != 0 || (offset && GET_CODE (offset) == MEM)) 342 { 343 if (ireg) 344 abort (); 345 ireg = reg1; 346 } 347 else 348 breg = reg1; 349 } 350 351 if (offset != 0) 352 output_address (offset); 353 354 if (breg != 0) 355 fprintf (file, "(%s)", reg_names[REGNO (breg)]); 356 357 if (ireg != 0) 358 { 359 if (GET_CODE (ireg) == MULT) 360 ireg = XEXP (ireg, 0); 361 if (GET_CODE (ireg) != REG) 362 abort (); 363 fprintf (file, "[%s]", reg_names[REGNO (ireg)]); 364 } 365 break; 366 367 default: 368 output_addr_const (file, addr); 369 } 370 } 371 372 const char * 373 rev_cond_name (op) 374 rtx op; 375 { 376 switch (GET_CODE (op)) 377 { 378 case EQ: 379 return "neq"; 380 case NE: 381 return "eql"; 382 case LT: 383 return "geq"; 384 case LE: 385 return "gtr"; 386 case GT: 387 return "leq"; 388 case GE: 389 return "lss"; 390 case LTU: 391 return "gequ"; 392 case LEU: 393 return "gtru"; 394 case GTU: 395 return "lequ"; 396 case GEU: 397 return "lssu"; 398 399 default: 400 abort (); 401 } 402 } 403 404 int 405 vax_float_literal(c) 406 register rtx c; 407 { 408 register enum machine_mode mode; 409 REAL_VALUE_TYPE r, s; 410 int i; 411 412 if (GET_CODE (c) != CONST_DOUBLE) 413 return 0; 414 415 mode = GET_MODE (c); 416 417 if (c == const_tiny_rtx[(int) mode][0] 418 || c == const_tiny_rtx[(int) mode][1] 419 || c == const_tiny_rtx[(int) mode][2]) 420 return 1; 421 422 REAL_VALUE_FROM_CONST_DOUBLE (r, c); 423 424 for (i = 0; i < 7; i++) 425 { 426 int x = 1 << i; 427 REAL_VALUE_FROM_INT (s, x, 0, mode); 428 429 if (REAL_VALUES_EQUAL (r, s)) 430 return 1; 431 if (!exact_real_inverse (mode, &s)) 432 abort (); 433 if (REAL_VALUES_EQUAL (r, s)) 434 return 1; 435 } 436 return 0; 437 } 438 439 440 /* Return the cost in cycles of a memory address, relative to register 441 indirect. 442 443 Each of the following adds the indicated number of cycles: 444 445 1 - symbolic address 446 1 - pre-decrement 447 1 - indexing and/or offset(register) 448 2 - indirect */ 449 450 451 int 452 vax_address_cost (addr) 453 register rtx addr; 454 { 455 int reg = 0, indexed = 0, indir = 0, offset = 0, predec = 0; 456 rtx plus_op0 = 0, plus_op1 = 0; 457 restart: 458 switch (GET_CODE (addr)) 459 { 460 case PRE_DEC: 461 predec = 1; 462 case REG: 463 case SUBREG: 464 case POST_INC: 465 reg = 1; 466 break; 467 case MULT: 468 indexed = 1; /* 2 on VAX 2 */ 469 break; 470 case CONST_INT: 471 /* byte offsets cost nothing (on a VAX 2, they cost 1 cycle) */ 472 if (offset == 0) 473 offset = (unsigned HOST_WIDE_INT)(INTVAL(addr)+128) > 256; 474 break; 475 case CONST: 476 case SYMBOL_REF: 477 offset = 1; /* 2 on VAX 2 */ 478 break; 479 case LABEL_REF: /* this is probably a byte offset from the pc */ 480 if (offset == 0) 481 offset = 1; 482 break; 483 case PLUS: 484 if (plus_op0) 485 plus_op1 = XEXP (addr, 0); 486 else 487 plus_op0 = XEXP (addr, 0); 488 addr = XEXP (addr, 1); 489 goto restart; 490 case MEM: 491 indir = 2; /* 3 on VAX 2 */ 492 addr = XEXP (addr, 0); 493 goto restart; 494 default: 495 break; 496 } 497 498 /* Up to 3 things can be added in an address. They are stored in 499 plus_op0, plus_op1, and addr. */ 500 501 if (plus_op0) 502 { 503 addr = plus_op0; 504 plus_op0 = 0; 505 goto restart; 506 } 507 if (plus_op1) 508 { 509 addr = plus_op1; 510 plus_op1 = 0; 511 goto restart; 512 } 513 /* Indexing and register+offset can both be used (except on a VAX 2) 514 without increasing execution time over either one alone. */ 515 if (reg && indexed && offset) 516 return reg + indir + offset + predec; 517 return reg + indexed + indir + offset + predec; 518 } 519 520 521 /* Cost of an expression on a VAX. This version has costs tuned for the 522 CVAX chip (found in the VAX 3 series) with comments for variations on 523 other models. */ 524 525 int 526 vax_rtx_cost (x) 527 register rtx x; 528 { 529 register enum rtx_code code = GET_CODE (x); 530 enum machine_mode mode = GET_MODE (x); 531 register int c; 532 int i = 0; /* may be modified in switch */ 533 const char *fmt = GET_RTX_FORMAT (code); /* may be modified in switch */ 534 535 switch (code) 536 { 537 case POST_INC: 538 return 2; 539 case PRE_DEC: 540 return 3; 541 case MULT: 542 switch (mode) 543 { 544 case DFmode: 545 c = 16; /* 4 on VAX 9000 */ 546 break; 547 case SFmode: 548 c = 9; /* 4 on VAX 9000, 12 on VAX 2 */ 549 break; 550 case DImode: 551 c = 16; /* 6 on VAX 9000, 28 on VAX 2 */ 552 break; 553 case SImode: 554 case HImode: 555 case QImode: 556 c = 10; /* 3-4 on VAX 9000, 20-28 on VAX 2 */ 557 break; 558 default: 559 return MAX_COST; /* Mode is not supported. */ 560 } 561 break; 562 case UDIV: 563 if (mode != SImode) 564 return MAX_COST; /* Mode is not supported. */ 565 c = 17; 566 break; 567 case DIV: 568 if (mode == DImode) 569 c = 30; /* highly variable */ 570 else if (mode == DFmode) 571 /* divide takes 28 cycles if the result is not zero, 13 otherwise */ 572 c = 24; 573 else 574 c = 11; /* 25 on VAX 2 */ 575 break; 576 case MOD: 577 c = 23; 578 break; 579 case UMOD: 580 if (mode != SImode) 581 return MAX_COST; /* Mode is not supported. */ 582 c = 29; 583 break; 584 case FLOAT: 585 c = 6 + (mode == DFmode) + (GET_MODE (XEXP (x, 0)) != SImode); 586 /* 4 on VAX 9000 */ 587 break; 588 case FIX: 589 c = 7; /* 17 on VAX 2 */ 590 break; 591 case ASHIFT: 592 case LSHIFTRT: 593 case ASHIFTRT: 594 if (mode == DImode) 595 c = 12; 596 else 597 c = 10; /* 6 on VAX 9000 */ 598 break; 599 case ROTATE: 600 case ROTATERT: 601 c = 6; /* 5 on VAX 2, 4 on VAX 9000 */ 602 if (GET_CODE (XEXP (x, 1)) == CONST_INT) 603 fmt = "e"; /* all constant rotate counts are short */ 604 break; 605 case PLUS: 606 case MINUS: 607 c = (mode == DFmode) ? 13 : 8; /* 6/8 on VAX 9000, 16/15 on VAX 2 */ 608 /* Small integer operands can use subl2 and addl2. */ 609 if ((GET_CODE (XEXP (x, 1)) == CONST_INT) 610 && (unsigned HOST_WIDE_INT)(INTVAL (XEXP (x, 1)) + 63) < 127) 611 fmt = "e"; 612 break; 613 case IOR: 614 case XOR: 615 c = 3; 616 break; 617 case AND: 618 /* AND is special because the first operand is complemented. */ 619 c = 3; 620 if (GET_CODE (XEXP (x, 0)) == CONST_INT) 621 { 622 if ((unsigned HOST_WIDE_INT)~INTVAL (XEXP (x, 0)) > 63) 623 c = 4; 624 fmt = "e"; 625 i = 1; 626 } 627 break; 628 case NEG: 629 if (mode == DFmode) 630 return 9; 631 else if (mode == SFmode) 632 return 6; 633 else if (mode == DImode) 634 return 4; 635 case NOT: 636 return 2; 637 case ZERO_EXTRACT: 638 case SIGN_EXTRACT: 639 c = 15; 640 break; 641 case MEM: 642 if (mode == DImode || mode == DFmode) 643 c = 5; /* 7 on VAX 2 */ 644 else 645 c = 3; /* 4 on VAX 2 */ 646 x = XEXP (x, 0); 647 if (GET_CODE (x) == REG || GET_CODE (x) == POST_INC) 648 return c; 649 return c + vax_address_cost (x); 650 default: 651 c = 3; 652 break; 653 } 654 655 656 /* Now look inside the expression. Operands which are not registers or 657 short constants add to the cost. 658 659 FMT and I may have been adjusted in the switch above for instructions 660 which require special handling */ 661 662 while (*fmt++ == 'e') 663 { 664 register rtx op = XEXP (x, i++); 665 code = GET_CODE (op); 666 667 /* A NOT is likely to be found as the first operand of an AND 668 (in which case the relevant cost is of the operand inside 669 the not) and not likely to be found anywhere else. */ 670 if (code == NOT) 671 op = XEXP (op, 0), code = GET_CODE (op); 672 673 switch (code) 674 { 675 case CONST_INT: 676 if ((unsigned HOST_WIDE_INT)INTVAL (op) > 63 677 && GET_MODE (x) != QImode) 678 c += 1; /* 2 on VAX 2 */ 679 break; 680 case CONST: 681 case LABEL_REF: 682 case SYMBOL_REF: 683 c += 1; /* 2 on VAX 2 */ 684 break; 685 case CONST_DOUBLE: 686 if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT) 687 { 688 /* Registers are faster than floating point constants -- even 689 those constants which can be encoded in a single byte. */ 690 if (vax_float_literal (op)) 691 c++; 692 else 693 c += (GET_MODE (x) == DFmode) ? 3 : 2; 694 } 695 else 696 { 697 if (CONST_DOUBLE_HIGH (op) != 0 698 || (unsigned)CONST_DOUBLE_LOW (op) > 63) 699 c += 2; 700 } 701 break; 702 case MEM: 703 c += 1; /* 2 on VAX 2 */ 704 if (GET_CODE (XEXP (op, 0)) != REG) 705 c += vax_address_cost (XEXP (op, 0)); 706 break; 707 case REG: 708 case SUBREG: 709 break; 710 default: 711 c += 1; 712 break; 713 } 714 } 715 return c; 716 } 717 718 #if VMS_TARGET 719 /* Additional support code for VMS target. */ 720 721 /* Linked list of all externals that are to be emitted when optimizing 722 for the global pointer if they haven't been declared by the end of 723 the program with an appropriate .comm or initialization. */ 724 725 static 726 struct extern_list { 727 struct extern_list *next; /* next external */ 728 const char *name; /* name of the external */ 729 int size; /* external's actual size */ 730 int in_const; /* section type flag */ 731 } *extern_head = 0, *pending_head = 0; 732 733 /* Check whether NAME is already on the external definition list. If not, 734 add it to either that list or the pending definition list. */ 735 736 void 737 vms_check_external (decl, name, pending) 738 tree decl; 739 const char *name; 740 int pending; 741 { 742 register struct extern_list *p, *p0; 743 744 for (p = extern_head; p; p = p->next) 745 if (!strcmp (p->name, name)) 746 return; 747 748 for (p = pending_head, p0 = 0; p; p0 = p, p = p->next) 749 if (!strcmp (p->name, name)) 750 { 751 if (pending) 752 return; 753 754 /* Was pending, but has now been defined; move it to other list. */ 755 if (p == pending_head) 756 pending_head = p->next; 757 else 758 p0->next = p->next; 759 p->next = extern_head; 760 extern_head = p; 761 return; 762 } 763 764 /* Not previously seen; create a new list entry. */ 765 p = (struct extern_list *) xmalloc (sizeof (struct extern_list)); 766 p->name = name; 767 768 if (pending) 769 { 770 /* Save the size and section type and link to `pending' list. */ 771 p->size = (DECL_SIZE (decl) == 0) ? 0 : 772 TREE_INT_CST_LOW (size_binop (CEIL_DIV_EXPR, DECL_SIZE (decl), 773 size_int (BITS_PER_UNIT))); 774 p->in_const = (TREE_READONLY (decl) && ! TREE_THIS_VOLATILE (decl)); 775 776 p->next = pending_head; 777 pending_head = p; 778 } 779 else 780 { 781 /* Size and section type don't matter; link to `declared' list. */ 782 p->size = p->in_const = 0; /* arbitrary init */ 783 784 p->next = extern_head; 785 extern_head = p; 786 } 787 return; 788 } 789 790 void 791 vms_flush_pending_externals (file) 792 FILE *file; 793 { 794 register struct extern_list *p; 795 796 while (pending_head) 797 { 798 /* Move next pending declaration to the "done" list. */ 799 p = pending_head; 800 pending_head = p->next; 801 p->next = extern_head; 802 extern_head = p; 803 804 /* Now output the actual declaration. */ 805 if (p->in_const) 806 const_section (); 807 else 808 data_section (); 809 fputs (".comm ", file); 810 assemble_name (file, p->name); 811 fprintf (file, ",%d\n", p->size); 812 } 813 } 814 815 static void 816 vms_asm_out_constructor (symbol, priority) 817 rtx symbol; 818 int priority ATTRIBUTE_UNUSED; 819 { 820 fprintf (asm_out_file,".globl $$PsectAttributes_NOOVR$$__gxx_init_1\n"); 821 data_section(); 822 fprintf (asm_out_file,"$$PsectAttributes_NOOVR$$__gxx_init_1:\n\t.long\t"); 823 assemble_name (asm_out_file, XSTR (symbol, 0)); 824 fputc ('\n', asm_out_file); 825 } 826 827 static void 828 vms_asm_out_destructor (symbol, priority) 829 rtx symbol; 830 int priority ATTRIBUTE_UNUSED; 831 { 832 fprintf (asm_out_file,".globl $$PsectAttributes_NOOVR$$__gxx_clean_1\n"); 833 data_section(); 834 fprintf (asm_out_file,"$$PsectAttributes_NOOVR$$__gxx_clean_1:\n\t.long\t"); 835 assemble_name (asm_out_file, XSTR (symbol, 0)); 836 fputc ('\n', asm_out_file); 837 } 838 839 static void 840 vms_select_section (exp, reloc, align) 841 tree exp; 842 int reloc ATTRIBUTE_UNUSED; 843 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED; 844 { 845 if (TREE_CODE (exp) == VAR_DECL) 846 { 847 if (TREE_READONLY (exp) && ! TREE_THIS_VOLATILE (exp) 848 && DECL_INITIAL (exp) 849 && (DECL_INITIAL (exp) == error_mark_node 850 || TREE_CONSTANT (DECL_INITIAL (exp)))) 851 { 852 if (TREE_PUBLIC (exp)) 853 const_section (); 854 else 855 text_section (); 856 } 857 else 858 data_section (); 859 } 860 if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c') 861 { 862 if (TREE_CODE (exp) == STRING_CST && flag_writable_strings) 863 data_section (); 864 else 865 text_section (); 866 } 867 } 868 869 /* Make sure that external variables are correctly addressed. Under VMS 870 there is some brain damage in the linker that requires us to do this. */ 871 872 static void 873 vms_encode_section_info (decl, first) 874 tree decl; 875 int first ATTRIBUTE_UNUSED; 876 { 877 if (DECL_EXTERNAL (decl) && TREE_PUBLIC (decl)) 878 SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1; 879 } 880 881 /* This is how to output a command to make the user-level label named NAME 882 defined for reference from other files. */ 883 static void 884 vms_globalize_label (stream, name) 885 FILE *stream; 886 const char *name; 887 { 888 default_globalize_label (stream, name); 889 vms_check_external (NULL_TREE, name, 0); 890 } 891 #endif /* VMS_TARGET */ 892 893 /* Additional support code for VMS host. */ 894 /* ??? This should really be in libiberty; vax.c is a target file. */ 895 #ifdef QSORT_WORKAROUND 896 /* 897 Do not use VAXCRTL's qsort() due to a severe bug: once you've 898 sorted something which has a size that's an exact multiple of 4 899 and is longword aligned, you cannot safely sort anything which 900 is either not a multiple of 4 in size or not longword aligned. 901 A static "move-by-longword" optimization flag inside qsort() is 902 never reset. This is known to affect VMS V4.6 through VMS V5.5-1, 903 and was finally fixed in VMS V5.5-2. 904 905 In this work-around an insertion sort is used for simplicity. 906 The qsort code from glibc should probably be used instead. 907 */ 908 void 909 not_qsort (array, count, size, compare) 910 void *array; 911 unsigned count, size; 912 int (*compare)(); 913 { 914 915 if (size == sizeof (short)) 916 { 917 register int i; 918 register short *next, *prev; 919 short tmp, *base = array; 920 921 for (next = base, i = count - 1; i > 0; i--) 922 { 923 prev = next++; 924 if ((*compare)(next, prev) < 0) 925 { 926 tmp = *next; 927 do *(prev + 1) = *prev; 928 while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0); 929 *(prev + 1) = tmp; 930 } 931 } 932 } 933 else if (size == sizeof (long)) 934 { 935 register int i; 936 register long *next, *prev; 937 long tmp, *base = array; 938 939 for (next = base, i = count - 1; i > 0; i--) 940 { 941 prev = next++; 942 if ((*compare)(next, prev) < 0) 943 { 944 tmp = *next; 945 do *(prev + 1) = *prev; 946 while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0); 947 *(prev + 1) = tmp; 948 } 949 } 950 } 951 else /* arbitrary size */ 952 { 953 register int i; 954 register char *next, *prev, *tmp = alloca (size), *base = array; 955 956 for (next = base, i = count - 1; i > 0; i--) 957 { /* count-1 forward iterations */ 958 prev = next, next += size; /* increment front pointer */ 959 if ((*compare)(next, prev) < 0) 960 { /* found element out of order; move others up then re-insert */ 961 memcpy (tmp, next, size); /* save smaller element */ 962 do { memcpy (prev + size, prev, size); /* move larger elem. up */ 963 prev -= size; /* decrement back pointer */ 964 } while (prev >= base ? (*compare)(tmp, prev) < 0 : 0); 965 memcpy (prev + size, tmp, size); /* restore small element */ 966 } 967 } 968 #ifdef USE_C_ALLOCA 969 alloca (0); 970 #endif 971 } 972 973 return; 974 } 975 #endif /* QSORT_WORKAROUND */ 976 977 /* Return 1 if insn A follows B. */ 978 979 static int 980 follows_p (a, b) 981 rtx a, b; 982 { 983 register rtx p; 984 985 for (p = a; p != b; p = NEXT_INSN (p)) 986 if (! p) 987 return 1; 988 989 return 0; 990 } 991 992 /* Returns 1 if we know operand OP was 0 before INSN. */ 993 994 int 995 reg_was_0_p (insn, op) 996 rtx insn, op; 997 { 998 rtx link; 999 1000 return ((link = find_reg_note (insn, REG_WAS_0, 0)) 1001 /* Make sure the insn that stored the 0 is still present 1002 and doesn't follow INSN in the insn sequence. */ 1003 && ! INSN_DELETED_P (XEXP (link, 0)) 1004 && GET_CODE (XEXP (link, 0)) != NOTE 1005 && ! follows_p (XEXP (link, 0), insn) 1006 /* Make sure cross jumping didn't happen here. */ 1007 && no_labels_between_p (XEXP (link, 0), insn) 1008 /* Make sure the reg hasn't been clobbered. */ 1009 && ! reg_set_between_p (op, XEXP (link, 0), insn)); 1010 } 1011 1012 static void 1013 vax_output_mi_thunk (file, thunk, delta, vcall_offset, function) 1014 FILE *file; 1015 tree thunk ATTRIBUTE_UNUSED; 1016 HOST_WIDE_INT delta; 1017 HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED; 1018 tree function; 1019 { 1020 fprintf (file, "\t.word 0x0ffc\n"); 1021 fprintf (file, "\taddl2 $"); 1022 fprintf (file, HOST_WIDE_INT_PRINT_DEC, delta); 1023 asm_fprintf (file, ",4(%Rap)\n"); 1024 fprintf (file, "\tjmp "); 1025 assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0)); 1026 fprintf (file, "+2\n"); 1027 } 1028