00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "config.h"
00023 #include "system.h"
00024 #include "rtl.h"
00025 #include "regs.h"
00026 #include "hard-reg-set.h"
00027 #include "real.h"
00028 #include "insn-config.h"
00029 #include "conditions.h"
00030 #include "function.h"
00031 #include "output.h"
00032 #include "insn-attr.h"
00033 #include "tree.h"
00034 #include "recog.h"
00035 #include "expr.h"
00036 #include "tm_p.h"
00037 #include "target.h"
00038 #include "target-def.h"
00039
00040 static int follows_p PARAMS ((rtx, rtx));
00041 static void vax_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
00042 #if VMS_TARGET
00043 static void vms_asm_out_constructor PARAMS ((rtx, int));
00044 static void vms_asm_out_destructor PARAMS ((rtx, int));
00045 #endif
00046
00047
00048 #undef TARGET_ASM_ALIGNED_HI_OP
00049 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
00050
00051 #undef TARGET_ASM_FUNCTION_PROLOGUE
00052 #define TARGET_ASM_FUNCTION_PROLOGUE vax_output_function_prologue
00053
00054 struct gcc_target targetm = TARGET_INITIALIZER;
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 static void
00066 vax_output_function_prologue (file, size)
00067 FILE * file;
00068 HOST_WIDE_INT size;
00069 {
00070 register int regno;
00071 register int mask = 0;
00072
00073 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
00074 if (regs_ever_live[regno] && !call_used_regs[regno])
00075 mask |= 1 << regno;
00076
00077 fprintf (file, "\t.word 0x%x\n", mask);
00078
00079 if (VMS_TARGET)
00080 {
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 const char *p = current_function_name;
00100 int is_main = strcmp ("main", p) == 0;
00101 # define __MAIN_NAME " main("
00102
00103 while (!is_main && *p != '\0')
00104 {
00105 if (*p == *__MAIN_NAME
00106 && strncmp (p, __MAIN_NAME, sizeof __MAIN_NAME - sizeof "") == 0)
00107 is_main = 1;
00108 else
00109 p++;
00110 }
00111
00112 if (is_main)
00113 fprintf (file, "\t%s\n\t%s\n", "clrl -(sp)", "jsb _C$MAIN_ARGS");
00114 }
00115
00116 size -= STARTING_FRAME_OFFSET;
00117 if (size >= 64)
00118 fprintf (file, "\tmovab %d(sp),sp\n", -size);
00119 else if (size)
00120 fprintf (file, "\tsubl2 $%d,sp\n", size);
00121 }
00122
00123
00124
00125 void
00126 split_quadword_operands (operands, low, n)
00127 rtx *operands, *low;
00128 int n ATTRIBUTE_UNUSED;
00129 {
00130 int i;
00131
00132
00133 low[0] = low[1] = low[2] = 0;
00134 for (i = 0; i < 3; i++)
00135 {
00136 if (low[i])
00137 ;
00138 else if (GET_CODE (operands[i]) == MEM
00139 && (GET_CODE (XEXP (operands[i], 0)) == POST_INC))
00140 {
00141 rtx addr = XEXP (operands[i], 0);
00142 operands[i] = low[i] = gen_rtx_MEM (SImode, addr);
00143 if (which_alternative == 0 && i == 0)
00144 {
00145 addr = XEXP (operands[i], 0);
00146 operands[i+1] = low[i+1] = gen_rtx_MEM (SImode, addr);
00147 }
00148 }
00149 else
00150 {
00151 low[i] = operand_subword (operands[i], 0, 0, DImode);
00152 operands[i] = operand_subword (operands[i], 1, 0, DImode);
00153 }
00154 }
00155 }
00156
00157 void
00158 print_operand_address (file, addr)
00159 FILE *file;
00160 register rtx addr;
00161 {
00162 register rtx reg1, breg, ireg;
00163 rtx offset;
00164
00165 retry:
00166 switch (GET_CODE (addr))
00167 {
00168 case MEM:
00169 fprintf (file, "*");
00170 addr = XEXP (addr, 0);
00171 goto retry;
00172
00173 case REG:
00174 fprintf (file, "(%s)", reg_names[REGNO (addr)]);
00175 break;
00176
00177 case PRE_DEC:
00178 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
00179 break;
00180
00181 case POST_INC:
00182 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
00183 break;
00184
00185 case PLUS:
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195 reg1 = 0; ireg = 0; breg = 0; offset = 0;
00196
00197 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
00198 || GET_CODE (XEXP (addr, 0)) == MEM)
00199 {
00200 offset = XEXP (addr, 0);
00201 addr = XEXP (addr, 1);
00202 }
00203 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
00204 || GET_CODE (XEXP (addr, 1)) == MEM)
00205 {
00206 offset = XEXP (addr, 1);
00207 addr = XEXP (addr, 0);
00208 }
00209 else if (GET_CODE (XEXP (addr, 1)) == MULT)
00210 {
00211 ireg = XEXP (addr, 1);
00212 addr = XEXP (addr, 0);
00213 }
00214 else if (GET_CODE (XEXP (addr, 0)) == MULT)
00215 {
00216 ireg = XEXP (addr, 0);
00217 addr = XEXP (addr, 1);
00218 }
00219 else if (GET_CODE (XEXP (addr, 1)) == REG)
00220 {
00221 reg1 = XEXP (addr, 1);
00222 addr = XEXP (addr, 0);
00223 }
00224 else if (GET_CODE (XEXP (addr, 0)) == REG)
00225 {
00226 reg1 = XEXP (addr, 0);
00227 addr = XEXP (addr, 1);
00228 }
00229 else
00230 abort ();
00231
00232 if (GET_CODE (addr) == REG)
00233 {
00234 if (reg1)
00235 ireg = addr;
00236 else
00237 reg1 = addr;
00238 }
00239 else if (GET_CODE (addr) == MULT)
00240 ireg = addr;
00241 else if (GET_CODE (addr) == PLUS)
00242 {
00243 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
00244 || GET_CODE (XEXP (addr, 0)) == MEM)
00245 {
00246 if (offset)
00247 {
00248 if (GET_CODE (offset) == CONST_INT)
00249 offset = plus_constant (XEXP (addr, 0), INTVAL (offset));
00250 else if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
00251 offset = plus_constant (offset, INTVAL (XEXP (addr, 0)));
00252 else
00253 abort ();
00254 }
00255 offset = XEXP (addr, 0);
00256 }
00257 else if (GET_CODE (XEXP (addr, 0)) == REG)
00258 {
00259 if (reg1)
00260 ireg = reg1, breg = XEXP (addr, 0), reg1 = 0;
00261 else
00262 reg1 = XEXP (addr, 0);
00263 }
00264 else if (GET_CODE (XEXP (addr, 0)) == MULT)
00265 {
00266 if (ireg)
00267 abort ();
00268 ireg = XEXP (addr, 0);
00269 }
00270 else
00271 abort ();
00272
00273 if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
00274 || GET_CODE (XEXP (addr, 1)) == MEM)
00275 {
00276 if (offset)
00277 {
00278 if (GET_CODE (offset) == CONST_INT)
00279 offset = plus_constant (XEXP (addr, 1), INTVAL (offset));
00280 else if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
00281 offset = plus_constant (offset, INTVAL (XEXP (addr, 1)));
00282 else
00283 abort ();
00284 }
00285 offset = XEXP (addr, 1);
00286 }
00287 else if (GET_CODE (XEXP (addr, 1)) == REG)
00288 {
00289 if (reg1)
00290 ireg = reg1, breg = XEXP (addr, 1), reg1 = 0;
00291 else
00292 reg1 = XEXP (addr, 1);
00293 }
00294 else if (GET_CODE (XEXP (addr, 1)) == MULT)
00295 {
00296 if (ireg)
00297 abort ();
00298 ireg = XEXP (addr, 1);
00299 }
00300 else
00301 abort ();
00302 }
00303 else
00304 abort ();
00305
00306
00307 if (reg1)
00308 {
00309 if (breg != 0 || (offset && GET_CODE (offset) == MEM))
00310 {
00311 if (ireg)
00312 abort ();
00313 ireg = reg1;
00314 }
00315 else
00316 breg = reg1;
00317 }
00318
00319 if (offset != 0)
00320 output_address (offset);
00321
00322 if (breg != 0)
00323 fprintf (file, "(%s)", reg_names[REGNO (breg)]);
00324
00325 if (ireg != 0)
00326 {
00327 if (GET_CODE (ireg) == MULT)
00328 ireg = XEXP (ireg, 0);
00329 if (GET_CODE (ireg) != REG)
00330 abort ();
00331 fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
00332 }
00333 break;
00334
00335 default:
00336 output_addr_const (file, addr);
00337 }
00338 }
00339
00340 const char *
00341 rev_cond_name (op)
00342 rtx op;
00343 {
00344 switch (GET_CODE (op))
00345 {
00346 case EQ:
00347 return "neq";
00348 case NE:
00349 return "eql";
00350 case LT:
00351 return "geq";
00352 case LE:
00353 return "gtr";
00354 case GT:
00355 return "leq";
00356 case GE:
00357 return "lss";
00358 case LTU:
00359 return "gequ";
00360 case LEU:
00361 return "gtru";
00362 case GTU:
00363 return "lequ";
00364 case GEU:
00365 return "lssu";
00366
00367 default:
00368 abort ();
00369 }
00370 }
00371
00372 int
00373 vax_float_literal(c)
00374 register rtx c;
00375 {
00376 register enum machine_mode mode;
00377 #if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
00378 int i;
00379 union {double d; int i[2];} val;
00380 #endif
00381
00382 if (GET_CODE (c) != CONST_DOUBLE)
00383 return 0;
00384
00385 mode = GET_MODE (c);
00386
00387 if (c == const_tiny_rtx[(int) mode][0]
00388 || c == const_tiny_rtx[(int) mode][1]
00389 || c == const_tiny_rtx[(int) mode][2])
00390 return 1;
00391
00392 #if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
00393
00394 val.i[0] = CONST_DOUBLE_LOW (c);
00395 val.i[1] = CONST_DOUBLE_HIGH (c);
00396
00397 for (i = 0; i < 7; i ++)
00398 if (val.d == 1 << i || val.d == 1 / (1 << i))
00399 return 1;
00400 #endif
00401 return 0;
00402 }
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416 int
00417 vax_address_cost (addr)
00418 register rtx addr;
00419 {
00420 int reg = 0, indexed = 0, indir = 0, offset = 0, predec = 0;
00421 rtx plus_op0 = 0, plus_op1 = 0;
00422 restart:
00423 switch (GET_CODE (addr))
00424 {
00425 case PRE_DEC:
00426 predec = 1;
00427 case REG:
00428 case SUBREG:
00429 case POST_INC:
00430 reg = 1;
00431 break;
00432 case MULT:
00433 indexed = 1;
00434 break;
00435 case CONST_INT:
00436
00437 if (offset == 0)
00438 offset = (unsigned)(INTVAL(addr)+128) > 256;
00439 break;
00440 case CONST:
00441 case SYMBOL_REF:
00442 offset = 1;
00443 break;
00444 case LABEL_REF:
00445 if (offset == 0)
00446 offset = 1;
00447 break;
00448 case PLUS:
00449 if (plus_op0)
00450 plus_op1 = XEXP (addr, 0);
00451 else
00452 plus_op0 = XEXP (addr, 0);
00453 addr = XEXP (addr, 1);
00454 goto restart;
00455 case MEM:
00456 indir = 2;
00457 addr = XEXP (addr, 0);
00458 goto restart;
00459 default:
00460 break;
00461 }
00462
00463
00464
00465
00466 if (plus_op0)
00467 {
00468 addr = plus_op0;
00469 plus_op0 = 0;
00470 goto restart;
00471 }
00472 if (plus_op1)
00473 {
00474 addr = plus_op1;
00475 plus_op1 = 0;
00476 goto restart;
00477 }
00478
00479
00480 if (reg && indexed && offset)
00481 return reg + indir + offset + predec;
00482 return reg + indexed + indir + offset + predec;
00483 }
00484
00485
00486
00487
00488
00489
00490 int
00491 vax_rtx_cost (x)
00492 register rtx x;
00493 {
00494 register enum rtx_code code = GET_CODE (x);
00495 enum machine_mode mode = GET_MODE (x);
00496 register int c;
00497 int i = 0;
00498 const char *fmt = GET_RTX_FORMAT (code);
00499
00500 switch (code)
00501 {
00502 case POST_INC:
00503 return 2;
00504 case PRE_DEC:
00505 return 3;
00506 case MULT:
00507 switch (mode)
00508 {
00509 case DFmode:
00510 c = 16;
00511 break;
00512 case SFmode:
00513 c = 9;
00514 break;
00515 case DImode:
00516 c = 16;
00517 break;
00518 case SImode:
00519 case HImode:
00520 case QImode:
00521 c = 10;
00522 break;
00523 default:
00524 return MAX_COST;
00525 }
00526 break;
00527 case UDIV:
00528 if (mode != SImode)
00529 return MAX_COST;
00530 c = 17;
00531 break;
00532 case DIV:
00533 if (mode == DImode)
00534 c = 30;
00535 else if (mode == DFmode)
00536
00537 c = 24;
00538 else
00539 c = 11;
00540 break;
00541 case MOD:
00542 c = 23;
00543 break;
00544 case UMOD:
00545 if (mode != SImode)
00546 return MAX_COST;
00547 c = 29;
00548 break;
00549 case FLOAT:
00550 c = 6 + (mode == DFmode) + (GET_MODE (XEXP (x, 0)) != SImode);
00551
00552 break;
00553 case FIX:
00554 c = 7;
00555 break;
00556 case ASHIFT:
00557 case LSHIFTRT:
00558 case ASHIFTRT:
00559 if (mode == DImode)
00560 c = 12;
00561 else
00562 c = 10;
00563 break;
00564 case ROTATE:
00565 case ROTATERT:
00566 c = 6;
00567 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
00568 fmt = "e";
00569 break;
00570 case PLUS:
00571
00572
00573 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
00574 if ((unsigned)(INTVAL (XEXP (x, 1)) + 63) < 127)
00575 fmt = "e";
00576 case MINUS:
00577 c = (mode == DFmode) ? 13 : 8;
00578 case IOR:
00579 case XOR:
00580 c = 3;
00581 break;
00582 case AND:
00583
00584 c = 3;
00585 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
00586 {
00587 if ((unsigned)~INTVAL (XEXP (x, 0)) > 63)
00588 c = 4;
00589 fmt = "e";
00590 i = 1;
00591 }
00592 break;
00593 case NEG:
00594 if (mode == DFmode)
00595 return 9;
00596 else if (mode == SFmode)
00597 return 6;
00598 else if (mode == DImode)
00599 return 4;
00600 case NOT:
00601 return 2;
00602 case ZERO_EXTRACT:
00603 case SIGN_EXTRACT:
00604 c = 15;
00605 break;
00606 case MEM:
00607 if (mode == DImode || mode == DFmode)
00608 c = 5;
00609 else
00610 c = 3;
00611 x = XEXP (x, 0);
00612 if (GET_CODE (x) == REG || GET_CODE (x) == POST_INC)
00613 return c;
00614 return c + vax_address_cost (x);
00615 default:
00616 c = 3;
00617 break;
00618 }
00619
00620
00621
00622
00623
00624
00625
00626
00627 while (*fmt++ == 'e')
00628 {
00629 register rtx op = XEXP (x, i++);
00630 code = GET_CODE (op);
00631
00632
00633
00634
00635 if (code == NOT)
00636 op = XEXP (op, 0), code = GET_CODE (op);
00637
00638 switch (code)
00639 {
00640 case CONST_INT:
00641 if ((unsigned)INTVAL (op) > 63 && GET_MODE (x) != QImode)
00642 c += 1;
00643 break;
00644 case CONST:
00645 case LABEL_REF:
00646 case SYMBOL_REF:
00647 c += 1;
00648 break;
00649 case CONST_DOUBLE:
00650 if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT)
00651 {
00652
00653
00654 if (vax_float_literal (op))
00655 c++;
00656 else
00657 c += (GET_MODE (x) == DFmode) ? 3 : 2;
00658 }
00659 else
00660 {
00661 if (CONST_DOUBLE_HIGH (op) != 0
00662 || (unsigned)CONST_DOUBLE_LOW (op) > 63)
00663 c += 2;
00664 }
00665 break;
00666 case MEM:
00667 c += 1;
00668 if (GET_CODE (XEXP (op, 0)) != REG)
00669 c += vax_address_cost (XEXP (op, 0));
00670 break;
00671 case REG:
00672 case SUBREG:
00673 break;
00674 default:
00675 c += 1;
00676 break;
00677 }
00678 }
00679 return c;
00680 }
00681
00682
00683
00684 static const char *const float_strings[] =
00685 {
00686 "1.70141173319264430e+38",
00687 "-1.70141173319264430e+38",
00688 "2.93873587705571877e-39",
00689 "-2.93873587705571877e-39"
00690 };
00691
00692 static REAL_VALUE_TYPE float_values[4];
00693
00694 static int inited_float_values = 0;
00695
00696
00697 int
00698 check_float_value (mode, d, overflow)
00699 enum machine_mode mode;
00700 REAL_VALUE_TYPE *d;
00701 int overflow;
00702 {
00703 if (inited_float_values == 0)
00704 {
00705 int i;
00706 for (i = 0; i < 4; i++)
00707 {
00708 float_values[i] = REAL_VALUE_ATOF (float_strings[i], DFmode);
00709 }
00710
00711 inited_float_values = 1;
00712 }
00713
00714 if (overflow)
00715 {
00716 memcpy (d, &float_values[0], sizeof (REAL_VALUE_TYPE));
00717 return 1;
00718 }
00719
00720 if ((mode) == SFmode)
00721 {
00722 REAL_VALUE_TYPE r;
00723 memcpy (&r, d, sizeof (REAL_VALUE_TYPE));
00724 if (REAL_VALUES_LESS (float_values[0], r))
00725 {
00726 memcpy (d, &float_values[0], sizeof (REAL_VALUE_TYPE));
00727 return 1;
00728 }
00729 else if (REAL_VALUES_LESS (r, float_values[1]))
00730 {
00731 memcpy (d, &float_values[1], sizeof (REAL_VALUE_TYPE));
00732 return 1;
00733 }
00734 else if (REAL_VALUES_LESS (dconst0, r)
00735 && REAL_VALUES_LESS (r, float_values[2]))
00736 {
00737 memcpy (d, &dconst0, sizeof (REAL_VALUE_TYPE));
00738 return 1;
00739 }
00740 else if (REAL_VALUES_LESS (r, dconst0)
00741 && REAL_VALUES_LESS (float_values[3], r))
00742 {
00743 memcpy (d, &dconst0, sizeof (REAL_VALUE_TYPE));
00744 return 1;
00745 }
00746 }
00747
00748 return 0;
00749 }
00750
00751 #if VMS_TARGET
00752
00753
00754
00755
00756
00757
00758 static
00759 struct extern_list {
00760 struct extern_list *next;
00761 const char *name;
00762 int size;
00763 int in_const;
00764 } *extern_head = 0, *pending_head = 0;
00765
00766
00767
00768
00769 void
00770 vms_check_external (decl, name, pending)
00771 tree decl;
00772 const char *name;
00773 int pending;
00774 {
00775 register struct extern_list *p, *p0;
00776
00777 for (p = extern_head; p; p = p->next)
00778 if (!strcmp (p->name, name))
00779 return;
00780
00781 for (p = pending_head, p0 = 0; p; p0 = p, p = p->next)
00782 if (!strcmp (p->name, name))
00783 {
00784 if (pending)
00785 return;
00786
00787
00788 if (p == pending_head)
00789 pending_head = p->next;
00790 else
00791 p0->next = p->next;
00792 p->next = extern_head;
00793 extern_head = p;
00794 return;
00795 }
00796
00797
00798 p = (struct extern_list *)permalloc ((long) sizeof (struct extern_list));
00799 p->name = name;
00800
00801 if (pending)
00802 {
00803
00804 p->size = (DECL_SIZE (decl) == 0) ? 0 :
00805 TREE_INT_CST_LOW (size_binop (CEIL_DIV_EXPR, DECL_SIZE (decl),
00806 size_int (BITS_PER_UNIT)));
00807 p->in_const = (TREE_READONLY (decl) && ! TREE_THIS_VOLATILE (decl));
00808
00809 p->next = pending_head;
00810 pending_head = p;
00811 }
00812 else
00813 {
00814
00815 p->size = p->in_const = 0;
00816
00817 p->next = extern_head;
00818 extern_head = p;
00819 }
00820 return;
00821 }
00822
00823 void
00824 vms_flush_pending_externals (file)
00825 FILE *file;
00826 {
00827 register struct extern_list *p;
00828
00829 while (pending_head)
00830 {
00831
00832 p = pending_head;
00833 pending_head = p->next;
00834 p->next = extern_head;
00835 extern_head = p;
00836
00837
00838 if (p->in_const)
00839 const_section ();
00840 else
00841 data_section ();
00842 fputs (".comm ", file);
00843 assemble_name (file, p->name);
00844 fprintf (file, ",%d\n", p->size);
00845 }
00846 }
00847
00848 static void
00849 vms_asm_out_constructor (symbol, priority)
00850 rtx symbol;
00851 int priority ATTRIBUTE_UNUSED;
00852 {
00853 fprintf (asm_out_file,".globl $$PsectAttributes_NOOVR$$__gxx_init_1\n");
00854 data_section();
00855 fprintf (asm_out_file,"$$PsectAttributes_NOOVR$$__gxx_init_1:\n\t.long\t");
00856 assemble_name (asm_out_file, XSTR (symbol, 0));
00857 fputc ('\n', asm_out_file);
00858 }
00859
00860 static void
00861 vms_asm_out_destructor (symbol, priority)
00862 rtx symbol;
00863 int priority ATTRIBUTE_UNUSED;
00864 {
00865 fprintf (asm_out_file,".globl $$PsectAttributes_NOOVR$$__gxx_clean_1\n");
00866 data_section();
00867 fprintf (asm_out_file,"$$PsectAttributes_NOOVR$$__gxx_clean_1:\n\t.long\t");
00868 assemble_name (asm_out_file, XSTR (symbol, 0));
00869 fputc ('\n', asm_out_file);
00870 }
00871 #endif
00872
00873
00874
00875 #ifdef QSORT_WORKAROUND
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888 void
00889 not_qsort (array, count, size, compare)
00890 void *array;
00891 unsigned count, size;
00892 int (*compare)();
00893 {
00894
00895 if (size == sizeof (short))
00896 {
00897 register int i;
00898 register short *next, *prev;
00899 short tmp, *base = array;
00900
00901 for (next = base, i = count - 1; i > 0; i--)
00902 {
00903 prev = next++;
00904 if ((*compare)(next, prev) < 0)
00905 {
00906 tmp = *next;
00907 do *(prev + 1) = *prev;
00908 while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0);
00909 *(prev + 1) = tmp;
00910 }
00911 }
00912 }
00913 else if (size == sizeof (long))
00914 {
00915 register int i;
00916 register long *next, *prev;
00917 long tmp, *base = array;
00918
00919 for (next = base, i = count - 1; i > 0; i--)
00920 {
00921 prev = next++;
00922 if ((*compare)(next, prev) < 0)
00923 {
00924 tmp = *next;
00925 do *(prev + 1) = *prev;
00926 while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0);
00927 *(prev + 1) = tmp;
00928 }
00929 }
00930 }
00931 else
00932 {
00933 register int i;
00934 register char *next, *prev, *tmp = alloca (size), *base = array;
00935
00936 for (next = base, i = count - 1; i > 0; i--)
00937 {
00938 prev = next, next += size;
00939 if ((*compare)(next, prev) < 0)
00940 {
00941 memcpy (tmp, next, size);
00942 do { memcpy (prev + size, prev, size);
00943 prev -= size;
00944 } while (prev >= base ? (*compare)(tmp, prev) < 0 : 0);
00945 memcpy (prev + size, tmp, size);
00946 }
00947 }
00948 #ifdef USE_C_ALLOCA
00949 alloca (0);
00950 #endif
00951 }
00952
00953 return;
00954 }
00955 #endif
00956
00957
00958
00959 static int
00960 follows_p (a, b)
00961 rtx a, b;
00962 {
00963 register rtx p;
00964
00965 for (p = a; p != b; p = NEXT_INSN (p))
00966 if (! p)
00967 return 1;
00968
00969 return 0;
00970 }
00971
00972
00973
00974 int
00975 reg_was_0_p (insn, op)
00976 rtx insn, op;
00977 {
00978 rtx link;
00979
00980 return ((link = find_reg_note (insn, REG_WAS_0, 0))
00981
00982
00983 && ! INSN_DELETED_P (XEXP (link, 0))
00984 && GET_CODE (XEXP (link, 0)) != NOTE
00985 && ! follows_p (XEXP (link, 0), insn)
00986
00987 && no_labels_between_p (XEXP (link, 0), insn)
00988
00989 && ! reg_set_between_p (op, XEXP (link, 0), insn));
00990 }