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