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
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 #include "config.h"
00082 #include "system.h"
00083 #include "rtl.h"
00084 #include "tree.h"
00085 #include "tm_p.h"
00086 #include "regs.h"
00087 #include "hard-reg-set.h"
00088 #include "real.h"
00089 #include "insn-config.h"
00090 #include "conditions.h"
00091 #include "output.h"
00092 #include "insn-attr.h"
00093 #include "flags.h"
00094 #include "except.h"
00095 #include "function.h"
00096 #include "recog.h"
00097 #include "expr.h"
00098 #include "optabs.h"
00099 #include "toplev.h"
00100 #include "basic-block.h"
00101 #include "ggc.h"
00102 #include "target.h"
00103 #include "target-def.h"
00104
00105
00106
00107 rtx pj_cmp_op0;
00108 rtx pj_cmp_op1;
00109 enum machine_mode pj_cmp_mode;
00110
00111 static void pj_output_rval PARAMS ((rtx, enum machine_mode, rtx));
00112 static void pj_output_store_into_lval PARAMS ((enum machine_mode mode, rtx op));
00113 static void pj_output_push_int PARAMS ((int));
00114 static void pj_output_load PARAMS ((enum machine_mode, int));
00115 static void pj_output_inc PARAMS ((rtx, int));
00116 static void pj_output_cnv_op PARAMS ((enum insn_code, rtx));
00117 static char mode_to_char PARAMS ((enum machine_mode));
00118 static void pj_output_varidx PARAMS ((enum machine_mode, int, int));
00119 static void pj_print_cond PARAMS ((enum rtx_code));
00120 static rtx *unique_src_operand PARAMS ((rtx *, rtx));
00121
00122
00123
00124 short pj_si_vars_offset_vec[FIRST_PSEUDO_REGISTER];
00125 short pj_di_vars_offset_vec[FIRST_PSEUDO_REGISTER];
00126 short pj_debugreg_renumber_vec[FIRST_PSEUDO_REGISTER];
00127
00128
00129
00130 static int nfakes;
00131
00132
00133
00134 int pj_stuff_on_line;
00135
00136
00137
00138 struct gcc_target targetm = TARGET_INITIALIZER;
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 static void
00149 pj_printf VPARAMS ((const char *template, ...))
00150 {
00151 register int c;
00152 int ops_read = 0;
00153 rtx operands[10];
00154
00155 VA_OPEN (argptr, template);
00156 VA_FIXEDARG (argptr, const char *, template);
00157
00158 while ((c = *template++))
00159 {
00160 int was_stuff_on_line = pj_stuff_on_line;
00161 pj_stuff_on_line = 1;
00162 switch (c)
00163 {
00164 case '\n':
00165 putc (c, asm_out_file);
00166 pj_stuff_on_line = 0;
00167 break;
00168 default:
00169 putc (c, asm_out_file);
00170 break;
00171 case '%':
00172 {
00173 switch (*template)
00174 {
00175 case '%':
00176 putc ('%', asm_out_file);
00177 template++;
00178 pj_stuff_on_line = 1;
00179 break;
00180 case '*':
00181
00182 if (was_stuff_on_line)
00183 fprintf (asm_out_file, "; ");
00184 template++;
00185 break;
00186 case 'd':
00187 template++;
00188 fprintf (asm_out_file, "%d", va_arg (argptr, int));
00189 break;
00190 case 'x':
00191 template++;
00192 fprintf (asm_out_file, "%x", va_arg (argptr, int));
00193 break;
00194 case 'c':
00195 template++;
00196 fprintf (asm_out_file, "%c", va_arg (argptr, int));
00197 break;
00198 case 's':
00199 template++;
00200 fputs (va_arg (argptr, const char *), asm_out_file);
00201 break;
00202 case 'X':
00203 template++;
00204 output_addr_const (asm_out_file, va_arg (argptr, rtx));
00205 break;
00206 default:
00207 {
00208 int code = 0;
00209 rtx send;
00210
00211 if (ISALPHA (*template))
00212 code = *template++;
00213 if (ISDIGIT (*template))
00214 {
00215 int num = atoi (template);
00216 template++;
00217 while (ops_read <= num)
00218 operands[ops_read++] = va_arg (argptr, rtx);
00219 send = operands[num];
00220 }
00221 else
00222 send = va_arg (argptr, rtx);
00223
00224
00225
00226
00227 if (send)
00228 pj_print_operand (asm_out_file, send, code);
00229 }
00230 }
00231 }
00232 }
00233 }
00234 VA_CLOSE (argptr);
00235 }
00236
00237
00238
00239
00240 static void
00241 pj_output_push_int (val)
00242 int val;
00243 {
00244 int low = ((val & 0x8000) ? ~0xffff : 0) | (val & 0xffff);
00245
00246 if (low == -1)
00247 pj_printf ("%*iconst_m1");
00248 else if (low >= 0 && low <= 5)
00249 pj_printf ("%*iconst_%d", low);
00250 else if (low >= -128 && low < 128)
00251 pj_printf ("%*bipush %d", low);
00252 else
00253 pj_printf ("%*sipush %d", low);
00254
00255 if ((low & 0xffff0000) != (val & 0xffff0000))
00256 pj_printf ("%*sethi 0x%x", (val >> 16) & 0xffff);
00257 }
00258
00259
00260
00261
00262 static void
00263 pj_output_print_add_k (int size)
00264 {
00265 if (size >= 0)
00266 {
00267 pj_output_push_int (size);
00268 pj_printf ("%*iadd");
00269 }
00270 else
00271 {
00272 pj_output_push_int (-size);
00273 pj_printf ("%*isub");
00274 }
00275 }
00276
00277
00278
00279
00280 static void
00281 pj_output_load (mode, uns)
00282 enum machine_mode mode;
00283 int uns;
00284 {
00285 int i;
00286 switch (GET_MODE_SIZE (mode))
00287 {
00288 case 1:
00289 pj_printf (uns ? "%*load_ubyte" : "%*load_byte");
00290 break;
00291 case 2:
00292 pj_printf (uns ? "%*load_char" : "%*load_short");
00293 break;
00294 case 8:
00295 if (TARGET_TM_EXTENSIONS)
00296 {
00297 pj_printf ("%*tm_load_long");
00298 break;
00299 }
00300
00301 default:
00302 for (i = GET_MODE_SIZE (mode); i > 4; i -= 4)
00303 {
00304 pj_printf ("%*dup");
00305 pj_output_print_add_k (i - 4);
00306 pj_printf ("%*load_word");
00307 pj_printf ("%*swap");
00308 }
00309 pj_printf ("%*load_word");
00310 }
00311 }
00312
00313
00314
00315 static void
00316 pj_output_inc (op, size)
00317 rtx op;
00318 int size;
00319 {
00320 if (STACK_REG_RTX_P (op))
00321 pj_printf ("%*iinc %d,%d", pj_si_vars_offset_vec[REGNO (op)], size);
00322 else
00323 {
00324 pj_output_rval (op, SImode, 0);
00325 pj_output_push_int (size);
00326 pj_printf ("%*iadd");
00327 pj_output_store_into_lval (SImode, op);
00328 }
00329 }
00330
00331
00332
00333 static void
00334 pj_output_cnv_op (e, op)
00335 enum insn_code e;
00336 rtx op;
00337 {
00338 pj_printf ((const char *) insn_data[(int) e].output, 0, XEXP (op, 0));
00339 }
00340
00341
00342
00343 static char
00344 mode_to_char (mode)
00345 enum machine_mode mode;
00346 {
00347 switch (mode)
00348 {
00349 case QImode:
00350 case HImode:
00351 case SImode:
00352 return 'i';
00353 break;
00354 case DImode:
00355 return 'l';
00356 break;
00357 case DFmode:
00358 return 'd';
00359 break;
00360 case SFmode:
00361 return 'f';
00362 break;
00363 default:
00364 abort ();
00365 }
00366 }
00367
00368
00369
00370
00371
00372
00373 static void
00374 pj_output_varidx (mode, do_store, idx)
00375 enum machine_mode mode;
00376 int do_store;
00377 int idx;
00378 {
00379 pj_printf ("%*%c%s%c%d",
00380 mode_to_char (mode),
00381 do_store ? "store" : "load",
00382 (GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8)
00383 && idx <= 3 ? '_' : ' ', idx);
00384 }
00385
00386
00387
00388 static void
00389 pj_output_rval (op, mode, outer_op)
00390 rtx op;
00391 enum machine_mode mode;
00392 rtx outer_op;
00393 {
00394 enum rtx_code code = GET_CODE (op);
00395
00396 optab tab;
00397
00398 if (code == DIV && GET_MODE_CLASS (mode) == MODE_INT)
00399 tab = sdiv_optab;
00400 else
00401 tab = code_to_optab[code];
00402
00403 if (code == PLUS)
00404 {
00405 pj_output_rval (XEXP (op, 0), mode, op);
00406 pj_output_rval (XEXP (op, 1), mode, op);
00407 pj_printf ("%*%cadd", mode_to_char (mode));
00408 }
00409 else if (tab && tab->handlers[mode].insn_code != CODE_FOR_nothing)
00410 {
00411 const char *const template =
00412 (const char *) insn_data[tab->handlers[mode].insn_code].output;
00413 if (code == NEG)
00414 pj_printf (template, 0, XEXP (op, 0));
00415 else
00416 pj_printf (template, 0, XEXP (op, 0), XEXP (op, 1));
00417 }
00418 else
00419 switch (GET_CODE (op))
00420 {
00421 case PC:
00422 fprintf (asm_out_file, " pc ");
00423 break;
00424
00425 case CONST:
00426 pj_output_rval (XEXP (op, 0), mode, op);
00427 break;
00428
00429 case MEM:
00430 pj_output_rval (XEXP (op, 0), Pmode, op);
00431 pj_output_load (mode, 0);
00432 break;
00433
00434 case SYMBOL_REF:
00435 pj_printf ("%*ipush %X", op);
00436 break;
00437
00438 case REG:
00439 switch (mode)
00440 {
00441 case SImode:
00442 case SFmode:
00443 case HImode:
00444 case QImode:
00445 if (pj_si_vars_offset_vec[REGNO (op)] >= 0)
00446 pj_output_varidx (mode, 0, pj_si_vars_offset_vec[REGNO (op)]);
00447 else
00448 pj_printf ("%*read_%s", reg_names[REGNO (op)]);
00449 break;
00450 case DImode:
00451 case DFmode:
00452 if (pj_di_vars_offset_vec[REGNO (op)] >= 0)
00453 pj_output_varidx (mode, 0, pj_di_vars_offset_vec[REGNO (op)]);
00454 else
00455 switch (REGNO (op))
00456 {
00457 case G1_REG:
00458 pj_printf ("%*read_global2");
00459 pj_printf ("%*read_global1");
00460 break;
00461
00462
00463
00464 case G0_REG:
00465 pj_printf ("%*read_optop");
00466 pj_printf ("%*read_global0");
00467 break;
00468
00469 default:
00470 abort ();
00471 }
00472 break;
00473 default:
00474 abort ();
00475 }
00476 break;
00477
00478 case CONST_DOUBLE:
00479 pj_printf (pj_standard_float_constant (op));
00480 break;
00481
00482 case CONST_INT:
00483 if (mode == SImode || mode == HImode || mode == QImode)
00484 pj_output_push_int (INTVAL (op));
00485 else if (mode == DImode)
00486 {
00487 int v = INTVAL (op);
00488 if (v == 1)
00489 pj_printf ("%*lconst_1", 0);
00490 else if (v == 0)
00491 pj_printf ("%*lconst_0", 0);
00492 else
00493 {
00494 rtx hi = GEN_INT (v < 0 ? -1 : 0);
00495 rtx lo = op;
00496 pj_output_rval (TARGET_LITTLE_ENDIAN ? hi : lo, SImode, op);
00497 pj_output_rval (TARGET_LITTLE_ENDIAN ? lo : hi, SImode, op);
00498 }
00499 }
00500 else
00501 abort ();
00502 break;
00503
00504 case FLOAT_TRUNCATE:
00505 pj_printf ("%S0%*d2f", XEXP (op, 0));
00506 break;
00507 case LABEL_REF:
00508 pj_printf ("%*ipush %X", XEXP (op, 0));
00509 break;
00510
00511 case SUBREG:
00512 pj_output_rval (alter_subreg (&op), mode, outer_op);
00513 break;
00514
00515 case POST_INC:
00516 pj_output_rval (XEXP (op, 0), mode, op);
00517 pj_output_inc (XEXP (op, 0), GET_MODE_SIZE (GET_MODE (outer_op)));
00518 break;
00519
00520 case POST_DEC:
00521 pj_output_rval (XEXP (op, 0), mode, op);
00522 pj_output_inc (XEXP (op, 0), -GET_MODE_SIZE (GET_MODE (outer_op)));
00523 break;
00524
00525 case PRE_INC:
00526 pj_output_inc (XEXP (op, 0), GET_MODE_SIZE (GET_MODE (outer_op)));
00527 pj_output_rval (XEXP (op, 0), mode, op);
00528 break;
00529
00530 case PRE_DEC:
00531 if (OPTOP_REG_RTX_P (XEXP (op, 0)))
00532 pj_output_rval (XEXP (op, 0), mode, op);
00533 else if (STACK_REG_RTX_P (XEXP (op, 0)))
00534 {
00535 pj_output_inc (XEXP (op, 0),
00536 -GET_MODE_SIZE (GET_MODE (outer_op)));
00537 pj_output_rval (XEXP (op, 0), mode, op);
00538 }
00539 else
00540 {
00541 pj_printf ("%S0", XEXP (op, 0));
00542 pj_output_print_add_k (-GET_MODE_SIZE (GET_MODE (outer_op)));
00543 pj_printf ("%*dup%R0", XEXP (op, 0));
00544 }
00545 break;
00546
00547 case FIX:
00548 pj_output_cnv_op (fixtrunctab[GET_MODE (XEXP (op, 0))][mode][0], op);
00549 break;
00550
00551 case FLOAT:
00552 if (mode == DFmode && GET_CODE (XEXP (op, 0)) == CONST_INT)
00553 pj_output_cnv_op (floattab[mode][SImode][0], op);
00554 else
00555 pj_output_cnv_op (floattab[mode][GET_MODE (XEXP (op, 0))][0], op);
00556 break;
00557
00558 case FLOAT_EXTEND:
00559 case SIGN_EXTEND:
00560
00561 if (mode == SImode && GET_CODE (XEXP (op, 0)) == MEM)
00562 pj_output_rval (XEXP (op, 0), GET_MODE (XEXP (op, 0)), op);
00563 else
00564 pj_output_cnv_op (extendtab[mode][GET_MODE (XEXP (op, 0))][0], op);
00565 break;
00566
00567 case ZERO_EXTEND:
00568 pj_output_cnv_op (extendtab[mode][GET_MODE (XEXP (op, 0))][1], op);
00569 break;
00570
00571 default:
00572 abort ();
00573 break;
00574 }
00575 }
00576
00577
00578
00579 static void
00580 pj_output_store_into_lval (mode, op)
00581 enum machine_mode mode;
00582 rtx op;
00583 {
00584 if (GET_CODE (op) == REG)
00585 {
00586 int rn = REGNO (op);
00587
00588
00589
00590 if (!OUTGOING_REG_RTX_P (op))
00591 {
00592 switch (GET_MODE (op))
00593 {
00594 case SImode:
00595 case QImode:
00596 case HImode:
00597 case SFmode:
00598 if (pj_si_vars_offset_vec[rn] >= 0)
00599 pj_output_varidx (mode, 1, pj_si_vars_offset_vec[rn]);
00600 else
00601 pj_printf ("%*write_%s", reg_names[rn]);
00602 break;
00603 case DImode:
00604 case DFmode:
00605 if (pj_di_vars_offset_vec[rn] >= 0)
00606 pj_output_varidx (mode, 1, pj_di_vars_offset_vec[rn]);
00607 else
00608 switch (rn)
00609 {
00610 case G1_REG:
00611 pj_printf ("%*write_global1");
00612 pj_printf ("%*write_global2");
00613 break;
00614 default:
00615 abort ();
00616 }
00617 break;
00618 default:
00619 abort ();
00620 }
00621 }
00622 }
00623 else
00624 {
00625 pj_output_rval (XEXP (op, 0), Pmode, op);
00626
00627 switch (GET_MODE_SIZE (mode))
00628 {
00629 case 1:
00630 pj_printf ("%*store_byte", 0);
00631 break;
00632 case 2:
00633 pj_printf ("%*store_short", 0);
00634 break;
00635 case 8:
00636 if (TARGET_TM_EXTENSIONS)
00637 {
00638 pj_printf ("%*tm_store_long");
00639 break;
00640 }
00641
00642 default:
00643 {
00644 int i;
00645 for (i = GET_MODE_SIZE (mode); i > 4; i -= 4)
00646 {
00647 pj_printf ("%*dup_x1", 0);
00648 pj_printf ("%*store_word", 0);
00649 pj_printf ("%*iconst_4", 0);
00650 pj_printf ("%*iadd", 0);
00651 }
00652 }
00653 pj_printf ("%*store_word", 0);
00654 break;
00655 }
00656 }
00657 }
00658
00659
00660
00661
00662 static void
00663 pj_print_cond (code)
00664 enum rtx_code code;
00665 {
00666 switch (code)
00667 {
00668 case EQ:
00669 fputs ("eq", asm_out_file);
00670 break;
00671 case NE:
00672 fputs ("ne", asm_out_file);
00673 break;
00674 case GT:
00675 case GTU:
00676 fputs ("gt", asm_out_file);
00677 break;
00678 case GE:
00679 case GEU:
00680 fputs ("ge", asm_out_file);
00681 break;
00682 case LT:
00683 case LTU:
00684 fputs ("lt", asm_out_file);
00685 break;
00686 case LE:
00687 case LEU:
00688 fputs ("le", asm_out_file);
00689 break;
00690 default:
00691 abort ();
00692 }
00693 }
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710 void
00711 pj_print_operand (stream, x, code)
00712 FILE *stream;
00713 rtx x;
00714 int code;
00715 {
00716 static int last_call_known;
00717 switch (code)
00718 {
00719 case 'C':
00720 if (GET_CODE (x) == SYMBOL_REF)
00721 {
00722 last_call_known = 1;
00723 pj_printf ("%*.check_call %0", x);
00724 }
00725 else
00726 last_call_known = 0;
00727 break;
00728
00729 case 'D':
00730 pj_output_rval (x,
00731 GET_MODE (x) == VOIDmode ? DImode : GET_MODE (x),
00732 NULL_RTX);
00733 break;
00734
00735 case 'E':
00736 if (last_call_known)
00737 pj_printf (",%d", INTVAL (x));
00738 break;
00739
00740 case 'I':
00741 pj_output_rval (XEXP (x, 0), GET_MODE (XEXP (x, 0)), NULL_RTX);
00742 break;
00743
00744 case 'J':
00745 if (GET_CODE (x) == CONST_INT)
00746 pj_printf ("%d", INTVAL (x));
00747 else if (GET_CODE (x) == REG)
00748 pj_printf ("%d", pj_si_vars_offset_vec[REGNO (x)]);
00749 else
00750 abort ();
00751 break;
00752
00753 case 'P':
00754 if (TARGET_LITTLE_ENDIAN)
00755 pj_printf ("%*iconst_0", 0);
00756 pj_output_rval (x,
00757 GET_MODE (x) == VOIDmode ? SImode : GET_MODE (x),
00758 NULL_RTX);
00759 if (!TARGET_LITTLE_ENDIAN)
00760 pj_printf ("%*iconst_0", 0);
00761 break;
00762
00763 case 'R':
00764 pj_output_store_into_lval (GET_MODE (x), x);
00765 break;
00766
00767 case 'S':
00768 pj_output_rval (x,
00769 GET_MODE (x) == VOIDmode ? SImode : GET_MODE (x),
00770 NULL_RTX);
00771 break;
00772
00773 case 'X':
00774 fputc (GET_CODE (x) == LT || GET_CODE (x) == LE ? 'g' : 'l', stream);
00775 break;
00776
00777 case 'Y':
00778 pj_print_cond (GET_CODE (x));
00779 break;
00780
00781 case 'Z':
00782 pj_print_cond (reverse_condition (GET_CODE (x)));
00783 break;
00784
00785 case '*':
00786 pj_printf ("%*");
00787 break;
00788
00789 default:
00790 output_addr_const (stream, x);
00791 break;
00792 }
00793 }
00794
00795
00796
00797
00798
00799 rtx
00800 pj_workout_arg_words (stack_size, next_arg_reg)
00801 rtx stack_size ATTRIBUTE_UNUSED;
00802 rtx next_arg_reg;
00803 {
00804 return GEN_INT ((next_arg_reg ? REGNO (next_arg_reg) - O0_REG : 0) + 2);
00805 }
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821 rtx
00822 pj_function_incoming_arg (cum, mode, passed_type, named_arg)
00823 CUMULATIVE_ARGS *cum;
00824 enum machine_mode mode;
00825 tree passed_type ATTRIBUTE_UNUSED;
00826 int named_arg ATTRIBUTE_UNUSED;
00827 {
00828 int arg_words = PJ_ARG_WORDS (mode);
00829
00830
00831
00832
00833
00834
00835 if (cum->total_words + arg_words <= ARGS_IN_REGS)
00836 {
00837 int i;
00838 if (mode == DImode || mode == DFmode)
00839 {
00840 cum->arg_adjust[cum->total_words + 0] = 1;
00841 cum->arg_adjust[cum->total_words + 1] = -1;
00842 }
00843 else
00844 for (i = 0; i < arg_words; i++)
00845 cum->arg_adjust[cum->total_words + i] = 0;
00846
00847 return gen_rtx (REG, mode, I0_REG + cum->total_words);
00848 }
00849 return NULL_RTX;
00850 }
00851
00852
00853
00854
00855 const char *
00856 pj_output_addsi3 (operands)
00857 rtx *operands;
00858 {
00859 if (OPTOP_REG_RTX_P (operands[0]) && OPTOP_REG_RTX_P (operands[1])
00860 && GET_CODE (operands[2]) == CONST_INT
00861 && INTVAL (operands[2]) >= -32 && INTVAL (operands[2]) <= 32)
00862 {
00863 static struct
00864 {
00865 const char *two;
00866 const char *one;
00867 }
00868 name[2] =
00869 {
00870 { "pop2", "pop"},
00871 { "lconst_0", "iconst_0"}
00872 };
00873 int size = INTVAL (operands[2]);
00874 int d = 0;
00875
00876 if (size < 0)
00877 {
00878 d = 1;
00879 size = -size;
00880 }
00881
00882 for (; size >= 8; size -= 8)
00883 output_asm_insn (name[d].two, 0);
00884
00885
00886 if (size > 0)
00887 output_asm_insn (name[d].one, 0);
00888
00889 return "";
00890 }
00891
00892 if (STACK_REG_RTX_P (operands[0])
00893 && rtx_equal_p (operands[0], operands[1])
00894 && GET_CODE (operands[2]) == CONST_INT
00895 && INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) <= 127)
00896 {
00897 return "iinc %J0,%J2";
00898 }
00899
00900 return "%S1%S2%*iadd%R0";
00901 }
00902
00903
00904
00905 void
00906 pj_expand_prologue ()
00907 {
00908 int i;
00909 int off = 0;
00910 int arg_words = current_function_args_info.named_words;
00911
00912 memset (pj_si_vars_offset_vec, -1, sizeof (pj_si_vars_offset_vec));
00913 memset (pj_di_vars_offset_vec, -1, sizeof (pj_di_vars_offset_vec));
00914
00915
00916 for (i = 0; i < current_function_args_info.named_words; i++)
00917 {
00918 pj_debugreg_renumber_vec[I0_REG + i]
00919 = off + R0_REG + current_function_args_info.arg_adjust[i];
00920 pj_si_vars_offset_vec[I0_REG + i]
00921 = off + current_function_args_info.arg_adjust[i];
00922 pj_di_vars_offset_vec[I0_REG + i] = off;
00923 off++;
00924 }
00925
00926 if (current_function_varargs || current_function_stdarg)
00927 {
00928
00929
00930
00931
00932
00933
00934
00935 emit_insn (gen_varargs (GEN_INT (arg_words * 4)));
00936 pj_si_vars_offset_vec[VA_REG] = off++;
00937 off++;
00938 arg_words += 2;
00939 }
00940
00941
00942 off += 2;
00943
00944
00945
00946 nfakes = 0;
00947
00948 for (i = LAST_I_REG; i >= R0_REG; i--)
00949 if (regs_ever_live[i] && pj_si_vars_offset_vec[i] == -1)
00950 {
00951 nfakes++;
00952 pj_si_vars_offset_vec[i] = off;
00953 pj_di_vars_offset_vec[i] = off - 1;
00954 pj_debugreg_renumber_vec[i] = off + R0_REG;
00955 off++;
00956 }
00957
00958 if (TARGET_TEST)
00959 {
00960 fprintf (asm_out_file, "\n\t! args %d, size %d, fakes %d\n",
00961 arg_words,
00962 get_frame_size () / 4,
00963 nfakes);
00964
00965 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
00966 if (pj_si_vars_offset_vec[i] >= 0)
00967 fprintf (asm_out_file, "\t!vars - %d %d: %s\n",
00968 pj_si_vars_offset_vec[i],
00969 pj_di_vars_offset_vec[i],
00970 reg_names[i]);
00971 }
00972
00973
00974 if (TARGET_TM_EXTENSIONS)
00975 RTX_FRAME_RELATED_P (emit_insn (gen_tm_frame (GEN_INT (arg_words),
00976 GEN_INT (nfakes)))) = 1;
00977 else
00978 RTX_FRAME_RELATED_P (emit_insn
00979 (gen_addsi3
00980 (gen_rtx_REG (SImode, OPTOP_REG),
00981 gen_rtx_REG (SImode, OPTOP_REG),
00982 GEN_INT (-nfakes * 4)))) = 1;
00983
00984
00985 if (frame_pointer_needed)
00986 emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
00987
00988 if (get_frame_size ())
00989 RTX_FRAME_RELATED_P (emit_insn (gen_addsi3 (stack_pointer_rtx,
00990 stack_pointer_rtx,
00991 GEN_INT
00992 (-get_frame_size ())))) = 1;
00993
00994 emit_insn (gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, OPTOP_REG)));
00995 }
00996
00997
00998
00999 void
01000 pj_expand_epilogue ()
01001 {
01002 if (frame_pointer_needed)
01003 emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
01004 else if (get_frame_size ())
01005 emit_insn (gen_addsi3 (stack_pointer_rtx,
01006 stack_pointer_rtx, GEN_INT (get_frame_size ())));
01007 if (nfakes)
01008 emit_insn (gen_addsi3 (gen_rtx_REG (SImode, OPTOP_REG),
01009 gen_rtx_REG (SImode, OPTOP_REG),
01010 GEN_INT (nfakes * 4)));
01011
01012
01013
01014
01015
01016
01017 if (current_function_varargs || current_function_stdarg)
01018 emit_insn (gen_varargs_finish
01019 (GEN_INT (current_function_args_info.named_words + 1)));
01020
01021 emit_insn (gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, OPTOP_REG)));
01022 }
01023
01024
01025
01026
01027 const char *
01028 pj_standard_float_constant (op)
01029 rtx op;
01030 {
01031 REAL_VALUE_TYPE r;
01032 enum machine_mode mode = GET_MODE (op);
01033
01034 if (GET_CODE (op) != CONST_DOUBLE || (mode != DFmode && mode != SFmode))
01035 return NULL;
01036
01037 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
01038
01039 if (REAL_VALUES_EQUAL (r, dconst0) && !REAL_VALUE_MINUS_ZERO (r))
01040 return mode == DFmode ? "%*dconst_0" : "%*fconst_0";
01041
01042 if (REAL_VALUES_EQUAL (r, dconst1))
01043 return mode == DFmode ? "%*dconst_1" : "%*fconst_1";
01044
01045 if (REAL_VALUES_EQUAL (r, dconst2))
01046 return mode == DFmode ? 0 : "%*fconst_2";
01047
01048 return NULL;
01049 }
01050
01051
01052
01053
01054
01055
01056 rtx
01057 pj_expand_builtin_va_arg (valist, type)
01058 tree valist;
01059 tree type;
01060 {
01061 tree addr_tree, t;
01062 HOST_WIDE_INT align;
01063 HOST_WIDE_INT rounded_size;
01064 rtx addr;
01065
01066
01067 align = PARM_BOUNDARY / BITS_PER_UNIT;
01068 rounded_size = (((int_size_in_bytes (type) + align - 1) / align) * align);
01069
01070
01071 addr_tree = valist;
01072 addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
01073 addr = copy_to_reg (addr);
01074
01075
01076 if (AGGREGATE_TYPE_P (type) || rounded_size > 8)
01077 {
01078 addr = gen_rtx_MEM (Pmode, addr);
01079 rounded_size = 4;
01080 }
01081
01082
01083 if (rounded_size > 4)
01084 addr = gen_rtx_PLUS (Pmode, addr, GEN_INT (-4));
01085
01086
01087 t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
01088 build (MINUS_EXPR, TREE_TYPE (valist), valist,
01089 build_int_2 (rounded_size, 0)));
01090
01091 TREE_SIDE_EFFECTS (t) = 1;
01092
01093 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
01094
01095 return addr;
01096 }
01097
01098
01099
01100
01101 int
01102 pj_source_operand (op, mode)
01103 rtx op;
01104 enum machine_mode mode;
01105 {
01106 return !OUTGOING_REG_RTX_P (op) && general_operand (op, mode);
01107 }
01108
01109
01110
01111 int
01112 pj_signed_comparison_operator (op, mode)
01113 rtx op;
01114 enum machine_mode mode;
01115 {
01116 if (mode != GET_MODE (op))
01117 return 0;
01118
01119 switch (GET_CODE (op))
01120 {
01121 case EQ:
01122 case NE:
01123 case LE:
01124 case LT:
01125 case GE:
01126 case GT:
01127 return 1;
01128 default:
01129 return 0;
01130 }
01131 }
01132
01133
01134
01135 int
01136 pj_unsigned_comparison_operator (op, mode)
01137 rtx op;
01138 enum machine_mode mode ATTRIBUTE_UNUSED;
01139 {
01140 if (mode != GET_MODE (op))
01141 return 0;
01142
01143 switch (GET_CODE (op))
01144 {
01145 case GTU:
01146 case GEU:
01147 case LTU:
01148 case LEU:
01149 return 1;
01150 default:
01151 return 0;
01152 }
01153 }
01154
01155
01156
01157
01158
01159 #define NOT_UNIQUE (&const0_rtx)
01160
01161 static rtx *
01162 unique_src_operand (pat, reg)
01163 rtx *pat;
01164 rtx reg;
01165 {
01166 register rtx *result = 0;
01167 register const char *fmt;
01168 register int i;
01169 register int j;
01170
01171 if (GET_CODE (*pat) == SET)
01172 {
01173 if (GET_CODE (XEXP (*pat, 0)) == MEM)
01174 result = unique_src_operand (&XEXP (SET_DEST (*pat), 0), reg);
01175 pat = &SET_SRC (*pat);
01176 }
01177
01178 if (GET_CODE (*pat) == REG && REGNO (*pat) == REGNO (reg))
01179 return pat;
01180
01181 fmt = GET_RTX_FORMAT (GET_CODE (*pat));
01182 for (i = GET_RTX_LENGTH (GET_CODE (*pat)) - 1; i >= 0; i--)
01183 {
01184 if (fmt[i] == 'e')
01185 {
01186 rtx *new_result = unique_src_operand (&XEXP (*pat, i), reg);
01187
01188 if (new_result)
01189 {
01190 if (result)
01191 return NOT_UNIQUE;
01192 result = new_result;
01193 }
01194 }
01195 else if (fmt[i] == 'E')
01196 {
01197 for (j = XVECLEN (*pat, i) - 1; j >= 0; j--)
01198 {
01199 rtx *new_result =
01200 unique_src_operand (&XVECEXP (*pat, i, j), reg);
01201
01202 if (new_result)
01203 {
01204 if (result)
01205 return NOT_UNIQUE;
01206 result = new_result;
01207 }
01208 }
01209 }
01210 }
01211 return result;
01212 }
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234 void
01235 pj_machine_dependent_reorg (insns)
01236 rtx insns;
01237 {
01238 rtx cursor;
01239
01240 if (!optimize || !TARGET_REORG)
01241 return;
01242
01243 for (cursor = insns; cursor; cursor = NEXT_INSN (cursor))
01244 {
01245 rtx links;
01246 rtx cursor_pat;
01247
01248
01249
01250 if ((GET_CODE (cursor) != INSN && GET_CODE (cursor) != JUMP_INSN)
01251 || GET_CODE (cursor_pat = PATTERN (cursor)) == USE
01252 || GET_CODE (cursor_pat) == CLOBBER
01253 || GET_CODE (cursor_pat) == ADDR_VEC
01254 || GET_CODE (cursor_pat) == ADDR_DIFF_VEC)
01255 continue;
01256
01257 for (links = LOG_LINKS (cursor); links; links = XEXP (links, 1))
01258 {
01259 rtx prev = XEXP (links, 0);
01260 rtx prev_pat;
01261 rtx prev_dest;
01262 rtx prev_src;
01263 rtx *dst_place;
01264
01265 if (GET_CODE (prev) == INSN
01266 && GET_CODE (prev_pat = PATTERN (prev)) == SET
01267 && GET_CODE (prev_dest = SET_DEST (prev_pat)) == REG
01268 && dead_or_set_p (cursor, prev_dest)
01269 && !reg_used_between_p (prev_dest, prev, cursor)
01270 && no_labels_between_p (prev, cursor)
01271 && no_jumps_between_p (prev, cursor)
01272 && !modified_between_p ((prev_src = SET_SRC (prev_pat)), prev,
01273 cursor)
01274 && (dst_place = unique_src_operand (&cursor_pat, prev_dest))
01275 && dst_place != NOT_UNIQUE
01276 && REGNO (prev_dest) != OPTOP_REG
01277 && GET_MODE (prev_dest) != XFmode
01278 && GET_MODE (*dst_place) == GET_MODE (SET_DEST (prev_pat)))
01279 {
01280 *dst_place = SET_SRC (prev_pat);
01281 PUT_CODE (prev, NOTE);
01282 NOTE_LINE_NUMBER (prev) = NOTE_INSN_DELETED;
01283 }
01284 }
01285 }
01286 }