00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "system.h"
00025 #include "tree.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 "expr.h"
00037 #include "function.h"
00038 #include "toplev.h"
00039 #include "cpplib.h"
00040 #include "c-lex.h"
00041 #include "ggc.h"
00042 #include "integrate.h"
00043 #include "tm_p.h"
00044 #include "target.h"
00045 #include "target-def.h"
00046
00047 #ifndef streq
00048 #define streq(a,b) (strcmp (a, b) == 0)
00049 #endif
00050
00051
00052 static void const_double_split PARAMS ((rtx, HOST_WIDE_INT *, HOST_WIDE_INT *));
00053 static int const_costs_int PARAMS ((HOST_WIDE_INT, int));
00054 static void substitute_ep_register PARAMS ((rtx, rtx, int, int, rtx *, rtx *));
00055 static int ep_memory_offset PARAMS ((enum machine_mode, int));
00056 static void v850_set_data_area PARAMS ((tree, v850_data_area));
00057 const struct attribute_spec v850_attribute_table[];
00058 static tree v850_handle_interrupt_attribute PARAMS ((tree *, tree, tree, int, bool *));
00059 static tree v850_handle_data_area_attribute PARAMS ((tree *, tree, tree, int, bool *));
00060 static void v850_insert_attributes PARAMS ((tree, tree *));
00061
00062
00063 int current_function_anonymous_args;
00064
00065
00066 struct small_memory_info small_memory[ (int)SMALL_MEMORY_max ] =
00067 {
00068
00069 { "tda", (char *)0, 0, 256 },
00070 { "sda", (char *)0, 0, 65536 },
00071 { "zda", (char *)0, 0, 32768 },
00072 };
00073
00074
00075 tree GHS_default_section_names [(int) COUNT_OF_GHS_SECTION_KINDS];
00076 tree GHS_current_section_names [(int) COUNT_OF_GHS_SECTION_KINDS];
00077
00078
00079
00080 data_area_stack_element * data_area_stack = NULL;
00081
00082
00083
00084 static int v850_interrupt_cache_p = FALSE;
00085
00086
00087 static int v850_interrupt_p = FALSE;
00088
00089
00090 #undef TARGET_ASM_ALIGNED_HI_OP
00091 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
00092
00093 #undef TARGET_ATTRIBUTE_TABLE
00094 #define TARGET_ATTRIBUTE_TABLE v850_attribute_table
00095
00096 #undef TARGET_INSERT_ATTRIBUTES
00097 #define TARGET_INSERT_ATTRIBUTES v850_insert_attributes
00098
00099 struct gcc_target targetm = TARGET_INITIALIZER;
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 void
00111 override_options ()
00112 {
00113 int i;
00114 extern int atoi PARAMS ((const char *));
00115
00116
00117 for (i = 0; i < (int)SMALL_MEMORY_max; i++)
00118 {
00119 if (small_memory[i].value)
00120 {
00121 if (!ISDIGIT (*small_memory[i].value))
00122 error ("%s=%s is not numeric",
00123 small_memory[i].name,
00124 small_memory[i].value);
00125 else
00126 {
00127 small_memory[i].max = atoi (small_memory[i].value);
00128 if (small_memory[i].max > small_memory[i].physical_max)
00129 error ("%s=%s is too large",
00130 small_memory[i].name,
00131 small_memory[i].value);
00132 }
00133 }
00134 }
00135 }
00136
00137
00138
00139
00140 void
00141 asm_file_start (file)
00142 FILE *file;
00143 {
00144 output_file_directive (file, main_input_filename);
00145 }
00146
00147
00148
00149
00150
00151 rtx
00152 function_arg (cum, mode, type, named)
00153 CUMULATIVE_ARGS *cum;
00154 enum machine_mode mode;
00155 tree type;
00156 int named;
00157 {
00158 rtx result = 0;
00159 int size, align;
00160
00161 if (TARGET_GHS && !named)
00162 return NULL_RTX;
00163
00164 if (mode == BLKmode)
00165 size = int_size_in_bytes (type);
00166 else
00167 size = GET_MODE_SIZE (mode);
00168
00169 if (type)
00170 align = TYPE_ALIGN (type) / BITS_PER_UNIT;
00171 else
00172 align = size;
00173
00174 cum->nbytes = (cum->nbytes + align - 1) &~(align - 1);
00175
00176 if (cum->nbytes > 4 * UNITS_PER_WORD)
00177 return 0;
00178
00179 if (type == NULL_TREE
00180 && cum->nbytes + size > 4 * UNITS_PER_WORD)
00181 return 0;
00182
00183 switch (cum->nbytes / UNITS_PER_WORD)
00184 {
00185 case 0:
00186 result = gen_rtx_REG (mode, 6);
00187 break;
00188 case 1:
00189 result = gen_rtx_REG (mode, 7);
00190 break;
00191 case 2:
00192 result = gen_rtx_REG (mode, 8);
00193 break;
00194 case 3:
00195 result = gen_rtx_REG (mode, 9);
00196 break;
00197 default:
00198 result = 0;
00199 }
00200
00201 return result;
00202 }
00203
00204
00205
00206
00207
00208 int
00209 function_arg_partial_nregs (cum, mode, type, named)
00210 CUMULATIVE_ARGS *cum;
00211 enum machine_mode mode;
00212 tree type;
00213 int named;
00214 {
00215 int size, align;
00216
00217 if (TARGET_GHS && !named)
00218 return 0;
00219
00220 if (mode == BLKmode)
00221 size = int_size_in_bytes (type);
00222 else
00223 size = GET_MODE_SIZE (mode);
00224
00225 if (type)
00226 align = TYPE_ALIGN (type) / BITS_PER_UNIT;
00227 else
00228 align = size;
00229
00230 cum->nbytes = (cum->nbytes + align - 1) &~(align - 1);
00231
00232 if (cum->nbytes > 4 * UNITS_PER_WORD)
00233 return 0;
00234
00235 if (cum->nbytes + size <= 4 * UNITS_PER_WORD)
00236 return 0;
00237
00238 if (type == NULL_TREE
00239 && cum->nbytes + size > 4 * UNITS_PER_WORD)
00240 return 0;
00241
00242 return (4 * UNITS_PER_WORD - cum->nbytes) / UNITS_PER_WORD;
00243 }
00244
00245
00246
00247
00248 static void
00249 const_double_split (x, p_high, p_low)
00250 rtx x;
00251 HOST_WIDE_INT *p_high;
00252 HOST_WIDE_INT *p_low;
00253 {
00254 if (GET_CODE (x) == CONST_DOUBLE)
00255 {
00256 long t[2];
00257 REAL_VALUE_TYPE rv;
00258
00259 switch (GET_MODE (x))
00260 {
00261 case DFmode:
00262 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
00263 REAL_VALUE_TO_TARGET_DOUBLE (rv, t);
00264 *p_high = t[1];
00265 *p_low = t[0];
00266 return;
00267
00268 case SFmode:
00269 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
00270 REAL_VALUE_TO_TARGET_SINGLE (rv, *p_high);
00271 *p_low = 0;
00272 return;
00273
00274 case VOIDmode:
00275 case DImode:
00276 *p_high = CONST_DOUBLE_HIGH (x);
00277 *p_low = CONST_DOUBLE_LOW (x);
00278 return;
00279
00280 default:
00281 break;
00282 }
00283 }
00284
00285 fatal_insn ("const_double_split got a bad insn:", x);
00286 }
00287
00288
00289
00290
00291 static int
00292 const_costs_int (value, zero_cost)
00293 HOST_WIDE_INT value;
00294 int zero_cost;
00295 {
00296 if (CONST_OK_FOR_I (value))
00297 return zero_cost;
00298 else if (CONST_OK_FOR_J (value))
00299 return 1;
00300 else if (CONST_OK_FOR_K (value))
00301 return 2;
00302 else
00303 return 4;
00304 }
00305
00306 int
00307 const_costs (r, c)
00308 rtx r;
00309 enum rtx_code c;
00310 {
00311 HOST_WIDE_INT high, low;
00312
00313 switch (c)
00314 {
00315 case CONST_INT:
00316 return const_costs_int (INTVAL (r), 0);
00317
00318 case CONST_DOUBLE:
00319 const_double_split (r, &high, &low);
00320 if (GET_MODE (r) == SFmode)
00321 return const_costs_int (high, 1);
00322 else
00323 return const_costs_int (high, 1) + const_costs_int (low, 1);
00324
00325 case SYMBOL_REF:
00326 case LABEL_REF:
00327 case CONST:
00328 return 2;
00329
00330 case HIGH:
00331 return 1;
00332
00333 default:
00334 return 4;
00335 }
00336 }
00337
00338
00339
00340
00341
00342 void
00343 print_operand (file, x, code)
00344 FILE *file;
00345 rtx x;
00346 int code;
00347 {
00348 HOST_WIDE_INT high, low;
00349
00350 switch (code)
00351 {
00352 case 'c':
00353
00354 if (GET_CODE (x) == SYMBOL_REF)
00355 {
00356 output_addr_const(file, x);
00357 break;
00358 }
00359
00360 case 'b':
00361 case 'B':
00362 case 'C':
00363 switch ((code == 'B' || code == 'C')
00364 ? reverse_condition (GET_CODE (x)) : GET_CODE (x))
00365 {
00366 case NE:
00367 if (code == 'c' || code == 'C')
00368 fprintf (file, "nz");
00369 else
00370 fprintf (file, "ne");
00371 break;
00372 case EQ:
00373 if (code == 'c' || code == 'C')
00374 fprintf (file, "z");
00375 else
00376 fprintf (file, "e");
00377 break;
00378 case GE:
00379 fprintf (file, "ge");
00380 break;
00381 case GT:
00382 fprintf (file, "gt");
00383 break;
00384 case LE:
00385 fprintf (file, "le");
00386 break;
00387 case LT:
00388 fprintf (file, "lt");
00389 break;
00390 case GEU:
00391 fprintf (file, "nl");
00392 break;
00393 case GTU:
00394 fprintf (file, "h");
00395 break;
00396 case LEU:
00397 fprintf (file, "nh");
00398 break;
00399 case LTU:
00400 fprintf (file, "l");
00401 break;
00402 default:
00403 abort ();
00404 }
00405 break;
00406 case 'F':
00407 if (GET_CODE (x) == CONST_INT)
00408 fprintf (file, "%d", (INTVAL (x) >= 0) ? 0 : -1);
00409 else if (GET_CODE (x) == CONST_DOUBLE)
00410 {
00411 const_double_split (x, &high, &low);
00412 fprintf (file, "%ld", (long) high);
00413 }
00414 else
00415 abort ();
00416 break;
00417 case 'G':
00418 if (GET_CODE (x) == CONST_INT)
00419 fprintf (file, "%ld", (long) INTVAL (x));
00420 else if (GET_CODE (x) == CONST_DOUBLE)
00421 {
00422 const_double_split (x, &high, &low);
00423 fprintf (file, "%ld", (long) low);
00424 }
00425 else
00426 abort ();
00427 break;
00428 case 'L':
00429 fprintf (file, "%d\n", INTVAL (x) & 0xffff);
00430 break;
00431 case 'M':
00432 fprintf (file, "%d", exact_log2 (INTVAL (x)));
00433 break;
00434 case 'O':
00435 if (special_symbolref_operand (x, VOIDmode))
00436 {
00437 const char *name;
00438
00439 if (GET_CODE (x) == SYMBOL_REF)
00440 name = XSTR (x, 0);
00441 else if (GET_CODE (x) == CONST)
00442 name = XSTR (XEXP (XEXP (x, 0), 0), 0);
00443 else
00444 abort ();
00445
00446 if (ZDA_NAME_P (name))
00447 fprintf (file, "zdaoff");
00448 else if (SDA_NAME_P (name))
00449 fprintf (file, "sdaoff");
00450 else if (TDA_NAME_P (name))
00451 fprintf (file, "tdaoff");
00452 else
00453 abort ();
00454 }
00455 else
00456 abort ();
00457 break;
00458 case 'P':
00459 if (special_symbolref_operand (x, VOIDmode))
00460 output_addr_const (file, x);
00461 else
00462 abort ();
00463 break;
00464 case 'Q':
00465 if (special_symbolref_operand (x, VOIDmode))
00466 {
00467 const char *name;
00468
00469 if (GET_CODE (x) == SYMBOL_REF)
00470 name = XSTR (x, 0);
00471 else if (GET_CODE (x) == CONST)
00472 name = XSTR (XEXP (XEXP (x, 0), 0), 0);
00473 else
00474 abort ();
00475
00476 if (ZDA_NAME_P (name))
00477 fprintf (file, "r0");
00478 else if (SDA_NAME_P (name))
00479 fprintf (file, "gp");
00480 else if (TDA_NAME_P (name))
00481 fprintf (file, "ep");
00482 else
00483 abort ();
00484 }
00485 else
00486 abort ();
00487 break;
00488 case 'R':
00489 switch (GET_CODE (x))
00490 {
00491 case REG:
00492 fprintf (file, reg_names[REGNO (x) + 1]);
00493 break;
00494 case MEM:
00495 x = XEXP (adjust_address (x, SImode, 4), 0);
00496 print_operand_address (file, x);
00497 if (GET_CODE (x) == CONST_INT)
00498 fprintf (file, "[r0]");
00499 break;
00500
00501 default:
00502 break;
00503 }
00504 break;
00505 case 'S':
00506 {
00507
00508 if (GET_CODE (x) == MEM && ep_memory_operand (x, GET_MODE (x), FALSE))
00509 fputs ("s", file);
00510
00511 break;
00512 }
00513 case 'T':
00514 {
00515
00516 if (GET_CODE (x) == MEM && ep_memory_operand (x, GET_MODE (x), TRUE))
00517 fputs ("s", file);
00518
00519 break;
00520 }
00521 case 'W':
00522 switch (GET_MODE (x))
00523 {
00524 default:
00525 abort ();
00526
00527 case QImode: fputs (".b", file); break;
00528 case HImode: fputs (".h", file); break;
00529 case SImode: fputs (".w", file); break;
00530 case SFmode: fputs (".w", file); break;
00531 }
00532 break;
00533 case '.':
00534 fputs (reg_names[0], file);
00535 break;
00536 case 'z':
00537 if (x == const0_rtx)
00538 fputs (reg_names[0], file);
00539 else if (GET_CODE (x) == REG)
00540 fputs (reg_names[REGNO (x)], file);
00541 else
00542 abort ();
00543 break;
00544 default:
00545 switch (GET_CODE (x))
00546 {
00547 case MEM:
00548 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
00549 output_address (gen_rtx_PLUS (SImode, gen_rtx (REG, SImode, 0),
00550 XEXP (x, 0)));
00551 else
00552 output_address (XEXP (x, 0));
00553 break;
00554
00555 case REG:
00556 fputs (reg_names[REGNO (x)], file);
00557 break;
00558 case SUBREG:
00559 fputs (reg_names[subreg_regno (x)], file);
00560 break;
00561 case CONST_INT:
00562 case SYMBOL_REF:
00563 case CONST:
00564 case LABEL_REF:
00565 case CODE_LABEL:
00566 print_operand_address (file, x);
00567 break;
00568 default:
00569 abort ();
00570 }
00571 break;
00572
00573 }
00574 }
00575
00576
00577
00578
00579 void
00580 print_operand_address (file, addr)
00581 FILE *file;
00582 rtx addr;
00583 {
00584 switch (GET_CODE (addr))
00585 {
00586 case REG:
00587 fprintf (file, "0[");
00588 print_operand (file, addr, 0);
00589 fprintf (file, "]");
00590 break;
00591 case LO_SUM:
00592 if (GET_CODE (XEXP (addr, 0)) == REG)
00593 {
00594
00595 fprintf (file, "lo(");
00596 print_operand (file, XEXP (addr, 1), 0);
00597 fprintf (file, ")[");
00598 print_operand (file, XEXP (addr, 0), 0);
00599 fprintf (file, "]");
00600 }
00601 break;
00602 case PLUS:
00603 if (GET_CODE (XEXP (addr, 0)) == REG
00604 || GET_CODE (XEXP (addr, 0)) == SUBREG)
00605 {
00606
00607 print_operand (file, XEXP (addr, 1), 0);
00608 fprintf (file, "[");
00609 print_operand (file, XEXP (addr, 0), 0);
00610 fprintf (file, "]");
00611 }
00612 else
00613 {
00614 print_operand (file, XEXP (addr, 0), 0);
00615 fprintf (file, "+");
00616 print_operand (file, XEXP (addr, 1), 0);
00617 }
00618 break;
00619 case SYMBOL_REF:
00620 if (ENCODED_NAME_P (XSTR (addr, 0)))
00621 {
00622 const char *name = XSTR (addr, 0);
00623 const char *off_name;
00624 const char *reg_name;
00625
00626 if (ZDA_NAME_P (name))
00627 {
00628 off_name = "zdaoff";
00629 reg_name = "r0";
00630 }
00631 else if (SDA_NAME_P (name))
00632 {
00633 off_name = "sdaoff";
00634 reg_name = "gp";
00635 }
00636 else if (TDA_NAME_P (name))
00637 {
00638 off_name = "tdaoff";
00639 reg_name = "ep";
00640 }
00641 else
00642 abort ();
00643
00644 fprintf (file, "%s(", off_name);
00645 output_addr_const (file, addr);
00646 fprintf (file, ")[%s]", reg_name);
00647 }
00648 else
00649 output_addr_const (file, addr);
00650 break;
00651 case CONST:
00652 if (special_symbolref_operand (addr, VOIDmode))
00653 {
00654 const char *name = XSTR (XEXP (XEXP (addr, 0), 0), 0);
00655 const char *off_name;
00656 const char *reg_name;
00657
00658 if (ZDA_NAME_P (name))
00659 {
00660 off_name = "zdaoff";
00661 reg_name = "r0";
00662 }
00663 else if (SDA_NAME_P (name))
00664 {
00665 off_name = "sdaoff";
00666 reg_name = "gp";
00667 }
00668 else if (TDA_NAME_P (name))
00669 {
00670 off_name = "tdaoff";
00671 reg_name = "ep";
00672 }
00673 else
00674 abort ();
00675
00676 fprintf (file, "%s(", off_name);
00677 output_addr_const (file, addr);
00678 fprintf (file, ")[%s]", reg_name);
00679 }
00680 else
00681 output_addr_const (file, addr);
00682 break;
00683 default:
00684 output_addr_const (file, addr);
00685 break;
00686 }
00687 }
00688
00689
00690
00691
00692
00693 const char *
00694 output_move_single (operands)
00695 rtx *operands;
00696 {
00697 rtx dst = operands[0];
00698 rtx src = operands[1];
00699
00700 if (REG_P (dst))
00701 {
00702 if (REG_P (src))
00703 return "mov %1,%0";
00704
00705 else if (GET_CODE (src) == CONST_INT)
00706 {
00707 HOST_WIDE_INT value = INTVAL (src);
00708
00709 if (CONST_OK_FOR_J (value))
00710 return "mov %1,%0";
00711
00712 else if (CONST_OK_FOR_K (value))
00713 return "movea lo(%1),%.,%0";
00714
00715 else if (CONST_OK_FOR_L (value))
00716 return "movhi hi(%1),%.,%0";
00717
00718 else
00719 return "movhi hi(%1),%.,%0\n\tmovea lo(%1),%0,%0";
00720 }
00721
00722 else if (GET_CODE (src) == CONST_DOUBLE && GET_MODE (src) == SFmode)
00723 {
00724 HOST_WIDE_INT high, low;
00725
00726 const_double_split (src, &high, &low);
00727 if (CONST_OK_FOR_J (high))
00728 return "mov %F1,%0";
00729
00730 else if (CONST_OK_FOR_K (high))
00731 return "movea lo(%F1),%.,%0";
00732
00733 else if (CONST_OK_FOR_L (high))
00734 return "movhi hi(%F1),%.,%0";
00735
00736 else
00737 return "movhi hi(%F1),%.,%0\n\tmovea lo(%F1),%0,%0";
00738 }
00739
00740 else if (GET_CODE (src) == MEM)
00741 return "%S1ld%W1 %1,%0";
00742
00743 else if (special_symbolref_operand (src, VOIDmode))
00744 return "movea %O1(%P1),%Q1,%0";
00745
00746 else if (GET_CODE (src) == LABEL_REF
00747 || GET_CODE (src) == SYMBOL_REF
00748 || GET_CODE (src) == CONST)
00749 {
00750 return "movhi hi(%1),%.,%0\n\tmovea lo(%1),%0,%0";
00751 }
00752
00753 else if (GET_CODE (src) == HIGH)
00754 return "movhi hi(%1),%.,%0";
00755
00756 else if (GET_CODE (src) == LO_SUM)
00757 {
00758 operands[2] = XEXP (src, 0);
00759 operands[3] = XEXP (src, 1);
00760 return "movea lo(%3),%2,%0";
00761 }
00762 }
00763
00764 else if (GET_CODE (dst) == MEM)
00765 {
00766 if (REG_P (src))
00767 return "%S0st%W0 %1,%0";
00768
00769 else if (GET_CODE (src) == CONST_INT && INTVAL (src) == 0)
00770 return "%S0st%W0 %.,%0";
00771
00772 else if (GET_CODE (src) == CONST_DOUBLE
00773 && CONST0_RTX (GET_MODE (dst)) == src)
00774 return "%S0st%W0 %.,%0";
00775 }
00776
00777 fatal_insn ("output_move_single:", gen_rtx_SET (VOIDmode, dst, src));
00778 return "";
00779 }
00780
00781
00782
00783
00784
00785 const char *
00786 output_move_double (operands)
00787 rtx *operands;
00788 {
00789 enum machine_mode mode = GET_MODE (operands[0]);
00790 rtx dst = operands[0];
00791 rtx src = operands[1];
00792
00793 if (register_operand (dst, mode)
00794 && register_operand (src, mode))
00795 {
00796 if (REGNO (src) + 1 == REGNO (dst))
00797 return "mov %R1,%R0\n\tmov %1,%0";
00798 else
00799 return "mov %1,%0\n\tmov %R1,%R0";
00800 }
00801
00802
00803 if (GET_CODE (dst) == MEM
00804 && ((GET_CODE (src) == CONST_INT && INTVAL (src) == 0)
00805 || (GET_CODE (src) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_G (src))))
00806 return "st.w %.,%0\n\tst.w %.,%R0";
00807
00808 if (GET_CODE (src) == CONST_INT || GET_CODE (src) == CONST_DOUBLE)
00809 {
00810 HOST_WIDE_INT high_low[2];
00811 int i;
00812 rtx xop[10];
00813
00814 if (GET_CODE (src) == CONST_DOUBLE)
00815 const_double_split (src, &high_low[1], &high_low[0]);
00816 else
00817 {
00818 high_low[0] = INTVAL (src);
00819 high_low[1] = (INTVAL (src) >= 0) ? 0 : -1;
00820 }
00821
00822 for (i = 0; i < 2; i++)
00823 {
00824 xop[0] = gen_rtx_REG (SImode, REGNO (dst)+i);
00825 xop[1] = GEN_INT (high_low[i]);
00826 output_asm_insn (output_move_single (xop), xop);
00827 }
00828
00829 return "";
00830 }
00831
00832 if (GET_CODE (src) == MEM)
00833 {
00834 int ptrreg = -1;
00835 int dreg = REGNO (dst);
00836 rtx inside = XEXP (src, 0);
00837
00838 if (GET_CODE (inside) == REG)
00839 ptrreg = REGNO (inside);
00840 else if (GET_CODE (inside) == SUBREG)
00841 ptrreg = subreg_regno (inside);
00842 else if (GET_CODE (inside) == PLUS)
00843 ptrreg = REGNO (XEXP (inside, 0));
00844 else if (GET_CODE (inside) == LO_SUM)
00845 ptrreg = REGNO (XEXP (inside, 0));
00846
00847 if (dreg == ptrreg)
00848 return "ld.w %R1,%R0\n\tld.w %1,%0";
00849 }
00850
00851 if (GET_CODE (src) == MEM)
00852 return "ld.w %1,%0\n\tld.w %R1,%R0";
00853
00854 if (GET_CODE (dst) == MEM)
00855 return "st.w %1,%0\n\tst.w %R1,%R0";
00856
00857 return "mov %1,%0\n\tmov %R1,%R0";
00858 }
00859
00860
00861
00862
00863
00864 static int
00865 ep_memory_offset (mode, unsignedp)
00866 enum machine_mode mode;
00867 int ATTRIBUTE_UNUSED unsignedp;
00868 {
00869 int max_offset = 0;
00870
00871 switch (mode)
00872 {
00873 case QImode:
00874 max_offset = (1 << 7);
00875 break;
00876
00877 case HImode:
00878 max_offset = (1 << 8);
00879 break;
00880
00881 case SImode:
00882 case SFmode:
00883 max_offset = (1 << 8);
00884 break;
00885
00886 default:
00887 break;
00888 }
00889
00890 return max_offset;
00891 }
00892
00893
00894
00895 int
00896 ep_memory_operand (op, mode, unsigned_load)
00897 rtx op;
00898 enum machine_mode mode;
00899 int unsigned_load;
00900 {
00901 rtx addr, op0, op1;
00902 int max_offset;
00903 int mask;
00904
00905 if (GET_CODE (op) != MEM)
00906 return FALSE;
00907
00908 max_offset = ep_memory_offset (mode, unsigned_load);
00909
00910 mask = GET_MODE_SIZE (mode) - 1;
00911
00912 addr = XEXP (op, 0);
00913 if (GET_CODE (addr) == CONST)
00914 addr = XEXP (addr, 0);
00915
00916 switch (GET_CODE (addr))
00917 {
00918 default:
00919 break;
00920
00921 case SYMBOL_REF:
00922 return TDA_NAME_P (XSTR (addr, 0));
00923
00924 case REG:
00925 return REGNO (addr) == EP_REGNUM;
00926
00927 case PLUS:
00928 op0 = XEXP (addr, 0);
00929 op1 = XEXP (addr, 1);
00930 if (GET_CODE (op1) == CONST_INT
00931 && INTVAL (op1) < max_offset
00932 && INTVAL (op1) >= 0
00933 && (INTVAL (op1) & mask) == 0)
00934 {
00935 if (GET_CODE (op0) == REG && REGNO (op0) == EP_REGNUM)
00936 return TRUE;
00937
00938 if (GET_CODE (op0) == SYMBOL_REF && TDA_NAME_P (XSTR (op0, 0)))
00939 return TRUE;
00940 }
00941 break;
00942 }
00943
00944 return FALSE;
00945 }
00946
00947
00948
00949 int
00950 reg_or_0_operand (op, mode)
00951 rtx op;
00952 enum machine_mode mode;
00953 {
00954 if (GET_CODE (op) == CONST_INT)
00955 return INTVAL (op) == 0;
00956
00957 else if (GET_CODE (op) == CONST_DOUBLE)
00958 return CONST_DOUBLE_OK_FOR_G (op);
00959
00960 else
00961 return register_operand (op, mode);
00962 }
00963
00964
00965
00966 int
00967 reg_or_int5_operand (op, mode)
00968 rtx op;
00969 enum machine_mode mode;
00970 {
00971 if (GET_CODE (op) == CONST_INT)
00972 return CONST_OK_FOR_J (INTVAL (op));
00973
00974 else
00975 return register_operand (op, mode);
00976 }
00977
00978
00979
00980 int
00981 call_address_operand (op, mode)
00982 rtx op;
00983 enum machine_mode ATTRIBUTE_UNUSED mode;
00984 {
00985
00986 if (TARGET_LONG_CALLS)
00987 return GET_CODE (op) == REG;
00988 return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG);
00989 }
00990
00991 int
00992 special_symbolref_operand (op, mode)
00993 rtx op;
00994 enum machine_mode ATTRIBUTE_UNUSED mode;
00995 {
00996 if (GET_CODE (op) == SYMBOL_REF)
00997 return ENCODED_NAME_P (XSTR (op, 0));
00998
00999 else if (GET_CODE (op) == CONST)
01000 return (GET_CODE (XEXP (op, 0)) == PLUS
01001 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
01002 && ENCODED_NAME_P (XSTR (XEXP (XEXP (op, 0), 0), 0))
01003 && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT
01004 && CONST_OK_FOR_K (INTVAL (XEXP (XEXP (op, 0), 1))));
01005
01006 return FALSE;
01007 }
01008
01009 int
01010 movsi_source_operand (op, mode)
01011 rtx op;
01012 enum machine_mode mode;
01013 {
01014
01015
01016 if (CONSTANT_P (op)
01017 && GET_CODE (op) != HIGH
01018 && GET_CODE (op) != CONSTANT_P_RTX
01019 && !(GET_CODE (op) == CONST_INT
01020 && (CONST_OK_FOR_J (INTVAL (op))
01021 || CONST_OK_FOR_K (INTVAL (op))
01022 || CONST_OK_FOR_L (INTVAL (op)))))
01023 return special_symbolref_operand (op, mode);
01024 else
01025 return general_operand (op, mode);
01026 }
01027
01028 int
01029 power_of_two_operand (op, mode)
01030 rtx op;
01031 enum machine_mode ATTRIBUTE_UNUSED mode;
01032 {
01033 if (GET_CODE (op) != CONST_INT)
01034 return 0;
01035
01036 if (exact_log2 (INTVAL (op)) == -1)
01037 return 0;
01038 return 1;
01039 }
01040
01041 int
01042 not_power_of_two_operand (op, mode)
01043 rtx op;
01044 enum machine_mode mode;
01045 {
01046 unsigned int mask;
01047
01048 if (mode == QImode)
01049 mask = 0xff;
01050 else if (mode == HImode)
01051 mask = 0xffff;
01052 else if (mode == SImode)
01053 mask = 0xffffffff;
01054 else
01055 return 0;
01056
01057 if (GET_CODE (op) != CONST_INT)
01058 return 0;
01059
01060 if (exact_log2 (~INTVAL (op) & mask) == -1)
01061 return 0;
01062 return 1;
01063 }
01064
01065
01066
01067
01068
01069 static void
01070 substitute_ep_register (first_insn, last_insn, uses, regno, p_r1, p_ep)
01071 rtx first_insn;
01072 rtx last_insn;
01073 int uses;
01074 int regno;
01075 rtx *p_r1;
01076 rtx *p_ep;
01077 {
01078 rtx reg = gen_rtx_REG (Pmode, regno);
01079 rtx insn;
01080
01081 if (!*p_r1)
01082 {
01083 regs_ever_live[1] = 1;
01084 *p_r1 = gen_rtx_REG (Pmode, 1);
01085 *p_ep = gen_rtx_REG (Pmode, 30);
01086 }
01087
01088 if (TARGET_DEBUG)
01089 fprintf (stderr, "\
01090 Saved %d bytes (%d uses of register %s) in function %s, starting as insn %d, ending at %d\n",
01091 2 * (uses - 3), uses, reg_names[regno],
01092 IDENTIFIER_POINTER (DECL_NAME (current_function_decl)),
01093 INSN_UID (first_insn), INSN_UID (last_insn));
01094
01095 if (GET_CODE (first_insn) == NOTE)
01096 first_insn = next_nonnote_insn (first_insn);
01097
01098 last_insn = next_nonnote_insn (last_insn);
01099 for (insn = first_insn; insn && insn != last_insn; insn = NEXT_INSN (insn))
01100 {
01101 if (GET_CODE (insn) == INSN)
01102 {
01103 rtx pattern = single_set (insn);
01104
01105
01106 if (pattern)
01107 {
01108 rtx *p_mem;
01109
01110 int unsignedp = FALSE;
01111
01112 if (GET_CODE (SET_DEST (pattern)) == MEM
01113 && GET_CODE (SET_SRC (pattern)) == MEM)
01114 p_mem = (rtx *)0;
01115
01116 else if (GET_CODE (SET_DEST (pattern)) == MEM)
01117 p_mem = &SET_DEST (pattern);
01118
01119 else if (GET_CODE (SET_SRC (pattern)) == MEM)
01120 p_mem = &SET_SRC (pattern);
01121
01122 else
01123 p_mem = (rtx *)0;
01124
01125 if (p_mem)
01126 {
01127 rtx addr = XEXP (*p_mem, 0);
01128
01129 if (GET_CODE (addr) == REG && REGNO (addr) == (unsigned) regno)
01130 *p_mem = change_address (*p_mem, VOIDmode, *p_ep);
01131
01132 else if (GET_CODE (addr) == PLUS
01133 && GET_CODE (XEXP (addr, 0)) == REG
01134 && REGNO (XEXP (addr, 0)) == (unsigned) regno
01135 && GET_CODE (XEXP (addr, 1)) == CONST_INT
01136 && ((INTVAL (XEXP (addr, 1)))
01137 < ep_memory_offset (GET_MODE (*p_mem),
01138 unsignedp))
01139 && ((INTVAL (XEXP (addr, 1))) >= 0))
01140 *p_mem = change_address (*p_mem, VOIDmode,
01141 gen_rtx_PLUS (Pmode,
01142 *p_ep,
01143 XEXP (addr, 1)));
01144 }
01145 }
01146 }
01147 }
01148
01149
01150 insn = prev_nonnote_insn (first_insn);
01151 if (insn && GET_CODE (insn) == INSN
01152 && GET_CODE (PATTERN (insn)) == SET
01153 && SET_DEST (PATTERN (insn)) == *p_ep
01154 && SET_SRC (PATTERN (insn)) == *p_r1)
01155 delete_insn (insn);
01156 else
01157 emit_insn_before (gen_rtx_SET (Pmode, *p_r1, *p_ep), first_insn);
01158
01159 emit_insn_before (gen_rtx_SET (Pmode, *p_ep, reg), first_insn);
01160 emit_insn_before (gen_rtx_SET (Pmode, *p_ep, *p_r1), last_insn);
01161 }
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172 void v850_reorg (start_insn)
01173 rtx start_insn;
01174 {
01175 struct
01176 {
01177 int uses;
01178 rtx first_insn;
01179 rtx last_insn;
01180 }
01181 regs[FIRST_PSEUDO_REGISTER];
01182
01183 int i;
01184 int use_ep = FALSE;
01185 rtx r1 = NULL_RTX;
01186 rtx ep = NULL_RTX;
01187 rtx insn;
01188 rtx pattern;
01189
01190
01191 if (!TARGET_EP)
01192 return;
01193
01194 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01195 {
01196 regs[i].uses = 0;
01197 regs[i].first_insn = NULL_RTX;
01198 regs[i].last_insn = NULL_RTX;
01199 }
01200
01201 for (insn = start_insn; insn != NULL_RTX; insn = NEXT_INSN (insn))
01202 {
01203 switch (GET_CODE (insn))
01204 {
01205
01206 default:
01207 if (!use_ep)
01208 {
01209 int max_uses = -1;
01210 int max_regno = -1;
01211
01212 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01213 {
01214 if (max_uses < regs[i].uses)
01215 {
01216 max_uses = regs[i].uses;
01217 max_regno = i;
01218 }
01219 }
01220
01221 if (max_uses > 3)
01222 substitute_ep_register (regs[max_regno].first_insn,
01223 regs[max_regno].last_insn,
01224 max_uses, max_regno, &r1, &ep);
01225 }
01226
01227 use_ep = FALSE;
01228 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01229 {
01230 regs[i].uses = 0;
01231 regs[i].first_insn = NULL_RTX;
01232 regs[i].last_insn = NULL_RTX;
01233 }
01234 break;
01235
01236 case NOTE:
01237 break;
01238
01239 case INSN:
01240 pattern = single_set (insn);
01241
01242
01243 if (pattern)
01244 {
01245 rtx src = SET_SRC (pattern);
01246 rtx dest = SET_DEST (pattern);
01247 rtx mem;
01248
01249 int unsignedp = FALSE;
01250
01251
01252
01253 if (GET_CODE (dest) == SUBREG
01254 && (GET_CODE (SUBREG_REG (dest)) == MEM
01255 || GET_CODE (SUBREG_REG (dest)) == REG))
01256 alter_subreg (&dest);
01257 if (GET_CODE (src) == SUBREG
01258 && (GET_CODE (SUBREG_REG (src)) == MEM
01259 || GET_CODE (SUBREG_REG (src)) == REG))
01260 alter_subreg (&src);
01261
01262 if (GET_CODE (dest) == MEM && GET_CODE (src) == MEM)
01263 mem = NULL_RTX;
01264
01265 else if (GET_CODE (dest) == MEM)
01266 mem = dest;
01267
01268 else if (GET_CODE (src) == MEM)
01269 mem = src;
01270
01271 else
01272 mem = NULL_RTX;
01273
01274 if (mem && ep_memory_operand (mem, GET_MODE (mem), unsignedp))
01275 use_ep = TRUE;
01276
01277 else if (!use_ep && mem
01278 && GET_MODE_SIZE (GET_MODE (mem)) <= UNITS_PER_WORD)
01279 {
01280 rtx addr = XEXP (mem, 0);
01281 int regno = -1;
01282 int short_p;
01283
01284 if (GET_CODE (addr) == REG)
01285 {
01286 short_p = TRUE;
01287 regno = REGNO (addr);
01288 }
01289
01290 else if (GET_CODE (addr) == PLUS
01291 && GET_CODE (XEXP (addr, 0)) == REG
01292 && GET_CODE (XEXP (addr, 1)) == CONST_INT
01293 && ((INTVAL (XEXP (addr, 1)))
01294 < ep_memory_offset (GET_MODE (mem), unsignedp))
01295 && ((INTVAL (XEXP (addr, 1))) >= 0))
01296 {
01297 short_p = TRUE;
01298 regno = REGNO (XEXP (addr, 0));
01299 }
01300
01301 else
01302 short_p = FALSE;
01303
01304 if (short_p)
01305 {
01306 regs[regno].uses++;
01307 regs[regno].last_insn = insn;
01308 if (!regs[regno].first_insn)
01309 regs[regno].first_insn = insn;
01310 }
01311 }
01312
01313
01314
01315 if (GET_CODE (dest) == REG)
01316 {
01317 enum machine_mode mode = GET_MODE (dest);
01318 int regno;
01319 int endregno;
01320
01321 regno = REGNO (dest);
01322 endregno = regno + HARD_REGNO_NREGS (regno, mode);
01323
01324 if (!use_ep)
01325 {
01326
01327
01328 int max_uses = -1;
01329 int max_regno = -1;
01330
01331 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01332 {
01333 if (max_uses < regs[i].uses)
01334 {
01335 max_uses = regs[i].uses;
01336 max_regno = i;
01337 }
01338 }
01339
01340 if (max_uses > 3
01341 && max_regno >= regno
01342 && max_regno < endregno)
01343 {
01344 substitute_ep_register (regs[max_regno].first_insn,
01345 regs[max_regno].last_insn,
01346 max_uses, max_regno, &r1,
01347 &ep);
01348
01349
01350
01351 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01352 {
01353 regs[i].uses = 0;
01354 regs[i].first_insn = NULL_RTX;
01355 regs[i].last_insn = NULL_RTX;
01356 }
01357 }
01358 }
01359
01360 for (i = regno; i < endregno; i++)
01361 {
01362 regs[i].uses = 0;
01363 regs[i].first_insn = NULL_RTX;
01364 regs[i].last_insn = NULL_RTX;
01365 }
01366 }
01367 }
01368 }
01369 }
01370 }
01371
01372
01373
01374 #define INTERRUPT_FIXED_NUM 4
01375
01376
01377 #define INTERRUPT_FIXED_SAVE_SIZE (4 * INTERRUPT_FIXED_NUM)
01378
01379
01380 #define INTERRUPT_REGPARM_NUM 4
01381
01382 #define INTERRUPT_ALL_SAVE_NUM \
01383 (30 - INTERRUPT_FIXED_NUM + INTERRUPT_REGPARM_NUM)
01384
01385 #define INTERRUPT_ALL_SAVE_SIZE (4 * INTERRUPT_ALL_SAVE_NUM)
01386
01387 int
01388 compute_register_save_size (p_reg_saved)
01389 long *p_reg_saved;
01390 {
01391 int size = 0;
01392 int i;
01393 int interrupt_handler = v850_interrupt_function_p (current_function_decl);
01394 int call_p = regs_ever_live [LINK_POINTER_REGNUM];
01395 long reg_saved = 0;
01396
01397
01398 if (current_function_profile && !call_p)
01399 regs_ever_live [LINK_POINTER_REGNUM] = call_p = 1;
01400
01401
01402 if (interrupt_handler)
01403 {
01404 for (i = 0; i <= 31; i++)
01405 switch (i)
01406 {
01407 default:
01408 if (regs_ever_live[i] || call_p)
01409 {
01410 size += 4;
01411 reg_saved |= 1L << i;
01412 }
01413 break;
01414
01415
01416 case 0:
01417 case STACK_POINTER_REGNUM:
01418 break;
01419
01420
01421
01422
01423
01424 case 1:
01425 case 4:
01426 case 10:
01427 case EP_REGNUM:
01428 size += 4;
01429 break;
01430 }
01431 }
01432 else
01433 {
01434
01435 for (i = 0; i <= 31; i++)
01436 if (regs_ever_live[i] && ((! call_used_regs[i])
01437 || i == LINK_POINTER_REGNUM))
01438 break;
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450 if (TARGET_PROLOG_FUNCTION
01451 && (i == 2 || i >= 20)
01452 && regs_ever_live[LINK_POINTER_REGNUM] ? (i < 28) : (i < 30))
01453 {
01454 if (i == 2)
01455 {
01456 size += 4;
01457 reg_saved |= 1L << i;
01458
01459 i = 20;
01460 }
01461
01462
01463
01464
01465 for (; i <= 29; i++)
01466 {
01467 size += 4;
01468 reg_saved |= 1L << i;
01469 }
01470
01471 if (regs_ever_live [LINK_POINTER_REGNUM])
01472 {
01473 size += 4;
01474 reg_saved |= 1L << LINK_POINTER_REGNUM;
01475 }
01476 }
01477 else
01478 {
01479 for (; i <= 31; i++)
01480 if (regs_ever_live[i] && ((! call_used_regs[i])
01481 || i == LINK_POINTER_REGNUM))
01482 {
01483 size += 4;
01484 reg_saved |= 1L << i;
01485 }
01486 }
01487 }
01488
01489 if (p_reg_saved)
01490 *p_reg_saved = reg_saved;
01491
01492 return size;
01493 }
01494
01495 int
01496 compute_frame_size (size, p_reg_saved)
01497 int size;
01498 long *p_reg_saved;
01499 {
01500 return (size
01501 + compute_register_save_size (p_reg_saved)
01502 + current_function_outgoing_args_size);
01503 }
01504
01505
01506 void
01507 expand_prologue ()
01508 {
01509 unsigned int i;
01510 int offset;
01511 unsigned int size = get_frame_size ();
01512 unsigned int actual_fsize;
01513 unsigned int init_stack_alloc = 0;
01514 rtx save_regs[32];
01515 rtx save_all;
01516 unsigned int num_save;
01517 unsigned int default_stack;
01518 int code;
01519 int interrupt_handler = v850_interrupt_function_p (current_function_decl);
01520 long reg_saved = 0;
01521
01522 actual_fsize = compute_frame_size (size, ®_saved);
01523
01524
01525 if (interrupt_handler)
01526 {
01527 emit_insn (gen_save_interrupt ());
01528
01529 actual_fsize -= INTERRUPT_FIXED_SAVE_SIZE;
01530
01531 if (((1L << LINK_POINTER_REGNUM) & reg_saved) != 0)
01532 actual_fsize -= INTERRUPT_ALL_SAVE_SIZE;
01533 }
01534
01535
01536 else if (current_function_anonymous_args)
01537 {
01538 if (TARGET_PROLOG_FUNCTION)
01539 {
01540 emit_insn (gen_save_r6_r9 ());
01541 }
01542 else
01543 {
01544 offset = 0;
01545 for (i = 6; i < 10; i++)
01546 {
01547 emit_move_insn (gen_rtx_MEM (SImode,
01548 plus_constant (stack_pointer_rtx,
01549 offset)),
01550 gen_rtx_REG (SImode, i));
01551 offset += 4;
01552 }
01553 }
01554 }
01555
01556
01557 num_save = 0;
01558 default_stack = 0;
01559 for (i = 1; i < 31; i++)
01560 {
01561 if (((1L << i) & reg_saved) != 0)
01562 save_regs[num_save++] = gen_rtx_REG (Pmode, i);
01563 }
01564
01565
01566
01567 if (((1L << LINK_POINTER_REGNUM) & reg_saved) != 0)
01568 {
01569 save_regs[num_save++] = gen_rtx_REG (Pmode, LINK_POINTER_REGNUM);
01570 default_stack = 16;
01571 }
01572
01573
01574
01575 save_all = NULL_RTX;
01576 if (TARGET_PROLOG_FUNCTION && num_save > 0 && actual_fsize >= default_stack)
01577 {
01578 int alloc_stack = (4 * num_save) + default_stack;
01579 int unalloc_stack = actual_fsize - alloc_stack;
01580 int save_func_len = 4;
01581 int save_normal_len;
01582
01583 if (unalloc_stack)
01584 save_func_len += CONST_OK_FOR_J (unalloc_stack) ? 2 : 4;
01585
01586
01587 if (TARGET_EP && num_save > 3 && (unsigned)actual_fsize < 255)
01588 save_normal_len = (3 * 2) + (2 * num_save);
01589 else
01590 save_normal_len = 4 * num_save;
01591
01592 save_normal_len += CONST_OK_FOR_J (actual_fsize) ? 2 : 4;
01593
01594
01595
01596
01597 if (save_func_len < save_normal_len)
01598 {
01599 save_all = gen_rtx_PARALLEL
01600 (VOIDmode,
01601 rtvec_alloc (num_save + (TARGET_V850 ? 2 : 1)));
01602
01603 XVECEXP (save_all, 0, 0)
01604 = gen_rtx_SET (VOIDmode,
01605 stack_pointer_rtx,
01606 plus_constant (stack_pointer_rtx, -alloc_stack));
01607
01608 if (TARGET_V850)
01609 {
01610 XVECEXP (save_all, 0, num_save+1)
01611 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 10));
01612 }
01613
01614 offset = - default_stack;
01615 for (i = 0; i < num_save; i++)
01616 {
01617 XVECEXP (save_all, 0, i+1)
01618 = gen_rtx_SET (VOIDmode,
01619 gen_rtx_MEM (Pmode,
01620 plus_constant (stack_pointer_rtx,
01621 offset)),
01622 save_regs[i]);
01623 offset -= 4;
01624 }
01625
01626 code = recog (save_all, NULL_RTX, NULL);
01627 if (code >= 0)
01628 {
01629 rtx insn = emit_insn (save_all);
01630 INSN_CODE (insn) = code;
01631 actual_fsize -= alloc_stack;
01632
01633 if (TARGET_DEBUG)
01634 fprintf (stderr, "\
01635 Saved %d bytes via prologue function (%d vs. %d) for function %s\n",
01636 save_normal_len - save_func_len,
01637 save_normal_len, save_func_len,
01638 IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
01639 }
01640 else
01641 save_all = NULL_RTX;
01642 }
01643 }
01644
01645
01646
01647 if (!save_all)
01648 {
01649
01650 if (interrupt_handler && ((1L << LINK_POINTER_REGNUM) & reg_saved) != 0)
01651 {
01652 emit_insn (gen_save_all_interrupt ());
01653 }
01654 else
01655 {
01656
01657
01658
01659 if (actual_fsize && !CONST_OK_FOR_K (-actual_fsize))
01660 init_stack_alloc = compute_register_save_size (NULL);
01661 else
01662 init_stack_alloc = actual_fsize;
01663
01664
01665 offset = init_stack_alloc - 4;
01666
01667 if (init_stack_alloc)
01668 emit_insn (gen_addsi3 (stack_pointer_rtx,
01669 stack_pointer_rtx,
01670 GEN_INT (-init_stack_alloc)));
01671
01672
01673 if (num_save > 0 && REGNO (save_regs[num_save-1]) == LINK_POINTER_REGNUM)
01674 {
01675 emit_move_insn (gen_rtx_MEM (SImode,
01676 plus_constant (stack_pointer_rtx,
01677 offset)),
01678 save_regs[--num_save]);
01679 offset -= 4;
01680 }
01681
01682 for (i = 0; i < num_save; i++)
01683 {
01684 emit_move_insn (gen_rtx_MEM (SImode,
01685 plus_constant (stack_pointer_rtx,
01686 offset)),
01687 save_regs[i]);
01688 offset -= 4;
01689 }
01690 }
01691 }
01692
01693
01694
01695
01696 if (actual_fsize > init_stack_alloc)
01697 {
01698 int diff = actual_fsize - init_stack_alloc;
01699 if (CONST_OK_FOR_K (diff))
01700 emit_insn (gen_addsi3 (stack_pointer_rtx,
01701 stack_pointer_rtx,
01702 GEN_INT (-diff)));
01703 else
01704 {
01705 rtx reg = gen_rtx_REG (Pmode, 12);
01706 emit_move_insn (reg, GEN_INT (-diff));
01707 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg));
01708 }
01709 }
01710
01711
01712 if (frame_pointer_needed)
01713 emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
01714 }
01715
01716
01717 void
01718 expand_epilogue ()
01719 {
01720 unsigned int i;
01721 int offset;
01722 unsigned int size = get_frame_size ();
01723 long reg_saved = 0;
01724 unsigned int actual_fsize = compute_frame_size (size, ®_saved);
01725 unsigned int init_stack_free = 0;
01726 rtx restore_regs[32];
01727 rtx restore_all;
01728 unsigned int num_restore;
01729 unsigned int default_stack;
01730 int code;
01731 int interrupt_handler = v850_interrupt_function_p (current_function_decl);
01732
01733
01734 if (interrupt_handler)
01735 {
01736 actual_fsize -= INTERRUPT_FIXED_SAVE_SIZE;
01737 if (((1L << LINK_POINTER_REGNUM) & reg_saved) != 0)
01738 actual_fsize -= INTERRUPT_ALL_SAVE_SIZE;
01739 }
01740
01741
01742 if (frame_pointer_needed)
01743 emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx);
01744
01745
01746 num_restore = 0;
01747 default_stack = 0;
01748 for (i = 1; i < 31; i++)
01749 {
01750 if (((1L << i) & reg_saved) != 0)
01751 restore_regs[num_restore++] = gen_rtx_REG (Pmode, i);
01752 }
01753
01754
01755
01756 if (((1L << LINK_POINTER_REGNUM) & reg_saved) != 0)
01757 {
01758 restore_regs[num_restore++] = gen_rtx_REG (Pmode, LINK_POINTER_REGNUM);
01759 default_stack = 16;
01760 }
01761
01762
01763
01764 restore_all = NULL_RTX;
01765
01766 if (TARGET_PROLOG_FUNCTION
01767 && num_restore > 0
01768 && actual_fsize >= default_stack
01769 && !interrupt_handler)
01770 {
01771 int alloc_stack = (4 * num_restore) + default_stack;
01772 int unalloc_stack = actual_fsize - alloc_stack;
01773 int restore_func_len = 4;
01774 int restore_normal_len;
01775
01776 if (unalloc_stack)
01777 restore_func_len += CONST_OK_FOR_J (unalloc_stack) ? 2 : 4;
01778
01779
01780 if (TARGET_EP && num_restore > 3 && (unsigned)actual_fsize < 255)
01781 restore_normal_len = (3 * 2) + (2 * num_restore);
01782 else
01783 restore_normal_len = 4 * num_restore;
01784
01785 restore_normal_len += (CONST_OK_FOR_J (actual_fsize) ? 2 : 4) + 2;
01786
01787
01788 if (restore_func_len < restore_normal_len)
01789 {
01790 restore_all = gen_rtx_PARALLEL (VOIDmode,
01791 rtvec_alloc (num_restore + 2));
01792 XVECEXP (restore_all, 0, 0) = gen_rtx_RETURN (VOIDmode);
01793 XVECEXP (restore_all, 0, 1)
01794 = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
01795 gen_rtx_PLUS (Pmode,
01796 stack_pointer_rtx,
01797 GEN_INT (alloc_stack)));
01798
01799 offset = alloc_stack - 4;
01800 for (i = 0; i < num_restore; i++)
01801 {
01802 XVECEXP (restore_all, 0, i+2)
01803 = gen_rtx_SET (VOIDmode,
01804 restore_regs[i],
01805 gen_rtx_MEM (Pmode,
01806 plus_constant (stack_pointer_rtx,
01807 offset)));
01808 offset -= 4;
01809 }
01810
01811 code = recog (restore_all, NULL_RTX, NULL);
01812
01813 if (code >= 0)
01814 {
01815 rtx insn;
01816
01817 actual_fsize -= alloc_stack;
01818 if (actual_fsize)
01819 {
01820 if (CONST_OK_FOR_K (actual_fsize))
01821 emit_insn (gen_addsi3 (stack_pointer_rtx,
01822 stack_pointer_rtx,
01823 GEN_INT (actual_fsize)));
01824 else
01825 {
01826 rtx reg = gen_rtx_REG (Pmode, 12);
01827 emit_move_insn (reg, GEN_INT (actual_fsize));
01828 emit_insn (gen_addsi3 (stack_pointer_rtx,
01829 stack_pointer_rtx,
01830 reg));
01831 }
01832 }
01833
01834 insn = emit_jump_insn (restore_all);
01835 INSN_CODE (insn) = code;
01836
01837 if (TARGET_DEBUG)
01838 fprintf (stderr, "\
01839 Saved %d bytes via epilogue function (%d vs. %d) in function %s\n",
01840 restore_normal_len - restore_func_len,
01841 restore_normal_len, restore_func_len,
01842 IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
01843 }
01844 else
01845 restore_all = NULL_RTX;
01846 }
01847 }
01848
01849
01850
01851 if (!restore_all)
01852 {
01853
01854 if (actual_fsize && !CONST_OK_FOR_K (-actual_fsize))
01855 init_stack_free = 4 * num_restore;
01856 else
01857 init_stack_free = actual_fsize;
01858
01859
01860 if (actual_fsize > init_stack_free)
01861 {
01862 int diff;
01863
01864 diff = actual_fsize - ((interrupt_handler) ? 0 : init_stack_free);
01865
01866 if (CONST_OK_FOR_K (diff))
01867 emit_insn (gen_addsi3 (stack_pointer_rtx,
01868 stack_pointer_rtx,
01869 GEN_INT (diff)));
01870 else
01871 {
01872 rtx reg = gen_rtx_REG (Pmode, 12);
01873 emit_move_insn (reg, GEN_INT (diff));
01874 emit_insn (gen_addsi3 (stack_pointer_rtx,
01875 stack_pointer_rtx,
01876 reg));
01877 }
01878 }
01879
01880
01881
01882 if (interrupt_handler && ((1L << LINK_POINTER_REGNUM) & reg_saved) != 0)
01883 {
01884 emit_insn (gen_restore_all_interrupt ());
01885 }
01886 else
01887 {
01888
01889 offset = init_stack_free - 4;
01890
01891
01892 if (num_restore > 0
01893 && REGNO (restore_regs [num_restore - 1]) == LINK_POINTER_REGNUM)
01894 {
01895 emit_move_insn (restore_regs[--num_restore],
01896 gen_rtx_MEM (SImode,
01897 plus_constant (stack_pointer_rtx,
01898 offset)));
01899 offset -= 4;
01900 }
01901
01902 for (i = 0; i < num_restore; i++)
01903 {
01904 emit_move_insn (restore_regs[i],
01905 gen_rtx_MEM (SImode,
01906 plus_constant (stack_pointer_rtx,
01907 offset)));
01908
01909 emit_insn (gen_rtx_USE (VOIDmode, restore_regs[i]));
01910 offset -= 4;
01911 }
01912
01913
01914 if (init_stack_free)
01915 emit_insn (gen_addsi3 (stack_pointer_rtx,
01916 stack_pointer_rtx,
01917 GEN_INT (init_stack_free)));
01918 }
01919
01920
01921 if (interrupt_handler)
01922 emit_jump_insn (gen_restore_interrupt ());
01923 else if (actual_fsize)
01924 emit_jump_insn (gen_return_internal ());
01925 else
01926 emit_jump_insn (gen_return ());
01927 }
01928
01929 current_function_anonymous_args = 0;
01930 v850_interrupt_cache_p = FALSE;
01931 v850_interrupt_p = FALSE;
01932 }
01933
01934
01935
01936
01937 void
01938 notice_update_cc (body, insn)
01939 rtx body;
01940 rtx insn;
01941 {
01942 switch (get_attr_cc (insn))
01943 {
01944 case CC_NONE:
01945
01946 break;
01947
01948 case CC_NONE_0HIT:
01949
01950 if (cc_status.value1 != 0
01951 && reg_overlap_mentioned_p (recog_data.operand[0], cc_status.value1))
01952 cc_status.value1 = 0;
01953 break;
01954
01955 case CC_SET_ZN:
01956
01957
01958 CC_STATUS_INIT;
01959 cc_status.flags |= CC_OVERFLOW_UNUSABLE | CC_NO_CARRY;
01960 cc_status.value1 = recog_data.operand[0];
01961 break;
01962
01963 case CC_SET_ZNV:
01964
01965
01966 CC_STATUS_INIT;
01967 cc_status.flags |= CC_NO_CARRY;
01968 cc_status.value1 = recog_data.operand[0];
01969 break;
01970
01971 case CC_COMPARE:
01972
01973 CC_STATUS_INIT;
01974 cc_status.value1 = SET_SRC (body);
01975 break;
01976
01977 case CC_CLOBBER:
01978
01979 CC_STATUS_INIT;
01980 break;
01981 }
01982 }
01983
01984
01985
01986 v850_data_area
01987 v850_get_data_area (decl)
01988 tree decl;
01989 {
01990 if (lookup_attribute ("sda", DECL_ATTRIBUTES (decl)) != NULL_TREE)
01991 return DATA_AREA_SDA;
01992
01993 if (lookup_attribute ("tda", DECL_ATTRIBUTES (decl)) != NULL_TREE)
01994 return DATA_AREA_TDA;
01995
01996 if (lookup_attribute ("zda", DECL_ATTRIBUTES (decl)) != NULL_TREE)
01997 return DATA_AREA_ZDA;
01998
01999 return DATA_AREA_NORMAL;
02000 }
02001
02002
02003
02004 static void
02005 v850_set_data_area (decl, data_area)
02006 tree decl;
02007 v850_data_area data_area;
02008 {
02009 tree name;
02010
02011 switch (data_area)
02012 {
02013 case DATA_AREA_SDA: name = get_identifier ("sda"); break;
02014 case DATA_AREA_TDA: name = get_identifier ("tda"); break;
02015 case DATA_AREA_ZDA: name = get_identifier ("zda"); break;
02016 default:
02017 return;
02018 }
02019
02020 DECL_ATTRIBUTES (decl) = tree_cons
02021 (name, NULL, DECL_ATTRIBUTES (decl));
02022 }
02023
02024 const struct attribute_spec v850_attribute_table[] =
02025 {
02026
02027 { "interrupt_handler", 0, 0, true, false, false, v850_handle_interrupt_attribute },
02028 { "interrupt", 0, 0, true, false, false, v850_handle_interrupt_attribute },
02029 { "sda", 0, 0, true, false, false, v850_handle_data_area_attribute },
02030 { "tda", 0, 0, true, false, false, v850_handle_data_area_attribute },
02031 { "zda", 0, 0, true, false, false, v850_handle_data_area_attribute },
02032 { NULL, 0, 0, false, false, false, NULL }
02033 };
02034
02035
02036
02037 static tree
02038 v850_handle_interrupt_attribute (node, name, args, flags, no_add_attrs)
02039 tree *node;
02040 tree name;
02041 tree args ATTRIBUTE_UNUSED;
02042 int flags ATTRIBUTE_UNUSED;
02043 bool *no_add_attrs;
02044 {
02045 if (TREE_CODE (*node) != FUNCTION_DECL)
02046 {
02047 warning ("`%s' attribute only applies to functions",
02048 IDENTIFIER_POINTER (name));
02049 *no_add_attrs = true;
02050 }
02051
02052 return NULL_TREE;
02053 }
02054
02055
02056
02057 static tree
02058 v850_handle_data_area_attribute (node, name, args, flags, no_add_attrs)
02059 tree *node;
02060 tree name;
02061 tree args ATTRIBUTE_UNUSED;
02062 int flags ATTRIBUTE_UNUSED;
02063 bool *no_add_attrs;
02064 {
02065 v850_data_area data_area;
02066 v850_data_area area;
02067 tree decl = *node;
02068
02069
02070 if (is_attribute_p ("sda", name))
02071 data_area = DATA_AREA_SDA;
02072 else if (is_attribute_p ("tda", name))
02073 data_area = DATA_AREA_TDA;
02074 else if (is_attribute_p ("zda", name))
02075 data_area = DATA_AREA_ZDA;
02076 else
02077 abort ();
02078
02079 switch (TREE_CODE (decl))
02080 {
02081 case VAR_DECL:
02082 if (current_function_decl != NULL_TREE)
02083 {
02084 error_with_decl (decl, "\
02085 a data area attribute cannot be specified for local variables");
02086 *no_add_attrs = true;
02087 }
02088
02089
02090
02091 case FUNCTION_DECL:
02092 area = v850_get_data_area (decl);
02093 if (area != DATA_AREA_NORMAL && data_area != area)
02094 {
02095 error_with_decl (decl, "\
02096 data area of '%s' conflicts with previous declaration");
02097 *no_add_attrs = true;
02098 }
02099 break;
02100
02101 default:
02102 break;
02103 }
02104
02105 return NULL_TREE;
02106 }
02107
02108
02109
02110
02111
02112 int
02113 v850_interrupt_function_p (func)
02114 tree func;
02115 {
02116 tree a;
02117 int ret = 0;
02118
02119 if (v850_interrupt_cache_p)
02120 return v850_interrupt_p;
02121
02122 if (TREE_CODE (func) != FUNCTION_DECL)
02123 return 0;
02124
02125 a = lookup_attribute ("interrupt_handler", DECL_ATTRIBUTES (func));
02126 if (a != NULL_TREE)
02127 ret = 1;
02128
02129 else
02130 {
02131 a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
02132 ret = a != NULL_TREE;
02133 }
02134
02135
02136
02137 if (reload_completed | reload_in_progress)
02138 v850_interrupt_p = ret;
02139
02140 return ret;
02141 }
02142
02143
02144 void
02145 v850_encode_data_area (decl)
02146 tree decl;
02147 {
02148 const char *str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
02149 int len = strlen (str);
02150 char * newstr;
02151
02152
02153 if (v850_get_data_area (decl) == DATA_AREA_NORMAL)
02154 {
02155 if (DECL_SECTION_NAME (decl))
02156 {
02157 const char *name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
02158
02159 if (streq (name, ".zdata") || streq (name, ".zbss"))
02160 v850_set_data_area (decl, DATA_AREA_ZDA);
02161
02162 else if (streq (name, ".sdata") || streq (name, ".sbss"))
02163 v850_set_data_area (decl, DATA_AREA_SDA);
02164
02165 else if (streq (name, ".tdata"))
02166 v850_set_data_area (decl, DATA_AREA_TDA);
02167 }
02168
02169
02170 else
02171 {
02172 int size = int_size_in_bytes (TREE_TYPE (decl));
02173 if (size <= 0)
02174 ;
02175
02176 else if (size <= small_memory [(int) SMALL_MEMORY_TDA].max)
02177 v850_set_data_area (decl, DATA_AREA_TDA);
02178
02179 else if (size <= small_memory [(int) SMALL_MEMORY_SDA].max)
02180 v850_set_data_area (decl, DATA_AREA_SDA);
02181
02182 else if (size <= small_memory [(int) SMALL_MEMORY_ZDA].max)
02183 v850_set_data_area (decl, DATA_AREA_ZDA);
02184 }
02185
02186 if (v850_get_data_area (decl) == DATA_AREA_NORMAL)
02187 return;
02188 }
02189
02190 newstr = alloca (len + 2);
02191
02192 strcpy (newstr + 1, str);
02193
02194 switch (v850_get_data_area (decl))
02195 {
02196 case DATA_AREA_ZDA: *newstr = ZDA_NAME_FLAG_CHAR; break;
02197 case DATA_AREA_TDA: *newstr = TDA_NAME_FLAG_CHAR; break;
02198 case DATA_AREA_SDA: *newstr = SDA_NAME_FLAG_CHAR; break;
02199 default: abort ();
02200 }
02201
02202 XSTR (XEXP (DECL_RTL (decl), 0), 0) = ggc_alloc_string (newstr, len + 2);
02203 }
02204
02205
02206
02207 int
02208 register_is_ok_for_epilogue (op, mode)
02209 rtx op;
02210 enum machine_mode ATTRIBUTE_UNUSED mode;
02211 {
02212
02213 return (GET_CODE (op) == REG)
02214 && (((REGNO (op) >= 20) && REGNO (op) <= 31)
02215 || REGNO (op) == 2);
02216 }
02217
02218
02219
02220 int
02221 pattern_is_ok_for_epilogue (op, mode)
02222 rtx op;
02223 enum machine_mode ATTRIBUTE_UNUSED mode;
02224 {
02225 int count = XVECLEN (op, 0);
02226 int i;
02227
02228
02229
02230 if (count <= 2)
02231 return 0;
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246 for (i = 3; i < count; i++)
02247 {
02248 rtx vector_element = XVECEXP (op, 0, i);
02249 rtx dest;
02250 rtx src;
02251 rtx plus;
02252
02253 if (GET_CODE (vector_element) != SET)
02254 return 0;
02255
02256 dest = SET_DEST (vector_element);
02257 src = SET_SRC (vector_element);
02258
02259 if (GET_CODE (dest) != REG
02260 || GET_MODE (dest) != SImode
02261 || ! register_is_ok_for_epilogue (dest, SImode)
02262 || GET_CODE (src) != MEM
02263 || GET_MODE (src) != SImode)
02264 return 0;
02265
02266 plus = XEXP (src, 0);
02267
02268 if (GET_CODE (plus) != PLUS
02269 || GET_CODE (XEXP (plus, 0)) != REG
02270 || GET_MODE (XEXP (plus, 0)) != SImode
02271 || REGNO (XEXP (plus, 0)) != STACK_POINTER_REGNUM
02272 || GET_CODE (XEXP (plus, 1)) != CONST_INT)
02273 return 0;
02274 }
02275
02276 return 1;
02277 }
02278
02279
02280
02281
02282
02283
02284 char *
02285 construct_restore_jr (op)
02286 rtx op;
02287 {
02288 int count = XVECLEN (op, 0);
02289 int stack_bytes;
02290 unsigned long int mask;
02291 unsigned long int first;
02292 unsigned long int last;
02293 int i;
02294 static char buff [100];
02295
02296 if (count <= 2)
02297 {
02298 error ("bogus JR construction: %d\n", count);
02299 return NULL;
02300 }
02301
02302
02303
02304 if (GET_CODE (XVECEXP (op, 0, 1)) != SET)
02305 abort ();
02306 if (GET_CODE (SET_SRC (XVECEXP (op, 0, 1))) != PLUS)
02307 abort ();
02308 if (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 1)), 1)) != CONST_INT)
02309 abort ();
02310
02311 stack_bytes = INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 1)), 1));
02312
02313
02314 stack_bytes -= (count - 2) * 4;
02315
02316
02317 if (stack_bytes != 0 && stack_bytes != 16)
02318 {
02319 error ("bad amount of stack space removal: %d", stack_bytes);
02320 return NULL;
02321 }
02322
02323
02324 mask = 0;
02325 for (i = 2; i < count; i++)
02326 {
02327 rtx vector_element = XVECEXP (op, 0, i);
02328
02329 if (GET_CODE (vector_element) != SET)
02330 abort ();
02331 if (GET_CODE (SET_DEST (vector_element)) != REG)
02332 abort ();
02333 if (! register_is_ok_for_epilogue (SET_DEST (vector_element), SImode))
02334 abort ();
02335
02336 mask |= 1 << REGNO (SET_DEST (vector_element));
02337 }
02338
02339
02340 for (first = 0; first < 32; first++)
02341 {
02342 if (mask & (1 << first))
02343 break;
02344 }
02345
02346 if (first >= 32)
02347 abort ();
02348
02349
02350 if (mask & (1 << LINK_POINTER_REGNUM))
02351 {
02352 if (stack_bytes != 16)
02353 abort ();
02354
02355 last = LINK_POINTER_REGNUM;
02356 }
02357 else
02358 {
02359 if (stack_bytes != 0)
02360 abort ();
02361
02362 if ((mask & (1 << 29)) == 0)
02363 abort ();
02364
02365 last = 29;
02366 }
02367
02368
02369
02370
02371
02372
02373 if (TARGET_LONG_CALLS)
02374 {
02375 char name[40];
02376
02377 if (first == last)
02378 sprintf (name, "__return_%s", reg_names [first]);
02379 else
02380 sprintf (name, "__return_%s_%s", reg_names [first], reg_names [last]);
02381
02382 sprintf (buff, "movhi hi(%s), r0, r6\n\tmovea lo(%s), r6, r6\n\tjmp r6",
02383 name, name);
02384 }
02385 else
02386 {
02387 if (first == last)
02388 sprintf (buff, "jr __return_%s", reg_names [first]);
02389 else
02390 sprintf (buff, "jr __return_%s_%s", reg_names [first], reg_names [last]);
02391 }
02392
02393 return buff;
02394 }
02395
02396
02397
02398
02399 int
02400 pattern_is_ok_for_prologue (op, mode)
02401 rtx op;
02402 enum machine_mode ATTRIBUTE_UNUSED mode;
02403 {
02404 int count = XVECLEN (op, 0);
02405 int i;
02406 rtx vector_element;
02407
02408
02409
02410 if (count <= 2)
02411 return 0;
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427 for (i = 2; i < count - 1; i++)
02428 {
02429 rtx dest;
02430 rtx src;
02431 rtx plus;
02432
02433 vector_element = XVECEXP (op, 0, i);
02434
02435 if (GET_CODE (vector_element) != SET)
02436 return 0;
02437
02438 dest = SET_DEST (vector_element);
02439 src = SET_SRC (vector_element);
02440
02441 if (GET_CODE (dest) != MEM
02442 || GET_MODE (dest) != SImode
02443 || GET_CODE (src) != REG
02444 || GET_MODE (src) != SImode
02445 || ! register_is_ok_for_epilogue (src, SImode))
02446 return 0;
02447
02448 plus = XEXP (dest, 0);
02449
02450 if ( GET_CODE (plus) != PLUS
02451 || GET_CODE (XEXP (plus, 0)) != REG
02452 || GET_MODE (XEXP (plus, 0)) != SImode
02453 || REGNO (XEXP (plus, 0)) != STACK_POINTER_REGNUM
02454 || GET_CODE (XEXP (plus, 1)) != CONST_INT)
02455 return 0;
02456
02457
02458
02459
02460 if (INTVAL (XEXP (plus, 1))
02461 <= INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)))
02462 {
02463 return 0;
02464 }
02465 }
02466
02467
02468 vector_element = XVECEXP (op, 0, i);
02469
02470 if (GET_CODE (vector_element) != CLOBBER
02471 || GET_CODE (XEXP (vector_element, 0)) != REG
02472 || REGNO (XEXP (vector_element, 0)) != 10)
02473 return 0;
02474
02475 return 1;
02476 }
02477
02478
02479
02480
02481
02482
02483 char *
02484 construct_save_jarl (op)
02485 rtx op;
02486 {
02487 int count = XVECLEN (op, 0);
02488 int stack_bytes;
02489 unsigned long int mask;
02490 unsigned long int first;
02491 unsigned long int last;
02492 int i;
02493 static char buff [100];
02494
02495 if (count <= 2)
02496 {
02497 error ("bogus JARL construction: %d\n", count);
02498 return NULL;
02499 }
02500
02501
02502 if (GET_CODE (XVECEXP (op, 0, 0)) != SET)
02503 abort ();
02504 if (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != PLUS)
02505 abort ();
02506 if (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0)) != REG)
02507 abort ();
02508 if (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)) != CONST_INT)
02509 abort ();
02510
02511
02512
02513 stack_bytes = INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1));
02514
02515
02516 stack_bytes += (count - 2) * 4;
02517
02518
02519 if (stack_bytes != 0 && stack_bytes != -16)
02520 {
02521 error ("bad amount of stack space removal: %d", stack_bytes);
02522 return NULL;
02523 }
02524
02525
02526 mask = 0;
02527 for (i = 1; i < count - 1; i++)
02528 {
02529 rtx vector_element = XVECEXP (op, 0, i);
02530
02531 if (GET_CODE (vector_element) != SET)
02532 abort ();
02533 if (GET_CODE (SET_SRC (vector_element)) != REG)
02534 abort ();
02535 if (! register_is_ok_for_epilogue (SET_SRC (vector_element), SImode))
02536 abort ();
02537
02538 mask |= 1 << REGNO (SET_SRC (vector_element));
02539 }
02540
02541
02542 for (first = 0; first < 32; first++)
02543 {
02544 if (mask & (1 << first))
02545 break;
02546 }
02547
02548 if (first >= 32)
02549 abort ();
02550
02551
02552 if (mask & (1 << LINK_POINTER_REGNUM))
02553 {
02554 if (stack_bytes != -16)
02555 abort ();
02556
02557 last = LINK_POINTER_REGNUM;
02558 }
02559 else
02560 {
02561 if (stack_bytes != 0)
02562 abort ();
02563 if ((mask & (1 << 29)) == 0)
02564 abort ();
02565
02566 last = 29;
02567 }
02568
02569
02570
02571
02572
02573
02574 if (TARGET_LONG_CALLS)
02575 {
02576 char name[40];
02577
02578 if (first == last)
02579 sprintf (name, "__save_%s", reg_names [first]);
02580 else
02581 sprintf (name, "__save_%s_%s", reg_names [first], reg_names [last]);
02582
02583 sprintf (buff, "movhi hi(%s), r0, r11\n\tmovea lo(%s), r11, r11\n\tjarl .+4, r10\n\tadd 4, r10\n\tjmp r11",
02584 name, name);
02585 }
02586 else
02587 {
02588 if (first == last)
02589 sprintf (buff, "jarl __save_%s, r10", reg_names [first]);
02590 else
02591 sprintf (buff, "jarl __save_%s_%s, r10", reg_names [first],
02592 reg_names [last]);
02593 }
02594
02595 return buff;
02596 }
02597
02598 extern tree last_assemble_variable_decl;
02599 extern int size_directive_output;
02600
02601
02602
02603 void
02604 v850_output_aligned_bss (file, decl, name, size, align)
02605 FILE * file;
02606 tree decl;
02607 const char * name;
02608 int size;
02609 int align;
02610 {
02611 ASM_GLOBALIZE_LABEL (file, name);
02612
02613 switch (v850_get_data_area (decl))
02614 {
02615 case DATA_AREA_ZDA:
02616 zbss_section ();
02617 break;
02618
02619 case DATA_AREA_SDA:
02620 sbss_section ();
02621 break;
02622
02623 case DATA_AREA_TDA:
02624 tdata_section ();
02625
02626 default:
02627 bss_section ();
02628 break;
02629 }
02630
02631 ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
02632 #ifdef ASM_DECLARE_OBJECT_NAME
02633 last_assemble_variable_decl = decl;
02634 ASM_DECLARE_OBJECT_NAME (file, name, decl);
02635 #else
02636
02637 ASM_OUTPUT_LABEL (file, name);
02638 #endif
02639 ASM_OUTPUT_SKIP (file, size ? size : 1);
02640 }
02641
02642
02643 void
02644 v850_output_common (file, decl, name, size, align)
02645 FILE * file;
02646 tree decl;
02647 const char * name;
02648 int size;
02649 int align;
02650 {
02651 if (decl == NULL_TREE)
02652 {
02653 fprintf (file, "%s", COMMON_ASM_OP);
02654 }
02655 else
02656 {
02657 switch (v850_get_data_area (decl))
02658 {
02659 case DATA_AREA_ZDA:
02660 fprintf (file, "%s", ZCOMMON_ASM_OP);
02661 break;
02662
02663 case DATA_AREA_SDA:
02664 fprintf (file, "%s", SCOMMON_ASM_OP);
02665 break;
02666
02667 case DATA_AREA_TDA:
02668 fprintf (file, "%s", TCOMMON_ASM_OP);
02669 break;
02670
02671 default:
02672 fprintf (file, "%s", COMMON_ASM_OP);
02673 break;
02674 }
02675 }
02676
02677 assemble_name (file, name);
02678 fprintf (file, ",%u,%u\n", size, align / BITS_PER_UNIT);
02679 }
02680
02681
02682 void
02683 v850_output_local (file, decl, name, size, align)
02684 FILE * file;
02685 tree decl;
02686 const char * name;
02687 int size;
02688 int align;
02689 {
02690 fprintf (file, "%s", LOCAL_ASM_OP);
02691 assemble_name (file, name);
02692 fprintf (file, "\n");
02693
02694 ASM_OUTPUT_ALIGNED_DECL_COMMON (file, decl, name, size, align);
02695 }
02696
02697
02698
02699 static void
02700 v850_insert_attributes (decl, attr_ptr)
02701 tree decl;
02702 tree *attr_ptr ATTRIBUTE_UNUSED;
02703 {
02704 if (data_area_stack
02705 && data_area_stack->data_area
02706 && current_function_decl == NULL_TREE
02707 && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == CONST_DECL)
02708 && v850_get_data_area (decl) == DATA_AREA_NORMAL)
02709 v850_set_data_area (decl, data_area_stack->data_area);
02710
02711
02712
02713
02714 if (GHS_default_section_names [(int) GHS_SECTION_KIND_SDATA] == NULL)
02715 {
02716 GHS_default_section_names [(int) GHS_SECTION_KIND_SDATA]
02717 = build_string (sizeof (".sdata")-1, ".sdata");
02718
02719 GHS_default_section_names [(int) GHS_SECTION_KIND_ROSDATA]
02720 = build_string (sizeof (".rosdata")-1, ".rosdata");
02721
02722 GHS_default_section_names [(int) GHS_SECTION_KIND_TDATA]
02723 = build_string (sizeof (".tdata")-1, ".tdata");
02724
02725 GHS_default_section_names [(int) GHS_SECTION_KIND_ZDATA]
02726 = build_string (sizeof (".zdata")-1, ".zdata");
02727
02728 GHS_default_section_names [(int) GHS_SECTION_KIND_ROZDATA]
02729 = build_string (sizeof (".rozdata")-1, ".rozdata");
02730 }
02731
02732 if (current_function_decl == NULL_TREE
02733 && (TREE_CODE (decl) == VAR_DECL
02734 || TREE_CODE (decl) == CONST_DECL
02735 || TREE_CODE (decl) == FUNCTION_DECL)
02736 && (!DECL_EXTERNAL (decl) || DECL_INITIAL (decl))
02737 && !DECL_SECTION_NAME (decl))
02738 {
02739 enum GHS_section_kind kind = GHS_SECTION_KIND_DEFAULT;
02740 tree chosen_section;
02741
02742 if (TREE_CODE (decl) == FUNCTION_DECL)
02743 kind = GHS_SECTION_KIND_TEXT;
02744 else
02745 {
02746
02747 switch (v850_get_data_area (decl))
02748 {
02749 default:
02750 abort ();
02751
02752 case DATA_AREA_SDA:
02753 kind = ((TREE_READONLY (decl))
02754 ? GHS_SECTION_KIND_ROSDATA
02755 : GHS_SECTION_KIND_SDATA);
02756 break;
02757
02758 case DATA_AREA_TDA:
02759 kind = GHS_SECTION_KIND_TDATA;
02760 break;
02761
02762 case DATA_AREA_ZDA:
02763 kind = ((TREE_READONLY (decl))
02764 ? GHS_SECTION_KIND_ROZDATA
02765 : GHS_SECTION_KIND_ZDATA);
02766 break;
02767
02768 case DATA_AREA_NORMAL:
02769 if (TREE_READONLY (decl))
02770 kind = GHS_SECTION_KIND_RODATA;
02771 else if (DECL_INITIAL (decl))
02772 kind = GHS_SECTION_KIND_DATA;
02773 else
02774 kind = GHS_SECTION_KIND_BSS;
02775 }
02776 }
02777
02778
02779
02780 chosen_section = GHS_current_section_names [(int) kind];
02781
02782
02783
02784 if (chosen_section == NULL)
02785 chosen_section = GHS_default_section_names [(int) kind];
02786
02787 if (chosen_section)
02788 {
02789
02790
02791
02792 DECL_SECTION_NAME (decl) = chosen_section;
02793 }
02794 }
02795 }
02796
02797
02798
02799 rtx
02800 v850_va_arg (valist, type)
02801 tree valist, type;
02802 {
02803 HOST_WIDE_INT size, rsize;
02804 tree addr, incr;
02805 rtx addr_rtx;
02806 int indirect;
02807
02808
02809 size = int_size_in_bytes (type);
02810 rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
02811 indirect = 0;
02812
02813 if (size > 8)
02814 {
02815 size = rsize = UNITS_PER_WORD;
02816 indirect = 1;
02817 }
02818
02819 addr = save_expr (valist);
02820 incr = fold (build (PLUS_EXPR, ptr_type_node, addr,
02821 build_int_2 (rsize, 0)));
02822
02823 incr = build (MODIFY_EXPR, ptr_type_node, valist, incr);
02824 TREE_SIDE_EFFECTS (incr) = 1;
02825 expand_expr (incr, const0_rtx, VOIDmode, EXPAND_NORMAL);
02826
02827 addr_rtx = expand_expr (addr, NULL, Pmode, EXPAND_NORMAL);
02828
02829 if (indirect)
02830 {
02831 addr_rtx = force_reg (Pmode, addr_rtx);
02832 addr_rtx = gen_rtx_MEM (Pmode, addr_rtx);
02833 set_mem_alias_set (addr_rtx, get_varargs_alias_set ());
02834 }
02835
02836 return addr_rtx;
02837 }
02838
02839
02840
02841
02842 rtx
02843 v850_return_addr (count)
02844 int count;
02845 {
02846 if (count != 0)
02847 return const0_rtx;
02848
02849 return get_hard_reg_initial_val (Pmode, LINK_POINTER_REGNUM);
02850 }