00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 #ifdef USE_PCH
00069 #include "cg_pch.h"
00070 #endif // USE_PCH
00071 #pragma hdrstop
00072
00073 #include <stdarg.h>
00074
00075 #include "defs.h"
00076 #include "config.h"
00077 #include "tracing.h"
00078 #include "erglob.h"
00079 #include "printsrc.h"
00080
00081 #include "import.h"
00082 #include "opt_alias_interface.h"
00083 #include "cg.h"
00084
00085 #include "cgir.h"
00086 #include "cg.h"
00087 #include "register.h"
00088 #include "cg_dep_graph.h"
00089 #include "cgprep.h"
00090 #include "cg_loop.h"
00091 #include "cgtarget.h"
00092 #include "cg_spill.h"
00093 #ifdef TARG_IA64
00094 #include "targ_sim.h"
00095 #endif
00096 #include "wn.h"
00097 #include "whirl2ops.h"
00098 #include "cgexp.h"
00099 #include "xstats.h"
00100 #include "tag.h"
00101
00102
00103 #define OP_Alloc(size) ((OP *)Pu_Alloc(size))
00104
00105
00106 #define Set_OP_code(o,opc) ((o)->opr = (mTOP)(opc))
00107 #define Set_OP_opnds(o,n) ((o)->opnds = (n))
00108 #define Set_OP_results(o,n) ((o)->results = (n))
00109
00110 #ifdef TARG_IA64
00111 BOOL
00112 OP_xfer(OP *op)
00113 {
00114 if(TOP_is_xfer(OP_code(op)))
00115 return TRUE;
00116
00117 if(OP_chk(op)){
00118 BB* home_bb = OP_bb(op);
00119 if(!home_bb)
00120 return FALSE;
00121 if(BB_succs_len(home_bb) != 2)
00122 return FALSE;
00123 if(op != BB_last_op(home_bb))
00124 return FALSE;
00125 return TRUE;
00126 }
00127 return FALSE;
00128 }
00129
00130
00131
00132
00133
00134
00135 BOOL
00136 OP_restore_b0(OP *op)
00137 {
00138 if(OP_results(op) != 1 || OP_call(op)) return FALSE;
00139 TN* res_tn = OP_result(op, 0);
00140 if(TN_is_constant(res_tn)) return FALSE;
00141 return (TN_register_class(res_tn) == ISA_REGISTER_CLASS_branch && TN_register(res_tn) == REGISTER_MIN+0);
00142 }
00143
00144
00145
00146
00147
00148 BOOL
00149 OP_restore_ar_pfs(OP *op)
00150 {
00151 if(OP_results(op) != 1) return FALSE;
00152 TN* res_tn = OP_result(op, 0);
00153 if(TN_is_constant(res_tn)) return FALSE;
00154 return TN_is_pfs_reg(res_tn);
00155 }
00156
00157
00158
00159
00160
00161 BOOL
00162 OP_def_ar_lc(OP *op)
00163 {
00164 if(OP_results(op) != 1) return FALSE;
00165 TN* res_tn = OP_result(op, 0);
00166 if(TN_is_constant(res_tn)) return FALSE;
00167 return TN_is_lc_reg(res_tn);
00168 }
00169
00170 static inline void
00171 Copy_GOT_Sym_Info (OP* new_op, OP* op) {
00172 if (OP_load_GOT_entry(op)){
00173 OP_MAP_Set (OP_Ld_GOT_2_Sym_Map,
00174 new_op,
00175 OP_MAP_Get (OP_Ld_GOT_2_Sym_Map, op));
00176 }
00177 }
00178
00179 #endif // TARG_IA64
00180
00181
00182
00183
00184 static inline void
00185 Copy_Asm_OP_Annot(OP* new_op, OP* op)
00186 {
00187 if (OP_code(op) == TOP_asm) {
00188 OP_MAP_Set(OP_Asm_Map, new_op, OP_MAP_Get(OP_Asm_Map, op));
00189 }
00190 }
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202 static OP *
00203 #ifdef TARG_IA64
00204 New_OP ( INT results, INT opnds, INT hidden_opnds)
00205 #else
00206 New_OP ( INT results, INT opnds )
00207 #endif
00208 {
00209 OP *op = OP_Alloc ( OP_sizeof(results, opnds
00210 #if defined(TARG_IA64)
00211 +hidden_opnds
00212 #endif
00213 ) );
00214 PU_OP_Cnt++;
00215 Set_OP_opnds(op, opnds);
00216 Set_OP_results(op, results);
00217 return op;
00218 }
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 OP *
00231 Dup_OP ( OP *op )
00232 {
00233 INT results = OP_results(op);
00234 INT opnds = OP_opnds(op);
00235 #ifdef TARG_IA64
00236 INT hidden_opnds = CGTARG_Max_Number_of_Hidden_Opnd (OP_code(op));
00237 OP *new_op = New_OP (results, opnds, hidden_opnds);
00238 #else
00239 OP *new_op = New_OP ( results, opnds );
00240 #endif
00241
00242 memcpy(new_op, op, OP_sizeof(results, opnds));
00243 new_op->next = new_op->prev = NULL;
00244 new_op->bb = NULL;
00245
00246 Copy_Asm_OP_Annot ( new_op, op );
00247 #ifdef TARG_IA64
00248 if (OP_load_GOT_entry(op)) {
00249 Copy_GOT_Sym_Info (new_op, op);
00250 }
00251 #endif
00252 if (OP_has_tag(op)) {
00253 Set_OP_Tag (new_op, Gen_Tag());
00254 }
00255
00256 #ifdef TARG_X8664
00257 if ( TOP_is_vector_high_loadstore ( OP_code ( new_op ) ) )
00258 Set_OP_cond_def_kind(new_op, OP_ALWAYS_COND_DEF);
00259 #endif
00260 #if defined(KEY) && !defined(TARG_NVISA)
00261
00262 if (OP_load(op)) {
00263 ST *spill_loc = CGSPILL_OP_Spill_Location(op);
00264 if (spill_loc != (ST *)0)
00265 CGSPILL_Inc_Restore_Count(spill_loc);
00266 }
00267 #endif
00268
00269 return new_op;
00270 }
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 inline void prepend_ops(OPS *ops, OP *first, OP *last)
00300 {
00301 OP **pprev = OPS_first(ops) ? &OPS_first(ops)->prev : &ops->last;
00302 first->prev = NULL;
00303 last->next = OPS_first(ops);
00304 ops->first = first;
00305 *pprev = last;
00306 }
00307
00308
00309 inline void append_ops(OPS *ops, OP *first, OP *last)
00310 {
00311 OP **pnext = OPS_last(ops) ? &OPS_last(ops)->next : &ops->first;
00312 last->next = NULL;
00313 first->prev = OPS_last(ops);
00314 ops->last = last;
00315 *pnext = first;
00316 }
00317
00318 inline void insert_ops_before(OPS *ops, OP *point, OP *first, OP *last)
00319 {
00320 OP **prevp = OP_prev(point) ? &OP_prev(point)->next : &ops->first;
00321 *prevp = first;
00322 last->next = point;
00323 first->prev = OP_prev(point);
00324 point->prev = last;
00325 }
00326
00327 inline void insert_ops_after(OPS *ops, OP *point, OP *first, OP *last)
00328 {
00329 OP **nextp = OP_next(point) ? &OP_next(point)->prev : &ops->last;
00330 *nextp = last;
00331 first->prev = point;
00332 last->next = OP_next(point);
00333 point->next = first;
00334 }
00335
00336 inline void insert_ops(OPS *ops, OP *point, OP *first, OP *last, BOOL before)
00337 {
00338 if (point == NULL) {
00339 if (before)
00340 prepend_ops(ops, first, last);
00341 else
00342 append_ops(ops, first, last);
00343 } else {
00344 if (before)
00345 insert_ops_before(ops, point, first, last);
00346 else
00347 insert_ops_after(ops, point, first, last);
00348 }
00349 }
00350
00351
00352
00353
00354
00355
00356
00357
00358 void BB_Sink_Op_Before(BB *bb, OP *op, OP *point)
00359 {
00360 if (OP_next(op) == point) return;
00361
00362 Is_True(OP_bb(op) == bb && OP_bb(point) == bb,
00363 ("Sink_Op_Before: must sink inside the bb."));
00364
00365
00366 OP *t1 = OP_prev(op);
00367 OP *t2 = OP_next(op);
00368 if (t1) t1->next = t2;
00369 if (t2) t2->prev = t1;
00370
00371
00372 OP *prev = OP_prev(point);
00373 op->prev = prev;
00374 op->next = point;
00375 prev->next = op;
00376 point->prev = op;
00377
00378 if (op == BB_first_op(OP_bb(op)))
00379 OP_bb(op)->ops.first = t2;
00380
00381 }
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402 #define ORDER_TYPE UINT16
00403 #define mORDER_TYPE mUINT16
00404 #define mMAP_IDX_TYPE mUINT16
00405 #define ORDER_BITS (sizeof(mORDER_TYPE) * 8)
00406 #define MIN_INITIAL_SPACING \
00407 ((mORDER_TYPE)1 << (ORDER_BITS-(sizeof(mMAP_IDX_TYPE)*8)))
00408 #define INITIAL_SPACING ((ORDER_TYPE)(MIN_INITIAL_SPACING * 8))
00409 #define MAX_ORDER ((ORDER_TYPE)-1)
00410
00411
00412 static void setup_ops(BB *bb, OP *first, OP *last, UINT32 len)
00413 {
00414 OP *op;
00415 ORDER_TYPE incr;
00416 ORDER_TYPE order_before;
00417 ORDER_TYPE order_after;
00418 ORDER_TYPE order;
00419
00420
00421
00422 if (len == 0) return;
00423
00424
00425
00426
00427 order_before = OP_prev(first) ? OP_prev(first)->order : 0;
00428 order_after = OP_next(last) ? OP_next(last)->order : MAX_ORDER;
00429
00430
00431
00432
00433
00434 incr = (order_after - order_before - 1) / (len + 1);
00435 if (incr > INITIAL_SPACING) incr = INITIAL_SPACING;
00436
00437
00438
00439
00440
00441 order = order_before;
00442 op = first;
00443 do {
00444 FmtAssert(op, ("input ops not connected properly"));
00445 op->bb = bb;
00446 op->map_idx = BB_New_Op_Map_Idx(bb);
00447 order += incr;
00448 op->order = order;
00449 REGISTER_CLASS_OP_Update_Mapping (op);
00450 op = OP_next(op);
00451 } while (op != OP_next(last));
00452
00453
00454
00455 if (incr != 0) goto done;
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468 do {
00469 if (OP_next(last)) {
00470 last = OP_next(last);
00471 order_after = OP_next(last) ? OP_next(last)->order : MAX_ORDER;
00472 } else if (OP_prev(first)) {
00473 first = OP_prev(first);
00474 order_before = OP_prev(first) ? OP_prev(first)->order : 0;
00475 } else {
00476 FmtAssert(FALSE, ("unable to reorder"));
00477 }
00478 len++;
00479 incr = (order_after - order_before - 1) / (len + 1);
00480 } while (incr == 0);
00481 if (incr > INITIAL_SPACING) incr = INITIAL_SPACING;
00482
00483
00484
00485 op = first;
00486 order = order_before;
00487 do {
00488 order += incr;
00489 op->order = order;
00490 op = OP_next(op);
00491 } while (op != OP_next(last));
00492
00493 done:
00494
00495
00496
00497 ;
00498
00499 #ifdef VERIFY_OPS
00500 {
00501 UINT16 len = 1;
00502 op = first;
00503 while (OP_prev(op)) op = OP_prev(op);
00504 while (OP_next(op)) {
00505 FmtAssert(op->order < OP_next(op)->order, ("OP order set wrong"));
00506 FmtAssert(op->bb == bb, ("OP bb set wrong"));
00507 op = OP_next(op);
00508 len++;
00509 }
00510 FmtAssert(len == BB_length(bb), ("BB_length set wrong"));
00511 }
00512 #endif
00513 }
00514
00515
00516 void OPS_Insert_Op(OPS *ops, OP *point, OP *op, BOOL before)
00517 {
00518 insert_ops(ops, point, op, op, before);
00519 ops->length++;
00520 }
00521
00522
00523 void OPS_Insert_Op_Before(OPS *ops, OP *point, OP *op)
00524 {
00525 insert_ops_before(ops, point, op, op);
00526 ops->length++;
00527 }
00528
00529
00530 void OPS_Insert_Op_After(OPS *ops, OP *point, OP *op)
00531 {
00532 insert_ops_after(ops, point, op, op);
00533 ops->length++;
00534 }
00535
00536
00537 void OPS_Append_Op(OPS *ops, OP *op)
00538 {
00539 append_ops(ops, op, op);
00540 ops->length++;
00541 }
00542
00543
00544 void OPS_Prepend_Op(OPS *ops, OP *op)
00545 {
00546 prepend_ops(ops, op, op);
00547 ops->length++;
00548 }
00549
00550
00551 void OPS_Insert_Ops(OPS *ops, OP *point, OPS *new_ops, BOOL before)
00552 {
00553 if (OPS_first(new_ops) == NULL) return;
00554 insert_ops(ops, point, OPS_first(new_ops), OPS_last(new_ops), before);
00555 ops->length += OPS_length(new_ops);
00556 }
00557
00558
00559 void OPS_Insert_Ops_Before(OPS *ops, OP *point, OPS *new_ops)
00560 {
00561 if (OPS_first(new_ops) == NULL) return;
00562 insert_ops_before(ops, point, OPS_first(new_ops), OPS_last(new_ops));
00563 ops->length += OPS_length(new_ops);
00564 }
00565
00566
00567 void OPS_Insert_Ops_After(OPS *ops, OP *point, OPS *new_ops)
00568 {
00569 if (OPS_first(new_ops) == NULL) return;
00570 insert_ops_after(ops, point, OPS_first(new_ops), OPS_last(new_ops));
00571 ops->length += OPS_length(new_ops);
00572 }
00573
00574
00575 void OPS_Append_Ops(OPS *ops, OPS *new_ops)
00576 {
00577 if (OPS_first(new_ops) == NULL) return;
00578 append_ops(ops, OPS_first(new_ops), OPS_last(new_ops));
00579 ops->length += OPS_length(new_ops);
00580 }
00581
00582
00583 void OPS_Prepend_Ops(OPS *ops, OPS *new_ops)
00584 {
00585 if (OPS_first(new_ops) == NULL) return;
00586 prepend_ops(ops, OPS_first(new_ops), OPS_last(new_ops));
00587 ops->length += OPS_length(new_ops);
00588 }
00589
00590
00591
00592 void BB_Update_OP_Order(BB *bb)
00593 {
00594 INT order = 0;
00595 INT incr = INITIAL_SPACING;
00596 for (OP *op = BB_first_op(bb); op; op = OP_next(op)) {
00597 order += incr;
00598 op->order = order;
00599 }
00600 }
00601
00602
00603
00604 void BB_Verify_OP_Order(BB *bb)
00605 {
00606 INT prev_order = -1;
00607 for (OP *op = BB_first_op(bb); op; op = OP_next(op)) {
00608 FmtAssert(prev_order < op->order,
00609 ("BB_Verify_OP_Order: OP_order() is not correct."));
00610 prev_order = op->order;
00611 }
00612 }
00613
00614
00615
00616
00617
00618
00619
00620
00621 void BB_Insert_Op(BB *bb, OP *point, OP *op, BOOL before)
00622 {
00623 Is_True(bb, ("can't insert in NULL BB"));
00624 insert_ops(&bb->ops, point, op, op, before);
00625 bb->ops.length++;
00626 setup_ops(bb, op, op, 1);
00627 }
00628
00629
00630 void BB_Insert_Op_Before(BB *bb, OP *point, OP *op)
00631 {
00632 Is_True(bb, ("can't insert in NULL BB"));
00633 insert_ops_before(&bb->ops, point, op, op);
00634 bb->ops.length++;
00635 setup_ops(bb, op, op, 1);
00636 }
00637
00638
00639 void BB_Insert_Op_After(BB *bb, OP *point, OP *op)
00640 {
00641 Is_True(bb, ("can't insert in NULL BB"));
00642 insert_ops_after(&bb->ops, point, op, op);
00643 bb->ops.length++;
00644 setup_ops(bb, op, op, 1);
00645 }
00646
00647
00648 void BB_Prepend_Op(BB *bb, OP *op)
00649 {
00650 Is_True(bb, ("can't insert in NULL BB"));
00651 prepend_ops(&bb->ops, op, op);
00652 bb->ops.length++;
00653 setup_ops(bb, op, op, 1);
00654 }
00655
00656
00657 void BB_Append_Op(BB *bb, OP *op)
00658 {
00659 Is_True(bb, ("can't insert in NULL BB"));
00660 append_ops(&bb->ops, op, op);
00661 bb->ops.length++;
00662 setup_ops(bb, op, op, 1);
00663 }
00664
00665
00666 void BB_Insert_Ops(BB *bb, OP *point, OPS *ops, BOOL before)
00667 {
00668 if (OPS_first(ops) == NULL) return;
00669 insert_ops(&bb->ops, point, OPS_first(ops), OPS_last(ops), before);
00670 bb->ops.length += OPS_length(ops);
00671 setup_ops(bb, OPS_first(ops), OPS_last(ops), OPS_length(ops));
00672 }
00673
00674
00675 void BB_Insert_Ops_Before(BB *bb, OP *point, OPS *ops)
00676 {
00677 if (OPS_first(ops) == NULL) return;
00678 insert_ops_before(&bb->ops, point, OPS_first(ops), OPS_last(ops));
00679 bb->ops.length += OPS_length(ops);
00680 setup_ops(bb, OPS_first(ops), OPS_last(ops), OPS_length(ops));
00681 }
00682
00683
00684 void BB_Insert_Ops_After(BB *bb, OP *point, OPS *ops)
00685 {
00686 if (OPS_first(ops) == NULL) return;
00687 insert_ops_after(&bb->ops, point, OPS_first(ops), OPS_last(ops));
00688 bb->ops.length += OPS_length(ops);
00689 setup_ops(bb, OPS_first(ops), OPS_last(ops), OPS_length(ops));
00690 }
00691
00692
00693 void BB_Insert_Noops(OP *op, INT num, BOOL before)
00694 {
00695 OPS new_ops = OPS_EMPTY;
00696 INT i;
00697
00698 for (i = 0; i < num; i++) {
00699 Exp_Noop (&new_ops);
00700 }
00701 BB_Insert_Ops(OP_bb(op), op, &new_ops, before);
00702 }
00703
00704
00705 void BB_Prepend_Ops(BB *bb, OPS *ops)
00706 {
00707 if (OPS_first(ops) == NULL) return;
00708 prepend_ops(&bb->ops, OPS_first(ops), OPS_last(ops));
00709 bb->ops.length += OPS_length(ops);
00710 setup_ops(bb, OPS_first(ops), OPS_last(ops), OPS_length(ops));
00711 }
00712
00713
00714 void BB_Append_Ops(BB *bb, OPS *ops)
00715 {
00716 if (OPS_first(ops) == NULL) return;
00717 append_ops(&bb->ops, OPS_first(ops), OPS_last(ops));
00718 bb->ops.length += OPS_length(ops);
00719 setup_ops(bb, OPS_first(ops), OPS_last(ops), OPS_length(ops));
00720 }
00721
00722
00723 void BB_Move_Op(BB *to_bb, OP *point, BB *from_bb, OP *op, BOOL before)
00724 {
00725 Is_True(OP_bb(op) == from_bb, ("op not in from_bb"));
00726 Is_True(OP_bb(point) == to_bb, ("point not in to_bb"));
00727 OPS_Remove_Op(&from_bb->ops, op);
00728 insert_ops(&to_bb->ops, point, op, op, before);
00729 to_bb->ops.length++;
00730 setup_ops(to_bb, op, op, 1);
00731 }
00732
00733
00734 void BB_Move_Op_Before(BB *to_bb, OP *point, BB *from_bb, OP *op)
00735 {
00736 Is_True(OP_bb(op) == from_bb, ("op not in from_bb"));
00737 Is_True(OP_bb(point) == to_bb, ("point not in to_bb"));
00738 OPS_Remove_Op(&from_bb->ops, op);
00739 insert_ops_before(&to_bb->ops, point, op, op);
00740 to_bb->ops.length++;
00741 setup_ops(to_bb, op, op, 1);
00742 }
00743
00744 void BB_Move_Op_After(BB *to_bb, OP *point, BB *from_bb, OP *op)
00745 {
00746 Is_True(OP_bb(op) == from_bb, ("op not in from_bb"));
00747 Is_True(OP_bb(point) == to_bb, ("point not in to_bb"));
00748 OPS_Remove_Op(&from_bb->ops, op);
00749 insert_ops_after(&to_bb->ops, point, op, op);
00750 to_bb->ops.length++;
00751 setup_ops(to_bb, op, op, 1);
00752 }
00753
00754
00755 void BB_Move_Op_To_Start(BB *to_bb, BB *from_bb, OP *op)
00756 {
00757 Is_True(OP_bb(op) == from_bb, ("op not in from_bb"));
00758 OPS_Remove_Op(&from_bb->ops, op);
00759 prepend_ops(&to_bb->ops, op, op);
00760 to_bb->ops.length++;
00761 setup_ops(to_bb, op, op, 1);
00762 }
00763
00764
00765 void BB_Move_Op_To_End(BB *to_bb, BB *from_bb, OP *op)
00766 {
00767 Is_True(OP_bb(op) == from_bb, ("op not in from_bb"));
00768 OPS_Remove_Op(&from_bb->ops, op);
00769 append_ops(&to_bb->ops, op, op);
00770 to_bb->ops.length++;
00771 setup_ops(to_bb, op, op, 1);
00772 }
00773
00774
00775 void BB_Append_All(BB *to_bb, BB *from_bb)
00776 {
00777 OPS the_ops;
00778
00779 if (BB_length(from_bb) == 0) return;
00780
00781 the_ops = from_bb->ops;
00782 BB_Remove_All(from_bb);
00783 BB_Append_Ops(to_bb, &the_ops);
00784 }
00785
00786
00787 void BB_Prepend_All (BB *to_bb, BB *from_bb)
00788 {
00789 OPS the_ops;
00790
00791 if (BB_length(from_bb) == 0) return;
00792
00793 the_ops = from_bb->ops;
00794 BB_Remove_All (from_bb);
00795 BB_Prepend_Ops (to_bb, &the_ops);
00796 }
00797
00798
00799 OP *BB_Remove_Branch(BB *bb)
00800 {
00801 OP *last_op;
00802 OP *br = BB_branch_op(bb);
00803
00804 if (br) {
00805 last_op = BB_last_op(bb);
00806 if (OP_noop(last_op)) BB_Remove_Op(bb, last_op);
00807 BB_Remove_Op(bb, br);
00808 }
00809
00810 return br;
00811 }
00812
00813
00814 void BB_Remove_Op(BB *bb, OP *op)
00815 {
00816 OP *orig_last_op = BB_last_op(bb);
00817
00818 OPS_Remove_Op(&bb->ops, op);
00819 op->bb = NULL;
00820
00821 #ifdef TARG_SL
00822 if (BB_has_tag(bb) && BB_length(bb)==0) {
00823 OP *nop = Mk_OP( TOP_nop );
00824 BB_Append_Op(bb, nop);
00825 }
00826 #endif
00827 }
00828
00829
00830 void BB_Remove_Ops(BB *bb, OPS *ops)
00831 {
00832 OP *op;
00833
00834 if (OPS_first(ops) == NULL) return;
00835
00836 OPS_Remove_Ops(&bb->ops, ops);
00837
00838 FOR_ALL_OPS_OPs(ops, op) op->bb = NULL;
00839 }
00840
00841
00842 void BB_Remove_All(BB *bb)
00843 {
00844 BB_Remove_Ops(bb, &bb->ops);
00845 BB_next_op_map_idx(bb) = 0;
00846 }
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856 OP *
00857 Mk_OP(TOP opr, ...)
00858 {
00859 va_list ap;
00860 INT i;
00861 INT results = TOP_fixed_results(opr);
00862 INT opnds = TOP_fixed_opnds(opr);
00863 #ifdef TARG_IA64
00864 OP *op = New_OP(results, opnds, CGTARG_Max_Number_of_Hidden_Opnd(opr));
00865 #else
00866 OP *op = New_OP(results, opnds);
00867 #endif
00868
00869 FmtAssert(!TOP_is_var_opnds(opr), ("Mk_OP not allowed with variable operands"));
00870
00871 Set_OP_code(op, opr);
00872
00873 va_start(ap, opr);
00874
00875 for (i = 0; i < results; ++i) {
00876 TN *result = va_arg(ap, TN *);
00877 Set_OP_result(op, i, result);
00878 }
00879 if (TOP_is_defs_fpu_int(opr)) Set_TN_is_fpu_int(OP_result(op, 0));
00880
00881 for (i = 0; i < opnds; ++i) {
00882 TN *opnd = va_arg(ap, TN *);
00883 Set_OP_opnd(op, i, opnd);
00884 }
00885
00886 va_end(ap);
00887
00888 CGTARG_Init_OP_cond_def_kind(op);
00889
00890 #if Is_True_On
00891 #ifdef TARG_X8664
00892
00893 if( Is_Target_32bit() &&
00894 !OP_dummy( op ) &&
00895 !OP_simulated(op) &&
00896 !OP_cond_move(op) &&
00897 OP_code(op) != TOP_leave ){
00898
00899 for( int i = 0; i < OP_results(op); i++ ){
00900 TN* tn = OP_result( op, i );
00901 if( tn != NULL &&
00902 OP_result_size( op, i ) > 32 &&
00903 TN_register_class(tn) == ISA_REGISTER_CLASS_integer ){
00904 FmtAssert( FALSE, ("i386 does not support 64-bit operation -- %s",
00905 TOP_Name(opr) ) );
00906 }
00907 }
00908
00909 const int base_idx = OP_find_opnd_use( op, OU_base );
00910 const int index_idx = OP_find_opnd_use( op, OU_index );
00911 const int target_idx = OP_find_opnd_use( op, OU_target );
00912
00913 for( int i = 0; i < OP_opnds(op); i++ ){
00914 TN* tn = OP_opnd( op, i );
00915 if( tn != NULL &&
00916 i != base_idx &&
00917 i != index_idx &&
00918 i != target_idx&&
00919 OP_opnd_size( op, i ) > 32 &&
00920 TN_register_class(tn) == ISA_REGISTER_CLASS_integer ){
00921 FmtAssert( FALSE, ("i386 does not support 64-bit operation -- %s",
00922 TOP_Name(opr) ) );
00923 }
00924 }
00925 }
00926 #endif // TARG_X8664
00927 #endif // Is_True_On
00928
00929 #ifdef TARG_X8664
00930 if ( TOP_is_vector_high_loadstore ( OP_code ( op ) ) )
00931 Set_OP_cond_def_kind(op, OP_ALWAYS_COND_DEF);
00932 #endif
00933 return op;
00934 }
00935
00936 OP *
00937 Mk_VarOP(TOP opr, INT results, INT opnds, TN **res_tn, TN **opnd_tn)
00938 {
00939 if (results != TOP_fixed_results(opr)) {
00940 FmtAssert(TOP_is_var_opnds(opr) && results > TOP_fixed_results(opr),
00941 ("%d is not enough results for %s", results, TOP_Name(opr)));
00942 }
00943 if (opnds != TOP_fixed_opnds(opr)) {
00944 FmtAssert(TOP_is_var_opnds(opr) && opnds > TOP_fixed_opnds(opr),
00945 ("%d is not enough operands for %s", opnds, TOP_Name(opr)));
00946 }
00947
00948 INT i;
00949 #ifdef TARG_IA64
00950 OP *op = New_OP(results, opnds, CGTARG_Max_Number_of_Hidden_Opnd(opr));
00951 #else
00952 OP *op = New_OP(results, opnds);
00953 #endif
00954
00955 Set_OP_code(op, opr);
00956
00957 for (i = 0; i < results; ++i) Set_OP_result(op, i, res_tn[i]);
00958 if (TOP_is_defs_fpu_int(opr)) Set_TN_is_fpu_int(res_tn[0]);
00959
00960 for (i = 0; i < opnds; ++i) Set_OP_opnd(op, i, opnd_tn[i]);
00961
00962 CGTARG_Init_OP_cond_def_kind(op);
00963
00964 return op;
00965 }
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978 void Print_OP_No_SrcLine(const OP *op)
00979 {
00980 INT16 i;
00981 WN *wn;
00982 BOOL cg_loop_op = Is_CG_LOOP_Op(op);
00983 #ifdef TARG_IA64
00984 if (OP_start_bundle(op)) fprintf( TFile, " }\n{\n");
00985 fprintf (TFile, "[%3d] ", OP_map_idx(op));
00986 fprintf (TFile, "[%4d] ", Srcpos_To_Line(OP_srcpos(op)));
00987 #elif defined(TARG_X8664)
00988 fprintf (TFile, "[%4d,%2d] ", Srcpos_To_Line(OP_srcpos(op)), OP_scycle(op) );
00989 #else
00990 fprintf (TFile, "[%4d] ", Srcpos_To_Line(OP_srcpos(op)));
00991 #endif
00992 if (OP_has_tag(op)) {
00993 LABEL_IDX tag = Get_OP_Tag(op);
00994 fprintf (TFile, "<tag %s>: ", LABEL_name(tag));
00995 }
00996 for (i = 0; i < OP_results(op); i++) {
00997 Print_TN(OP_result(op,i),FALSE);
00998 fprintf(TFile, " ");
00999 }
01000 fprintf(TFile, ":- ");
01001 fprintf(TFile, "%s ", TOP_Name(OP_code(op)));
01002 #ifdef TARG_IA64
01003 if ( OP_variant(op) != 0 ) {
01004 fprintf ( TFile, "(%x) ", OP_variant(op));
01005 }
01006 #endif
01007 for (i=0; i<OP_opnds(op); i++) {
01008 TN *tn = OP_opnd(op,i);
01009 Print_TN(tn,FALSE);
01010 if ( cg_loop_op ) {
01011 INT omega = TN_is_symbol(tn) ? OP_restore_omega(op) : OP_omega(op,i);
01012 if (omega) fprintf(TFile, "[%d]", omega);
01013 }
01014 if (OP_Defs_TN(op, tn)) fprintf(TFile, "<defopnd>");
01015 fprintf(TFile, " ");
01016 }
01017
01018 #ifdef TARG_SL
01019
01020 TN_LIST *extra_opnds = op->extra_operand;
01021 if( extra_opnds )
01022 fprintf( TFile, " ExtraOpndList: ");
01023 while( extra_opnds ){
01024 TN* opnd_tn = TN_LIST_first( extra_opnds );
01025 Print_TN( opnd_tn, FALSE );
01026 extra_opnds = TN_LIST_rest( extra_opnds );
01027 }
01028
01029 TN_LIST *extra_results = op->extra_result;
01030 if( extra_results )
01031 fprintf( TFile, " ExtraResultList: ");
01032 while( extra_results ){
01033 TN* res_tn = TN_LIST_first( extra_results );
01034 Print_TN( res_tn, FALSE );
01035 extra_results = TN_LIST_rest( extra_results );
01036 }
01037 #endif
01038
01039 fprintf(TFile, ";");
01040
01041
01042
01043 if (OP_glue(op)) fprintf (TFile, " glue");
01044 if (OP_no_alias(op)) fprintf (TFile, " noalias");
01045 if (OP_copy(op)) fprintf (TFile, " copy");
01046 if (OP_volatile(op)) fprintf (TFile, " volatile");
01047 if (OP_side_effects(op)) fprintf (TFile, " side_effects");
01048 if (OP_hoisted(op)) fprintf (TFile, " hoisted");
01049 if (OP_cond_def(op)) fprintf (TFile, " cond_def");
01050 if (OP_end_group(op)) fprintf (TFile, " end_group");
01051 if (OP_tail_call(op)) fprintf (TFile, " tail_call");
01052 if (OP_no_move_before_gra(op)) fprintf (TFile, " no_move");
01053 if (OP_spadjust_plus(op)) fprintf (TFile, " spadjust_plus");
01054 if (OP_spadjust_minus(op)) fprintf (TFile, " spadjust_minus");
01055 #ifdef TARG_IA64
01056 if (OP_Scheduled(op)) fprintf (TFile, " scheduled");
01057 if (OP_start_bundle(op)) fprintf (TFile, " start_bundle");
01058 if (OP_safe_load(op)) fprintf (TFile, " safe_load");
01059 #endif
01060
01061 if (wn = Get_WN_From_Memory_OP(op)) {
01062 char buf[500];
01063 buf[0] = '\0';
01064 if (Alias_Manager) Print_alias_info (buf, Alias_Manager, wn);
01065 #ifdef TARG_X8664
01066 fprintf(TFile, " WN %s", buf);
01067 #else
01068 fprintf(TFile, " WN=0x%p %s", wn, buf);
01069 #endif
01070 }
01071 if (OP_unrolling(op)) {
01072 UINT16 unr = OP_unrolling(op);
01073 fprintf(TFile, " %d%s unrolling", unr,
01074 unr == 1 ? "st" : unr == 2 ? "nd" : unr == 3 ? "rd" : "th");
01075 }
01076 fprintf(TFile, "\n");
01077 }
01078
01079 void Print_OP( const OP *op )
01080 {
01081 Print_Src_Line (OP_srcpos(op), TFile);
01082 Print_OP_No_SrcLine(op);
01083 }
01084
01085 void Print_OPs( const OP *op )
01086 {
01087 for ( ; op; op = OP_next(op))
01088 Print_OP(op);
01089 }
01090
01091 void Print_OPS( const OPS *ops )
01092 {
01093 OP *op;
01094 FOR_ALL_OPS_OPs_FWD(ops, op)
01095 Print_OP(op);
01096 }
01097
01098 void Print_OPs_No_SrcLines( const OP *op )
01099 {
01100 for ( ; op; op = OP_next(op))
01101 Print_OP_No_SrcLine(op);
01102 }
01103
01104 void Print_OPS_No_SrcLines( const OPS *ops )
01105 {
01106 OP *op;
01107 FOR_ALL_OPS_OPs_FWD(ops, op)
01108 Print_OP_No_SrcLine(op);
01109 }
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122 BOOL
01123 OP_Defs_Reg(const OP *op, ISA_REGISTER_CLASS cl, REGISTER reg)
01124 {
01125 register INT num;
01126
01127 for ( num = 0; num < OP_results(op); num++ ) {
01128 TN *res_tn = OP_result(op,num);
01129 if (TN_is_register(res_tn)) {
01130 if (TN_register_class(res_tn) == cl && TN_register(res_tn) == reg ) {
01131 return TRUE;
01132 }
01133 }
01134 }
01135
01136
01137 return FALSE;
01138 }
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149 BOOL
01150 OP_Refs_Reg(const OP *op, ISA_REGISTER_CLASS cl, REGISTER reg)
01151 {
01152 register INT num;
01153
01154 for ( num = 0; num < OP_opnds(op); num++ ) {
01155 TN *opnd_tn = OP_opnd(op,num);
01156 if (TN_is_register(opnd_tn)) {
01157 if (TN_register_class(opnd_tn) == cl && TN_register(opnd_tn) == reg ) {
01158 return TRUE;
01159 }
01160 }
01161 }
01162
01163 #ifdef KEY
01164 if( OP_cond_def( op ) ){
01165 for ( num = 0; num < OP_results(op); num++ ) {
01166 TN* result_tn = OP_result( op, num );
01167 if (TN_is_register(result_tn) &&
01168 TN_register_class(result_tn) == cl &&
01169 TN_register(result_tn) == reg ) {
01170 return TRUE;
01171 }
01172 }
01173 }
01174 #endif
01175
01176
01177 return FALSE;
01178 }
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190 BOOL
01191 OP_Defs_TN(const OP *op, const struct tn *res)
01192 {
01193 register INT num;
01194
01195 for ( num = 0; num < OP_results(op); num++ ) {
01196 if ( OP_result(op,num) == res ) {
01197 return( TRUE );
01198 }
01199 }
01200
01201
01202 return( FALSE );
01203 }
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215 BOOL
01216 OP_Refs_TN( const OP *op, const struct tn *opnd )
01217 {
01218 register INT16 num;
01219
01220 for ( num = 0; num < OP_opnds(op); num++ ) {
01221 if ( OP_opnd(op,num) == opnd ) {
01222 return( TRUE );
01223 }
01224 }
01225
01226 #ifdef KEY
01227 if( OP_cond_def( op ) ){
01228 for ( num = 0; num < OP_results(op); num++ ) {
01229 if( OP_result( op, num ) == opnd )
01230 return TRUE;
01231 }
01232 }
01233 #endif
01234
01235
01236 return( FALSE );
01237 }
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248 INT16
01249 OP_Real_Ops( const OP *op )
01250 {
01251 if ( op == NULL || OP_dummy(op) ) {
01252 return 0;
01253 }
01254 else if ( OP_simulated(op) ) {
01255 return Simulated_Op_Real_Ops (op);
01256 }
01257 return 1;
01258 }
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269 INT
01270 OP_Real_Inst_Words( const OP *op )
01271 {
01272 if ( op == NULL || OP_dummy(op) ) {
01273 return 0;
01274 }
01275 else if ( OP_simulated(op) ) {
01276 return Simulated_Op_Real_Inst_Words (op);
01277 }
01278
01279 return OP_inst_words(op);
01280 }
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290 BOOL
01291 OP_Is_Float_Mem( const OP *op )
01292 {
01293 return (OP_load(op) && TN_is_float(OP_result(op, 0))) ||
01294 (OP_store(op) && TN_is_float(OP_opnd(op, 0)));
01295 }
01296
01297
01298
01299
01300
01301
01302
01303
01304 BOOL
01305 OP_Alloca_Barrier(OP *op )
01306 {
01307 return (OP_code(op) == TOP_spadjust && Get_WN_From_Memory_OP(op));
01308 }
01309
01310
01311
01312
01313
01314
01315 BOOL
01316 Is_Delay_Slot_Op (OP *xfer_op, OP *op)
01317 {
01318 if (op == NULL || OP_xfer(op) || OP_Real_Ops(op) != 1) return FALSE;
01319
01320
01321
01322 if (xfer_op && OP_uncond(xfer_op) &&
01323 (OP_imul(op) || OP_idiv(op))) return FALSE;
01324
01325
01326 if (OP_has_hazard(op) || OP_has_implicit_interactions(op))
01327 return FALSE;
01328 return TRUE;
01329 }
01330
01331
01332
01333
01334 void dump_op (const OP *op)
01335 {
01336 FILE *f;
01337 f = TFile;
01338 Set_Trace_File_internal(stdout);
01339 Print_OP_No_SrcLine(op);
01340 Set_Trace_File_internal(f);
01341 }
01342
01343 void dump_ops (const OPS *ops)
01344 {
01345 FILE *f;
01346 f = TFile;
01347 Set_Trace_File_internal(stdout);
01348 Print_OPS(ops);
01349 Set_Trace_File_internal(f);
01350 }
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361 BOOL OP_cond_def(const OP *op)
01362 {
01363 return OP_cond_def_kind(op) == OP_ALWAYS_COND_DEF ||
01364 ((OP_cond_def_kind(op) == OP_PREDICATED_DEF) &&
01365 !TN_is_true_pred(OP_opnd(op, OP_PREDICATE_OPND)));
01366 }
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378 BOOL OP_has_implicit_interactions(OP *op)
01379 {
01380 if (OP_volatile(op) || OP_side_effects(op))
01381 return TRUE;
01382
01383 INT i;
01384 for (i = 0; i < OP_opnds(op); i++) {
01385 TN *opnd_tn = OP_opnd(op, i);
01386 if (TN_is_tag(opnd_tn)) return TRUE;
01387 }
01388
01389 return FALSE;
01390 }
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400 void OP_Base_Offset_TNs(OP *memop, TN **base_tn, TN **offset_tn)
01401 {
01402 #ifdef TARG_X8664
01403 Is_True(OP_load(memop) || OP_load_exe(memop) || OP_store(memop), ("not a load or store"));
01404 #else
01405 Is_True(OP_load(memop) || OP_store(memop), ("not a load or store"));
01406 #endif
01407
01408 INT offset_num = OP_find_opnd_use (memop, OU_offset);
01409 INT base_num = OP_find_opnd_use (memop, OU_base);
01410
01411 *offset_tn = NULL;
01412
01413 *base_tn = base_num >= 0 ? OP_opnd(memop, base_num) : NULL;
01414
01415
01416
01417
01418 if (offset_num < 0) {
01419 if( *base_tn ){
01420 DEF_KIND kind;
01421 OP *defop = TN_Reaching_Value_At_Op(*base_tn, memop, &kind, TRUE);
01422 if (defop && OP_iadd(defop) && kind == VAL_KNOWN) {
01423 TN *defop_offset_tn = OP_opnd(defop, 1);
01424 TN *defop_base_tn = OP_opnd(defop, 2);
01425 if (defop_base_tn == *base_tn && TN_has_value(defop_base_tn)) {
01426 *offset_tn = defop_offset_tn;
01427 }
01428 }
01429 }
01430 } else {
01431 *offset_tn = OP_opnd(memop, offset_num);
01432 }
01433 }
01434
01435
01436
01437
01438 BOOL
01439 OP_Is_Copy_To_Save_TN(const OP* op)
01440 {
01441 INT i;
01442
01443 for ( i = OP_results(op) - 1; i >= 0; --i ) {
01444 TN* tn = OP_result(op,i);
01445 if ( TN_is_save_reg(tn)) return TRUE;
01446 }
01447
01448 return FALSE;
01449 }
01450
01451
01452
01453 BOOL
01454 OP_Is_Copy_From_Save_TN( const OP* op )
01455 {
01456 INT i;
01457
01458
01459
01460
01461
01462 for ( i = OP_results(op) - 1; i >= 0; --i ) {
01463 if ( TN_is_dedicated(OP_result(op,i)) ) break;
01464 }
01465 if ( i < 0 ) return FALSE;
01466
01467 for ( i = OP_opnds(op) - 1; i >= 0; --i ) {
01468 TN* tn = OP_opnd(op,i);
01469 if ( TN_Is_Allocatable(tn) && TN_is_save_reg(tn))
01470 return TRUE;
01471 }
01472
01473 return FALSE;
01474 }
01475
01476
01477 #ifdef TARG_IA64
01478
01479
01480
01481
01482
01483
01484
01485 BOOL OP_ld_st_unat(OP *op)
01486 {
01487 mTOP opcode = OP_code(op);
01488 if(opcode == TOP_mov_f_ar || opcode == TOP_mov_t_ar_r ||
01489 opcode == TOP_mov_f_ar_m || opcode == TOP_mov_t_ar_r_m)
01490 {
01491 for(INT i=0; i<OP_results(op); i++)
01492 {
01493 if(OP_result(op,i) ==
01494 Build_Dedicated_TN(ISA_REGISTER_CLASS_application,(REGISTER)(REGISTER_MIN + 36),0))
01495 return TRUE;
01496 }
01497 for(INT i=0;i<OP_opnds(op); i++)
01498 {
01499 if(OP_opnd(op,i) ==
01500 Build_Dedicated_TN(ISA_REGISTER_CLASS_application,(REGISTER)(REGISTER_MIN + 36),0))
01501 return TRUE;
01502 }
01503 }
01504 return FALSE;
01505 }
01506
01507 BOOL OP_def_return_value(OP* op)
01508 {
01509 for (INT i = OP_results(op) - 1 ; i >= 0 ; i--) {
01510 mTN_NUM n = TN_number(OP_result(op,i));
01511 if ((n >= First_Int_Preg_Return_Offset &&
01512 n <= Last_Int_Preg_Return_Offset) ||
01513 (n >= First_Float_Preg_Return_Offset &&
01514 n <= Last_Float_Preg_Return_Offset)) {
01515 return TRUE;
01516 }
01517 }
01518 return FALSE;
01519 }
01520
01521 BOOL OP_use_return_value (OP* op) {
01522 for (INT i = 0; i < OP_opnds (op); i++) {
01523 TN* opnd = OP_opnd(op, i);
01524 if (TN_is_constant(opnd)) { continue; }
01525
01526 mTN_NUM n = TN_number(opnd);
01527 if ((n >= First_Int_Preg_Return_Offset &&
01528 n <= Last_Int_Preg_Return_Offset) ||
01529 (n >= First_Float_Preg_Return_Offset &&
01530 n <= Last_Float_Preg_Return_Offset)) {
01531 return TRUE;
01532 }
01533 }
01534 return FALSE;
01535 }
01536
01537
01538
01539 void
01540 Add_Hidden_Operands (OP* op, const vector<TN*>& hopnds) {
01541 if (hopnds.size () == 0) return;
01542
01543 INT t = CGTARG_Max_Number_of_Hidden_Opnd (OP_code(op));
01544 Is_True (t > 0, ("Op does not have hidden openrands"));
01545 Is_True (hopnds.size() <= t, ("Expected at most %d hidden operands"));
01546 Is_True (OP_hidden_opnds(op) == 0, ("Hidden operands are added once"));
01547
01548
01549 if (OP_results(op) != 0) {
01550 INT32 from_idx = op->opnds+op->results - 1;
01551 INT32 to_idx = from_idx + hopnds.size();
01552 for (INT32 count = OP_results(op); count > 0; count--) {
01553 op->res_opnd[to_idx--] = op->res_opnd[from_idx--];
01554 }
01555 }
01556
01557
01558 for (INT32 i = 0; i < hopnds.size (); ++i) {
01559 op->res_opnd[op->opnds+i] = hopnds[i];
01560 }
01561
01562 op->hidden_opnds = hopnds.size();
01563 op->opnds += hopnds.size ();
01564 }
01565
01566 #endif // TARG_IA64
01567
01568
01569 #ifdef KEY
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579 BOOL
01580 TN_Pair_In_OP(OP* op, struct tn *tn_res, struct tn *tn_opnd)
01581 {
01582 INT i;
01583 for (i = 0; i < OP_results(op); i++) {
01584 if (tn_res == OP_result(op,i)) {
01585 break;
01586 }
01587 }
01588 if (i == OP_results(op)) {
01589 TN_size(tn_res);
01590
01591
01592
01593 BOOL result_match = FALSE;
01594 if (TN_register(tn_res) != REGISTER_UNDEFINED) {
01595 for (int j = 0; j < OP_results(op); j++) {
01596 TN *res = OP_result(op, j);
01597 if (TN_register_and_class(res) == TN_register_and_class(tn_res)) {
01598 result_match = TRUE;
01599 }
01600 }
01601 }
01602 if (!result_match)
01603 return FALSE;
01604 }
01605 for (i = 0; i < OP_opnds(op); i++) {
01606 if (tn_opnd == OP_opnd(op,i)) {
01607 return TRUE;
01608 }
01609 }
01610 return FALSE;
01611 }
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622 INT
01623 TN_Resnum_In_OP (OP* op, struct tn *tn, BOOL match_assigned_reg)
01624 {
01625 for (INT i = 0; i < OP_results(op); i++) {
01626 TN *res = OP_result(op, i);
01627 if (tn == res) {
01628 return i;
01629 }
01630
01631 if (match_assigned_reg &&
01632 TN_register(res) != REGISTER_UNDEFINED &&
01633 TN_register_and_class(res) == TN_register_and_class(tn)) {
01634 return i;
01635 }
01636 }
01637 FmtAssert (FALSE,
01638 ("TN_resnum_in_OP: Could not find <tn> in results list\n"));
01639 return -1;
01640 }
01641 #endif
01642
01643 #if defined(TARG_SL) || defined(TARG_MIPS)
01644 #include "targ_sim.h"
01645 BOOL OP_def_return_value(OP* op)
01646 {
01647 for (INT i = OP_results(op) - 1 ; i >= 0 ; i--) {
01648 mTN_NUM n = TN_number(OP_result(op,i));
01649 if ((n >= First_Int_Preg_Return_Offset &&
01650 n <= Last_Int_Preg_Return_Offset) ||
01651 (n >= First_Float_Preg_Return_Offset &&
01652 n <= Last_Float_Preg_Return_Offset)) {
01653 return TRUE;
01654 }
01655 }
01656 return FALSE;
01657 }
01658
01659 #endif
01660