00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025 #include "system.h"
00026 #include "rtl.h"
00027 #include "regs.h"
00028 #include "hard-reg-set.h"
00029 #include "real.h"
00030 #include "insn-config.h"
00031 #include "conditions.h"
00032 #include "output.h"
00033 #include "insn-attr.h"
00034 #include "flags.h"
00035 #include "recog.h"
00036 #include "obstack.h"
00037 #include "tree.h"
00038 #include "function.h"
00039 #include "expr.h"
00040 #include "toplev.h"
00041 #include "tm_p.h"
00042 #include "target.h"
00043 #include "target-def.h"
00044
00045 #define min(A,B) ((A) < (B) ? (A) : (B))
00046 #define max(A,B) ((A) > (B) ? (A) : (B))
00047
00048 static int unsigned_comparisons_p PARAMS ((rtx));
00049 static void output_loadsave_fpregs PARAMS ((FILE *, enum rtx_code, rtx));
00050 static void output_fpops PARAMS ((FILE *));
00051 static void init_fpops PARAMS ((void));
00052 static int memory_offset_in_range_p PARAMS ((rtx, enum machine_mode, int, int));
00053 static unsigned int hash_rtx PARAMS ((rtx));
00054 static void romp_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
00055 static void romp_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
00056
00057
00058 #undef TARGET_ASM_FUNCTION_PROLOGUE
00059 #define TARGET_ASM_FUNCTION_PROLOGUE romp_output_function_prologue
00060 #undef TARGET_ASM_FUNCTION_EPILOGUE
00061 #define TARGET_ASM_FUNCTION_EPILOGUE romp_output_function_epilogue
00062
00063 struct gcc_target targetm = TARGET_INITIALIZER;
00064
00065
00066
00067
00068
00069
00070 int
00071 next_insn_tests_no_unsigned (insn)
00072 rtx insn;
00073 {
00074 register rtx next = next_cc0_user (insn);
00075
00076 if (next == 0)
00077 {
00078 if (find_reg_note (insn, REG_UNUSED, cc0_rtx))
00079 return 1;
00080 else
00081 abort ();
00082 }
00083
00084 return ((GET_CODE (next) == JUMP_INSN
00085 || GET_CODE (next) == INSN
00086 || GET_CODE (next) == CALL_INSN)
00087 && ! unsigned_comparisons_p (PATTERN (next)));
00088 }
00089
00090 static int
00091 unsigned_comparisons_p (x)
00092 rtx x;
00093 {
00094 register const char *fmt;
00095 register int len, i;
00096 register enum rtx_code code = GET_CODE (x);
00097
00098 switch (code)
00099 {
00100 case REG:
00101 case PC:
00102 case CC0:
00103 case CONST_INT:
00104 case CONST_DOUBLE:
00105 case CONST:
00106 case LABEL_REF:
00107 case SYMBOL_REF:
00108 return 0;
00109
00110 case LTU:
00111 case GTU:
00112 case LEU:
00113 case GEU:
00114 return (XEXP (x, 0) == cc0_rtx || XEXP (x, 1) == cc0_rtx);
00115 default:
00116 break;
00117 }
00118
00119 len = GET_RTX_LENGTH (code);
00120 fmt = GET_RTX_FORMAT (code);
00121
00122 for (i = 0; i < len; i++)
00123 {
00124 if (fmt[i] == 'e')
00125 {
00126 if (unsigned_comparisons_p (XEXP (x, i)))
00127 return 1;
00128 }
00129 else if (fmt[i] == 'E')
00130 {
00131 register int j;
00132 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
00133 if (unsigned_comparisons_p (XVECEXP (x, i, j)))
00134 return 1;
00135 }
00136 }
00137
00138 return 0;
00139 }
00140
00141
00142
00143
00144
00145
00146
00147 void
00148 update_cc (body, insn)
00149 rtx body ATTRIBUTE_UNUSED;
00150 rtx insn;
00151 {
00152 switch (get_attr_cc (insn))
00153 {
00154 case CC_NONE:
00155
00156 break;
00157
00158 case CC_CHANGE0:
00159
00160
00161 if (cc_status.value1 != 0
00162 && reg_overlap_mentioned_p (recog_data.operand[0], cc_status.value1))
00163 cc_status.value1 = 0;
00164
00165 if (cc_status.value2 != 0
00166 && reg_overlap_mentioned_p (recog_data.operand[0], cc_status.value2))
00167 cc_status.value2 = 0;
00168
00169 break;
00170
00171 case CC_COPY1TO0:
00172
00173
00174 if (cc_status.value1 != 0
00175 && reg_overlap_mentioned_p (recog_data.operand[0], cc_status.value1))
00176 cc_status.value1 = 0;
00177
00178 if (cc_status.value2 != 0
00179 && reg_overlap_mentioned_p (recog_data.operand[0], cc_status.value2))
00180 cc_status.value2 = 0;
00181
00182 if (cc_status.value1 != 0
00183 && rtx_equal_p (cc_status.value1, recog_data.operand[1]))
00184 cc_status.value2 = recog_data.operand[0];
00185
00186 if (cc_status.value2 != 0
00187 && rtx_equal_p (cc_status.value2, recog_data.operand[1]))
00188 cc_status.value1 = recog_data.operand[0];
00189
00190 break;
00191
00192 case CC_CLOBBER:
00193
00194 CC_STATUS_INIT;
00195 break;
00196
00197 case CC_SETS:
00198
00199 CC_STATUS_INIT;
00200 cc_status.flags |= CC_NO_OVERFLOW;
00201 cc_status.value1 = recog_data.operand[0];
00202 break;
00203
00204 case CC_COMPARE:
00205
00206
00207 {
00208 register rtx p = PATTERN (insn);
00209
00210 CC_STATUS_INIT;
00211
00212 if (GET_CODE (p) == PARALLEL)
00213 p = XVECEXP (p, 0, 0);
00214 cc_status.value1 = SET_SRC (p);
00215
00216 if (GET_CODE (SET_SRC (p)) == REG)
00217 cc_status.flags |= CC_NO_OVERFLOW;
00218 if (! next_insn_tests_no_unsigned (insn))
00219 cc_status.flags |= CC_UNSIGNED;
00220 }
00221 break;
00222
00223 case CC_TBIT:
00224
00225 CC_STATUS_INIT;
00226 cc_status.flags = CC_IN_TB | CC_NOT_NEGATIVE;
00227 break;
00228
00229 default:
00230 abort ();
00231 }
00232 }
00233
00234
00235
00236
00237
00238 int
00239 restore_compare_p (op)
00240 rtx op;
00241 {
00242 enum rtx_code code = GET_CODE (op);
00243
00244 return (((code == GEU || code == LEU || code == GTU || code == LTU)
00245 && ! (cc_status.flags & CC_UNSIGNED))
00246 || ((code == GE || code == LE || code == GT || code == LT)
00247 && (cc_status.flags & CC_UNSIGNED)));
00248 }
00249
00250
00251
00252
00253 const char *
00254 output_in_line_mul ()
00255 {
00256 static char insns[200];
00257 int i;
00258
00259 strcpy (insns, "s %0,%0\n");
00260 strcat (insns, "\tmts r10,%1\n");
00261 for (i = 0; i < 16; i++)
00262 strcat (insns, "\tm %0,%2\n");
00263 strcat (insns, "\tmfs r10,%0");
00264
00265 return insns;
00266 }
00267
00268
00269
00270
00271
00272 static int
00273 memory_offset_in_range_p (op, mode, low, high)
00274 register rtx op;
00275 enum machine_mode mode;
00276 int low, high;
00277 {
00278 int offset = 0;
00279
00280 if (! memory_operand (op, mode))
00281 return 0;
00282
00283 while (GET_CODE (op) == SUBREG)
00284 {
00285 offset += SUBREG_BYTE (op);
00286 op = SUBREG_REG (op);
00287 }
00288
00289
00290
00291 if (GET_CODE (op) != MEM)
00292 abort ();
00293
00294
00295 mode = GET_MODE (op);
00296 op = XEXP (op, 0);
00297 if (GET_CODE (op) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (op))
00298 offset = get_pool_offset (op) + 12;
00299 else if (GET_CODE (op) == PLUS)
00300 {
00301 if (GET_CODE (XEXP (op, 1)) != CONST_INT
00302 || ! register_operand (XEXP (op, 0), Pmode))
00303 return 0;
00304
00305 offset += INTVAL (XEXP (op, 1));
00306 }
00307
00308 else if (! register_operand (op, Pmode))
00309 return 0;
00310
00311 return (offset >= low && offset <= high
00312 && (offset % GET_MODE_SIZE (mode) == 0));
00313 }
00314
00315
00316
00317
00318 int
00319 zero_memory_operand (op, mode)
00320 rtx op;
00321 enum machine_mode mode;
00322 {
00323 return memory_offset_in_range_p (op, mode, 0, 0);
00324 }
00325
00326
00327
00328 int
00329 short_memory_operand (op, mode)
00330 rtx op;
00331 enum machine_mode mode;
00332 {
00333 if (mode == VOIDmode)
00334 mode = GET_MODE (op);
00335
00336 return memory_offset_in_range_p (op, mode, 0,
00337 15 * min (UNITS_PER_WORD,
00338 GET_MODE_SIZE (mode)));
00339 }
00340
00341
00342
00343
00344 int
00345 symbolic_memory_operand (op, mode)
00346 register rtx op;
00347 enum machine_mode mode;
00348 {
00349 if (! memory_operand (op, mode))
00350 return 0;
00351
00352 while (GET_CODE (op) == SUBREG)
00353 op = SUBREG_REG (op);
00354
00355 if (GET_CODE (op) != MEM)
00356 abort ();
00357
00358 op = XEXP (op, 0);
00359 if (constant_pool_address_operand (op, VOIDmode))
00360 return 0;
00361 else
00362 return romp_symbolic_operand (op, Pmode)
00363 || (GET_CODE (op) == PLUS && register_operand (XEXP (op, 0), Pmode)
00364 && romp_symbolic_operand (XEXP (op, 1), Pmode));
00365 }
00366
00367
00368
00369
00370 int
00371 current_function_operand (op, mode)
00372 rtx op;
00373 enum machine_mode mode ATTRIBUTE_UNUSED;
00374 {
00375 if (GET_CODE (op) != MEM || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
00376 || ! CONSTANT_POOL_ADDRESS_P (XEXP (op, 0)))
00377 return 0;
00378
00379 op = get_pool_constant (XEXP (op, 0));
00380 return (GET_CODE (op) == SYMBOL_REF
00381 && ! strcmp (current_function_name, XSTR (op, 0)));
00382 }
00383
00384
00385
00386 int
00387 null_epilogue ()
00388 {
00389 return (reload_completed
00390 && first_reg_to_save () == 16
00391 && ! romp_pushes_stack ());
00392 }
00393
00394
00395
00396 int
00397 constant_pool_address_operand (op, mode)
00398 rtx op;
00399 enum machine_mode mode ATTRIBUTE_UNUSED;
00400 {
00401 return ((GET_CODE (op) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (op))
00402 || (GET_CODE (op) == CONST && GET_CODE (XEXP (op, 0)) == PLUS
00403 && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT
00404 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
00405 && CONSTANT_POOL_ADDRESS_P (XEXP (XEXP (op, 0), 0))));
00406 }
00407
00408
00409
00410
00411 int
00412 romp_symbolic_operand (op, mode)
00413 register rtx op;
00414 enum machine_mode mode ATTRIBUTE_UNUSED;
00415 {
00416 switch (GET_CODE (op))
00417 {
00418 case SYMBOL_REF:
00419 case LABEL_REF:
00420 return ! op->integrated;
00421
00422 case CONST:
00423 op = XEXP (op, 0);
00424 return (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
00425 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
00426 && GET_CODE (XEXP (op, 1)) == CONST_INT;
00427
00428 default:
00429 return 0;
00430 }
00431 }
00432
00433
00434
00435 int
00436 constant_operand (op, mode)
00437 register rtx op;
00438 enum machine_mode mode;
00439 {
00440 switch (GET_CODE (op))
00441 {
00442 case LABEL_REF:
00443 case SYMBOL_REF:
00444 case PLUS:
00445 case CONST:
00446 return romp_symbolic_operand (op,mode);
00447
00448 case CONST_INT:
00449 return (unsigned int) (INTVAL (op) + 0x8000) < 0x10000
00450 || (INTVAL (op) & 0xffff) == 0 || (INTVAL (op) & 0xffff0000) == 0;
00451
00452 default:
00453 return 0;
00454 }
00455 }
00456
00457
00458
00459
00460
00461 int
00462 reg_or_cint_operand (op, mode)
00463 register rtx op;
00464 enum machine_mode mode;
00465 {
00466 if (GET_CODE (op) == CONST_INT)
00467 return constant_operand (op, mode);
00468
00469 return register_operand (op, mode);
00470 }
00471
00472
00473
00474 int
00475 reg_or_any_cint_operand (op, mode)
00476 register rtx op;
00477 enum machine_mode mode;
00478 {
00479 return GET_CODE (op) == CONST_INT || register_operand (op, mode);
00480 }
00481
00482
00483
00484 int
00485 reg_or_D_operand (op, mode)
00486 register rtx op;
00487 enum machine_mode mode;
00488 {
00489 if (GET_CODE (op) == CONST_INT)
00490 return (unsigned) (INTVAL (op) + 0x8000) < 0x10000;
00491
00492 return register_operand (op, mode);
00493 }
00494
00495
00496
00497
00498 int
00499 reg_or_add_operand (op, mode)
00500 register rtx op;
00501 enum machine_mode mode;
00502 {
00503 return reg_or_D_operand (op, mode) || romp_symbolic_operand (op, mode)
00504 || (GET_CODE (op) == CONST_INT && (INTVAL (op) & 0xffff) == 0);
00505 }
00506
00507
00508
00509
00510 int
00511 reg_or_and_operand (op, mode)
00512 register rtx op;
00513 enum machine_mode mode;
00514 {
00515 if (reg_or_cint_operand (op, mode))
00516 return 1;
00517
00518 if (GET_CODE (op) != CONST_INT)
00519 return 0;
00520
00521 return (INTVAL (op) & 0xffff) == 0xffff
00522 || (INTVAL (op) & 0xffff0000) == 0xffff0000;
00523 }
00524
00525
00526
00527 int
00528 reg_or_mem_operand (op, mode)
00529 register rtx op;
00530 register enum machine_mode mode;
00531 {
00532 return register_operand (op, mode) || memory_operand (op, mode);
00533 }
00534
00535
00536
00537
00538 int
00539 reg_or_nonsymb_mem_operand (op, mode)
00540 register rtx op;
00541 enum machine_mode mode;
00542 {
00543 if (register_operand (op, mode))
00544 return 1;
00545
00546 if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode))
00547 return 1;
00548
00549 return 0;
00550 }
00551
00552
00553
00554
00555 int
00556 romp_operand (op, mode)
00557 register rtx op;
00558 enum machine_mode mode;
00559 {
00560 if (GET_CODE (op) == CONST_INT)
00561 return constant_operand (op, mode);
00562
00563 return general_operand (op, mode);
00564 }
00565
00566
00567
00568 int
00569 reg_0_operand (op, mode)
00570 rtx op;
00571 enum machine_mode mode;
00572 {
00573 return ((mode == VOIDmode || mode == GET_MODE (op))
00574 && GET_CODE (op) == REG && REGNO (op) == 0);
00575 }
00576
00577
00578
00579 int
00580 reg_15_operand (op, mode)
00581 rtx op;
00582 enum machine_mode mode;
00583 {
00584 return ((mode == VOIDmode || mode == GET_MODE (op))
00585 && GET_CODE (op) == REG && REGNO (op) == 15);
00586 }
00587
00588
00589
00590 int
00591 float_binary (op, mode)
00592 register rtx op;
00593 enum machine_mode mode;
00594 {
00595 if (mode != VOIDmode && mode != GET_MODE (op))
00596 return 0;
00597
00598 if (GET_MODE (op) != SFmode && GET_MODE (op) != DFmode)
00599 return 0;
00600
00601 switch (GET_CODE (op))
00602 {
00603 case PLUS:
00604 case MINUS:
00605 case MULT:
00606 case DIV:
00607 return GET_MODE (XEXP (op, 0)) == GET_MODE (op)
00608 && GET_MODE (XEXP (op, 1)) == GET_MODE (op);
00609
00610 default:
00611 return 0;
00612 }
00613 }
00614
00615
00616
00617 int
00618 float_unary (op, mode)
00619 register rtx op;
00620 enum machine_mode mode;
00621 {
00622 if (mode != VOIDmode && mode != GET_MODE (op))
00623 return 0;
00624
00625 if (GET_MODE (op) != SFmode && GET_MODE (op) != DFmode)
00626 return 0;
00627
00628 return (GET_CODE (op) == NEG || GET_CODE (op) == ABS)
00629 && GET_MODE (XEXP (op, 0)) == GET_MODE (op);
00630 }
00631
00632
00633
00634
00635 int
00636 float_conversion (op, mode)
00637 register rtx op;
00638 enum machine_mode mode;
00639 {
00640 if (mode != VOIDmode && mode != GET_MODE (op))
00641 return 0;
00642
00643 switch (GET_CODE (op))
00644 {
00645 case FLOAT_TRUNCATE:
00646 return GET_MODE (op) == SFmode && GET_MODE (XEXP (op, 0)) == DFmode;
00647
00648 case FLOAT_EXTEND:
00649 return GET_MODE (op) == DFmode && GET_MODE (XEXP (op, 0)) == SFmode;
00650
00651 case FLOAT:
00652 return ((GET_MODE (XEXP (op, 0)) == SImode
00653 || GET_CODE (XEXP (op, 0)) == CONST_INT)
00654 && (GET_MODE (op) == SFmode || GET_MODE (op) == DFmode));
00655
00656 case FIX:
00657 return ((GET_MODE (op) == SImode
00658 || GET_CODE (XEXP (op, 0)) == CONST_INT)
00659 && (GET_MODE (XEXP (op, 0)) == SFmode
00660 || GET_MODE (XEXP (op, 0)) == DFmode));
00661
00662 default:
00663 return 0;
00664 }
00665 }
00666
00667
00668
00669 void
00670 print_operand (file, x, code)
00671 FILE *file;
00672 rtx x;
00673 int code;
00674 {
00675 int i;
00676
00677 switch (code)
00678 {
00679 case 'B':
00680
00681 if (GET_CODE (x) != CONST_INT)
00682 output_operand_lossage ("invalid %%B value");
00683
00684 fprintf (file, "%d", INTVAL (x) / 8);
00685 break;
00686
00687 case 'L':
00688
00689 if (GET_CODE (x) != CONST_INT)
00690 output_operand_lossage ("invalid %%L value");
00691
00692 fprintf (file, "%d", INTVAL (x) & 0xffff);
00693 break;
00694
00695 case 's':
00696
00697 if (GET_CODE (x) != CONST_INT)
00698 output_operand_lossage ("invalid %%s value");
00699
00700 if (INTVAL (x) >= 16)
00701 fprintf (file, "16");
00702
00703 break;
00704
00705 case 'S':
00706
00707
00708 if (GET_CODE (x) != CONST_INT)
00709 output_operand_lossage ("invalid %%S value");
00710
00711 fprintf (file, "%d", INTVAL (x) & 15);
00712 break;
00713
00714 case 'b':
00715
00716
00717 if (GET_CODE (x) != CONST_INT)
00718 output_operand_lossage ("invalid %%b value");
00719
00720 if ((i = exact_log2 (INTVAL (x))) >= 0)
00721 fprintf (file, "%d", (31 - i) % 16);
00722 else if ((i = exact_log2 (~ INTVAL (x))) >= 0)
00723 fprintf (file, "%d", (31 - i) % 16);
00724 else
00725 output_operand_lossage ("invalid %%b value");
00726
00727 break;
00728
00729 case 'h':
00730
00731 if (GET_CODE (x) != CONST_INT)
00732 output_operand_lossage ("invalid %%h value");
00733
00734 if ((INTVAL (x) & 0xffff0000) == 0)
00735 fprintf (file, "l");
00736 else if ((INTVAL (x) & 0xffff) == 0)
00737 fprintf (file, "u");
00738 else
00739 output_operand_lossage ("invalid %%h value");
00740
00741 break;
00742
00743 case 'H':
00744
00745 if (GET_CODE (x) != CONST_INT)
00746 output_operand_lossage ("invalid %%H value");
00747
00748 if ((INTVAL (x) & 0xffff0000) == 0)
00749 fprintf (file, "%d", INTVAL (x) & 0xffff);
00750 else if ((INTVAL (x) & 0xffff) == 0)
00751 fprintf (file, "%d", (INTVAL (x) >> 16) & 0xffff);
00752 else
00753 output_operand_lossage ("invalid %%H value");
00754
00755 break;
00756
00757 case 'z':
00758
00759
00760
00761
00762
00763
00764 if (GET_CODE (x) != CONST_INT)
00765 output_operand_lossage ("invalid %%z value");
00766
00767 if ((INTVAL (x) & 0xffff0000) == 0)
00768 fprintf (file, "lz");
00769 else if ((INTVAL (x) & 0xffff0000) == 0xffff0000)
00770 fprintf (file, "lo");
00771 else if ((INTVAL (x) & 0xffff) == 0)
00772 fprintf (file, "uz");
00773 else if ((INTVAL (x) & 0xffff) == 0xffff)
00774 fprintf (file, "uo");
00775 else
00776 output_operand_lossage ("invalid %%z value");
00777
00778 break;
00779
00780 case 'Z':
00781
00782
00783 if (GET_CODE (x) != CONST_INT)
00784 output_operand_lossage ("invalid %%Z value");
00785
00786 if ((INTVAL (x) & 0xffff0000) == 0
00787 || (INTVAL (x) & 0xffff0000) == 0xffff0000)
00788 fprintf (file, "%d", INTVAL (x) & 0xffff);
00789 else if ((INTVAL (x) & 0xffff) == 0 || (INTVAL (x) & 0xffff) == 0xffff)
00790 fprintf (file, "%d", (INTVAL (x) >> 16) & 0xffff);
00791 else
00792 output_operand_lossage ("invalid %%Z value");
00793
00794 break;
00795
00796 case 'k':
00797
00798 if (GET_CODE (x) != CONST_INT)
00799 output_operand_lossage ("invalid %%k value");
00800
00801 if ((INTVAL (x) & 0xffff0000) == 0
00802 || (INTVAL (x) & 0xffff0000) == 0xffff0000)
00803 fprintf (file, "l");
00804 else if ((INTVAL (x) & 0xffff) == 0
00805 || (INTVAL (x) & 0xffff) == 0xffff)
00806 fprintf (file, "u");
00807 else
00808 output_operand_lossage ("invalid %%k value");
00809
00810 break;
00811
00812 case 't':
00813
00814 if (GET_CODE (x) != CONST_INT)
00815 output_operand_lossage ("invalid %%k value");
00816
00817 if (INTVAL (x) < 16)
00818 fprintf (file, "u");
00819 else
00820 fprintf (file, "l");
00821 break;
00822
00823 case 'M':
00824
00825
00826 if (short_memory_operand (x, VOIDmode))
00827 fprintf (file, "s");
00828 break;
00829
00830 case 'N':
00831
00832 if (zero_memory_operand (x, VOIDmode))
00833 fprintf (file, "s");
00834 break;
00835
00836 case 'O':
00837
00838
00839 if (GET_CODE (x) == REG)
00840 fprintf (file, "%s", reg_names[REGNO (x) + 1]);
00841 else if (GET_CODE (x) == MEM)
00842 print_operand (file, gen_rtx_MEM (GET_MODE (x),
00843 plus_constant (XEXP (x, 0), 4)), 0);
00844 else
00845 abort ();
00846 break;
00847
00848 case 'C':
00849
00850 if (! constant_pool_address_operand (x, VOIDmode))
00851 abort ();
00852 if (GET_CODE (x) == SYMBOL_REF)
00853 fprintf (file, "%d", get_pool_offset (x) + 12);
00854 else
00855
00856 fprintf (file, "%d",
00857 (get_pool_offset (XEXP (XEXP (x, 0), 0)) + 12
00858 + INTVAL (XEXP (XEXP (x, 0), 1))));
00859 break;
00860
00861 case 'j':
00862
00863 switch (GET_CODE (x))
00864 {
00865 case EQ:
00866 if (cc_status.flags & CC_IN_TB)
00867 fprintf (file, "ntb");
00868 else
00869 fprintf (file, "eq");
00870 break;
00871
00872 case NE:
00873 if (cc_status.flags & CC_IN_TB)
00874 fprintf (file, "tb");
00875 else
00876 fprintf (file, "ne");
00877 break;
00878
00879 case GT:
00880 case GTU:
00881 fprintf (file, "h");
00882 break;
00883
00884 case LT:
00885 case LTU:
00886 fprintf (file, "l");
00887 break;
00888
00889 case GE:
00890 case GEU:
00891 fprintf (file, "he");
00892 break;
00893
00894 case LE:
00895 case LEU:
00896 fprintf (file, "le");
00897 break;
00898
00899 default:
00900 output_operand_lossage ("invalid %%j value");
00901 }
00902 break;
00903
00904 case 'J':
00905
00906 switch (GET_CODE (x))
00907 {
00908 case EQ:
00909 if (cc_status.flags & CC_IN_TB)
00910 fprintf (file, "tb");
00911 else
00912 fprintf (file, "ne");
00913 break;
00914
00915 case NE:
00916 if (cc_status.flags & CC_IN_TB)
00917 fprintf (file, "ntb");
00918 else
00919 fprintf (file, "eq");
00920 break;
00921
00922 case GT:
00923 case GTU:
00924 fprintf (file, "le");
00925 break;
00926
00927 case LT:
00928 case LTU:
00929 fprintf (file, "he");
00930 break;
00931
00932 case GE:
00933 case GEU:
00934 fprintf (file, "l");
00935 break;
00936
00937 case LE:
00938 case LEU:
00939 fprintf (file, "h");
00940 break;
00941
00942 default:
00943 output_operand_lossage ("invalid %%j value");
00944 }
00945 break;
00946
00947 case '.':
00948
00949 break;
00950
00951 case '#':
00952
00953 if (dbr_sequence_length ())
00954 fprintf (file, "x");
00955 break;
00956
00957 case 0:
00958 if (GET_CODE (x) == REG)
00959 fprintf (file, "%s", reg_names[REGNO (x)]);
00960 else if (GET_CODE (x) == MEM)
00961 {
00962 if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
00963 && current_function_operand (x, Pmode))
00964 fprintf (file, "r14");
00965 else
00966 output_address (XEXP (x, 0));
00967 }
00968 else
00969 output_addr_const (file, x);
00970 break;
00971
00972 default:
00973 output_operand_lossage ("invalid %%xn code");
00974 }
00975 }
00976
00977
00978
00979
00980
00981
00982 int
00983 first_reg_to_save()
00984 {
00985 int first_reg;
00986
00987
00988 for (first_reg = 6; first_reg <= 15; first_reg++)
00989 if (regs_ever_live[first_reg])
00990 break;
00991
00992
00993
00994 if (first_reg > 14 && romp_using_r14 ())
00995 first_reg = 14;
00996
00997 return first_reg;
00998 }
00999
01000
01001
01002
01003 int
01004 romp_sa_size ()
01005 {
01006 int size;
01007 int i;
01008
01009
01010
01011
01012 size = 4 + 4 + 1 + (16 - first_reg_to_save ());
01013
01014
01015
01016
01017 for (i = 2 + (TARGET_FP_REGS != 0); i <= 7; i++)
01018 if (regs_ever_live[i + 17])
01019 {
01020 size += 18;
01021 break;
01022 }
01023
01024 return size * 4;
01025 }
01026
01027
01028
01029
01030 int
01031 romp_makes_calls ()
01032 {
01033 rtx insn;
01034
01035 for (insn = get_insns (); insn; insn = next_insn (insn))
01036 {
01037 if (GET_CODE (insn) == CALL_INSN)
01038 return 1;
01039 else if (GET_CODE (insn) == INSN)
01040 {
01041 rtx body = PATTERN (insn);
01042
01043 if (GET_CODE (body) != USE && GET_CODE (body) != CLOBBER
01044 && GET_CODE (body) != ADDR_VEC
01045 && GET_CODE (body) != ADDR_DIFF_VEC
01046 && get_attr_type (insn) == TYPE_FP)
01047 return 1;
01048 }
01049 }
01050
01051 return 0;
01052 }
01053
01054
01055
01056
01057 int
01058 romp_using_r14 ()
01059 {
01060
01061
01062 return (write_symbols != NO_DEBUG || current_function_profile
01063 || get_pool_size () != 0 || romp_makes_calls ());
01064 }
01065
01066
01067
01068 int
01069 romp_pushes_stack ()
01070 {
01071
01072
01073
01074
01075 return (frame_pointer_needed || write_symbols != NO_DEBUG
01076 || (romp_sa_size () + get_frame_size ()) > 100
01077 || romp_makes_calls ());
01078 }
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088 static void
01089 romp_output_function_prologue (file, size)
01090 FILE *file;
01091 HOST_WIDE_INT size;
01092 {
01093 int first_reg;
01094 int reg_save_offset;
01095 HOST_WIDE_INT fp_save = size + current_function_outgoing_args_size;
01096
01097 init_fpops ();
01098
01099
01100 size += romp_sa_size () + current_function_outgoing_args_size;
01101
01102
01103
01104 first_reg = first_reg_to_save();
01105 reg_save_offset = - (4 + 4 + 1 + (16 - first_reg)) * 4;
01106 if (first_reg == 15)
01107 fprintf (file, "\tst r15,%d(r1)\n", reg_save_offset);
01108 else if (first_reg < 16)
01109 fprintf (file, "\tstm r%d,%d(r1)\n", first_reg, reg_save_offset);
01110
01111
01112 if (romp_using_r14 ())
01113 fprintf (file, "\tcas r14,r0,r0\n");
01114
01115
01116 if (frame_pointer_needed)
01117 fprintf (file, "\tcal r13,-%d(r1)\n", romp_sa_size () + 64);
01118
01119
01120 if (romp_pushes_stack ())
01121 {
01122 if (size >= 32768)
01123 {
01124 if (size >= 65536)
01125 {
01126 fprintf (file, "\tcau r0,%d(r0)\n", size >> 16);
01127 fprintf (file, "\toil r0,r0,%d\n", size & 0xffff);
01128 }
01129 else
01130 fprintf (file, "\tcal16 r0,%d(r0)\n", size);
01131 fprintf (file, "\ts r1,r0\n");
01132 }
01133 else
01134 fprintf (file, "\tcal r1,-%d(r1)\n", size);
01135 }
01136
01137
01138 output_loadsave_fpregs (file, USE,
01139 plus_constant (stack_pointer_rtx, fp_save));
01140 }
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167 void
01168 output_encoded_offset (file, reg_offset)
01169 FILE *file;
01170 unsigned reg_offset;
01171 {
01172
01173 reg_offset = (reg_offset + 3) / 4;
01174
01175
01176 if (reg_offset < (1 << 6))
01177
01178 fprintf (file, "\t.byte %d\n", reg_offset);
01179 else if (reg_offset < (1 << (6 + 8)))
01180
01181 fprintf (file, "\t.short %d\n", (1 << (6 + 8)) + reg_offset);
01182 else if (reg_offset < (1 << (6 + 8 + 8)))
01183 {
01184
01185 fprintf (file, "\t.byte %d\n", (2 << 6) + (reg_offset >> ( 6+ 8)));
01186 fprintf (file, "\t.short %d\n", reg_offset % (1 << (6 + 8)));
01187 }
01188 else
01189 {
01190
01191 fprintf (file, "\t.short %d", (3 << (6 + 8)) + (reg_offset >> (6 + 8)));
01192 fprintf (file, "\t.short %d\n", reg_offset % (1 << (6 + 8)));
01193 }
01194 }
01195
01196
01197
01198 static void
01199 romp_output_function_epilogue (file, size)
01200 FILE *file;
01201 HOST_WIDE_INT size;
01202 {
01203 int first_reg = first_reg_to_save();
01204 int pushes_stack = romp_pushes_stack ();
01205 int reg_save_offset = - ((16 - first_reg) + 1 + 4 + 4) * 4;
01206 HOST_WIDE_INT total_size = (size + romp_sa_size ()
01207 + current_function_outgoing_args_size);
01208 HOST_WIDE_INT fp_save = size + current_function_outgoing_args_size;
01209 int long_frame = total_size >= 32768;
01210 rtx insn = get_last_insn ();
01211 int write_code = 1;
01212
01213 int nargs = 0;
01214 tree argptr;
01215
01216
01217
01218
01219
01220 for (argptr = DECL_ARGUMENTS (current_function_decl);
01221 argptr; argptr = TREE_CHAIN (argptr))
01222 {
01223 int this_size = int_size_in_bytes (TREE_TYPE (argptr));
01224
01225 if (this_size > 0)
01226 nargs += (this_size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
01227 }
01228
01229
01230
01231 if (GET_CODE (insn) == NOTE)
01232 insn = prev_nonnote_insn (insn);
01233 if (insn && GET_CODE (insn) == BARRIER)
01234 write_code = 0;
01235
01236
01237 if (write_code)
01238 output_loadsave_fpregs (file, CLOBBER,
01239 plus_constant (gen_rtx_REG (Pmode, 1), fp_save));
01240
01241
01242
01243
01244 if (pushes_stack && ! long_frame)
01245 reg_save_offset += total_size;
01246 else if (long_frame && write_code)
01247 fprintf (file, "\tcal r1,%d(r13)\n", romp_sa_size () + 64);
01248
01249
01250 if (first_reg == 15 && write_code)
01251 fprintf (file, "\tl r15,%d(r1)\n", reg_save_offset);
01252 else if (first_reg < 16 && write_code)
01253 fprintf (file, "\tlm r%d,%d(r1)\n", first_reg, reg_save_offset);
01254 if (first_reg == 16) first_reg = 0;
01255
01256
01257 if (pushes_stack)
01258 {
01259 if (write_code)
01260 {
01261 if (long_frame)
01262 fprintf (file, "\tbr r15\n");
01263 else
01264 fprintf (file, "\tbrx r15\n\tcal r1,%d(r1)\n", total_size);
01265 }
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283 fprintf (file, "\t.long 0x%x\n", 0xdf07df08 + first_reg * 0x10);
01284
01285 if (nargs > 15) nargs = 15;
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296 fprintf (file, "\t.byte 0x%x1\n", nargs);
01297 output_encoded_offset (file, total_size);
01298 }
01299 else
01300 {
01301 if (write_code)
01302 fprintf (file, "\tbr r15\n");
01303
01304
01305
01306
01307
01308
01309
01310
01311 fprintf (file, "\t.long 0xdf02df00\n");
01312 }
01313
01314
01315 output_fpops (file);
01316 }
01317
01318
01319
01320
01321
01322 struct symref_hashent {
01323 rtx symref;
01324 struct symref_hashent *next;
01325 };
01326
01327 #define SYMHASHSIZE 151
01328 #define HASHBITS 65535
01329
01330
01331
01332 static struct symref_hashent *symref_hash_table[SYMHASHSIZE];
01333
01334
01335
01336
01337 rtx
01338 get_symref (name)
01339 register const char *name;
01340 {
01341 extern struct obstack permanent_obstack;
01342 register const char *sp = name;
01343 unsigned int hash = 0;
01344 struct symref_hashent *p, **last_p;
01345
01346
01347 while (*sp)
01348 hash = (hash << 4) + *sp++;
01349
01350
01351
01352 hash = (hash & HASHBITS) % SYMHASHSIZE;
01353 for (last_p = &symref_hash_table[hash], p = *last_p;
01354 p; last_p = &p->next, p = *last_p)
01355 if (strcmp (name, XSTR (p->symref, 0)) == 0)
01356 break;
01357
01358
01359 if (p == 0)
01360 {
01361
01362 p = *last_p = (struct symref_hashent *)
01363 permalloc (sizeof (struct symref_hashent));
01364 p->symref = gen_rtx_SYMBOL_REF (Pmode,
01365 obstack_copy0 (&permanent_obstack,
01366 name, strlen (name)));
01367 p->next = 0;
01368 }
01369
01370 return p->symref;
01371 }
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388 int
01389 check_precision (opmode, op1, op2)
01390 enum machine_mode opmode;
01391 rtx op1, op2;
01392 {
01393 if (opmode == SFmode)
01394 return 1;
01395
01396
01397
01398 if (GET_CODE (op1) != FLOAT && GET_CODE (op1) != FLOAT_EXTEND)
01399 return 1;
01400
01401 if (op2 && GET_CODE (op2) != FLOAT && GET_CODE (op2) != FLOAT_EXTEND)
01402 return 1;
01403
01404 return 0;
01405 }
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415 struct fp_op {
01416 struct fp_op *next_same_hash;
01417 struct fp_op *next_in_mem;
01418 int mem_offset;
01419 short size;
01420 short noperands;
01421 rtx ops[3];
01422 enum rtx_code opcode;
01423 };
01424
01425
01426 #define FP_HASH_SIZE 101
01427
01428
01429 static struct fp_op *fp_hash_table[FP_HASH_SIZE];
01430
01431
01432 static struct fp_op *first_fpop;
01433
01434
01435 static struct fp_op *last_fpop_in_mem;
01436
01437
01438 static int subr_number = 0;
01439
01440
01441 int data_offset;
01442
01443
01444
01445 static unsigned int
01446 hash_rtx (x)
01447 register rtx x;
01448 {
01449 register unsigned int hash = (((int) GET_CODE (x) << 10)
01450 + ((int) GET_MODE (x) << 20));
01451 register int i;
01452 register const char *fmt = GET_RTX_FORMAT (GET_CODE (x));
01453
01454 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (x)); i++)
01455 if (fmt[i] == 'e')
01456 hash += hash_rtx (XEXP (x, i));
01457 else if (fmt[i] == 'u')
01458 hash += (unsigned HOST_WIDE_INT) XEXP (x, i);
01459 else if (fmt[i] == 'i')
01460 hash += XINT (x, i);
01461 else if (fmt[i] == 's')
01462 hash += (unsigned HOST_WIDE_INT) XSTR (x, i);
01463
01464 return hash;
01465 }
01466
01467
01468
01469
01470
01471
01472
01473
01474 const char *
01475 output_fpop (code, op0, op1, op2, insn)
01476 enum rtx_code code;
01477 rtx op0, op1, op2;
01478 rtx insn ATTRIBUTE_UNUSED;
01479 {
01480 static char outbuf[40];
01481 unsigned int hash, hash0, hash1, hash2;
01482 int size, i;
01483 register struct fp_op *fpop, *last_fpop;
01484 int dyadic = (op2 != 0);
01485 enum machine_mode opmode;
01486 int noperands;
01487 rtx tem;
01488 unsigned int tem_hash;
01489 int fr0_avail = 0;
01490
01491
01492
01493
01494 hash0 = op0 ? hash_rtx (op0) : 0;
01495 hash1 = op1 ? hash_rtx (op1) : 0;
01496 hash2 = op2 ? hash_rtx (op2) : 0;
01497
01498 if (hash0 > hash1 && code == EQ)
01499 {
01500 tem = op0; op0 = op1; op1 = tem;
01501 tem_hash = hash0; hash0 = hash1; hash1 = tem_hash;
01502 }
01503 else if (hash1 > hash2 && (code == PLUS || code == MULT))
01504 {
01505 tem = op1; op1 = op2; op2 = tem;
01506 tem_hash = hash1; hash1 = hash2; hash2 = tem_hash;
01507 }
01508
01509
01510
01511
01512 if (op2 && (code == PLUS || code == MULT)
01513 && (rtx_equal_p (op0, op2)
01514 || (GET_CODE (op0) == REG && GET_CODE (op2) == REG
01515 && REGNO (op0) == REGNO (op2))))
01516 {
01517 tem = op1; op1 = op2; op2 = tem;
01518 tem_hash = hash1; hash1 = hash2; hash2 = tem_hash;
01519 }
01520
01521
01522
01523
01524 if (op1 && rtx_equal_p (op0, op1)
01525 && code != EQ && code != GE && code != SET
01526 && ((GET_MODE (op1) != SFmode && GET_MODE (op1) != SImode)
01527 || GET_CODE (op0) != REG || FP_REGNO_P (REGNO (op0))))
01528 {
01529 op1 = op2;
01530 op2 = 0;
01531 }
01532
01533 noperands = 1 + (op1 != 0) + (op2 != 0);
01534
01535
01536
01537 hash = ((int) code << 13) + (hash0 << 2) + (hash1 << 1) + hash2;
01538
01539 hash %= FP_HASH_SIZE;
01540 for (fpop = fp_hash_table[hash], last_fpop = 0;
01541 fpop;
01542 last_fpop = fpop, fpop = fpop->next_same_hash)
01543 if (fpop->opcode == code && noperands == fpop->noperands
01544 && (op0 == 0 || rtx_equal_p (op0, fpop->ops[0]))
01545 && (op1 == 0 || rtx_equal_p (op1, fpop->ops[1]))
01546 && (op2 == 0 || rtx_equal_p (op2, fpop->ops[2])))
01547 goto win;
01548
01549
01550 fpop = (struct fp_op *) xmalloc (sizeof (struct fp_op));
01551 fpop->mem_offset = data_offset;
01552 fpop->opcode = code;
01553 fpop->noperands = noperands;
01554 fpop->ops[0] = op0;
01555 fpop->ops[1] = op1;
01556 fpop->ops[2] = op2;
01557
01558
01559
01560
01561
01562
01563 size = 24;
01564 if (op0 && (GET_CODE (op0) != REG
01565 || ! FP_REGNO_P (REGNO (op0)) || REGNO (op0) == 23))
01566 size += 32;
01567
01568 if (op1 && (GET_CODE (op1) != REG
01569 || ! FP_REGNO_P (REGNO (op1)) || REGNO (op1) == 23))
01570 size += 32;
01571
01572 if (op2 && (GET_CODE (op2) != REG
01573 || ! FP_REGNO_P (REGNO (op2)) || REGNO (op2) == 23))
01574 size += 32;
01575
01576
01577 if ((op0 && GET_MODE (op0) == DFmode)
01578 || (op1 && GET_MODE (op1) == DFmode)
01579 || (op2 && GET_MODE (op2) == DFmode))
01580 opmode = DFmode;
01581 else
01582 opmode = SFmode;
01583
01584 if (op0 && GET_MODE (op0) != opmode)
01585 size += 12;
01586 if (op1 && GET_MODE (op1) != opmode)
01587 size += 12;
01588 if (op2 && GET_MODE (op2) != opmode)
01589 size += 12;
01590
01591
01592 if (op2 && GET_MODE (op0) != GET_MODE (op2))
01593 size += 12;
01594
01595
01596 if (code == EQ)
01597 size += 32;
01598 else if (code == GE)
01599 size += 64;
01600 else if (code == USE || code == CLOBBER)
01601 {
01602
01603
01604
01605 size = 36 - 24;
01606 for (i = 0; i <= 7; i++)
01607 if (INTVAL (op0) & (1 << (7-i)))
01608 size += 24 + 8 * (i == 7);
01609 }
01610
01611
01612 size +=16;
01613
01614
01615
01616
01617
01618 i = 0;
01619 if (op0 && GET_CODE (op0) == REG && FP_REGNO_P (REGNO (op0)))
01620 i++;
01621 if (op1 && GET_CODE (op1) == REG && FP_REGNO_P (REGNO (op1)))
01622 i++;
01623 if (op2 && GET_CODE (op2) == REG && FP_REGNO_P (REGNO (op2)))
01624 i++;
01625
01626 if ((op0 == 0 || GET_CODE (op0) != REG || REGNO(op0) != 17)
01627 && (op1 == 0 || GET_CODE (op1) != REG || REGNO(op1) != 17)
01628 && (op2 == 0 || GET_CODE (op2) != REG || REGNO(op2) != 17))
01629 fr0_avail = 1;
01630
01631 if (dyadic)
01632 {
01633 if (i == 0)
01634 size += fr0_avail ? 64 : 112;
01635 else if (fpop->noperands == 2 && i == 1)
01636 size += fr0_avail ? 0 : 64;
01637 else if (fpop->noperands == 3)
01638 {
01639 if (GET_CODE (op0) == REG && FP_REGNO_P (REGNO (op0))
01640 && GET_CODE (op2) == REG && FP_REGNO_P (REGNO (op2)))
01641 {
01642 if (REGNO (op0) == REGNO (op2))
01643 #if 1
01644
01645 abort ();
01646 #else
01647 size += fr0_avail ? 0 : 64;
01648 #endif
01649 }
01650 else
01651 {
01652 i = 0;
01653 if (GET_CODE (op0) == REG && FP_REGNO_P (REGNO (op0)))
01654 i++;
01655 if (GET_CODE (op2) == REG && FP_REGNO_P (REGNO (op2)))
01656 i++;
01657 if (i == 0)
01658 size += fr0_avail ? 64 : 112;
01659 else if (i == 1)
01660 size += fr0_avail ? 0 : 64;
01661 }
01662 }
01663 }
01664 else if (code != USE && code != CLOBBER
01665 && (GET_CODE (op0) != REG || ! FP_REGNO_P (REGNO (op0))))
01666 size += 64;
01667
01668 if (! TARGET_FULL_FP_BLOCKS)
01669 {
01670
01671 size = 12;
01672 if (code == USE || code == CLOBBER)
01673 size += 2;
01674 else
01675 {
01676 if (op0) size += 2;
01677 if (op1) size += 2;
01678 if (op2) size += 2;
01679 }
01680
01681
01682 if (size % UNITS_PER_WORD)
01683 size += 2;
01684
01685
01686 if (code != USE && code != CLOBBER && op0 && GET_CODE (op0) != REG)
01687 size += 4;
01688 if (op1 && GET_CODE (op1) != REG)
01689 size += 4;
01690 if (op2 && GET_CODE (op2) != REG)
01691 size += 4;
01692
01693 if (code != USE && code != CLOBBER &&
01694 op0 && GET_CODE (op0) == CONST_DOUBLE && GET_MODE (op0) == DFmode)
01695 size += 4;
01696 if (op1 && GET_CODE (op1) == CONST_DOUBLE && GET_MODE (op1) == DFmode)
01697 size += 4;
01698 if (op2 && GET_CODE (op2) == CONST_DOUBLE && GET_MODE (op2) == DFmode)
01699 size += 4;
01700 }
01701
01702
01703 fpop->size = size;
01704 data_offset += size / UNITS_PER_WORD;
01705 fpop->next_in_mem = 0;
01706 fpop->next_same_hash = 0;
01707
01708 if (last_fpop_in_mem)
01709 last_fpop_in_mem->next_in_mem = fpop;
01710 else
01711 first_fpop = fpop;
01712 last_fpop_in_mem = fpop;
01713
01714 if (last_fpop)
01715 last_fpop->next_same_hash = fpop;
01716 else
01717 fp_hash_table[hash] = fpop;
01718
01719 win:
01720
01721
01722 if (fpop->mem_offset < 32768 / UNITS_PER_WORD)
01723 sprintf (outbuf, "cal r15,%d(r14)\n\tbalr%s r15,r15",
01724 fpop->mem_offset * UNITS_PER_WORD,
01725 dbr_sequence_length () ? "x" : "");
01726 else
01727 sprintf (outbuf, "get r15,$L%dF%d\n\tbalr%s r15,r15",
01728 subr_number, fpop->mem_offset * UNITS_PER_WORD,
01729 dbr_sequence_length () ? "x" : "");
01730 return outbuf;
01731 }
01732
01733
01734
01735
01736
01737
01738
01739 static void
01740 output_loadsave_fpregs (file, code, addr)
01741 FILE *file;
01742 enum rtx_code code;
01743 rtx addr;
01744 {
01745 register int i;
01746 register int mask = 0;
01747
01748 for (i = 2 + (TARGET_FP_REGS != 0); i <= 7; i++)
01749 if (regs_ever_live[i + 17])
01750 mask |= 1 << (7 - i);
01751
01752 if (mask)
01753 fprintf (file, "\t%s\n",
01754 output_fpop (code, GEN_INT (mask), gen_rtx_MEM (Pmode, addr),
01755 0, const0_rtx));
01756
01757 }
01758
01759
01760
01761 static void
01762 output_fpops (file)
01763 FILE *file;
01764 {
01765 register struct fp_op *fpop;
01766 register int size_so_far;
01767 register int i;
01768 rtx immed[3];
01769
01770 if (first_fpop == 0)
01771 return;
01772
01773 data_section ();
01774
01775 ASM_OUTPUT_ALIGN (file, 2);
01776
01777 for (fpop = first_fpop; fpop; fpop = fpop->next_in_mem)
01778 {
01779 if (fpop->mem_offset < 32768 / UNITS_PER_WORD)
01780 fprintf (file, "# data area offset = %d\n",
01781 fpop->mem_offset * UNITS_PER_WORD);
01782 else
01783 fprintf (file, "L%dF%d:\n",
01784 subr_number, fpop->mem_offset * UNITS_PER_WORD);
01785
01786 fprintf (file, "\tcas r0,r15,r0\n");
01787 fprintf (file, "\t.long FPGLUE\n");
01788 switch (fpop->opcode)
01789 {
01790 case USE:
01791 fprintf (file, "\t.byte 0x1d\t# STOREM\n");
01792 break;
01793 case CLOBBER:
01794 fprintf (file, "\t.byte 0x0f\t# LOADM\n");
01795 break;
01796 case ABS:
01797 fprintf (file, "\t.byte 0x00\t# ABS\n");
01798 break;
01799 case PLUS:
01800 fprintf (file, "\t.byte 0x02\t# ADD\n");
01801 break;
01802 case EQ:
01803 fprintf (file, "\t.byte 0x07\t# CMP\n");
01804 break;
01805 case GE:
01806 fprintf (file, "\t.byte 0x08\t# CMPT\n");
01807 break;
01808 case DIV:
01809 fprintf (file, "\t.byte 0x0c\t# DIV\n");
01810 break;
01811 case SET:
01812 fprintf (file, "\t.byte 0x14\t# MOVE\n");
01813 break;
01814 case MULT:
01815 fprintf (file, "\t.byte 0x15\t# MUL\n");
01816 break;
01817 case NEG:
01818 fprintf (file, "\t.byte 0x16\t# NEG\n");
01819 break;
01820 case SQRT:
01821 fprintf (file, "\t.byte 0x1c\t# SQRT\n");
01822 break;
01823 case MINUS:
01824 fprintf (file, "\t.byte 0x1e\t# SUB\n");
01825 break;
01826 default:
01827 abort ();
01828 }
01829
01830 fprintf (file, "\t.byte %d\n", fpop->noperands);
01831 fprintf (file, "\t.short 0x8001\n");
01832
01833 if ((fpop->ops[0] == 0
01834 || GET_CODE (fpop->ops[0]) != REG || REGNO(fpop->ops[0]) != 17)
01835 && (fpop->ops[1] == 0 || GET_CODE (fpop->ops[1]) != REG
01836 || REGNO(fpop->ops[1]) != 17)
01837 && (fpop->ops[2] == 0 || GET_CODE (fpop->ops[2]) != REG
01838 || REGNO(fpop->ops[2]) != 17))
01839 fprintf (file, "\t.byte %d, 0x80\n", fpop->size);
01840 else
01841 fprintf (file, "\t.byte %d, 0\n", fpop->size);
01842 size_so_far = 12;
01843 for (i = 0; i < fpop->noperands; i++)
01844 {
01845 register int type;
01846 register int opbyte;
01847 register const char *desc0;
01848 char desc1[50];
01849
01850 immed[i] = 0;
01851 switch (GET_MODE (fpop->ops[i]))
01852 {
01853 case SImode:
01854 case VOIDmode:
01855 desc0 = "int";
01856 type = 0;
01857 break;
01858 case SFmode:
01859 desc0 = "float";
01860 type = 2;
01861 break;
01862 case DFmode:
01863 desc0 = "double";
01864 type = 3;
01865 break;
01866 default:
01867 abort ();
01868 }
01869
01870 switch (GET_CODE (fpop->ops[i]))
01871 {
01872 case REG:
01873 strcpy(desc1, reg_names[REGNO (fpop->ops[i])]);
01874 if (FP_REGNO_P (REGNO (fpop->ops[i])))
01875 {
01876 type += 0x10;
01877 opbyte = REGNO (fpop->ops[i]) - 17;
01878 }
01879 else
01880 {
01881 type += 0x00;
01882 opbyte = REGNO (fpop->ops[i]);
01883 if (type == 3)
01884 opbyte = (opbyte << 4) + opbyte + 1;
01885 }
01886 break;
01887
01888 case MEM:
01889 type += 0x30;
01890 if (GET_CODE (XEXP (fpop->ops[i], 0)) == PLUS)
01891 {
01892 immed[i] = XEXP (XEXP (fpop->ops[i], 0), 1);
01893 opbyte = REGNO (XEXP (XEXP (fpop->ops[i], 0), 0));
01894 if (GET_CODE (immed[i]) == CONST_INT)
01895 sprintf (desc1, "%d(%s)", INTVAL (immed[i]),
01896 reg_names[opbyte]);
01897 else
01898 sprintf (desc1, "<memory> (%s)", reg_names[opbyte]);
01899 }
01900 else if (GET_CODE (XEXP (fpop->ops[i], 0)) == REG)
01901 {
01902 opbyte = REGNO (XEXP (fpop->ops[i], 0));
01903 immed[i] = const0_rtx;
01904 sprintf (desc1, "(%s)", reg_names[opbyte]);
01905 }
01906 else
01907 {
01908 immed[i] = XEXP (fpop->ops[i], 0);
01909 opbyte = 0;
01910 sprintf(desc1, "<memory>");
01911 }
01912 break;
01913
01914 case CONST_INT:
01915 case CONST_DOUBLE:
01916 case CONST:
01917 case SYMBOL_REF:
01918 case LABEL_REF:
01919 type += 0x20;
01920 opbyte = 0;
01921 immed[i] = fpop->ops[i];
01922 desc1[0] = '$';
01923 desc1[1] = '\0';
01924 break;
01925
01926 default:
01927 abort ();
01928 }
01929
01930
01931 if (i == 0 && (fpop->opcode == USE || fpop->opcode == CLOBBER))
01932 type = 0xff, opbyte = INTVAL (fpop->ops[0]), immed[i] = 0;
01933
01934 fprintf (file, "\t.byte 0x%x,0x%x # (%s) %s\n",
01935 type, opbyte, desc0, desc1);
01936
01937 size_so_far += 2;
01938 }
01939
01940
01941 if (size_so_far % UNITS_PER_WORD)
01942 {
01943 fprintf (file, "\t.space 2\n");
01944 size_so_far += 2;
01945 }
01946
01947 for (i = 0; i < fpop->noperands; i++)
01948 if (immed[i])
01949 switch (GET_MODE (immed[i]))
01950 {
01951 case SImode:
01952 case VOIDmode:
01953 size_so_far += 4;
01954 fprintf (file, "\t.long ");
01955 output_addr_const (file, immed[i]);
01956 fprintf (file, "\n");
01957 break;
01958
01959 case DFmode:
01960 size_so_far += 4;
01961 case SFmode:
01962 size_so_far += 4;
01963 if (GET_CODE (immed[i]) == CONST_DOUBLE)
01964 {
01965 union real_extract u;
01966
01967 memcpy (&u, &CONST_DOUBLE_LOW (immed[i]), sizeof u);
01968 assemble_real (u.d, GET_MODE (immed[i]),
01969 GET_MODE_ALIGNMENT (GET_MODE (immed[i])));
01970 }
01971 else
01972 abort ();
01973 break;
01974
01975 default:
01976 abort ();
01977 }
01978
01979 if (size_so_far != fpop->size)
01980 {
01981 if (TARGET_FULL_FP_BLOCKS)
01982 fprintf (file, "\t.space %d\n", fpop->size - size_so_far);
01983 else
01984 abort ();
01985 }
01986 }
01987
01988
01989 subr_number++;
01990 text_section ();
01991 }
01992
01993
01994
01995 static void
01996 init_fpops()
01997 {
01998 register int i;
01999
02000 first_fpop = last_fpop_in_mem = 0;
02001 for (i = 0; i < FP_HASH_SIZE; i++)
02002 fp_hash_table[i] = 0;
02003 }
02004
02005
02006
02007
02008
02009
02010 int
02011 romp_debugger_auto_correction(offset)
02012 int offset;
02013 {
02014 int fp_to_sp;
02015
02016
02017
02018
02019 INITIAL_ELIMINATION_OFFSET (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM,
02020 fp_to_sp);
02021
02022
02023
02024
02025
02026 return -(offset+fp_to_sp+4);
02027 }
02028
02029
02030
02031
02032
02033 int
02034 romp_debugger_arg_correction (offset)
02035 int offset;
02036 {
02037 int fp_to_argp;
02038
02039 INITIAL_ELIMINATION_OFFSET (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM,
02040 fp_to_argp);
02041
02042
02043
02044
02045 return (offset - fp_to_argp);
02046 }
02047
02048 void
02049 romp_initialize_trampoline (tramp, fnaddr, cxt)
02050 rtx tramp, fnaddr, cxt;
02051 {
02052 rtx addr, temp, val;
02053
02054 temp = expand_simple_binop (SImode, PLUS, tramp, GEN_INT (4),
02055 0, 1, OPTAB_LIB_WIDEN);
02056 emit_move_insn (gen_rtx_MEM (SImode, memory_address (SImode, tramp)), temp);
02057
02058 val = force_reg (SImode, cxt);
02059 addr = memory_address (HImode, plus_constant (tramp, 10));
02060 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, val));
02061 temp = expand_shift (RSHIFT_EXPR, SImode, val, build_int_2 (16, 0), 0, 1);
02062 addr = memory_address (HImode, plus_constant (tramp, 6));
02063 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, temp));
02064
02065 val = force_reg (SImode, fnaddr);
02066 addr = memory_address (HImode, plus_constant (tramp, 24));
02067 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, val));
02068 temp = expand_shift (RSHIFT_EXPR, SImode, val, build_int_2 (16, 0), 0, 1);
02069 addr = memory_address (HImode, plus_constant (tramp, 20));
02070 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, temp));
02071 }