00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "config.h"
00023 #include "system.h"
00024 #include "rtl.h"
00025 #include "regs.h"
00026 #include "hard-reg-set.h"
00027 #include "real.h"
00028 #include "insn-config.h"
00029 #include "conditions.h"
00030 #include "insn-attr.h"
00031 #include "flags.h"
00032 #include "tree.h"
00033 #include "expr.h"
00034 #include "except.h"
00035 #include "function.h"
00036 #include "toplev.h"
00037 #include "recog.h"
00038 #include "tm_p.h"
00039 #include "debug.h"
00040 #include "output.h"
00041 #include "target.h"
00042 #include "target-def.h"
00043
00044
00045
00046 #define ADDITIVE_SIZE_MODIFIER(size) \
00047 ((size) <= 63 ? "q" : (size) <= 255 ? "u.b" : (size) <= 65535 ? "u.w" : ".d")
00048
00049 #define ASSERT_PLT_UNSPEC(x) \
00050 do \
00051 { \
00052 if (XEXP (x, 1) != NULL_RTX \
00053 || (GET_CODE (XVECEXP (x, 0, 0)) != SYMBOL_REF \
00054 && GET_CODE (XVECEXP (x, 0, 0)) != LABEL_REF)) \
00055 abort (); \
00056 } while (0)
00057
00058 #define LOSE_AND_RETURN(msgid, x) \
00059 do \
00060 { \
00061 cris_operand_lossage (msgid, x); \
00062 return; \
00063 } while (0)
00064
00065
00066 struct machine_function
00067 {
00068 int needs_return_address_on_stack;
00069 };
00070
00071
00072
00073 static char cris_output_insn_is_bound = 0;
00074
00075
00076
00077
00078
00079 static int cris_pic_sympart_only = 0;
00080
00081
00082 static int cris_reg_overlap_mentioned_p PARAMS ((rtx, rtx));
00083
00084 static void cris_print_base PARAMS ((rtx, FILE *));
00085
00086 static void cris_print_index PARAMS ((rtx, FILE *));
00087
00088 static void cris_init_machine_status PARAMS ((struct function *));
00089
00090 static int cris_initial_frame_pointer_offset PARAMS ((void));
00091
00092 static int saved_regs_mentioned PARAMS ((rtx));
00093
00094 static void cris_target_asm_function_prologue
00095 PARAMS ((FILE *, HOST_WIDE_INT));
00096
00097 static void cris_target_asm_function_epilogue
00098 PARAMS ((FILE *, HOST_WIDE_INT));
00099
00100 static void cris_operand_lossage PARAMS ((const char *, rtx));
00101
00102
00103
00104
00105 static char save_last[80];
00106
00107
00108 const char *cris_max_stackframe_str;
00109
00110
00111 const char *cris_cpu_str;
00112
00113
00114 const char *cris_tune_str;
00115
00116
00117 const char *cris_elinux_stacksize_str;
00118
00119
00120
00121 int cris_max_stackframe = 0;
00122
00123
00124 int cris_cpu_version = CRIS_DEFAULT_CPU_VERSION;
00125
00126 #undef TARGET_ASM_ALIGNED_HI_OP
00127 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
00128 #undef TARGET_ASM_ALIGNED_SI_OP
00129 #define TARGET_ASM_ALIGNED_SI_OP "\t.dword\t"
00130 #undef TARGET_ASM_ALIGNED_DI_OP
00131 #define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t"
00132
00133
00134
00135
00136 #undef TARGET_ASM_UNALIGNED_HI_OP
00137 #define TARGET_ASM_UNALIGNED_HI_OP TARGET_ASM_ALIGNED_HI_OP
00138
00139 #undef TARGET_ASM_UNALIGNED_SI_OP
00140 #define TARGET_ASM_UNALIGNED_SI_OP TARGET_ASM_ALIGNED_SI_OP
00141
00142 #undef TARGET_ASM_UNALIGNED_DI_OP
00143 #define TARGET_ASM_UNALIGNED_DI_OP TARGET_ASM_ALIGNED_DI_OP
00144
00145 #undef TARGET_ASM_FUNCTION_PROLOGUE
00146 #define TARGET_ASM_FUNCTION_PROLOGUE cris_target_asm_function_prologue
00147
00148 #undef TARGET_ASM_FUNCTION_EPILOGUE
00149 #define TARGET_ASM_FUNCTION_EPILOGUE cris_target_asm_function_epilogue
00150
00151 struct gcc_target targetm = TARGET_INITIALIZER;
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 int
00163 cris_bdap_operand (op, mode)
00164 rtx op;
00165 enum machine_mode mode;
00166 {
00167 register enum rtx_code code = GET_CODE (op);
00168
00169 if (mode != SImode && (mode != VOIDmode || GET_MODE (op) != VOIDmode))
00170 return 0;
00171
00172
00173 if (register_operand (op, mode)
00174 || (CONSTANT_P (op) && !(flag_pic && cris_symbol (op))))
00175 return 1;
00176
00177
00178 if (code == MEM)
00179 {
00180 rtx tem = XEXP (op, 0);
00181
00182 if (mode == SImode
00183 && (register_operand (tem, SImode)
00184 || (GET_CODE (tem) == POST_INC
00185 && register_operand (XEXP (tem, 0), SImode))))
00186 return 1;
00187 else
00188 return 0;
00189 }
00190
00191
00192 if (code == SIGN_EXTEND)
00193 {
00194 rtx tem = XEXP (op, 0);
00195
00196 if (GET_CODE (tem) != MEM)
00197 return 0;
00198
00199 tem = XEXP (tem, 0);
00200 if (mode == SImode
00201 && (register_operand (tem, SImode)
00202 || (GET_CODE (tem) == POST_INC
00203 && register_operand (XEXP (tem, 0), SImode))))
00204 return 1;
00205 else
00206 return 0;
00207 }
00208
00209 return 0;
00210 }
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 int
00222 cris_bdap_biap_operand (op, mode)
00223 rtx op;
00224 enum machine_mode mode;
00225 {
00226 register enum rtx_code code = GET_CODE (op);
00227 rtx reg;
00228 rtx val;
00229
00230
00231 if (cris_bdap_operand (op, mode))
00232 return 1;
00233
00234 if (mode != SImode && (mode != VOIDmode || GET_MODE (op) != VOIDmode))
00235 return 0;
00236
00237
00238 if (code != MULT)
00239 return 0;
00240
00241
00242 if (GET_CODE (XEXP (op, 0)) == CONST_INT)
00243 {
00244 val = XEXP (op, 0);
00245 reg = XEXP (op, 1);
00246 }
00247 else
00248 {
00249 val = XEXP (op, 1);
00250 reg = XEXP (op, 0);
00251 }
00252
00253
00254 if (! register_operand (reg, SImode) || GET_CODE (val) != CONST_INT)
00255 return 0;
00256
00257
00258 if ((code == MULT
00259 && (INTVAL (val) == 1 || INTVAL (val) == 2 || INTVAL (val) == 4)))
00260 return 1;
00261
00262 return 0;
00263 }
00264
00265
00266
00267
00268 int
00269 cris_orthogonal_operator (x, mode)
00270 rtx x;
00271 enum machine_mode mode;
00272 {
00273 enum rtx_code code = GET_CODE (x);
00274
00275 if (mode == VOIDmode)
00276 mode = GET_MODE (x);
00277
00278 return (GET_MODE (x) == mode
00279 && (code == PLUS || code == MINUS
00280 || code == IOR || code == AND || code == UMIN));
00281 }
00282
00283
00284
00285
00286 int
00287 cris_commutative_orth_op (x, mode)
00288 rtx x;
00289 enum machine_mode mode;
00290 {
00291 enum rtx_code code = GET_CODE (x);
00292
00293 if (mode == VOIDmode)
00294 mode = GET_MODE (x);
00295
00296 return (GET_MODE (x) == mode &&
00297 (code == PLUS
00298 || code == IOR || code == AND || code == UMIN));
00299 }
00300
00301
00302
00303 int
00304 cris_operand_extend_operator (x, mode)
00305 rtx x;
00306 enum machine_mode mode;
00307 {
00308 enum rtx_code code = GET_CODE (x);
00309
00310 if (mode == VOIDmode)
00311 mode = GET_MODE (x);
00312
00313 return (GET_MODE (x) == mode
00314 && (code == PLUS || code == MINUS || code == UMIN));
00315 }
00316
00317
00318
00319
00320 int
00321 cris_extend_operator (x, mode)
00322 rtx x;
00323 enum machine_mode mode;
00324 {
00325 enum rtx_code code = GET_CODE (x);
00326
00327 if (mode == VOIDmode)
00328 mode = GET_MODE (x);
00329
00330 return
00331 (GET_MODE (x) == mode && (code == SIGN_EXTEND || code == ZERO_EXTEND));
00332 }
00333
00334
00335
00336 int
00337 cris_plus_or_bound_operator (x, mode)
00338 rtx x;
00339 enum machine_mode mode;
00340 {
00341 enum rtx_code code = GET_CODE (x);
00342
00343 if (mode == VOIDmode)
00344 mode = GET_MODE (x);
00345
00346 return
00347 (GET_MODE (x) == mode && (code == UMIN || code == PLUS));
00348 }
00349
00350
00351
00352
00353
00354 int
00355 cris_general_operand_or_symbol (op, mode)
00356 rtx op;
00357 enum machine_mode mode;
00358 {
00359 return general_operand (op, mode)
00360 || (CONSTANT_P (op) && cris_symbol (op));
00361 }
00362
00363
00364
00365
00366
00367 int
00368 cris_general_operand_or_gotless_symbol (op, mode)
00369 rtx op;
00370 enum machine_mode mode;
00371 {
00372 return general_operand (op, mode)
00373 || (CONSTANT_P (op) && cris_gotless_symbol (op));
00374 }
00375
00376
00377
00378
00379
00380 int
00381 cris_general_operand_or_plt_symbol (op, mode)
00382 rtx op;
00383 enum machine_mode mode;
00384 {
00385 return general_operand (op, mode)
00386 || (GET_CODE (op) == CONST
00387 && GET_CODE (XEXP (op, 0)) == UNSPEC
00388 && !TARGET_AVOID_GOTPLT);
00389 }
00390
00391
00392
00393
00394
00395
00396
00397 int
00398 cris_mem_call_operand (op, mode)
00399 rtx op;
00400 enum machine_mode mode;
00401 {
00402 rtx xmem;
00403
00404 if (GET_CODE (op) != MEM)
00405 return 0;
00406
00407 if (memory_operand (op, mode))
00408 return 1;
00409
00410 xmem = XEXP (op, 0);
00411
00412 return cris_general_operand_or_symbol (xmem, GET_MODE (op));
00413 }
00414
00415
00416
00417 void
00418 cris_conditional_register_usage ()
00419 {
00420
00421
00422 if (flag_pic)
00423 fixed_regs[PIC_OFFSET_TABLE_REGNUM]
00424 = call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
00425 }
00426
00427
00428
00429
00430 int
00431 cris_cfun_uses_pic_table ()
00432 {
00433 return current_function_uses_pic_offset_table;
00434 }
00435
00436
00437
00438
00439
00440 const char *
00441 cris_op_str (x)
00442 rtx x;
00443 {
00444 cris_output_insn_is_bound = 0;
00445 switch (GET_CODE (x))
00446 {
00447 case PLUS:
00448 return "add";
00449 break;
00450
00451 case MINUS:
00452 return "sub";
00453 break;
00454
00455 case MULT:
00456 return "mul";
00457 break;
00458
00459 case DIV:
00460 return "div";
00461 break;
00462
00463 case AND:
00464 return "and";
00465 break;
00466
00467 case IOR:
00468 return "or";
00469 break;
00470
00471 case XOR:
00472 return "xor";
00473 break;
00474
00475 case NOT:
00476 return "not";
00477 break;
00478
00479 case ASHIFT:
00480 return "lsl";
00481 break;
00482
00483 case LSHIFTRT:
00484 return "lsr";
00485 break;
00486
00487 case ASHIFTRT:
00488 return "asr";
00489 break;
00490
00491 case UMIN:
00492
00493
00494 cris_output_insn_is_bound = 1;
00495 return "bound";
00496 break;
00497
00498 default:
00499 return "Unknown operator";
00500 break;
00501 }
00502 }
00503
00504
00505
00506
00507
00508
00509 static void
00510 cris_operand_lossage (msgid, op)
00511 const char *msgid;
00512 rtx op;
00513 {
00514 debug_rtx (op);
00515 output_operand_lossage ("%s", msgid);
00516 }
00517
00518
00519
00520 static void
00521 cris_print_index (index, file)
00522 rtx index;
00523 FILE * file;
00524 {
00525 rtx inner = XEXP (index, 0);
00526
00527
00528
00529 if (GET_CODE (index) != CONST_INT || INTVAL (index) >= 0)
00530 putc ('+', file);
00531
00532 if (REG_P (index))
00533 fprintf (file, "$%s.b", reg_names[REGNO (index)]);
00534 else if (CONSTANT_P (index))
00535 cris_output_addr_const (file, index);
00536 else if (GET_CODE (index) == MULT)
00537 {
00538 fprintf (file, "$%s.",
00539 reg_names[REGNO (XEXP (index, 0))]);
00540
00541 putc (INTVAL (XEXP (index, 1)) == 2 ? 'w' : 'd', file);
00542 }
00543 else if (GET_CODE (index) == SIGN_EXTEND &&
00544 GET_CODE (inner) == MEM)
00545 {
00546 rtx inner_inner = XEXP (inner, 0);
00547
00548 if (GET_CODE (inner_inner) == POST_INC)
00549 {
00550 fprintf (file, "[$%s+].",
00551 reg_names[REGNO (XEXP (inner_inner, 0))]);
00552 putc (GET_MODE (inner) == HImode ? 'w' : 'b', file);
00553 }
00554 else
00555 {
00556 fprintf (file, "[$%s].", reg_names[REGNO (inner_inner)]);
00557
00558 putc (GET_MODE (inner) == HImode ? 'w' : 'b', file);
00559 }
00560 }
00561 else if (GET_CODE (index) == MEM)
00562 {
00563 if (GET_CODE (inner) == POST_INC)
00564 fprintf (file, "[$%s+].d", reg_names[REGNO (XEXP (inner, 0))]);
00565 else
00566 fprintf (file, "[$%s].d", reg_names[REGNO (inner)]);
00567 }
00568 else
00569 cris_operand_lossage ("unexpected index-type in cris_print_index",
00570 index);
00571 }
00572
00573
00574
00575 static void
00576 cris_print_base (base, file)
00577 rtx base;
00578 FILE *file;
00579 {
00580 if (REG_P (base))
00581 fprintf (file, "$%s", reg_names[REGNO (base)]);
00582 else if (GET_CODE (base) == POST_INC)
00583 fprintf (file, "$%s+", reg_names[REGNO (XEXP (base, 0))]);
00584 else
00585 cris_operand_lossage ("unexpected base-type in cris_print_base",
00586 base);
00587 }
00588
00589
00590
00591 int
00592 cris_fatal (arg)
00593 char *arg;
00594 {
00595 internal_error (arg);
00596
00597
00598 return 0;
00599 }
00600
00601
00602
00603 static void
00604 cris_target_asm_function_prologue (file, size)
00605 FILE *file;
00606 HOST_WIDE_INT size;
00607 {
00608 int regno;
00609
00610
00611 int cfoa_size = current_function_outgoing_args_size;
00612 int last_movem_reg = -1;
00613 int doing_dwarf = dwarf2out_do_frame ();
00614 int framesize;
00615 int faked_args_size = 0;
00616 int cfa_write_offset = 0;
00617 char *cfa_label = NULL;
00618 int return_address_on_stack
00619 = regs_ever_live[CRIS_SRP_REGNUM]
00620 || cfun->machine->needs_return_address_on_stack != 0;
00621
00622
00623 if (!TARGET_PROLOGUE_EPILOGUE)
00624 return;
00625
00626 if (size < 0)
00627 abort ();
00628
00629
00630 if (TARGET_STACK_ALIGN)
00631 size = TARGET_ALIGN_BY_32 ? (size + 3) & ~3 : (size + 1) & ~1;
00632
00633 if (current_function_pretend_args_size)
00634 {
00635 int pretend = current_function_pretend_args_size;
00636 for (regno = CRIS_FIRST_ARG_REG + CRIS_MAX_ARGS_IN_REGS - 1;
00637 pretend > 0;
00638 regno--, pretend -= 4)
00639 {
00640 fprintf (file, "\tpush $%s\n", reg_names[regno]);
00641 faked_args_size += 4;
00642 }
00643 }
00644
00645 framesize = faked_args_size;
00646
00647 if (doing_dwarf)
00648 {
00649
00650
00651
00652
00653
00654
00655 int cfa_offset
00656 = faked_args_size
00657 + (return_address_on_stack ? 4 : 0)
00658 + (frame_pointer_needed ? 4 : 0);
00659
00660 int cfa_reg;
00661
00662 if (frame_pointer_needed)
00663 cfa_reg = FRAME_POINTER_REGNUM;
00664 else
00665 {
00666 cfa_reg = STACK_POINTER_REGNUM;
00667 cfa_offset += cris_initial_frame_pointer_offset ();
00668 }
00669
00670 cfa_label = dwarf2out_cfi_label ();
00671 dwarf2out_def_cfa (cfa_label, cfa_reg, cfa_offset);
00672
00673 cfa_write_offset = - faked_args_size - 4;
00674 }
00675
00676
00677 if (return_address_on_stack)
00678 {
00679 fprintf (file, "\tPush $srp\n");
00680 framesize += 4;
00681
00682 if (doing_dwarf)
00683 {
00684 dwarf2out_return_save (cfa_label, cfa_write_offset);
00685 cfa_write_offset -= 4;
00686 }
00687 }
00688
00689
00690 if (frame_pointer_needed)
00691 {
00692 fprintf (file, "\tpush $%s\n\tmove.d $sp,$%s\n",
00693 reg_names[FRAME_POINTER_REGNUM],
00694 reg_names[FRAME_POINTER_REGNUM]);
00695 framesize += 4;
00696
00697 if (doing_dwarf)
00698 {
00699 dwarf2out_reg_save (cfa_label, FRAME_POINTER_REGNUM,
00700 cfa_write_offset);
00701 cfa_write_offset -= 4;
00702 }
00703 }
00704
00705
00706 cfa_write_offset -= size;
00707
00708
00709
00710 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
00711 {
00712 if ((((regs_ever_live[regno]
00713 && !call_used_regs[regno])
00714 || (regno == (int) PIC_OFFSET_TABLE_REGNUM
00715 && (current_function_uses_pic_offset_table
00716
00717 || (flag_pic
00718 && regs_ever_live[regno + 1]
00719 && !call_used_regs[regno + 1]))))
00720 && (regno != FRAME_POINTER_REGNUM || !frame_pointer_needed)
00721 && regno != CRIS_SRP_REGNUM)
00722 || (current_function_calls_eh_return
00723 && (regno == EH_RETURN_DATA_REGNO (0)
00724 || regno == EH_RETURN_DATA_REGNO (1)
00725 || regno == EH_RETURN_DATA_REGNO (2)
00726 || regno == EH_RETURN_DATA_REGNO (3))))
00727 {
00728
00729 if (regno == last_movem_reg + 1)
00730
00731 last_movem_reg++;
00732 else
00733 {
00734
00735
00736 if (last_movem_reg != -1)
00737 {
00738
00739
00740
00741
00742 if ((last_movem_reg + 1) * 4 + size >= 64
00743 && (last_movem_reg + 1) * 4 + size <= 128
00744 && cris_cpu_version >= CRIS_CPU_SVINTO
00745 && TARGET_SIDE_EFFECT_PREFIXES)
00746 fprintf (file, "\tmovem $%s,[$sp=$sp-%d]\n",
00747 reg_names[last_movem_reg],
00748 (last_movem_reg + 1) * 4 + size);
00749 else
00750 {
00751
00752 fprintf (file, "\tsub%s %d,$sp\n",
00753 ADDITIVE_SIZE_MODIFIER ((last_movem_reg + 1)
00754 * 4 + size),
00755 (last_movem_reg + 1) * 4 + size);
00756
00757 fprintf (file, "\tmovem $%s,[$sp]\n",
00758 reg_names[last_movem_reg]);
00759 }
00760
00761 framesize += (last_movem_reg + 1) * 4 + size;
00762
00763 if (TARGET_PDEBUG)
00764 fprintf (file, "; frame %d, #regs %d, bytes %d args %d\n",
00765 size,
00766 last_movem_reg + 1,
00767 (last_movem_reg + 1) * 4,
00768 current_function_args_size);
00769
00770 last_movem_reg = -1;
00771 size = 0;
00772 }
00773 else if (size > 0)
00774 {
00775
00776
00777 fprintf (file, "\tSub%s %d,$sp\n",
00778 ADDITIVE_SIZE_MODIFIER (size),
00779 size);
00780 framesize += size;
00781 size = 0;
00782 }
00783
00784 fprintf (file, "\tPush $%s\n", reg_names[regno]);
00785 framesize += 4;
00786 }
00787
00788 if (doing_dwarf)
00789 {
00790
00791
00792
00793 dwarf2out_reg_save (cfa_label, regno, cfa_write_offset);
00794 cfa_write_offset -= 4;
00795 }
00796 }
00797 }
00798
00799
00800
00801 if (last_movem_reg != -1)
00802 {
00803
00804
00805
00806
00807
00808 if ((last_movem_reg + 1) * 4 + size >= 64
00809 && (last_movem_reg + 1) * 4 + size <= 128
00810 && cris_cpu_version >= CRIS_CPU_SVINTO
00811 && TARGET_SIDE_EFFECT_PREFIXES)
00812 fprintf (file, "\tmovem $%s,[$sp=$sp-%d]\n",
00813 reg_names[last_movem_reg],
00814 (last_movem_reg+1) * 4 + size);
00815 else
00816 {
00817
00818
00819 fprintf (file, "\tsub%s %d,$sp\n",
00820 ADDITIVE_SIZE_MODIFIER ((last_movem_reg + 1) * 4 + size),
00821 (last_movem_reg + 1) * 4 + size);
00822
00823
00824
00825
00826 fprintf (file, "\tmovem $%s,[$sp]\n", reg_names[last_movem_reg]);
00827 }
00828
00829 framesize += (last_movem_reg + 1) * 4 + size;
00830
00831 if (TARGET_PDEBUG)
00832 fprintf (file, "; frame %d, #regs %d, bytes %d args %d\n",
00833 size,
00834 last_movem_reg + 1,
00835 (last_movem_reg + 1) * 4,
00836 current_function_args_size);
00837
00838
00839 if (cfoa_size)
00840 {
00841
00842
00843 fprintf (file, "\tSub%s %d,$sp\n",
00844 ADDITIVE_SIZE_MODIFIER (cfoa_size),
00845 cfoa_size);
00846 framesize += cfoa_size;
00847 }
00848 }
00849 else if ((size + cfoa_size) > 0)
00850 {
00851
00852
00853
00854 fprintf (file, "\tSub%s %d,$sp\n",
00855 ADDITIVE_SIZE_MODIFIER (size + cfoa_size),
00856 cfoa_size + size);
00857 framesize += size + cfoa_size;
00858 }
00859
00860
00861 if (current_function_uses_pic_offset_table)
00862 asm_fprintf (file, "\tmove.d $pc,$%s\n\tsub.d .:GOTOFF,$%s\n",
00863 reg_names[PIC_OFFSET_TABLE_REGNUM],
00864 reg_names[PIC_OFFSET_TABLE_REGNUM]);
00865
00866 if (TARGET_PDEBUG)
00867 fprintf (file,
00868 "; parm #%d @ %d; frame %d, FP-SP is %d; leaf: %s%s; fp %s, outg: %d arg %d\n",
00869 CRIS_MAX_ARGS_IN_REGS + 1, FIRST_PARM_OFFSET (0),
00870 get_frame_size (),
00871 cris_initial_frame_pointer_offset (),
00872 leaf_function_p () ? "yes" : "no",
00873 return_address_on_stack ? "no" :"yes",
00874 frame_pointer_needed ? "yes" : "no",
00875 cfoa_size, current_function_args_size);
00876
00877 if (cris_max_stackframe && framesize > cris_max_stackframe)
00878 warning ("stackframe too big: %d bytes", framesize);
00879 }
00880
00881
00882
00883
00884
00885 static int
00886 saved_regs_mentioned (x)
00887 rtx x;
00888 {
00889 int i;
00890 const char *fmt;
00891 RTX_CODE code;
00892
00893
00894
00895 code = GET_CODE (x);
00896
00897 switch (code)
00898 {
00899 case REG:
00900 i = REGNO (x);
00901 return !call_used_regs[i];
00902
00903 case SUBREG:
00904
00905
00906 i = REGNO (SUBREG_REG (x));
00907 return !call_used_regs[i];
00908
00909 default:
00910 ;
00911 }
00912
00913 fmt = GET_RTX_FORMAT (code);
00914 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
00915 {
00916 if (fmt[i] == 'e')
00917 {
00918 if (saved_regs_mentioned (XEXP (x, i)))
00919 return 1;
00920 }
00921 else if (fmt[i] == 'E')
00922 {
00923 int j;
00924 for (j = XVECLEN (x, i) - 1; j >=0; j--)
00925 if (saved_regs_mentioned (XEXP (x, i)))
00926 return 1;
00927 }
00928 }
00929
00930 return 0;
00931 }
00932
00933
00934
00935 int
00936 cris_eligible_for_epilogue_delay (insn)
00937 rtx insn;
00938 {
00939
00940 if (get_attr_slottable (insn) != SLOTTABLE_YES)
00941 return 0;
00942
00943
00944
00945 if (reg_mentioned_p (stack_pointer_rtx, PATTERN (insn)))
00946 return 0;
00947
00948
00949
00950 if (frame_pointer_needed
00951 && reg_mentioned_p (frame_pointer_rtx, PATTERN (insn)))
00952 return 0;
00953
00954
00955
00956
00957 if (saved_regs_mentioned (PATTERN (insn)))
00958 return 0;
00959
00960
00961 return 1;
00962 }
00963
00964
00965
00966
00967 int
00968 cris_delay_slots_for_epilogue ()
00969 {
00970
00971
00972 if (regs_ever_live[CRIS_SRP_REGNUM]
00973 || cfun->machine->needs_return_address_on_stack != 0)
00974 return 0;
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984 cris_target_asm_function_epilogue (NULL, get_frame_size ());
00985
00986 if (*save_last)
00987 return 1;
00988 return 0;
00989 }
00990
00991
00992
00993
00994
00995 static void
00996 cris_target_asm_function_epilogue (file, size)
00997 FILE *file;
00998 HOST_WIDE_INT size;
00999 {
01000 int regno;
01001 int last_movem_reg = -1;
01002 rtx insn = get_last_insn ();
01003 int argspace_offset = current_function_outgoing_args_size;
01004 int pretend = current_function_pretend_args_size;
01005 int return_address_on_stack
01006 = regs_ever_live[CRIS_SRP_REGNUM]
01007 || cfun->machine->needs_return_address_on_stack != 0;
01008
01009 save_last[0] = 0;
01010
01011 if (file && !TARGET_PROLOGUE_EPILOGUE)
01012 return;
01013
01014 if (TARGET_PDEBUG && file)
01015 fprintf (file, ";;\n");
01016
01017
01018 if (TARGET_STACK_ALIGN)
01019 size = TARGET_ALIGN_BY_32 ? (size + 3) & ~3 : (size + 1) & ~1;
01020
01021
01022
01023 if (GET_CODE (insn) == NOTE)
01024 insn = prev_nonnote_insn (insn);
01025 if (insn
01026 && (GET_CODE (insn) == BARRIER
01027
01028
01029
01030
01031 || (GET_CODE (insn) == JUMP_INSN
01032 && GET_CODE (PATTERN (insn)) == RETURN)))
01033 {
01034 if (TARGET_PDEBUG && file)
01035 fprintf (file, ";;;;;\n");
01036 return;
01037 }
01038
01039
01040
01041 for (regno = 0;
01042 regno < FIRST_PSEUDO_REGISTER;
01043 regno++)
01044 if ((((regs_ever_live[regno]
01045 && !call_used_regs[regno])
01046 || (regno == (int) PIC_OFFSET_TABLE_REGNUM
01047 && (current_function_uses_pic_offset_table
01048
01049 || (flag_pic
01050 && regs_ever_live[regno + 1]
01051 && !call_used_regs[regno + 1]))))
01052 && (regno != FRAME_POINTER_REGNUM || !frame_pointer_needed)
01053 && regno != CRIS_SRP_REGNUM)
01054 || (current_function_calls_eh_return
01055 && (regno == EH_RETURN_DATA_REGNO (0)
01056 || regno == EH_RETURN_DATA_REGNO (1)
01057 || regno == EH_RETURN_DATA_REGNO (2)
01058 || regno == EH_RETURN_DATA_REGNO (3))))
01059
01060 {
01061 if (regno == last_movem_reg + 1)
01062 last_movem_reg++;
01063 else
01064 break;
01065 }
01066
01067 for (regno = FIRST_PSEUDO_REGISTER - 1;
01068 regno > last_movem_reg;
01069 regno--)
01070 if ((((regs_ever_live[regno]
01071 && !call_used_regs[regno])
01072 || (regno == (int) PIC_OFFSET_TABLE_REGNUM
01073 && (current_function_uses_pic_offset_table
01074
01075 || (flag_pic
01076 && regs_ever_live[regno + 1]
01077 && !call_used_regs[regno + 1]))))
01078 && (regno != FRAME_POINTER_REGNUM || !frame_pointer_needed)
01079 && regno != CRIS_SRP_REGNUM)
01080 || (current_function_calls_eh_return
01081 && (regno == EH_RETURN_DATA_REGNO (0)
01082 || regno == EH_RETURN_DATA_REGNO (1)
01083 || regno == EH_RETURN_DATA_REGNO (2)
01084 || regno == EH_RETURN_DATA_REGNO (3))))
01085 {
01086 if (argspace_offset)
01087 {
01088
01089
01090 if (file)
01091 fprintf (file, "\tAdd%s %d,$sp\n",
01092 ADDITIVE_SIZE_MODIFIER (argspace_offset),
01093 argspace_offset);
01094
01095
01096 argspace_offset = 0;
01097 }
01098
01099
01100 if (*save_last && file)
01101 fprintf (file, save_last);
01102 sprintf (save_last, "\tPop $%s\n", reg_names[regno]);
01103 }
01104
01105 if (last_movem_reg != -1)
01106 {
01107 if (argspace_offset)
01108 {
01109
01110
01111 if (*save_last && file)
01112 {
01113 fprintf (file, save_last);
01114 *save_last = 0;
01115 }
01116
01117 if (file)
01118 fprintf (file, "\tAdd%s %d,$sp\n",
01119 ADDITIVE_SIZE_MODIFIER (argspace_offset),
01120 argspace_offset);
01121 argspace_offset = 0;
01122 }
01123
01124 else if (*save_last && file)
01125 fprintf (file, save_last);
01126 sprintf (save_last, "\tmovem [$sp+],$%s\n", reg_names[last_movem_reg]);
01127 }
01128
01129
01130 if (frame_pointer_needed)
01131 {
01132 if (*save_last && file)
01133 fprintf (file, save_last);
01134
01135 if (file)
01136 fprintf (file, "\tmove.d $%s,$sp\n",
01137 reg_names[FRAME_POINTER_REGNUM]);
01138 sprintf (save_last, "\tPop $%s\n",
01139 reg_names[FRAME_POINTER_REGNUM]);
01140 }
01141 else
01142 {
01143
01144
01145
01146
01147
01148 size += argspace_offset;
01149
01150 if (size)
01151 {
01152 if (*save_last && file)
01153 fprintf (file, save_last);
01154
01155 sprintf (save_last, "\tadd%s %d,$sp\n",
01156 ADDITIVE_SIZE_MODIFIER (size), size);
01157 }
01158
01159
01160
01161 if (size > 63)
01162 {
01163 if (file)
01164 fprintf (file, save_last);
01165 *save_last = 0;
01166 }
01167 }
01168
01169
01170
01171
01172 if (return_address_on_stack && pretend == 0)
01173 {
01174 if (*save_last && file)
01175 fprintf (file, save_last);
01176 *save_last = 0;
01177
01178 if (file)
01179 {
01180 if (current_function_calls_eh_return)
01181 {
01182
01183
01184 fprintf (file, "\tpop $srp\n");
01185 fprintf (file, "\tret\n");
01186 fprintf (file, "\tadd.d $%s,$sp\n", reg_names[CRIS_STACKADJ_REG]);
01187 }
01188 else
01189 fprintf (file, "\tJump [$sp+]\n");
01190
01191
01192 if (current_function_epilogue_delay_list)
01193 internal_error ("allocated but unused delay list in epilogue");
01194 }
01195 return;
01196 }
01197
01198
01199
01200
01201
01202 if (current_function_calls_eh_return)
01203 internal_error ("unexpected function type needing stack adjustment for\
01204 __builtin_eh_return");
01205
01206
01207
01208 if (pretend)
01209 {
01210
01211 if (return_address_on_stack)
01212 {
01213 if (*save_last && file)
01214 fprintf (file, save_last);
01215 *save_last = 0;
01216
01217 if (file)
01218 fprintf (file, "\tpop $srp\n");
01219 }
01220
01221 if (*save_last && file)
01222 fprintf (file, save_last);
01223
01224 sprintf (save_last, "\tadd%s %d,$sp\n",
01225 ADDITIVE_SIZE_MODIFIER (pretend), pretend);
01226 }
01227
01228
01229 if (file && current_function_epilogue_delay_list)
01230 {
01231
01232
01233
01234 if (*save_last)
01235 fprintf (file, save_last);
01236
01237 fprintf (file, "\tRet\n");
01238
01239
01240 final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
01241 file, 1, -2, 1);
01242 }
01243 else if (file)
01244 {
01245 fprintf (file, "\tRet\n");
01246
01247
01248
01249 if (*save_last)
01250 fprintf (file, save_last);
01251 else
01252 fprintf (file, "\tnOp\n");
01253 }
01254 }
01255
01256
01257
01258 void
01259 cris_print_operand (file, x, code)
01260 FILE *file;
01261 rtx x;
01262 int code;
01263 {
01264 rtx operand = x;
01265
01266
01267 static const char *mults[] = { "BAD:0", ".b", ".w", "BAD:3", ".d" };
01268
01269
01270
01271
01272
01273
01274
01275 switch (code)
01276 {
01277 case 'b':
01278
01279
01280 if (GET_CODE (x) != CONST_INT
01281 || ! CONST_OK_FOR_LETTER_P (INTVAL (x), 'O'))
01282 LOSE_AND_RETURN ("invalid operand for 'b' modifier", x);
01283 fprintf (file, "%d", INTVAL (x)| (INTVAL (x) <= 255 ? ~255 : ~65535));
01284 return;
01285
01286 case 'x':
01287
01288 fprintf (file, "%s", cris_op_str (operand));
01289 return;
01290
01291 case 'v':
01292
01293 if (! flag_pic || ! CONSTANT_P (x) || ! cris_gotless_symbol (x))
01294 LOSE_AND_RETURN ("invalid operand for 'v' modifier", x);
01295 cris_pic_sympart_only++;
01296 cris_output_addr_const (file, x);
01297 cris_pic_sympart_only--;
01298 return;
01299
01300 case 'P':
01301
01302
01303 if (! flag_pic || ! CONSTANT_P (x) || ! cris_gotless_symbol (x))
01304 LOSE_AND_RETURN ("invalid operand for 'P' modifier", x);
01305 fprintf (file, "$%s", reg_names [PIC_OFFSET_TABLE_REGNUM]);
01306 return;
01307
01308 case 'p':
01309
01310 if (GET_CODE (x) != CONST_INT || exact_log2 (INTVAL (x)) < 0 )
01311 LOSE_AND_RETURN ("invalid operand for 'p' modifier", x);
01312 fprintf (file, "%d", exact_log2 (INTVAL (x)));
01313 return;
01314
01315 case 's':
01316
01317
01318
01319 cris_output_insn_is_bound = 0;
01320 if (GET_MODE (x) == VOIDmode && GET_CODE (x) == CONST_INT)
01321 {
01322 if (INTVAL (x) >= 0)
01323 {
01324 if (INTVAL (x) <= 255)
01325 putc ('b', file);
01326 else if (INTVAL (x) <= 65535)
01327 putc ('w', file);
01328 else
01329 putc ('d', file);
01330 }
01331 else
01332 putc ('d', file);
01333 return;
01334 }
01335
01336
01337 putc ((GET_MODE (x) == SImode || GET_MODE (x) == SFmode)
01338 ? 'd' : GET_MODE (x) == HImode ? 'w'
01339 : GET_MODE (x) == QImode ? 'b'
01340
01341 : 'X',
01342 file);
01343 return;
01344
01345 case 'z':
01346
01347
01348 if (GET_CODE (x) != CONST_INT
01349 || INTVAL (x) < -32768 || INTVAL (x) > 65535)
01350 LOSE_AND_RETURN ("invalid operand for 'z' modifier", x);
01351 putc (INTVAL (x) >= -128 && INTVAL (x) <= 255 ? 'b' : 'w', file);
01352 return;
01353
01354 case '#':
01355
01356
01357 if (dbr_sequence_length () == 0)
01358 fputs ("\n\tnop", file);
01359 return;
01360
01361 case 'H':
01362
01363 switch (GET_CODE (operand))
01364 {
01365 case CONST_INT:
01366 if (HOST_BITS_PER_WIDE_INT == 32)
01367
01368 fprintf (file, INTVAL (operand) < 0 ? "-1" : "0");
01369 else
01370 fprintf (file, "0x%x", (unsigned int)(INTVAL (x) >> 31 >> 1));
01371 return;
01372
01373 case CONST_DOUBLE:
01374
01375 if (GET_MODE (operand) == VOIDmode)
01376 {
01377 fprintf (file, "0x%x", CONST_DOUBLE_HIGH (x));
01378 return;
01379 }
01380 else
01381 LOSE_AND_RETURN ("invalid operand for 'H' modifier", x);
01382
01383 case REG:
01384
01385
01386 if (REGNO (operand) > STACK_POINTER_REGNUM - 2)
01387 LOSE_AND_RETURN ("bad register", operand);
01388 fprintf (file, "$%s", reg_names[REGNO (operand) + 1]);
01389 return;
01390
01391 case MEM:
01392
01393 {
01394 rtx adj_mem = operand;
01395 int size
01396 = GET_MODE_BITSIZE (GET_MODE (operand)) / BITS_PER_UNIT;
01397
01398
01399
01400
01401
01402 if (GET_CODE (XEXP (adj_mem, 0)) != POST_INC)
01403 adj_mem
01404 = adjust_address (adj_mem, GET_MODE (adj_mem), size / 2);
01405
01406 output_address (XEXP (adj_mem, 0));
01407 return;
01408 }
01409
01410 default:
01411 LOSE_AND_RETURN ("invalid operand for 'H' modifier", x);
01412 }
01413
01414 case 'L':
01415
01416 operand = XEXP (operand, 0);
01417 break;
01418
01419 case 'e':
01420
01421
01422 if (GET_CODE (operand) != SIGN_EXTEND
01423 && GET_CODE (operand) != ZERO_EXTEND
01424 && GET_CODE (operand) != CONST_INT)
01425 LOSE_AND_RETURN ("invalid operand for 'e' modifier", x);
01426
01427 if (cris_output_insn_is_bound)
01428 {
01429 cris_output_insn_is_bound = 0;
01430 return;
01431 }
01432
01433 putc (GET_CODE (operand) == SIGN_EXTEND
01434 || (GET_CODE (operand) == CONST_INT && INTVAL (operand) < 0)
01435 ? 's' : 'u', file);
01436 return;
01437
01438 case 'm':
01439
01440
01441 if (GET_CODE (operand) != SIGN_EXTEND && GET_CODE (operand) != ZERO_EXTEND)
01442 LOSE_AND_RETURN ("invalid operand for 'm' modifier", x);
01443 cris_print_operand (file, XEXP (operand, 0), 's');
01444 return;
01445
01446 case 'M':
01447
01448 if (GET_CODE (operand) == CONST_DOUBLE)
01449 {
01450 fprintf (file, "0x%x", CONST_DOUBLE_LOW (x));
01451 return;
01452 }
01453 else if (HOST_BITS_PER_WIDE_INT > 32 && GET_CODE (operand) == CONST_INT)
01454 {
01455 fprintf (file, "0x%x",
01456 INTVAL (x) & ((unsigned int) 0x7fffffff * 2 + 1));
01457 return;
01458 }
01459
01460
01461 break;
01462
01463 case 'A':
01464
01465
01466 if (GET_CODE (operand) != CONST_INT)
01467 LOSE_AND_RETURN ("invalid operand for 'A' modifier", x);
01468 fprintf (file, INTVAL (operand) < 0 ? "adds.w" : "addq");
01469 return;
01470
01471 case 'D':
01472
01473
01474 if (GET_CODE (operand) != CONST_INT)
01475 LOSE_AND_RETURN ("invalid operand for 'D' modifier", x);
01476 fprintf (file, INTVAL (operand) < 0 ? "subs.w" : "subq");
01477 return;
01478
01479 case 'S':
01480
01481
01482 cris_print_index (operand, file);
01483 return;
01484
01485 case 'T':
01486
01487
01488 if (GET_CODE (operand) != CONST_INT || INTVAL (operand) > 4)
01489 LOSE_AND_RETURN ("invalid operand for 'T' modifier", x);
01490 fprintf (file, "%s", mults[INTVAL (operand)]);
01491 return;
01492
01493 case 0:
01494
01495 break;
01496
01497 default:
01498 LOSE_AND_RETURN ("invalid operand modifier letter", x);
01499 }
01500
01501
01502 switch (GET_CODE (operand))
01503 {
01504 case REG:
01505 if (REGNO (operand) > 15)
01506 internal_error ("internal error: bad register: %d", REGNO (operand));
01507 fprintf (file, "$%s", reg_names[REGNO (operand)]);
01508 return;
01509
01510 case MEM:
01511 output_address (XEXP (operand, 0));
01512 return;
01513
01514 case CONST_DOUBLE:
01515 if (GET_MODE (operand) == VOIDmode)
01516
01517 output_addr_const (file, operand);
01518 else
01519 {
01520
01521
01522
01523 REAL_VALUE_TYPE r;
01524 long l;
01525
01526
01527 REAL_VALUE_FROM_CONST_DOUBLE (r, operand);
01528 REAL_VALUE_TO_TARGET_SINGLE (r, l);
01529
01530 fprintf (file, "0x%lx", l);
01531 }
01532 return;
01533
01534 case UNSPEC:
01535 ASSERT_PLT_UNSPEC (operand);
01536
01537
01538 case CONST:
01539 cris_output_addr_const (file, operand);
01540 return;
01541
01542 case MULT:
01543 case ASHIFT:
01544 {
01545
01546 int i = GET_CODE (XEXP (operand, 1)) == CONST_INT
01547 ? INTVAL (XEXP (operand, 1)) : INTVAL (XEXP (operand, 0));
01548 rtx reg = GET_CODE (XEXP (operand, 1)) == CONST_INT
01549 ? XEXP (operand, 0) : XEXP (operand, 1);
01550
01551 if (GET_CODE (reg) != REG
01552 || (GET_CODE (XEXP (operand, 0)) != CONST_INT
01553 && GET_CODE (XEXP (operand, 1)) != CONST_INT))
01554 LOSE_AND_RETURN ("unexpected multiplicative operand", x);
01555
01556 cris_print_base (reg, file);
01557 fprintf (file, ".%c",
01558 i == 0 || (i == 1 && GET_CODE (operand) == MULT) ? 'b'
01559 : i == 4 ? 'd'
01560 : (i == 2 && GET_CODE (operand) == MULT) || i == 1 ? 'w'
01561 : 'd');
01562 return;
01563 }
01564
01565 default:
01566
01567
01568 if (CONSTANT_P (operand))
01569 {
01570 cris_output_addr_const (file, operand);
01571 return;
01572 }
01573
01574 LOSE_AND_RETURN ("unexpected operand", x);
01575 }
01576 }
01577
01578
01579
01580 void
01581 cris_print_operand_address (file, x)
01582 FILE *file;
01583 rtx x;
01584 {
01585
01586 putc ('[', file);
01587
01588 if (CONSTANT_ADDRESS_P (x))
01589 cris_output_addr_const (file, x);
01590 else if (BASE_OR_AUTOINCR_P (x))
01591 cris_print_base (x, file);
01592 else if (GET_CODE (x) == PLUS)
01593 {
01594 rtx x1, x2;
01595
01596 x1 = XEXP (x, 0);
01597 x2 = XEXP (x, 1);
01598 if (BASE_P (x1))
01599 {
01600 cris_print_base (x1, file);
01601 cris_print_index (x2, file);
01602 }
01603 else if (BASE_P (x2))
01604 {
01605 cris_print_base (x2, file);
01606 cris_print_index (x1, file);
01607 }
01608 else
01609 LOSE_AND_RETURN ("unrecognized address", x);
01610 }
01611 else if (GET_CODE (x) == MEM)
01612 {
01613
01614 putc ('[', file);
01615 cris_print_base (XEXP (x, 0), file);
01616 putc (']', file);
01617 }
01618 else
01619 LOSE_AND_RETURN ("unrecognized address", x);
01620
01621 putc (']', file);
01622 }
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632 rtx
01633 cris_return_addr_rtx (count, frameaddr)
01634 int count;
01635 rtx frameaddr ATTRIBUTE_UNUSED;
01636 {
01637 cfun->machine->needs_return_address_on_stack = 1;
01638
01639
01640
01641
01642 return count == 0
01643 ? gen_rtx_MEM (Pmode, plus_constant (virtual_incoming_args_rtx, -4))
01644 : NULL_RTX;
01645 }
01646
01647
01648
01649
01650 static int
01651 cris_initial_frame_pointer_offset ()
01652 {
01653 int regno;
01654
01655
01656 int offs = 0;
01657
01658
01659 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
01660 if ((((regs_ever_live[regno]
01661 && !call_used_regs[regno])
01662 || (regno == (int) PIC_OFFSET_TABLE_REGNUM
01663 && (current_function_uses_pic_offset_table
01664
01665 || (flag_pic
01666 && regs_ever_live[regno + 1]
01667 && !call_used_regs[regno + 1]))))
01668 && (regno != FRAME_POINTER_REGNUM || !frame_pointer_needed)
01669 && regno != CRIS_SRP_REGNUM)
01670 || (current_function_calls_eh_return
01671 && (regno == EH_RETURN_DATA_REGNO (0)
01672 || regno == EH_RETURN_DATA_REGNO (1)
01673 || regno == EH_RETURN_DATA_REGNO (2)
01674 || regno == EH_RETURN_DATA_REGNO (3))))
01675 offs += 4;
01676
01677
01678 offs += get_frame_size ();
01679
01680
01681 offs += current_function_outgoing_args_size;
01682
01683
01684 if (TARGET_STACK_ALIGN)
01685 offs = TARGET_ALIGN_BY_32 ? (offs + 3) & ~3 : (offs + 1) & ~1;
01686
01687 return offs;
01688 }
01689
01690
01691
01692
01693
01694
01695 int
01696 cris_initial_elimination_offset (fromreg, toreg)
01697 int fromreg;
01698 int toreg;
01699 {
01700 int fp_sp_offset
01701 = cris_initial_frame_pointer_offset ();
01702
01703
01704
01705 int return_address_on_stack
01706 = regs_ever_live[CRIS_SRP_REGNUM]
01707 || cfun->machine->needs_return_address_on_stack != 0;
01708
01709
01710 int ap_fp_offset = 4 + (return_address_on_stack ? 4 : 0);
01711
01712 if (fromreg == ARG_POINTER_REGNUM
01713 && toreg == FRAME_POINTER_REGNUM)
01714 return ap_fp_offset;
01715
01716
01717
01718 if (fromreg == FRAME_POINTER_REGNUM
01719 && toreg == STACK_POINTER_REGNUM)
01720 return fp_sp_offset;
01721
01722
01723 if (fromreg == ARG_POINTER_REGNUM
01724 && toreg == STACK_POINTER_REGNUM)
01725 return ap_fp_offset + fp_sp_offset - 4;
01726
01727 abort ();
01728 }
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741 void
01742 cris_notice_update_cc (exp, insn)
01743 rtx exp;
01744 rtx insn;
01745 {
01746
01747
01748
01749
01750 if (TARGET_CCINIT)
01751 {
01752 CC_STATUS_INIT;
01753 return;
01754 }
01755
01756
01757
01758 switch (get_attr_cc (insn))
01759 {
01760 case CC_NONE:
01761
01762
01763 if (GET_CODE (exp) == SET)
01764 {
01765 if (cc_status.value1
01766 && cris_reg_overlap_mentioned_p (SET_DEST (exp),
01767 cc_status.value1))
01768 cc_status.value1 = 0;
01769
01770 if (cc_status.value2
01771 && cris_reg_overlap_mentioned_p (SET_DEST (exp),
01772 cc_status.value2))
01773 cc_status.value2 = 0;
01774 }
01775 return;
01776
01777 case CC_CLOBBER:
01778 CC_STATUS_INIT;
01779 break;
01780
01781 case CC_NORMAL:
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818 if (GET_CODE (exp) == SET)
01819 {
01820
01821
01822 if (SET_DEST (exp) == pc_rtx)
01823 return;
01824
01825
01826
01827 if (SET_DEST (exp) == cc0_rtx)
01828 {
01829 cc_status.value1 = SET_SRC (exp);
01830 cc_status.value2 = 0;
01831
01832
01833 if (GET_CODE (SET_SRC (exp)) == ZERO_EXTRACT
01834 && XEXP (SET_SRC (exp), 1) == const1_rtx)
01835 {
01836 if (GET_CODE (XEXP (SET_SRC (exp), 0)) == CONST_INT)
01837
01838 cc_status.flags = CC_INVERTED;
01839 else
01840
01841 cc_status.flags = CC_Z_IN_NOT_N;
01842 }
01843 else
01844 cc_status.flags = 0;
01845
01846 if (GET_CODE (SET_SRC (exp)) == COMPARE)
01847 {
01848 if (!REG_P (XEXP (SET_SRC (exp), 0))
01849 && XEXP (SET_SRC (exp), 1) != const0_rtx)
01850
01851
01852
01853
01854 cc_status.flags = CC_REVERSED;
01855
01856
01857
01858 cc_status.value2
01859 = gen_rtx_MINUS (GET_MODE (SET_SRC (exp)),
01860 XEXP (SET_SRC (exp), 0),
01861 XEXP (SET_SRC (exp), 1));
01862 }
01863 return;
01864 }
01865 else if (REG_P (SET_DEST (exp))
01866 || (GET_CODE (SET_DEST (exp)) == STRICT_LOW_PART
01867 && REG_P (XEXP (SET_DEST (exp), 0))))
01868 {
01869
01870
01871
01872
01873
01874 if (GET_MODE_SIZE (GET_MODE (SET_DEST (exp))) > UNITS_PER_WORD
01875 || GET_MODE_CLASS (GET_MODE (SET_DEST (exp))) == MODE_FLOAT)
01876 {
01877
01878 if (GET_MODE (SET_DEST (exp)) == DImode
01879 && (GET_CODE (SET_SRC (exp)) == PLUS
01880 || GET_CODE (SET_SRC (exp)) == MINUS))
01881 {
01882 cc_status.flags = 0;
01883 cc_status.value1 = SET_DEST (exp);
01884 cc_status.value2 = SET_SRC (exp);
01885
01886 if (cris_reg_overlap_mentioned_p (cc_status.value1,
01887 cc_status.value2))
01888 cc_status.value2 = 0;
01889
01890
01891
01892
01893 cc_status.flags |= CC_NO_OVERFLOW;
01894
01895 return;
01896 }
01897 }
01898 else if (SET_SRC (exp) == const0_rtx)
01899 {
01900
01901
01902 if ((cc_status.value1
01903 && cris_reg_overlap_mentioned_p (SET_DEST (exp),
01904 cc_status.value1)))
01905 cc_status.value1 = 0;
01906
01907 if ((cc_status.value2
01908 && cris_reg_overlap_mentioned_p (SET_DEST (exp),
01909 cc_status.value2)))
01910 cc_status.value2 = 0;
01911
01912 return;
01913 }
01914 else
01915 {
01916 cc_status.flags = 0;
01917 cc_status.value1 = SET_DEST (exp);
01918 cc_status.value2 = SET_SRC (exp);
01919
01920 if (cris_reg_overlap_mentioned_p (cc_status.value1,
01921 cc_status.value2))
01922 cc_status.value2 = 0;
01923
01924
01925
01926
01927 if (GET_CODE (SET_SRC (exp)) == PLUS
01928 || GET_CODE (SET_SRC (exp)) == MINUS
01929 || GET_CODE (SET_SRC (exp)) == NEG)
01930 cc_status.flags |= CC_NO_OVERFLOW;
01931
01932 return;
01933 }
01934 }
01935 else if (GET_CODE (SET_DEST (exp)) == MEM
01936 || (GET_CODE (SET_DEST (exp)) == STRICT_LOW_PART
01937 && GET_CODE (XEXP (SET_DEST (exp), 0)) == MEM))
01938 {
01939
01940
01941 if ((cc_status.value1
01942 && cris_reg_overlap_mentioned_p (SET_DEST (exp),
01943 cc_status.value1)))
01944 cc_status.value1 = 0;
01945
01946 if ((cc_status.value2
01947 && cris_reg_overlap_mentioned_p (SET_DEST (exp),
01948 cc_status.value2)))
01949 cc_status.value2 = 0;
01950
01951 return;
01952 }
01953 }
01954 else if (GET_CODE (exp) == PARALLEL)
01955 {
01956 if (GET_CODE (XVECEXP (exp, 0, 0)) == SET
01957 && GET_CODE (XVECEXP (exp, 0, 1)) == SET
01958 && REG_P (XEXP (XVECEXP (exp, 0, 1), 0)))
01959 {
01960 if (REG_P (XEXP (XVECEXP (exp, 0, 0), 0))
01961 && GET_CODE (XEXP (XVECEXP (exp, 0, 0), 1)) == MEM)
01962 {
01963
01964
01965 cc_status.value1 = XEXP (XVECEXP (exp, 0, 0), 0);
01966 cc_status.value2
01967 = gen_rtx_MEM (GET_MODE (XEXP (XVECEXP (exp, 0, 0), 0)),
01968 XEXP (XVECEXP (exp, 0, 1), 0));
01969 cc_status.flags = 0;
01970
01971
01972
01973 if (cris_reg_overlap_mentioned_p (cc_status.value1,
01974 cc_status.value2))
01975 internal_error ("internal error: sideeffect-insn affecting main effect");
01976 return;
01977 }
01978 else if ((REG_P (XEXP (XVECEXP (exp, 0, 0), 1))
01979 || XEXP (XVECEXP (exp, 0, 0), 1) == const0_rtx)
01980 && GET_CODE (XEXP (XVECEXP (exp, 0, 0), 0)) == MEM)
01981 {
01982
01983
01984 if (cc_status.value1
01985 && cris_reg_overlap_mentioned_p (XEXP
01986 (XVECEXP
01987 (exp, 0, 0), 0),
01988 cc_status.value1))
01989 cc_status.value1 = 0;
01990
01991 if (cc_status.value1
01992 && cris_reg_overlap_mentioned_p (XEXP
01993 (XVECEXP
01994 (exp, 0, 1), 0),
01995 cc_status.value1))
01996 cc_status.value1 = 0;
01997
01998 if (cc_status.value2
01999 && cris_reg_overlap_mentioned_p (XEXP
02000 (XVECEXP
02001 (exp, 0, 0), 0),
02002 cc_status.value2))
02003 cc_status.value2 = 0;
02004
02005 if (cc_status.value2
02006 && cris_reg_overlap_mentioned_p (XEXP
02007 (XVECEXP
02008 (exp, 0, 1), 0),
02009 cc_status.value2))
02010 cc_status.value2 = 0;
02011
02012 return;
02013 }
02014 }
02015 }
02016 break;
02017
02018 default:
02019
02020 abort ();
02021 }
02022
02023 CC_STATUS_INIT;
02024 }
02025
02026
02027
02028
02029
02030 int
02031 cris_simple_epilogue ()
02032 {
02033 int regno;
02034 int reglimit = STACK_POINTER_REGNUM;
02035 int lastreg = -1;
02036
02037 if (! reload_completed
02038 || frame_pointer_needed
02039 || get_frame_size () != 0
02040 || current_function_pretend_args_size
02041 || current_function_args_size
02042 || current_function_outgoing_args_size
02043 || current_function_calls_eh_return
02044
02045
02046
02047
02048
02049
02050
02051 || current_function_epilogue_delay_list != NULL
02052
02053
02054
02055 || !TARGET_PROLOGUE_EPILOGUE)
02056 return 0;
02057
02058
02059
02060 for (regno = 0; regno < reglimit; regno++)
02061 if ((regs_ever_live[regno] && ! call_used_regs[regno])
02062 || (regno == (int) PIC_OFFSET_TABLE_REGNUM
02063 && (current_function_uses_pic_offset_table
02064
02065 || (flag_pic
02066 && regs_ever_live[regno + 1]
02067 && !call_used_regs[regno + 1]))))
02068 {
02069 if (lastreg != regno - 1)
02070 return 0;
02071 lastreg = regno;
02072 }
02073
02074 return 1;
02075 }
02076
02077
02078
02079 int
02080 cris_address_cost (x)
02081 rtx x;
02082 {
02083
02084
02085
02086
02087
02088
02089 if (BASE_OR_AUTOINCR_P (x))
02090 return 0;
02091
02092
02093
02094 if (GET_CODE (x) == MEM)
02095 return (2 + 4) / 2;
02096
02097
02098
02099
02100
02101
02102 if (CONSTANT_P (x))
02103 return flag_pic && cris_got_symbol (x) ? 2 * (2 + 4) / 2 : (2 + 4) / 2;
02104
02105
02106 if (GET_CODE (x) == PLUS)
02107 {
02108 rtx tem1 = XEXP (x, 0);
02109 rtx tem2 = XEXP (x, 1);
02110
02111
02112
02113
02114 if ((GET_CODE (tem1) == MULT && BIAP_INDEX_P (tem1))
02115 || REG_P (tem1))
02116 return 2 / 2;
02117
02118
02119
02120 if (GET_CODE (tem2) == CONST_INT
02121 && INTVAL (tem2) < 128 && INTVAL (tem2) >= -128)
02122 return 2 / 2;
02123
02124
02125
02126 if (GET_CODE (tem2) == CONST_INT
02127 && CONST_OK_FOR_LETTER_P (INTVAL (tem2), 'L'))
02128 return (2 + 2) / 2;
02129
02130
02131 if (CONSTANT_P (tem2))
02132 return (2 + 2 + 2) / 2;
02133
02134
02135
02136
02137
02138
02139 return (2 + 2 + 2) / 2;
02140 }
02141
02142
02143
02144 return 10;
02145 }
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162 int
02163 cris_side_effect_mode_ok (code, ops, lreg, rreg, rval, multop, other_op)
02164 enum rtx_code code;
02165 rtx *ops;
02166 int lreg, rreg, rval, multop, other_op;
02167 {
02168
02169 int mult = multop < 0 ? 1 : INTVAL (ops[multop]);
02170
02171 rtx reg_rtx = ops[rreg];
02172 rtx val_rtx = ops[rval];
02173
02174
02175
02176
02177 if (! BASE_P (reg_rtx))
02178 reg_rtx = val_rtx, val_rtx = ops[rreg];
02179
02180
02181
02182 if (! BASE_P (reg_rtx))
02183 return 0;
02184
02185
02186 if (!TARGET_SIDE_EFFECT_PREFIXES)
02187 return 0;
02188
02189
02190
02191 if (GET_CODE (val_rtx) == MULT)
02192 {
02193 mult = INTVAL (XEXP (val_rtx, 1));
02194 val_rtx = XEXP (val_rtx, 0);
02195 code = MULT;
02196 }
02197
02198
02199 if (other_op >= 0)
02200 {
02201 if (GET_MODE_SIZE (GET_MODE (ops[other_op])) > UNITS_PER_WORD)
02202 return 0;
02203
02204
02205
02206
02207 if ((BASE_P (ops[lreg])
02208 && BASE_P (ops[other_op])
02209 && REGNO (ops[lreg]) == REGNO (ops[other_op]))
02210 || rtx_equal_p (ops[other_op], ops[lreg]))
02211 return 0;
02212 }
02213
02214
02215 if (ops[lreg] == frame_pointer_rtx || ops[rreg] == frame_pointer_rtx
02216 || ops[rval] == frame_pointer_rtx
02217 || (other_op >= 0 && ops[other_op] == frame_pointer_rtx))
02218 return 0;
02219
02220 if (code == PLUS
02221 && ! BASE_P (val_rtx))
02222 {
02223
02224
02225
02226 if (rtx_equal_p (ops[lreg], reg_rtx)
02227 && GET_CODE (val_rtx) == CONST_INT
02228 && (INTVAL (val_rtx) <= 63 && INTVAL (val_rtx) >= -63))
02229 return 0;
02230
02231
02232
02233 if (CONSTANT_P (val_rtx))
02234 return flag_pic == 0 || cris_symbol (val_rtx) == 0;
02235
02236 if (GET_CODE (val_rtx) == MEM
02237 && BASE_OR_AUTOINCR_P (XEXP (val_rtx, 0)))
02238 return 1;
02239
02240 if (GET_CODE (val_rtx) == SIGN_EXTEND
02241 && GET_CODE (XEXP (val_rtx, 0)) == MEM
02242 && BASE_OR_AUTOINCR_P (XEXP (XEXP (val_rtx, 0), 0)))
02243 return 1;
02244
02245
02246 return 0;
02247 }
02248 else if (code == MULT
02249 || (code == PLUS && BASE_P (val_rtx)))
02250 {
02251
02252 if (rtx_equal_p (ops[lreg], reg_rtx)
02253 || (mult == 1 && rtx_equal_p (ops[lreg], val_rtx)))
02254 return 0;
02255
02256
02257 if (mult != 1 && mult != 2 && mult != 4)
02258 return 0;
02259
02260
02261 if (! BASE_P (reg_rtx))
02262 return 0;
02263
02264
02265
02266 return 1;
02267 }
02268
02269
02270 internal_error ("internal error: cris_side_effect_mode_ok with bad operands");
02271 }
02272
02273
02274
02275
02276
02277
02278
02279 static int
02280 cris_reg_overlap_mentioned_p (x, in)
02281 rtx x, in;
02282 {
02283
02284
02285 if (GET_CODE (in) == STRICT_LOW_PART)
02286 in = XEXP (in, 0);
02287
02288 return reg_overlap_mentioned_p (x, in);
02289 }
02290
02291
02292
02293
02294 void
02295 cris_target_asm_named_section (name, flags)
02296 const char *name;
02297 unsigned int flags;
02298 {
02299 if (! TARGET_ELF)
02300 default_no_named_section (name, flags);
02301 else
02302 default_elf_asm_named_section (name, flags);
02303 }
02304
02305
02306
02307 int
02308 cris_legitimate_pic_operand (x)
02309 rtx x;
02310 {
02311
02312
02313
02314
02315
02316
02317
02318 return ! cris_symbol (x) || cris_got_symbol (x);
02319 }
02320
02321
02322
02323
02324 int
02325 cris_symbol (x)
02326 rtx x;
02327 {
02328 switch (GET_CODE (x))
02329 {
02330 case SYMBOL_REF:
02331 case LABEL_REF:
02332 return 1;
02333
02334 case UNSPEC:
02335
02336 ASSERT_PLT_UNSPEC (x);
02337 return 1;
02338
02339 case CONST:
02340 return cris_symbol (XEXP (x, 0));
02341
02342 case PLUS:
02343 case MINUS:
02344 return cris_symbol (XEXP (x, 0)) || cris_symbol (XEXP (x, 1));
02345
02346 case CONST_INT:
02347 case CONST_DOUBLE:
02348 case CONSTANT_P_RTX:
02349 return 0;
02350
02351 default:
02352 fatal_insn ("unrecognized supposed constant", x);
02353 }
02354
02355 return 1;
02356 }
02357
02358
02359
02360
02361
02362
02363 int
02364 cris_gotless_symbol (x)
02365 rtx x;
02366 {
02367 switch (GET_CODE (x))
02368 {
02369 case UNSPEC:
02370 ASSERT_PLT_UNSPEC (x);
02371 return 1;
02372
02373 case SYMBOL_REF:
02374 if (flag_pic && cfun != NULL)
02375 current_function_uses_pic_offset_table = 1;
02376 return SYMBOL_REF_FLAG (x);
02377
02378 case LABEL_REF:
02379
02380
02381
02382
02383
02384
02385 return 1;
02386
02387 case CONST:
02388 return cris_gotless_symbol (XEXP (x, 0));
02389
02390 case PLUS:
02391 case MINUS:
02392 {
02393 int x0 = cris_gotless_symbol (XEXP (x, 0)) != 0;
02394 int x1 = cris_gotless_symbol (XEXP (x, 1)) != 0;
02395
02396
02397
02398 return
02399 (x0 ^ x1)
02400 && ! (x0 == 0 && cris_symbol (XEXP (x, 0)))
02401 && ! (x1 == 0 && cris_symbol (XEXP (x, 1)));
02402 }
02403
02404 case CONST_INT:
02405 case CONST_DOUBLE:
02406 case CONSTANT_P_RTX:
02407 return 0;
02408
02409 default:
02410 fatal_insn ("unrecognized supposed constant", x);
02411 }
02412
02413 return 1;
02414 }
02415
02416
02417
02418
02419 int
02420 cris_got_symbol (x)
02421 rtx x;
02422 {
02423 switch (GET_CODE (x))
02424 {
02425 case UNSPEC:
02426 ASSERT_PLT_UNSPEC (x);
02427 return 0;
02428
02429 case SYMBOL_REF:
02430 if (flag_pic && cfun != NULL)
02431 current_function_uses_pic_offset_table = 1;
02432 return ! SYMBOL_REF_FLAG (x);
02433
02434 case CONST:
02435 return cris_got_symbol (XEXP (x, 0));
02436
02437 case LABEL_REF:
02438
02439
02440 case PLUS:
02441 case MINUS:
02442
02443 return 0;
02444
02445 case CONST_INT:
02446 case CONST_DOUBLE:
02447 case CONSTANT_P_RTX:
02448 return 0;
02449
02450 default:
02451 fatal_insn ("unrecognized supposed constant in cris_global_pic_symbol",
02452 x);
02453 }
02454
02455 return 1;
02456 }
02457
02458
02459
02460
02461 void
02462 cris_override_options ()
02463 {
02464 if (cris_max_stackframe_str)
02465 {
02466 cris_max_stackframe = atoi (cris_max_stackframe_str);
02467
02468
02469 if (cris_max_stackframe < 0 || cris_max_stackframe > 0x20000000)
02470 internal_error ("-max-stackframe=%d is not usable, not between 0 and %d",
02471 cris_max_stackframe, 0x20000000);
02472 }
02473
02474
02475 if (TARGET_SVINTO && cris_cpu_version < CRIS_CPU_SVINTO)
02476 cris_cpu_version = CRIS_CPU_SVINTO;
02477 else if (TARGET_ETRAX4_ADD && cris_cpu_version < CRIS_CPU_ETRAX4)
02478 cris_cpu_version = CRIS_CPU_ETRAX4;
02479
02480
02481 if (cris_cpu_str)
02482 {
02483 cris_cpu_version
02484 = (*cris_cpu_str == 'v' ? atoi (cris_cpu_str + 1) : -1);
02485
02486 if (strcmp ("etrax4", cris_cpu_str) == 0)
02487 cris_cpu_version = 3;
02488
02489 if (strcmp ("svinto", cris_cpu_str) == 0
02490 || strcmp ("etrax100", cris_cpu_str) == 0)
02491 cris_cpu_version = 8;
02492
02493 if (strcmp ("ng", cris_cpu_str) == 0
02494 || strcmp ("etrax100lx", cris_cpu_str) == 0)
02495 cris_cpu_version = 10;
02496
02497 if (cris_cpu_version < 0 || cris_cpu_version > 10)
02498 error ("unknown CRIS version specification in -march= or -mcpu= : %s",
02499 cris_cpu_str);
02500
02501
02502 if (cris_cpu_version >= CRIS_CPU_ETRAX4)
02503 target_flags |= TARGET_MASK_ETRAX4_ADD;
02504
02505
02506 if (cris_cpu_version >= CRIS_CPU_SVINTO)
02507 target_flags
02508 |= (TARGET_MASK_SVINTO | TARGET_MASK_ALIGN_BY_32
02509 | TARGET_MASK_STACK_ALIGN | TARGET_MASK_CONST_ALIGN
02510 | TARGET_MASK_DATA_ALIGN);
02511
02512
02513
02514
02515 }
02516
02517 if (cris_tune_str)
02518 {
02519 int cris_tune
02520 = (*cris_tune_str == 'v' ? atoi (cris_tune_str + 1) : -1);
02521
02522 if (strcmp ("etrax4", cris_tune_str) == 0)
02523 cris_tune = 3;
02524
02525 if (strcmp ("svinto", cris_tune_str) == 0
02526 || strcmp ("etrax100", cris_tune_str) == 0)
02527 cris_tune = 8;
02528
02529 if (strcmp ("ng", cris_tune_str) == 0
02530 || strcmp ("etrax100lx", cris_tune_str) == 0)
02531 cris_tune = 10;
02532
02533 if (cris_tune < 0 || cris_tune > 10)
02534 error ("unknown CRIS cpu version specification in -mtune= : %s",
02535 cris_tune_str);
02536
02537 if (cris_tune >= CRIS_CPU_SVINTO)
02538
02539
02540 target_flags
02541 |= (TARGET_MASK_STACK_ALIGN | TARGET_MASK_CONST_ALIGN
02542 | TARGET_MASK_DATA_ALIGN | TARGET_MASK_ALIGN_BY_32);
02543 }
02544
02545 if (flag_pic)
02546 {
02547
02548
02549
02550 if (! TARGET_LINUX)
02551 {
02552 error ("-fPIC and -fpic are not supported in this configuration");
02553 flag_pic = 0;
02554 }
02555
02556
02557
02558
02559
02560
02561
02562 flag_no_function_cse = 1;
02563 }
02564
02565 if ((write_symbols == DWARF_DEBUG
02566 || write_symbols == DWARF2_DEBUG) && ! TARGET_ELF)
02567 {
02568 warning ("that particular -g option is invalid with -maout and -melinux");
02569 write_symbols = DBX_DEBUG;
02570 }
02571
02572
02573 init_machine_status = cris_init_machine_status;
02574 }
02575
02576
02577
02578 void
02579 cris_asm_output_mi_thunk (stream, thunkdecl, delta, funcdecl)
02580 FILE *stream;
02581 tree thunkdecl ATTRIBUTE_UNUSED;
02582 int delta;
02583 tree funcdecl;
02584 {
02585 if (delta > 0)
02586 asm_fprintf (stream, "\tadd%s %d,$%s\n",
02587 ADDITIVE_SIZE_MODIFIER (delta), delta,
02588 reg_names[CRIS_FIRST_ARG_REG]);
02589 else if (delta < 0)
02590 asm_fprintf (stream, "\tsub%s %d,$%s\n",
02591 ADDITIVE_SIZE_MODIFIER (-delta), -delta,
02592 reg_names[CRIS_FIRST_ARG_REG]);
02593
02594 if (flag_pic)
02595 {
02596 const char *name = XSTR (XEXP (DECL_RTL (funcdecl), 0), 0);
02597
02598 STRIP_NAME_ENCODING (name, name);
02599 fprintf (stream, "add.d ");
02600 assemble_name (stream, name);
02601 fprintf (stream, "%s,$pc\n", CRIS_PLT_PCOFFSET_SUFFIX);
02602 }
02603 else
02604 {
02605 fprintf (stream, "jump ");
02606 assemble_name (stream, XSTR (XEXP (DECL_RTL (funcdecl), 0), 0));
02607 fprintf (stream, "\n");
02608 }
02609 }
02610
02611
02612
02613
02614
02615
02616
02617 rtx
02618 cris_expand_builtin_va_arg (valist, type)
02619 tree valist;
02620 tree type;
02621 {
02622 tree addr_tree, t;
02623 rtx addr;
02624 tree passed_size = size_zero_node;
02625 tree type_size = NULL;
02626 tree size3 = size_int (3);
02627 tree size4 = size_int (4);
02628 tree size8 = size_int (8);
02629 tree rounded_size;
02630
02631
02632 addr_tree = valist;
02633
02634 if (type == error_mark_node
02635 || (type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type))) == NULL
02636 || TREE_OVERFLOW (type_size))
02637
02638
02639 rounded_size = size_zero_node;
02640 else
02641 rounded_size
02642 = fold (build (MULT_EXPR, sizetype,
02643 fold (build (TRUNC_DIV_EXPR, sizetype,
02644 fold (build (PLUS_EXPR, sizetype,
02645 type_size, size3)),
02646 size4)),
02647 size4));
02648
02649 if (!integer_zerop (rounded_size))
02650 {
02651
02652
02653
02654
02655 passed_size
02656 = (!really_constant_p (type_size)
02657 ? size4
02658 : fold (build (COND_EXPR, sizetype,
02659 fold (build (GT_EXPR, sizetype,
02660 rounded_size,
02661 size8)),
02662 size4,
02663 rounded_size)));
02664
02665 addr_tree
02666 = (!really_constant_p (type_size)
02667 ? build1 (INDIRECT_REF, build_pointer_type (type), addr_tree)
02668 : fold (build (COND_EXPR, TREE_TYPE (addr_tree),
02669 fold (build (GT_EXPR, sizetype,
02670 rounded_size,
02671 size8)),
02672 build1 (INDIRECT_REF, build_pointer_type (type),
02673 addr_tree),
02674 addr_tree)));
02675 }
02676
02677 addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
02678 addr = copy_to_reg (addr);
02679
02680 if (!integer_zerop (rounded_size))
02681 {
02682
02683 t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
02684 build (PLUS_EXPR, TREE_TYPE (valist), valist,
02685 passed_size));
02686 TREE_SIDE_EFFECTS (t) = 1;
02687 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
02688 }
02689
02690 return addr;
02691 }
02692
02693
02694
02695
02696 void
02697 cris_init_expanders ()
02698 {
02699
02700 }
02701
02702
02703
02704 static void
02705 cris_init_machine_status (p)
02706 struct function *p;
02707 {
02708 p->machine = xcalloc (1, sizeof (struct machine_function));
02709 }
02710
02711
02712
02713
02714 rtx
02715 cris_split_movdx (operands)
02716 rtx *operands;
02717 {
02718 enum machine_mode mode = GET_MODE (operands[0]);
02719 rtx dest = operands[0];
02720 rtx src = operands[1];
02721 rtx val;
02722
02723
02724
02725
02726 if (GET_CODE (dest) == SUBREG || GET_CODE (src) == SUBREG)
02727 abort ();
02728
02729 start_sequence ();
02730 if (GET_CODE (dest) == REG)
02731 {
02732 int dregno = REGNO (dest);
02733
02734
02735 if (GET_CODE (src) == REG)
02736 {
02737 int sregno = REGNO (src);
02738
02739 int reverse = (dregno == sregno + 1);
02740
02741
02742
02743
02744 emit_insn (gen_rtx_SET (VOIDmode,
02745 operand_subword (dest, reverse, TRUE, mode),
02746 operand_subword (src, reverse, TRUE, mode)));
02747
02748 emit_insn (gen_rtx_SET (VOIDmode,
02749 operand_subword (dest, !reverse, TRUE, mode),
02750 operand_subword (src, !reverse, TRUE, mode)));
02751 }
02752
02753 else if (GET_CODE (src) == CONST_INT || GET_CODE (src) == CONST_DOUBLE)
02754 {
02755 rtx words[2];
02756 split_double (src, &words[0], &words[1]);
02757 emit_insn (gen_rtx_SET (VOIDmode,
02758 operand_subword (dest, 0, TRUE, mode),
02759 words[0]));
02760
02761 emit_insn (gen_rtx_SET (VOIDmode,
02762 operand_subword (dest, 1, TRUE, mode),
02763 words[1]));
02764 }
02765
02766 else if (GET_CODE (src) == MEM)
02767 {
02768
02769
02770 rtx addr = XEXP (src, 0);
02771 int reverse
02772 = (refers_to_regno_p (dregno, dregno + 1, addr, NULL) != 0);
02773
02774
02775
02776
02777
02778
02779
02780
02781
02782 if (GET_CODE (addr) == POST_INC)
02783 {
02784 emit_insn (gen_rtx_SET (VOIDmode,
02785 operand_subword (dest, 0, TRUE, mode),
02786 change_address (src, SImode, addr)));
02787 emit_insn (gen_rtx_SET (VOIDmode,
02788 operand_subword (dest, 1, TRUE, mode),
02789 change_address (src, SImode, addr)));
02790 }
02791 else
02792 {
02793
02794
02795
02796
02797 if (side_effects_p (addr))
02798 fatal_insn ("unexpected side-effects in address", addr);
02799
02800 emit_insn (gen_rtx_SET
02801 (VOIDmode,
02802 operand_subword (dest, reverse, TRUE, mode),
02803 change_address
02804 (src, SImode,
02805 plus_constant (addr,
02806 reverse * UNITS_PER_WORD))));
02807 emit_insn (gen_rtx_SET
02808 (VOIDmode,
02809 operand_subword (dest, ! reverse, TRUE, mode),
02810 change_address
02811 (src, SImode,
02812 plus_constant (addr,
02813 (! reverse) *
02814 UNITS_PER_WORD))));
02815 }
02816 }
02817 else
02818 abort ();
02819 }
02820
02821 else if (GET_CODE (dest) == MEM
02822 && (GET_CODE (src) == REG
02823 || src == const0_rtx
02824 || src == CONST0_RTX (DFmode)))
02825 {
02826 rtx addr = XEXP (dest, 0);
02827
02828 if (GET_CODE (addr) == POST_INC)
02829 {
02830 emit_insn (gen_rtx_SET (VOIDmode,
02831 change_address (dest, SImode, addr),
02832 operand_subword (src, 0, TRUE, mode)));
02833 emit_insn (gen_rtx_SET (VOIDmode,
02834 change_address (dest, SImode, addr),
02835 operand_subword (src, 1, TRUE, mode)));
02836 }
02837 else
02838 {
02839
02840
02841
02842 if (side_effects_p (addr))
02843 fatal_insn ("unexpected side-effects in address", addr);
02844
02845 emit_insn (gen_rtx_SET
02846 (VOIDmode,
02847 change_address (dest, SImode, addr),
02848 operand_subword (src, 0, TRUE, mode)));
02849
02850 emit_insn (gen_rtx_SET
02851 (VOIDmode,
02852 change_address (dest, SImode,
02853 plus_constant (addr,
02854 UNITS_PER_WORD)),
02855 operand_subword (src, 1, TRUE, mode)));
02856 }
02857 }
02858
02859 else
02860 abort ();
02861
02862 val = gen_sequence ();
02863 end_sequence ();
02864 return val;
02865 }
02866
02867
02868
02869
02870
02871
02872
02873
02874 void
02875 cris_output_addr_const (file, x)
02876 FILE *file;
02877 rtx x;
02878 {
02879 int is_plt = 0;
02880
02881 restart:
02882 switch (GET_CODE (x))
02883 {
02884 case UNSPEC:
02885 ASSERT_PLT_UNSPEC (x);
02886 x = XVECEXP (x, 0, 0);
02887 is_plt = 1;
02888
02889
02890 case SYMBOL_REF:
02891 if (flag_pic)
02892 {
02893 const char *origstr = XSTR (x, 0);
02894 const char *str;
02895
02896 STRIP_NAME_ENCODING (str, origstr);
02897
02898 if (is_plt)
02899 {
02900 if (cris_pic_sympart_only)
02901 {
02902 assemble_name (file, str);
02903 fprintf (file, ":PLTG");
02904 }
02905 else
02906 {
02907 if (TARGET_AVOID_GOTPLT)
02908
02909 abort ();
02910
02911 fprintf (file, "[$%s+", reg_names [PIC_OFFSET_TABLE_REGNUM]);
02912 assemble_name (file, XSTR (x, 0));
02913
02914 if (flag_pic == 1)
02915 fprintf (file, ":GOTPLT16]");
02916 else
02917 fprintf (file, ":GOTPLT]");
02918 }
02919 }
02920 else if (cris_gotless_symbol (x))
02921 {
02922 if (! cris_pic_sympart_only)
02923 fprintf (file, "$%s+", reg_names [PIC_OFFSET_TABLE_REGNUM]);
02924 assemble_name (file, str);
02925 fprintf (file, ":GOTOFF");
02926 }
02927 else if (cris_got_symbol (x))
02928 {
02929 if (cris_pic_sympart_only)
02930 abort ();
02931 fprintf (file, "[$%s+", reg_names [PIC_OFFSET_TABLE_REGNUM]);
02932 assemble_name (file, XSTR (x, 0));
02933
02934 if (flag_pic == 1)
02935 fprintf (file, ":GOT16]");
02936 else
02937 fprintf (file, ":GOT]");
02938 }
02939 else
02940 LOSE_AND_RETURN ("unexpected PIC symbol", x);
02941
02942
02943 if (! current_function_uses_pic_offset_table)
02944 output_operand_lossage ("PIC register isn't set up");
02945 }
02946 else
02947 assemble_name (file, XSTR (x, 0));
02948 break;
02949
02950 case LABEL_REF:
02951
02952
02953
02954 if (GET_CODE (XEXP (x, 0)) != CODE_LABEL
02955 && (GET_CODE (XEXP (x, 0)) != NOTE
02956 || NOTE_LINE_NUMBER (XEXP (x, 0)) != NOTE_INSN_DELETED_LABEL))
02957 fatal_insn ("unexpected address expression", x);
02958
02959 if (flag_pic)
02960 {
02961 if (cris_gotless_symbol (x))
02962 {
02963 if (! cris_pic_sympart_only)
02964 fprintf (file, "$%s+", reg_names [PIC_OFFSET_TABLE_REGNUM]);
02965 cris_output_addr_const (file, XEXP (x, 0));
02966
02967 fprintf (file, ":GOTOFF");
02968 }
02969 else
02970
02971 fatal_insn ("unexpected PIC symbol", x);
02972
02973
02974 if (! current_function_uses_pic_offset_table)
02975 internal_error ("emitting PIC operand, but PIC register isn't set up");
02976 break;
02977 }
02978
02979 output_addr_const (file, x);
02980 break;
02981
02982 case NOTE:
02983 if (NOTE_LINE_NUMBER (x) != NOTE_INSN_DELETED_LABEL)
02984 fatal_insn ("unexpected NOTE as addr_const:", x);
02985 case CODE_LABEL:
02986 case CONST_INT:
02987 case CONST_DOUBLE:
02988 case ZERO_EXTEND:
02989 case SIGN_EXTEND:
02990 output_addr_const (file, x);
02991 break;
02992
02993 case CONST:
02994
02995
02996 cris_output_addr_const (file, XEXP (x, 0));
02997 break;
02998
02999 case PLUS:
03000
03001 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
03002 {
03003 cris_output_addr_const (file, XEXP (x, 1));
03004 if (INTVAL (XEXP (x, 0)) >= 0)
03005 fprintf (file, "+");
03006 output_addr_const (file, XEXP (x, 0));
03007 }
03008 else
03009 {
03010 cris_output_addr_const (file, XEXP (x, 0));
03011 if (GET_CODE (XEXP (x, 1)) != CONST_INT
03012 || INTVAL (XEXP (x, 1)) >= 0)
03013 fprintf (file, "+");
03014 cris_output_addr_const (file, XEXP (x, 1));
03015 }
03016 break;
03017
03018 case MINUS:
03019
03020
03021 x = simplify_subtraction (x);
03022 if (GET_CODE (x) != MINUS)
03023 goto restart;
03024
03025 cris_output_addr_const (file, XEXP (x, 0));
03026 fprintf (file, "-");
03027 if ((GET_CODE (XEXP (x, 1)) == CONST_INT
03028 && INTVAL (XEXP (x, 1)) < 0)
03029 || GET_CODE (XEXP (x, 1)) != CONST_INT)
03030 {
03031 fprintf (file, "%s", targetm.asm_out.open_paren);
03032 cris_output_addr_const (file, XEXP (x, 1));
03033 fprintf (file, "%s", targetm.asm_out.close_paren);
03034 }
03035 else
03036 output_addr_const (file, XEXP (x, 1));
03037 break;
03038
03039 default:
03040 LOSE_AND_RETURN ("unexpected address expression", x);
03041 }
03042 }
03043
03044
03045
03046
03047
03048
03049 void
03050 cris_encode_section_info (exp)
03051 tree exp;
03052 {
03053 if (flag_pic)
03054 {
03055 if (DECL_P (exp))
03056 {
03057 if (TREE_CODE (exp) == FUNCTION_DECL
03058 && (TREE_PUBLIC (exp) || DECL_WEAK (exp)))
03059 SYMBOL_REF_FLAG (XEXP (DECL_RTL (exp), 0)) = 0;
03060 else
03061 SYMBOL_REF_FLAG (XEXP (DECL_RTL (exp), 0))
03062 = ! TREE_PUBLIC (exp) && ! DECL_WEAK (exp);
03063 }
03064 else
03065
03066 SYMBOL_REF_FLAG (XEXP (TREE_CST_RTL (exp), 0)) = 1;
03067 }
03068 }
03069
03070 #if 0
03071
03072
03073
03074
03075 enum rtx_code Get_code PARAMS ((rtx));
03076
03077 enum rtx_code
03078 Get_code (x)
03079 rtx x;
03080 {
03081 return GET_CODE (x);
03082 }
03083
03084 const char *Get_mode PARAMS ((rtx));
03085
03086 const char *
03087 Get_mode (x)
03088 rtx x;
03089 {
03090 return GET_MODE_NAME (GET_MODE (x));
03091 }
03092
03093 rtx Xexp PARAMS ((rtx, int));
03094
03095 rtx
03096 Xexp (x, n)
03097 rtx x;
03098 int n;
03099 {
03100 return XEXP (x, n);
03101 }
03102
03103 rtx Xvecexp PARAMS ((rtx, int, int));
03104
03105 rtx
03106 Xvecexp (x, n, m)
03107 rtx x;
03108 int n;
03109 {
03110 return XVECEXP (x, n, m);
03111 }
03112
03113 int Get_rtx_len PARAMS ((rtx));
03114
03115 int
03116 Get_rtx_len (x)
03117 rtx x;
03118 {
03119 return GET_RTX_LENGTH (GET_CODE (x));
03120 }
03121
03122
03123
03124
03125 rtx Next_insn PARAMS ((rtx));
03126
03127 rtx
03128 Next_insn (insn)
03129 rtx insn;
03130 {
03131 return NEXT_INSN (insn);
03132 }
03133
03134 rtx Prev_insn PARAMS ((rtx));
03135
03136 rtx
03137 Prev_insn (insn)
03138 rtx insn;
03139 {
03140 return PREV_INSN (insn);
03141 }
03142 #endif
03143
03144
03145
03146
03147
03148
03149