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