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 "coretypes.h"
00025 #include "tm.h"
00026 #include "rtl.h"
00027 #include "tree.h"
00028 #include "tm_p.h"
00029 #include "assert.h"
00030 #include "mcore.h"
00031 #include "regs.h"
00032 #include "hard-reg-set.h"
00033 #include "real.h"
00034 #include "insn-config.h"
00035 #include "conditions.h"
00036 #include "output.h"
00037 #include "insn-attr.h"
00038 #include "flags.h"
00039 #include "obstack.h"
00040 #include "expr.h"
00041 #include "reload.h"
00042 #include "recog.h"
00043 #include "function.h"
00044 #include "ggc.h"
00045 #include "toplev.h"
00046 #include "target.h"
00047 #include "target-def.h"
00048
00049
00050
00051
00052 const char * mcore_stack_increment_string = 0;
00053 int mcore_stack_increment = STACK_UNITS_MAXSTEP;
00054
00055
00056 char * mcore_current_function_name = 0;
00057 long mcore_current_compilation_timestamp = 0;
00058
00059
00060
00061
00062
00063 rtx arch_compare_op0;
00064 rtx arch_compare_op1;
00065
00066
00067
00068 const int regno_reg_class[FIRST_PSEUDO_REGISTER] =
00069 {
00070 GENERAL_REGS, ONLYR1_REGS, LRW_REGS, LRW_REGS,
00071 LRW_REGS, LRW_REGS, LRW_REGS, LRW_REGS,
00072 LRW_REGS, LRW_REGS, LRW_REGS, LRW_REGS,
00073 LRW_REGS, LRW_REGS, LRW_REGS, GENERAL_REGS,
00074 GENERAL_REGS, C_REGS, NO_REGS, NO_REGS,
00075 };
00076
00077
00078
00079 const enum reg_class reg_class_from_letter[] =
00080 {
00081 LRW_REGS, ONLYR1_REGS, C_REGS, NO_REGS,
00082 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00083 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00084 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00085 NO_REGS, GENERAL_REGS, NO_REGS, NO_REGS,
00086 NO_REGS, NO_REGS, NO_REGS, ALL_REGS,
00087 NO_REGS, NO_REGS
00088 };
00089
00090 struct mcore_frame
00091 {
00092 int arg_size;
00093 int reg_size;
00094 int reg_mask;
00095 int local_size;
00096 int outbound_size;
00097 int pad_outbound;
00098 int pad_local;
00099 int pad_reg;
00100
00101 #define MAX_STACK_GROWS 4
00102 int growth[MAX_STACK_GROWS];
00103 int arg_offset;
00104 int reg_offset;
00105 int reg_growth;
00106 int local_growth;
00107 };
00108
00109 typedef enum
00110 {
00111 COND_NO,
00112 COND_MOV_INSN,
00113 COND_CLR_INSN,
00114 COND_INC_INSN,
00115 COND_DEC_INSN,
00116 COND_BRANCH_INSN
00117 }
00118 cond_type;
00119
00120 static void output_stack_adjust (int, int);
00121 static int calc_live_regs (int *);
00122 static int const_ok_for_mcore (int);
00123 static int try_constant_tricks (long, int *, int *);
00124 static const char * output_inline_const (enum machine_mode, rtx *);
00125 static void layout_mcore_frame (struct mcore_frame *);
00126 static void mcore_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode, tree, int *, int);
00127 static cond_type is_cond_candidate (rtx);
00128 static rtx emit_new_cond_insn (rtx, int);
00129 static rtx conditionalize_block (rtx);
00130 static void conditionalize_optimization (void);
00131 static void mcore_reorg (void);
00132 static rtx handle_structs_in_regs (enum machine_mode, tree, int);
00133 static void mcore_mark_dllexport (tree);
00134 static void mcore_mark_dllimport (tree);
00135 static int mcore_dllexport_p (tree);
00136 static int mcore_dllimport_p (tree);
00137 const struct attribute_spec mcore_attribute_table[];
00138 static tree mcore_handle_naked_attribute (tree *, tree, tree, int, bool *);
00139 #ifdef OBJECT_FORMAT_ELF
00140 static void mcore_asm_named_section (const char *,
00141 unsigned int, tree);
00142 #endif
00143 static void mcore_unique_section (tree, int);
00144 static void mcore_encode_section_info (tree, rtx, int);
00145 static const char *mcore_strip_name_encoding (const char *);
00146 static int mcore_const_costs (rtx, RTX_CODE);
00147 static int mcore_and_cost (rtx);
00148 static int mcore_ior_cost (rtx);
00149 static bool mcore_rtx_costs (rtx, int, int, int *);
00150 static void mcore_external_libcall (rtx);
00151 static bool mcore_return_in_memory (tree, tree);
00152 static int mcore_arg_partial_bytes (CUMULATIVE_ARGS *,
00153 enum machine_mode,
00154 tree, bool);
00155
00156
00157
00158 #undef TARGET_ASM_EXTERNAL_LIBCALL
00159 #define TARGET_ASM_EXTERNAL_LIBCALL mcore_external_libcall
00160
00161 #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
00162 #undef TARGET_MERGE_DECL_ATTRIBUTES
00163 #define TARGET_MERGE_DECL_ATTRIBUTES merge_dllimport_decl_attributes
00164 #endif
00165
00166 #ifdef OBJECT_FORMAT_ELF
00167 #undef TARGET_ASM_UNALIGNED_HI_OP
00168 #define TARGET_ASM_UNALIGNED_HI_OP "\t.short\t"
00169 #undef TARGET_ASM_UNALIGNED_SI_OP
00170 #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
00171 #endif
00172
00173 #undef TARGET_ATTRIBUTE_TABLE
00174 #define TARGET_ATTRIBUTE_TABLE mcore_attribute_table
00175 #undef TARGET_ASM_UNIQUE_SECTION
00176 #define TARGET_ASM_UNIQUE_SECTION mcore_unique_section
00177 #undef TARGET_ASM_FUNCTION_RODATA_SECTION
00178 #define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
00179 #undef TARGET_ENCODE_SECTION_INFO
00180 #define TARGET_ENCODE_SECTION_INFO mcore_encode_section_info
00181 #undef TARGET_STRIP_NAME_ENCODING
00182 #define TARGET_STRIP_NAME_ENCODING mcore_strip_name_encoding
00183 #undef TARGET_RTX_COSTS
00184 #define TARGET_RTX_COSTS mcore_rtx_costs
00185 #undef TARGET_ADDRESS_COST
00186 #define TARGET_ADDRESS_COST hook_int_rtx_0
00187 #undef TARGET_MACHINE_DEPENDENT_REORG
00188 #define TARGET_MACHINE_DEPENDENT_REORG mcore_reorg
00189
00190 #undef TARGET_PROMOTE_FUNCTION_ARGS
00191 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
00192 #undef TARGET_PROMOTE_FUNCTION_RETURN
00193 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
00194 #undef TARGET_PROMOTE_PROTOTYPES
00195 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
00196
00197 #undef TARGET_RETURN_IN_MEMORY
00198 #define TARGET_RETURN_IN_MEMORY mcore_return_in_memory
00199 #undef TARGET_MUST_PASS_IN_STACK
00200 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
00201 #undef TARGET_PASS_BY_REFERENCE
00202 #define TARGET_PASS_BY_REFERENCE hook_pass_by_reference_must_pass_in_stack
00203 #undef TARGET_ARG_PARTIAL_BYTES
00204 #define TARGET_ARG_PARTIAL_BYTES mcore_arg_partial_bytes
00205
00206 #undef TARGET_SETUP_INCOMING_VARARGS
00207 #define TARGET_SETUP_INCOMING_VARARGS mcore_setup_incoming_varargs
00208
00209 struct gcc_target targetm = TARGET_INITIALIZER;
00210
00211
00212 static void
00213 output_stack_adjust (int direction, int size)
00214 {
00215
00216 if (direction < 0 && size > mcore_stack_increment && mcore_stack_increment > 0)
00217 {
00218 rtx tmp = gen_rtx_REG (SImode, 1);
00219 rtx memref;
00220
00221 emit_insn (gen_movsi (tmp, GEN_INT (mcore_stack_increment)));
00222 do
00223 {
00224 emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
00225 memref = gen_rtx_MEM (SImode, stack_pointer_rtx);
00226 MEM_VOLATILE_P (memref) = 1;
00227 emit_insn (gen_movsi (memref, stack_pointer_rtx));
00228 size -= mcore_stack_increment;
00229 }
00230 while (size > mcore_stack_increment);
00231
00232
00233
00234 }
00235
00236 if (size)
00237 {
00238 rtx insn;
00239 rtx val = GEN_INT (size);
00240
00241 if (size > 32)
00242 {
00243 rtx nval = gen_rtx_REG (SImode, 1);
00244 emit_insn (gen_movsi (nval, val));
00245 val = nval;
00246 }
00247
00248 if (direction > 0)
00249 insn = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, val);
00250 else
00251 insn = gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, val);
00252
00253 emit_insn (insn);
00254 }
00255 }
00256
00257
00258
00259
00260 static int
00261 calc_live_regs (int * count)
00262 {
00263 int reg;
00264 int live_regs_mask = 0;
00265
00266 * count = 0;
00267
00268 for (reg = 0; reg < FIRST_PSEUDO_REGISTER; reg++)
00269 {
00270 if (regs_ever_live[reg] && !call_used_regs[reg])
00271 {
00272 (*count)++;
00273 live_regs_mask |= (1 << reg);
00274 }
00275 }
00276
00277 return live_regs_mask;
00278 }
00279
00280
00281
00282 void
00283 mcore_print_operand_address (FILE * stream, rtx x)
00284 {
00285 switch (GET_CODE (x))
00286 {
00287 case REG:
00288 fprintf (stream, "(%s)", reg_names[REGNO (x)]);
00289 break;
00290
00291 case PLUS:
00292 {
00293 rtx base = XEXP (x, 0);
00294 rtx index = XEXP (x, 1);
00295
00296 if (GET_CODE (base) != REG)
00297 {
00298
00299 rtx temp = base;
00300 base = index;
00301 index = temp;
00302 }
00303
00304 switch (GET_CODE (index))
00305 {
00306 case CONST_INT:
00307 fprintf (stream, "(%s," HOST_WIDE_INT_PRINT_DEC ")",
00308 reg_names[REGNO(base)], INTVAL (index));
00309 break;
00310
00311 default:
00312 debug_rtx (x);
00313
00314 abort ();
00315 }
00316 }
00317
00318 break;
00319
00320 default:
00321 output_addr_const (stream, x);
00322 break;
00323 }
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 void
00339 mcore_print_operand (FILE * stream, rtx x, int code)
00340 {
00341 switch (code)
00342 {
00343 case 'N':
00344 if (INTVAL(x) == -1)
00345 fprintf (asm_out_file, "32");
00346 else
00347 fprintf (asm_out_file, "%d", exact_log2 (INTVAL (x) + 1));
00348 break;
00349 case 'P':
00350 fprintf (asm_out_file, "%d", exact_log2 (INTVAL (x)));
00351 break;
00352 case 'Q':
00353 fprintf (asm_out_file, "%d", exact_log2 (~INTVAL (x)));
00354 break;
00355 case 'O':
00356 fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
00357 break;
00358 case 'M':
00359 fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, - INTVAL (x));
00360 break;
00361 case 'R':
00362
00363 switch (GET_CODE (x))
00364 {
00365 case REG:
00366 fputs (reg_names[REGNO (x) + 1], (stream));
00367 break;
00368 case MEM:
00369 mcore_print_operand_address
00370 (stream, XEXP (adjust_address (x, SImode, 4), 0));
00371 break;
00372 default:
00373 abort ();
00374 }
00375 break;
00376 case 'U':
00377 fprintf (asm_out_file, "%s-%s", reg_names[REGNO (x)],
00378 reg_names[REGNO (x) + 3]);
00379 break;
00380 case 'x':
00381 fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX, INTVAL (x));
00382 break;
00383 case 'X':
00384 fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, 3 - INTVAL (x) / 8);
00385 break;
00386
00387 default:
00388 switch (GET_CODE (x))
00389 {
00390 case REG:
00391 fputs (reg_names[REGNO (x)], (stream));
00392 break;
00393 case MEM:
00394 output_address (XEXP (x, 0));
00395 break;
00396 default:
00397 output_addr_const (stream, x);
00398 break;
00399 }
00400 break;
00401 }
00402 }
00403
00404
00405
00406 static int
00407 mcore_const_costs (rtx exp, enum rtx_code code)
00408 {
00409 int val = INTVAL (exp);
00410
00411
00412 if ( CONST_OK_FOR_I (val)
00413 || CONST_OK_FOR_M (val)
00414 || CONST_OK_FOR_N (val)
00415 || (code == PLUS && CONST_OK_FOR_L (val)))
00416 return 1;
00417 else if (code == AND
00418 && ( CONST_OK_FOR_M (~val)
00419 || CONST_OK_FOR_N (~val)))
00420 return 2;
00421 else if (code == PLUS
00422 && ( CONST_OK_FOR_I (-val)
00423 || CONST_OK_FOR_M (-val)
00424 || CONST_OK_FOR_N (-val)))
00425 return 2;
00426
00427 return 5;
00428 }
00429
00430
00431
00432
00433
00434 static int
00435 mcore_and_cost (rtx x)
00436 {
00437 int val;
00438
00439 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
00440 return 2;
00441
00442 val = INTVAL (XEXP (x, 1));
00443
00444
00445 if (CONST_OK_FOR_K (val) || CONST_OK_FOR_M (~val))
00446 return 2;
00447
00448 else if (const_ok_for_mcore (val))
00449 return 3;
00450
00451 else if (TARGET_HARDLIT && mcore_const_ok_for_inline (val))
00452 return 4;
00453
00454
00455 return 5;
00456 }
00457
00458
00459
00460 static int
00461 mcore_ior_cost (rtx x)
00462 {
00463 int val;
00464
00465 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
00466 return 2;
00467
00468 val = INTVAL (XEXP (x, 1));
00469
00470
00471 if (CONST_OK_FOR_M (val))
00472 return 2;
00473
00474 else if (const_ok_for_mcore (val))
00475 return 3;
00476
00477 else if (TARGET_HARDLIT && mcore_const_ok_for_inline (val))
00478 return 4;
00479
00480
00481 return 5;
00482 }
00483
00484 static bool
00485 mcore_rtx_costs (rtx x, int code, int outer_code, int * total)
00486 {
00487 switch (code)
00488 {
00489 case CONST_INT:
00490 *total = mcore_const_costs (x, outer_code);
00491 return true;
00492 case CONST:
00493 case LABEL_REF:
00494 case SYMBOL_REF:
00495 *total = 5;
00496 return true;
00497 case CONST_DOUBLE:
00498 *total = 10;
00499 return true;
00500
00501 case AND:
00502 *total = COSTS_N_INSNS (mcore_and_cost (x));
00503 return true;
00504
00505 case IOR:
00506 *total = COSTS_N_INSNS (mcore_ior_cost (x));
00507 return true;
00508
00509 case DIV:
00510 case UDIV:
00511 case MOD:
00512 case UMOD:
00513 case FLOAT:
00514 case FIX:
00515 *total = COSTS_N_INSNS (100);
00516 return true;
00517
00518 default:
00519 return false;
00520 }
00521 }
00522
00523
00524
00525
00526
00527 int
00528 mcore_modify_comparison (enum rtx_code code)
00529 {
00530 rtx op1 = arch_compare_op1;
00531
00532 if (GET_CODE (op1) == CONST_INT)
00533 {
00534 int val = INTVAL (op1);
00535
00536 switch (code)
00537 {
00538 case LE:
00539 if (CONST_OK_FOR_J (val + 1))
00540 {
00541 arch_compare_op1 = GEN_INT (val + 1);
00542 return 1;
00543 }
00544 break;
00545
00546 default:
00547 break;
00548 }
00549 }
00550
00551 return 0;
00552 }
00553
00554
00555
00556 rtx
00557 mcore_gen_compare_reg (enum rtx_code code)
00558 {
00559 rtx op0 = arch_compare_op0;
00560 rtx op1 = arch_compare_op1;
00561 rtx cc_reg = gen_rtx_REG (CCmode, CC_REG);
00562
00563 if (CONSTANT_P (op1) && GET_CODE (op1) != CONST_INT)
00564 op1 = force_reg (SImode, op1);
00565
00566
00567
00568 switch (code)
00569 {
00570 case EQ:
00571 code = NE;
00572
00573
00574 case NE:
00575 if (GET_CODE (op1) == CONST_INT && ! CONST_OK_FOR_K (INTVAL (op1)))
00576 op1 = force_reg (SImode, op1);
00577 break;
00578
00579 case LE:
00580 code = GT;
00581
00582
00583 case GT:
00584 if (GET_CODE (op1) == CONST_INT)
00585 op1 = force_reg (SImode, op1);
00586 break;
00587
00588 case GE:
00589 code = LT;
00590
00591
00592 case LT:
00593 if (GET_CODE (op1) == CONST_INT &&
00594
00595 INTVAL (op1) != 0 &&
00596 ! CONST_OK_FOR_J (INTVAL (op1)))
00597 op1 = force_reg (SImode, op1);
00598 break;
00599
00600 case GTU:
00601 if (GET_CODE (op1) == CONST_INT && INTVAL (op1) == 0)
00602 {
00603
00604
00605
00606
00607
00608
00609
00610 abort ();
00611 break;
00612 }
00613 code = LEU;
00614
00615
00616 case LEU:
00617 if (GET_CODE (op1) == CONST_INT && INTVAL (op1) != 0)
00618 op1 = force_reg (SImode, op1);
00619 break;
00620
00621 case LTU:
00622 code = GEU;
00623
00624
00625 case GEU:
00626 if (GET_CODE (op1) == CONST_INT && INTVAL (op1) != 0)
00627 op1 = force_reg (SImode, op1);
00628 break;
00629
00630 default:
00631 break;
00632 }
00633
00634 emit_insn (gen_rtx_SET (VOIDmode, cc_reg, gen_rtx_fmt_ee (code, CCmode, op0, op1)));
00635
00636 return cc_reg;
00637 }
00638
00639 int
00640 mcore_symbolic_address_p (rtx x)
00641 {
00642 switch (GET_CODE (x))
00643 {
00644 case SYMBOL_REF:
00645 case LABEL_REF:
00646 return 1;
00647 case CONST:
00648 x = XEXP (x, 0);
00649 return ( (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
00650 || GET_CODE (XEXP (x, 0)) == LABEL_REF)
00651 && GET_CODE (XEXP (x, 1)) == CONST_INT);
00652 default:
00653 return 0;
00654 }
00655 }
00656
00657 int
00658 mcore_call_address_operand (rtx x, enum machine_mode mode)
00659 {
00660 return register_operand (x, mode) || CONSTANT_P (x);
00661 }
00662
00663
00664
00665 char *
00666 mcore_output_call (rtx operands[], int index)
00667 {
00668 static char buffer[20];
00669 rtx addr = operands [index];
00670
00671 if (REG_P (addr))
00672 {
00673 if (TARGET_CG_DATA)
00674 {
00675 if (mcore_current_function_name == 0)
00676 abort ();
00677
00678 ASM_OUTPUT_CG_EDGE (asm_out_file, mcore_current_function_name,
00679 "unknown", 1);
00680 }
00681
00682 sprintf (buffer, "jsr\t%%%d", index);
00683 }
00684 else
00685 {
00686 if (TARGET_CG_DATA)
00687 {
00688 if (mcore_current_function_name == 0)
00689 abort ();
00690
00691 if (GET_CODE (addr) != SYMBOL_REF)
00692 abort ();
00693
00694 ASM_OUTPUT_CG_EDGE (asm_out_file, mcore_current_function_name, XSTR (addr, 0), 0);
00695 }
00696
00697 sprintf (buffer, "jbsr\t%%%d", index);
00698 }
00699
00700 return buffer;
00701 }
00702
00703
00704
00705 static int
00706 const_ok_for_mcore (int value)
00707 {
00708 if (value >= 0 && value <= 127)
00709 return 1;
00710
00711
00712 if ((value & (value - 1)) == 0)
00713 return 1;
00714
00715
00716 if ((value & (value + 1)) == 0)
00717 return 1;
00718
00719 return 0;
00720 }
00721
00722
00723
00724 int
00725 mcore_const_ok_for_inline (long value)
00726 {
00727 int x, y;
00728
00729 return try_constant_tricks (value, & x, & y) > 0;
00730 }
00731
00732
00733
00734 int
00735 mcore_const_trick_uses_not (long value)
00736 {
00737 int x, y;
00738
00739 return try_constant_tricks (value, & x, & y) == 2;
00740 }
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758 static int
00759 try_constant_tricks (long value, int * x, int * y)
00760 {
00761 int i;
00762 unsigned bit, shf, rot;
00763
00764 if (const_ok_for_mcore (value))
00765 return 1;
00766
00767 if (TARGET_HARDLIT)
00768 {
00769 if (const_ok_for_mcore (~value))
00770 {
00771 *x = ~value;
00772 return 2;
00773 }
00774
00775 for (i = 1; i <= 32; i++)
00776 {
00777 if (const_ok_for_mcore (value - i))
00778 {
00779 *x = value - i;
00780 *y = i;
00781
00782 return 3;
00783 }
00784
00785 if (const_ok_for_mcore (value + i))
00786 {
00787 *x = value + i;
00788 *y = i;
00789
00790 return 4;
00791 }
00792 }
00793
00794 bit = 0x80000000L;
00795
00796 for (i = 0; i <= 31; i++)
00797 {
00798 if (const_ok_for_mcore (i - value))
00799 {
00800 *x = i - value;
00801 *y = i;
00802
00803 return 5;
00804 }
00805
00806 if (const_ok_for_mcore (value & ~bit))
00807 {
00808 *y = bit;
00809 *x = value & ~bit;
00810
00811 return 6;
00812 }
00813
00814 if (const_ok_for_mcore (value | bit))
00815 {
00816 *y = ~bit;
00817 *x = value | bit;
00818
00819 return 7;
00820 }
00821
00822 bit >>= 1;
00823 }
00824
00825 shf = value;
00826 rot = value;
00827
00828 for (i = 1; i < 31; i++)
00829 {
00830 int c;
00831
00832
00833 c = rot << 31;
00834 rot >>= 1;
00835 rot &= 0x7FFFFFFF;
00836 rot |= c;
00837
00838 if (const_ok_for_mcore (rot))
00839 {
00840 *y = i;
00841 *x = rot;
00842
00843 return 8;
00844 }
00845
00846 if (shf & 1)
00847 shf = 0;
00848
00849 shf >>= 1;
00850
00851 if (shf != 0 && const_ok_for_mcore (shf))
00852 {
00853 *y = i;
00854 *x = shf;
00855
00856 return 9;
00857 }
00858 }
00859
00860 if ((value % 3) == 0 && const_ok_for_mcore (value / 3))
00861 {
00862 *x = value / 3;
00863
00864 return 10;
00865 }
00866
00867 if ((value % 5) == 0 && const_ok_for_mcore (value / 5))
00868 {
00869 *x = value / 5;
00870
00871 return 11;
00872 }
00873 }
00874
00875 return 0;
00876 }
00877
00878
00879
00880
00881
00882
00883
00884 int
00885 mcore_is_dead (rtx first, rtx reg)
00886 {
00887 rtx insn;
00888
00889
00890 if (GET_CODE (reg) == SUBREG)
00891 reg = SUBREG_REG (reg);
00892
00893
00894 if (dead_or_set_p (first, reg))
00895 return 1;
00896
00897
00898
00899 for (insn = NEXT_INSN (first); insn; insn = NEXT_INSN (insn))
00900 {
00901 if (GET_CODE (insn) == JUMP_INSN)
00902 return 0;
00903
00904 else if (GET_CODE(insn) == CALL_INSN)
00905 {
00906
00907 if (reg_referenced_p (reg, PATTERN (insn))
00908 || find_reg_fusage (insn, USE, reg))
00909 return 0;
00910 else if (dead_or_set_p (insn, reg))
00911 return 1;
00912 }
00913 else if (GET_CODE (insn) == INSN)
00914 {
00915 if (reg_referenced_p (reg, PATTERN (insn)))
00916 return 0;
00917 else if (dead_or_set_p (insn, reg))
00918 return 1;
00919 }
00920 }
00921
00922
00923
00924 return 0;
00925 }
00926
00927
00928
00929 int
00930 mcore_num_ones (int mask)
00931 {
00932
00933 mask = (mask >> 1 & 0x55555555) + (mask & 0x55555555);
00934 mask = ((mask >> 2) & 0x33333333) + (mask & 0x33333333);
00935 mask = ((mask >> 4) + mask) & 0x0f0f0f0f;
00936 mask = ((mask >> 8) + mask);
00937
00938 return (mask + (mask >> 16)) & 0xff;
00939 }
00940
00941
00942
00943 int
00944 mcore_num_zeros (int mask)
00945 {
00946 return 32 - mcore_num_ones (mask);
00947 }
00948
00949
00950
00951 int
00952 mcore_byte_offset (unsigned int mask)
00953 {
00954 if (mask == 0x00ffffffL)
00955 return 0;
00956 else if (mask == 0xff00ffffL)
00957 return 1;
00958 else if (mask == 0xffff00ffL)
00959 return 2;
00960 else if (mask == 0xffffff00L)
00961 return 3;
00962
00963 return -1;
00964 }
00965
00966
00967
00968 int
00969 mcore_halfword_offset (unsigned int mask)
00970 {
00971 if (mask == 0x0000ffffL)
00972 return 0;
00973 else if (mask == 0xffff0000L)
00974 return 1;
00975
00976 return -1;
00977 }
00978
00979
00980
00981 const char *
00982 mcore_output_bseti (rtx dst, int mask)
00983 {
00984 rtx out_operands[2];
00985 int bit;
00986
00987 out_operands[0] = dst;
00988
00989 for (bit = 0; bit < 32; bit++)
00990 {
00991 if ((mask & 0x1) == 0x1)
00992 {
00993 out_operands[1] = GEN_INT (bit);
00994
00995 output_asm_insn ("bseti\t%0,%1", out_operands);
00996 }
00997 mask >>= 1;
00998 }
00999
01000 return "";
01001 }
01002
01003
01004
01005 const char *
01006 mcore_output_bclri (rtx dst, int mask)
01007 {
01008 rtx out_operands[2];
01009 int bit;
01010
01011 out_operands[0] = dst;
01012
01013 for (bit = 0; bit < 32; bit++)
01014 {
01015 if ((mask & 0x1) == 0x0)
01016 {
01017 out_operands[1] = GEN_INT (bit);
01018
01019 output_asm_insn ("bclri\t%0,%1", out_operands);
01020 }
01021
01022 mask >>= 1;
01023 }
01024
01025 return "";
01026 }
01027
01028
01029
01030
01031
01032 const char *
01033 mcore_output_cmov (rtx operands[], int cmp_t, const char * test)
01034 {
01035 int load_value;
01036 int adjust_value;
01037 rtx out_operands[4];
01038
01039 out_operands[0] = operands[0];
01040
01041
01042 if (const_ok_for_mcore (INTVAL (operands[1])))
01043 {
01044 out_operands[1] = operands[1];
01045 out_operands[2] = operands[2];
01046 }
01047 else if (const_ok_for_mcore (INTVAL (operands[2])))
01048 {
01049 out_operands[1] = operands[2];
01050 out_operands[2] = operands[1];
01051
01052
01053 cmp_t = (cmp_t == 0);
01054 }
01055 load_value = INTVAL (out_operands[1]);
01056 adjust_value = INTVAL (out_operands[2]);
01057
01058
01059
01060 if (test)
01061 output_asm_insn (test, operands);
01062
01063
01064
01065
01066
01067 if (load_value >= 0 && load_value <= 127)
01068 output_asm_insn ("movi\t%0,%1", out_operands);
01069 else if ((load_value & (load_value - 1)) == 0)
01070 output_asm_insn ("bgeni\t%0,%P1", out_operands);
01071 else if ((load_value & (load_value + 1)) == 0)
01072 output_asm_insn ("bmaski\t%0,%N1", out_operands);
01073
01074
01075 if (load_value > adjust_value)
01076 {
01077 if (cmp_t)
01078 output_asm_insn ("decf\t%0", out_operands);
01079 else
01080 output_asm_insn ("dect\t%0", out_operands);
01081 }
01082 else
01083 {
01084 if (cmp_t)
01085 output_asm_insn ("incf\t%0", out_operands);
01086 else
01087 output_asm_insn ("inct\t%0", out_operands);
01088 }
01089
01090 return "";
01091 }
01092
01093
01094
01095
01096 const char *
01097 mcore_output_andn (rtx insn ATTRIBUTE_UNUSED, rtx operands[])
01098 {
01099 int x, y;
01100 rtx out_operands[3];
01101 const char * load_op;
01102 char buf[256];
01103
01104 if (try_constant_tricks (INTVAL (operands[1]), &x, &y) != 2)
01105 abort ();
01106
01107 out_operands[0] = operands[0];
01108 out_operands[1] = GEN_INT(x);
01109 out_operands[2] = operands[2];
01110
01111 if (x >= 0 && x <= 127)
01112 load_op = "movi\t%0,%1";
01113
01114
01115 else if ((x & (x - 1)) == 0)
01116 load_op = "bgeni\t%0,%P1";
01117
01118
01119 else if ((x & (x + 1)) == 0)
01120 load_op = "bmaski\t%0,%N1";
01121
01122 else
01123 load_op = "BADMOVI\t%0,%1";
01124
01125 sprintf (buf, "%s\n\tandn\t%%2,%%0", load_op);
01126 output_asm_insn (buf, out_operands);
01127
01128 return "";
01129 }
01130
01131
01132
01133 static const char *
01134 output_inline_const (enum machine_mode mode, rtx operands[])
01135 {
01136 int x = 0, y = 0;
01137 int trick_no;
01138 rtx out_operands[3];
01139 char buf[256];
01140 char load_op[256];
01141 const char *dst_fmt;
01142 int value;
01143
01144 value = INTVAL (operands[1]);
01145
01146 if ((trick_no = try_constant_tricks (value, &x, &y)) == 0)
01147 {
01148
01149
01150
01151 abort ();
01152 }
01153
01154 if (trick_no == 1)
01155 x = value;
01156
01157
01158 out_operands[0] = operands[0];
01159 out_operands[1] = GEN_INT (x);
01160
01161 if (trick_no > 2)
01162 out_operands[2] = GEN_INT (y);
01163
01164
01165 if (mode == DImode && (! TARGET_LITTLE_END))
01166 dst_fmt = "%R0";
01167 else
01168 dst_fmt = "%0";
01169
01170 if (x >= 0 && x <= 127)
01171 sprintf (load_op, "movi\t%s,%%1", dst_fmt);
01172
01173
01174 else if ((x & (x - 1)) == 0)
01175 sprintf (load_op, "bgeni\t%s,%%P1", dst_fmt);
01176
01177
01178 else if ((x & (x + 1)) == 0)
01179 sprintf (load_op, "bmaski\t%s,%%N1", dst_fmt);
01180
01181 else
01182 sprintf (load_op, "BADMOVI\t%s,%%1", dst_fmt);
01183
01184 switch (trick_no)
01185 {
01186 case 1:
01187 strcpy (buf, load_op);
01188 break;
01189 case 2:
01190 sprintf (buf, "%s\n\tnot\t%s\t// %d 0x%x", load_op, dst_fmt, value, value);
01191 break;
01192 case 3:
01193 sprintf (buf, "%s\n\taddi\t%s,%%2\t// %d 0x%x", load_op, dst_fmt, value, value);
01194 break;
01195 case 4:
01196 sprintf (buf, "%s\n\tsubi\t%s,%%2\t// %d 0x%x", load_op, dst_fmt, value, value);
01197 break;
01198 case 5:
01199
01200 sprintf (buf, "%s\n\trsubi\t%s,%%2\t// %d 0x%x", load_op, dst_fmt, value, value);
01201 break;
01202 case 6:
01203 sprintf (buf, "%s\n\tbseti\t%s,%%P2\t// %d 0x%x", load_op, dst_fmt, value, value);
01204 break;
01205 case 7:
01206 sprintf (buf, "%s\n\tbclri\t%s,%%Q2\t// %d 0x%x", load_op, dst_fmt, value, value);
01207 break;
01208 case 8:
01209 sprintf (buf, "%s\n\trotli\t%s,%%2\t// %d 0x%x", load_op, dst_fmt, value, value);
01210 break;
01211 case 9:
01212 sprintf (buf, "%s\n\tlsli\t%s,%%2\t// %d 0x%x", load_op, dst_fmt, value, value);
01213 break;
01214 case 10:
01215 sprintf (buf, "%s\n\tixh\t%s,%s\t// %d 0x%x", load_op, dst_fmt, dst_fmt, value, value);
01216 break;
01217 case 11:
01218 sprintf (buf, "%s\n\tixw\t%s,%s\t// %d 0x%x", load_op, dst_fmt, dst_fmt, value, value);
01219 break;
01220 default:
01221 return "";
01222 }
01223
01224 output_asm_insn (buf, out_operands);
01225
01226 return "";
01227 }
01228
01229
01230
01231 const char *
01232 mcore_output_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[],
01233 enum machine_mode mode ATTRIBUTE_UNUSED)
01234 {
01235 rtx dst = operands[0];
01236 rtx src = operands[1];
01237
01238 if (GET_CODE (dst) == REG)
01239 {
01240 if (GET_CODE (src) == REG)
01241 {
01242 if (REGNO (src) == CC_REG)
01243 return "mvc\t%0";
01244 else
01245 return "mov\t%0,%1";
01246 }
01247 else if (GET_CODE (src) == MEM)
01248 {
01249 if (GET_CODE (XEXP (src, 0)) == LABEL_REF)
01250 return "lrw\t%0,[%1]";
01251 else
01252 switch (GET_MODE (src))
01253 {
01254 case SImode:
01255 return "ldw\t%0,%1";
01256 case HImode:
01257 return "ld.h\t%0,%1";
01258 case QImode:
01259 return "ld.b\t%0,%1";
01260 default:
01261 abort ();
01262 }
01263 }
01264 else if (GET_CODE (src) == CONST_INT)
01265 {
01266 int x, y;
01267
01268 if (CONST_OK_FOR_I (INTVAL (src)))
01269 return "movi\t%0,%1";
01270 else if (CONST_OK_FOR_M (INTVAL (src)))
01271 return "bgeni\t%0,%P1\t// %1 %x1";
01272 else if (CONST_OK_FOR_N (INTVAL (src)))
01273 return "bmaski\t%0,%N1\t// %1 %x1";
01274 else if (try_constant_tricks (INTVAL (src), &x, &y))
01275 return output_inline_const (SImode, operands);
01276 else
01277 return "lrw\t%0,%x1\t// %1";
01278 }
01279 else
01280 return "lrw\t%0, %1";
01281 }
01282 else if (GET_CODE (dst) == MEM)
01283 switch (GET_MODE (dst))
01284 {
01285 case SImode:
01286 return "stw\t%1,%0";
01287 case HImode:
01288 return "st.h\t%1,%0";
01289 case QImode:
01290 return "st.b\t%1,%0";
01291 default:
01292 abort ();
01293 }
01294
01295 abort ();
01296 }
01297
01298
01299
01300
01301
01302 const char *
01303 mcore_output_movedouble (rtx operands[], enum machine_mode mode ATTRIBUTE_UNUSED)
01304 {
01305 rtx dst = operands[0];
01306 rtx src = operands[1];
01307
01308 if (GET_CODE (dst) == REG)
01309 {
01310 if (GET_CODE (src) == REG)
01311 {
01312 int dstreg = REGNO (dst);
01313 int srcreg = REGNO (src);
01314
01315
01316 if (srcreg + 1 == dstreg)
01317 return "mov %R0,%R1\n\tmov %0,%1";
01318 else
01319 return "mov %0,%1\n\tmov %R0,%R1";
01320 }
01321 else if (GET_CODE (src) == MEM)
01322 {
01323 rtx memexp = memexp = XEXP (src, 0);
01324 int dstreg = REGNO (dst);
01325 int basereg = -1;
01326
01327 if (GET_CODE (memexp) == LABEL_REF)
01328 return "lrw\t%0,[%1]\n\tlrw\t%R0,[%R1]";
01329 else if (GET_CODE (memexp) == REG)
01330 basereg = REGNO (memexp);
01331 else if (GET_CODE (memexp) == PLUS)
01332 {
01333 if (GET_CODE (XEXP (memexp, 0)) == REG)
01334 basereg = REGNO (XEXP (memexp, 0));
01335 else if (GET_CODE (XEXP (memexp, 1)) == REG)
01336 basereg = REGNO (XEXP (memexp, 1));
01337 else
01338 abort ();
01339 }
01340 else
01341 abort ();
01342
01343
01344 if (dstreg == basereg)
01345 {
01346
01347 return "ldw\t%R0,%R1\n\tldw\t%0,%1";
01348
01349
01350
01351 }
01352 else
01353 return "ldw\t%0,%1\n\tldw\t%R0,%R1";
01354 }
01355 else if (GET_CODE (src) == CONST_INT)
01356 {
01357 if (TARGET_LITTLE_END)
01358 {
01359 if (CONST_OK_FOR_I (INTVAL (src)))
01360 output_asm_insn ("movi %0,%1", operands);
01361 else if (CONST_OK_FOR_M (INTVAL (src)))
01362 output_asm_insn ("bgeni %0,%P1", operands);
01363 else if (INTVAL (src) == -1)
01364 output_asm_insn ("bmaski %0,32", operands);
01365 else if (CONST_OK_FOR_N (INTVAL (src)))
01366 output_asm_insn ("bmaski %0,%N1", operands);
01367 else
01368 abort ();
01369
01370 if (INTVAL (src) < 0)
01371 return "bmaski %R0,32";
01372 else
01373 return "movi %R0,0";
01374 }
01375 else
01376 {
01377 if (CONST_OK_FOR_I (INTVAL (src)))
01378 output_asm_insn ("movi %R0,%1", operands);
01379 else if (CONST_OK_FOR_M (INTVAL (src)))
01380 output_asm_insn ("bgeni %R0,%P1", operands);
01381 else if (INTVAL (src) == -1)
01382 output_asm_insn ("bmaski %R0,32", operands);
01383 else if (CONST_OK_FOR_N (INTVAL (src)))
01384 output_asm_insn ("bmaski %R0,%N1", operands);
01385 else
01386 abort ();
01387
01388 if (INTVAL (src) < 0)
01389 return "bmaski %0,32";
01390 else
01391 return "movi %0,0";
01392 }
01393 }
01394 else
01395 abort ();
01396 }
01397 else if (GET_CODE (dst) == MEM && GET_CODE (src) == REG)
01398 return "stw\t%1,%0\n\tstw\t%R1,%R0";
01399 else
01400 abort ();
01401 }
01402
01403
01404
01405
01406
01407 int
01408 mcore_general_movsrc_operand (rtx op, enum machine_mode mode)
01409 {
01410
01411 if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == LABEL_REF)
01412 return 1;
01413
01414 return general_operand (op, mode);
01415 }
01416
01417
01418
01419 int
01420 mcore_general_movdst_operand (rtx op, enum machine_mode mode)
01421 {
01422 if (GET_CODE (op) == REG && REGNO (op) == CC_REG)
01423 return 0;
01424
01425 return general_operand (op, mode);
01426 }
01427
01428
01429
01430 int
01431 mcore_arith_reg_operand (rtx op, enum machine_mode mode)
01432 {
01433 if (! register_operand (op, mode))
01434 return 0;
01435
01436 if (GET_CODE (op) == SUBREG)
01437 op = SUBREG_REG (op);
01438
01439 if (GET_CODE (op) == REG)
01440 return REGNO (op) != CC_REG;
01441
01442 return 1;
01443 }
01444
01445
01446
01447
01448 int
01449 mcore_reload_operand (rtx op, enum machine_mode mode)
01450 {
01451 if (mcore_arith_reg_operand (op, mode))
01452 return 1;
01453
01454 if (! reload_in_progress)
01455 return 0;
01456
01457 return GET_CODE (op) == MEM;
01458 }
01459
01460
01461
01462 int
01463 mcore_arith_J_operand (rtx op, enum machine_mode mode)
01464 {
01465 if (register_operand (op, mode))
01466 return 1;
01467
01468 if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_J (INTVAL (op)))
01469 return 1;
01470
01471 return 0;
01472 }
01473
01474
01475
01476 int
01477 mcore_arith_K_operand (rtx op, enum machine_mode mode)
01478 {
01479 if (register_operand (op, mode))
01480 return 1;
01481
01482 if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op)))
01483 return 1;
01484
01485 return 0;
01486 }
01487
01488
01489
01490 int
01491 mcore_arith_K_operand_not_0 (rtx op, enum machine_mode mode)
01492 {
01493 if (register_operand (op, mode))
01494 return 1;
01495
01496 if ( GET_CODE (op) == CONST_INT
01497 && CONST_OK_FOR_K (INTVAL (op))
01498 && INTVAL (op) != 0)
01499 return 1;
01500
01501 return 0;
01502 }
01503
01504 int
01505 mcore_arith_K_S_operand (rtx op, enum machine_mode mode)
01506 {
01507 if (register_operand (op, mode))
01508 return 1;
01509
01510 if (GET_CODE (op) == CONST_INT)
01511 {
01512 if (CONST_OK_FOR_K (INTVAL (op)) || CONST_OK_FOR_M (~INTVAL (op)))
01513 return 1;
01514 }
01515
01516 return 0;
01517 }
01518
01519 int
01520 mcore_arith_S_operand (rtx op)
01521 {
01522 if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_M (~INTVAL (op)))
01523 return 1;
01524
01525 return 0;
01526 }
01527
01528 int
01529 mcore_arith_M_operand (rtx op, enum machine_mode mode)
01530 {
01531 if (register_operand (op, mode))
01532 return 1;
01533
01534 if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_M (INTVAL (op)))
01535 return 1;
01536
01537 return 0;
01538 }
01539
01540
01541
01542 int
01543 mcore_arith_imm_operand (rtx op, enum machine_mode mode)
01544 {
01545 if (register_operand (op, mode))
01546 return 1;
01547
01548 if (GET_CODE (op) == CONST_INT && const_ok_for_mcore (INTVAL (op)))
01549 return 1;
01550
01551 return 0;
01552 }
01553
01554 int
01555 mcore_arith_any_imm_operand (rtx op, enum machine_mode mode)
01556 {
01557 if (register_operand (op, mode))
01558 return 1;
01559
01560 if (GET_CODE (op) == CONST_INT)
01561 return 1;
01562
01563 return 0;
01564 }
01565
01566
01567
01568 int
01569 mcore_arith_O_operand (rtx op, enum machine_mode mode)
01570 {
01571 if (register_operand (op, mode))
01572 return 1;
01573
01574 if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_O (INTVAL (op)))
01575 return 1;
01576
01577 return 0;
01578 }
01579
01580
01581
01582 int
01583 mcore_literal_K_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01584 {
01585 if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op)))
01586 return 1;
01587
01588 return 0;
01589 }
01590
01591
01592
01593 int
01594 mcore_addsub_operand (rtx op, enum machine_mode mode)
01595 {
01596 if (register_operand (op, mode))
01597 return 1;
01598
01599 if (GET_CODE (op) == CONST_INT)
01600 {
01601 return 1;
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613 }
01614
01615 return 0;
01616 }
01617
01618
01619
01620 int
01621 mcore_compare_operand (rtx op, enum machine_mode mode)
01622 {
01623 if (register_operand (op, mode))
01624 return 1;
01625
01626 if (GET_CODE (op) == CONST_INT && INTVAL (op) == 0)
01627 return 1;
01628
01629 return 0;
01630 }
01631
01632
01633
01634 int
01635 mcore_expand_insv (rtx operands[])
01636 {
01637 int width = INTVAL (operands[1]);
01638 int posn = INTVAL (operands[2]);
01639 int mask;
01640 rtx mreg, sreg, ereg;
01641
01642
01643
01644
01645 if (width == 1 && GET_CODE (operands[3]) == CONST_INT)
01646 {
01647
01648
01649 if ((INTVAL(operands[3])&1) == 0)
01650 {
01651 mask = ~(1 << posn);
01652 emit_insn (gen_rtx_SET (SImode, operands[0],
01653 gen_rtx_AND (SImode, operands[0], GEN_INT (mask))));
01654 }
01655 else
01656 {
01657 mask = 1 << posn;
01658 emit_insn (gen_rtx_SET (SImode, operands[0],
01659 gen_rtx_IOR (SImode, operands[0], GEN_INT (mask))));
01660 }
01661
01662 return 1;
01663 }
01664
01665
01666
01667 if (! TARGET_W_FIELD)
01668 return 0;
01669
01670 if (width == 8 && posn % 8 == 0)
01671
01672 return 0;
01673
01674 if (width == 16 && posn % 16 == 0)
01675
01676 return 0;
01677
01678
01679
01680
01681
01682
01683
01684 if (GET_CODE (operands[3]) == CONST_INT &&
01685 INTVAL (operands[3]) == ((1 << width) - 1))
01686 {
01687 mreg = force_reg (SImode, GEN_INT (INTVAL (operands[3]) << posn));
01688 emit_insn (gen_rtx_SET (SImode, operands[0],
01689 gen_rtx_IOR (SImode, operands[0], mreg)));
01690 return 1;
01691 }
01692
01693
01694 mreg = force_reg (SImode, GEN_INT (~(((1 << width) - 1) << posn)));
01695
01696
01697 emit_insn (gen_rtx_SET (SImode, operands[0],
01698 gen_rtx_AND (SImode, operands[0], mreg)));
01699
01700
01701 if (GET_CODE (operands[3]) == CONST_INT && INTVAL (operands[3]) == 0)
01702 return 1;
01703
01704
01705
01706
01707 sreg = copy_to_mode_reg (SImode, operands[3]);
01708
01709
01710
01711
01712
01713
01714 if (width + posn != (int) GET_MODE_SIZE (SImode))
01715 {
01716 ereg = force_reg (SImode, GEN_INT ((1 << width) - 1));
01717 emit_insn (gen_rtx_SET (SImode, sreg,
01718 gen_rtx_AND (SImode, sreg, ereg)));
01719 }
01720
01721
01722 if (posn != 0)
01723 emit_insn (gen_rtx_SET (SImode, sreg,
01724 gen_rtx_ASHIFT (SImode, sreg, GEN_INT (posn))));
01725
01726 emit_insn (gen_rtx_SET (SImode, operands[0],
01727 gen_rtx_IOR (SImode, operands[0], sreg)));
01728
01729 return 1;
01730 }
01731
01732
01733
01734
01735 int
01736 mcore_load_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01737 {
01738 int count = XVECLEN (op, 0);
01739 int dest_regno;
01740 rtx src_addr;
01741 int i;
01742
01743
01744 if (count <= 1
01745 || GET_CODE (XVECEXP (op, 0, 0)) != SET
01746 || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
01747 || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM)
01748 return 0;
01749
01750 dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
01751 src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
01752
01753 for (i = 1; i < count; i++)
01754 {
01755 rtx elt = XVECEXP (op, 0, i);
01756
01757 if (GET_CODE (elt) != SET
01758 || GET_CODE (SET_DEST (elt)) != REG
01759 || GET_MODE (SET_DEST (elt)) != SImode
01760 || REGNO (SET_DEST (elt)) != (unsigned) (dest_regno + i)
01761 || GET_CODE (SET_SRC (elt)) != MEM
01762 || GET_MODE (SET_SRC (elt)) != SImode
01763 || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
01764 || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
01765 || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
01766 || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != i * 4)
01767 return 0;
01768 }
01769
01770 return 1;
01771 }
01772
01773
01774
01775 int
01776 mcore_store_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01777 {
01778 int count = XVECLEN (op, 0);
01779 int src_regno;
01780 rtx dest_addr;
01781 int i;
01782
01783
01784 if (count <= 1
01785 || GET_CODE (XVECEXP (op, 0, 0)) != SET
01786 || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM
01787 || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)
01788 return 0;
01789
01790 src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
01791 dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
01792
01793 for (i = 1; i < count; i++)
01794 {
01795 rtx elt = XVECEXP (op, 0, i);
01796
01797 if (GET_CODE (elt) != SET
01798 || GET_CODE (SET_SRC (elt)) != REG
01799 || GET_MODE (SET_SRC (elt)) != SImode
01800 || REGNO (SET_SRC (elt)) != (unsigned) (src_regno + i)
01801 || GET_CODE (SET_DEST (elt)) != MEM
01802 || GET_MODE (SET_DEST (elt)) != SImode
01803 || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
01804 || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
01805 || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
01806 || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != i * 4)
01807 return 0;
01808 }
01809
01810 return 1;
01811 }
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828 static const enum machine_mode mode_from_align[] =
01829 {
01830 VOIDmode, QImode, HImode, VOIDmode, SImode,
01831 };
01832
01833 static void
01834 block_move_sequence (rtx dst_mem, rtx src_mem, int size, int align)
01835 {
01836 rtx temp[2];
01837 enum machine_mode mode[2];
01838 int amount[2];
01839 bool active[2];
01840 int phase = 0;
01841 int next;
01842 int offset_ld = 0;
01843 int offset_st = 0;
01844 rtx x;
01845
01846 x = XEXP (dst_mem, 0);
01847 if (!REG_P (x))
01848 {
01849 x = force_reg (Pmode, x);
01850 dst_mem = replace_equiv_address (dst_mem, x);
01851 }
01852
01853 x = XEXP (src_mem, 0);
01854 if (!REG_P (x))
01855 {
01856 x = force_reg (Pmode, x);
01857 src_mem = replace_equiv_address (src_mem, x);
01858 }
01859
01860 active[0] = active[1] = false;
01861
01862 do
01863 {
01864 next = phase;
01865 phase ^= 1;
01866
01867 if (size > 0)
01868 {
01869 int next_amount;
01870
01871 next_amount = (size >= 4 ? 4 : (size >= 2 ? 2 : 1));
01872 next_amount = MIN (next_amount, align);
01873
01874 amount[next] = next_amount;
01875 mode[next] = mode_from_align[next_amount];
01876 temp[next] = gen_reg_rtx (mode[next]);
01877
01878 x = adjust_address (src_mem, mode[next], offset_ld);
01879 emit_insn (gen_rtx_SET (VOIDmode, temp[next], x));
01880
01881 offset_ld += next_amount;
01882 size -= next_amount;
01883 active[next] = true;
01884 }
01885
01886 if (active[phase])
01887 {
01888 active[phase] = false;
01889
01890 x = adjust_address (dst_mem, mode[phase], offset_st);
01891 emit_insn (gen_rtx_SET (VOIDmode, x, temp[phase]));
01892
01893 offset_st += amount[phase];
01894 }
01895 }
01896 while (active[next]);
01897 }
01898
01899 bool
01900 mcore_expand_block_move (rtx *operands)
01901 {
01902 HOST_WIDE_INT align, bytes, max;
01903
01904 if (GET_CODE (operands[2]) != CONST_INT)
01905 return false;
01906
01907 bytes = INTVAL (operands[2]);
01908 align = INTVAL (operands[3]);
01909
01910 if (bytes <= 0)
01911 return false;
01912 if (align > 4)
01913 align = 4;
01914
01915 switch (align)
01916 {
01917 case 4:
01918 if (bytes & 1)
01919 max = 4*4;
01920 else if (bytes & 3)
01921 max = 8*4;
01922 else
01923 max = 16*4;
01924 break;
01925 case 2:
01926 max = 4*2;
01927 break;
01928 case 1:
01929 max = 4*1;
01930 break;
01931 default:
01932 abort ();
01933 }
01934
01935 if (bytes <= max)
01936 {
01937 block_move_sequence (operands[0], operands[1], bytes, align);
01938 return true;
01939 }
01940
01941 return false;
01942 }
01943
01944
01945
01946 static int number_of_regs_before_varargs;
01947
01948
01949
01950 static int current_function_anonymous_args;
01951
01952 #define STACK_BYTES (STACK_BOUNDARY/BITS_PER_UNIT)
01953 #define STORE_REACH (64)
01954 #define ADDI_REACH (32)
01955
01956 static void
01957 layout_mcore_frame (struct mcore_frame * infp)
01958 {
01959 int n;
01960 unsigned int i;
01961 int nbytes;
01962 int regarg;
01963 int localregarg;
01964 int localreg;
01965 int outbounds;
01966 unsigned int growths;
01967 int step;
01968
01969
01970
01971 nbytes = current_function_pretend_args_size;
01972
01973
01974 if (current_function_anonymous_args)
01975 nbytes += (NPARM_REGS - number_of_regs_before_varargs) * UNITS_PER_WORD;
01976
01977 infp->arg_size = nbytes;
01978
01979
01980 infp->reg_mask = calc_live_regs (& n);
01981 infp->reg_size = n * 4;
01982
01983
01984 infp->local_size = get_frame_size ();
01985 infp->outbound_size = current_function_outgoing_args_size;
01986
01987
01988 if (infp->local_size % STACK_BYTES)
01989 infp->local_size = (infp->local_size + STACK_BYTES - 1) & ~ (STACK_BYTES -1);
01990
01991
01992
01993 infp->pad_local = 0;
01994 infp->pad_reg = 0;
01995 infp->pad_outbound = 0;
01996 if (infp->outbound_size % STACK_BYTES)
01997 infp->pad_outbound = STACK_BYTES - (infp->outbound_size % STACK_BYTES);
01998
01999
02000
02001
02002
02003
02004 for (i = 0; i < ARRAY_SIZE (infp->growth); i++)
02005 infp->growth[i] = 0;
02006
02007 regarg = infp->reg_size + infp->arg_size;
02008 localregarg = infp->local_size + regarg;
02009 localreg = infp->local_size + infp->reg_size;
02010 outbounds = infp->outbound_size + infp->pad_outbound;
02011 growths = 0;
02012
02013
02014
02015
02016
02017 if (localregarg <= ADDI_REACH
02018 && (infp->reg_size <= 8 || (infp->reg_mask & 0xc000) != 0xc000))
02019 {
02020
02021 if (localregarg % STACK_BYTES)
02022 infp->pad_reg = STACK_BYTES - (localregarg % STACK_BYTES);
02023
02024 step = localregarg + infp->pad_reg;
02025 infp->reg_offset = infp->local_size;
02026
02027 if (outbounds + step <= ADDI_REACH && !frame_pointer_needed)
02028 {
02029 step += outbounds;
02030 infp->reg_offset += outbounds;
02031 outbounds = 0;
02032 }
02033
02034 infp->arg_offset = step - 4;
02035 infp->growth[growths++] = step;
02036 infp->reg_growth = growths;
02037 infp->local_growth = growths;
02038
02039
02040 if (outbounds)
02041 infp->growth[growths++] = outbounds;
02042
02043 goto finish;
02044 }
02045
02046
02047
02048
02049
02050 if (localregarg <= STORE_REACH
02051 && (infp->local_size > ADDI_REACH)
02052 && (infp->reg_size <= 8 || (infp->reg_mask & 0xc000) != 0xc000))
02053 {
02054 int all;
02055
02056
02057 if (localregarg % STACK_BYTES)
02058 infp->pad_reg = STACK_BYTES - (localregarg % STACK_BYTES);
02059
02060 all = localregarg + infp->pad_reg + infp->pad_local;
02061 step = ADDI_REACH;
02062 if (step > all)
02063 step = all;
02064
02065
02066 infp->arg_offset = step - 4;
02067 infp->growth[growths++] = step;
02068 infp->reg_growth = growths;
02069 infp->reg_offset = step - infp->pad_reg - infp->reg_size;
02070 all -= step;
02071
02072
02073 if (outbounds + all <= ADDI_REACH && !frame_pointer_needed)
02074 {
02075 all += outbounds;
02076 outbounds = 0;
02077 }
02078
02079
02080 step = all;
02081 infp->growth[growths++] = step;
02082 infp->local_growth = growths;
02083 all -= step;
02084
02085 assert (all == 0);
02086
02087
02088 if (outbounds)
02089 infp->growth[growths++] = outbounds;
02090
02091 goto finish;
02092 }
02093
02094
02095
02096
02097 if ((regarg % STACK_BYTES) == 0)
02098 {
02099 infp->growth[growths++] = regarg;
02100 infp->reg_growth = growths;
02101 infp->arg_offset = regarg - 4;
02102 infp->reg_offset = 0;
02103
02104 if (infp->local_size % STACK_BYTES)
02105 infp->pad_local = STACK_BYTES - (infp->local_size % STACK_BYTES);
02106
02107 step = infp->local_size + infp->pad_local;
02108
02109 if (!frame_pointer_needed)
02110 {
02111 step += outbounds;
02112 outbounds = 0;
02113 }
02114
02115 infp->growth[growths++] = step;
02116 infp->local_growth = growths;
02117
02118
02119 if (outbounds)
02120 infp->growth[growths++] = outbounds;
02121
02122 goto finish;
02123 }
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133
02134 if (regarg % STACK_BYTES != 0)
02135 infp->pad_reg = STACK_BYTES - (regarg % STACK_BYTES);
02136
02137 infp->growth[growths++] = infp->arg_size + infp->reg_size + infp->pad_reg;
02138 infp->reg_growth = growths;
02139 infp->arg_offset = infp->growth[0] - 4;
02140 infp->reg_offset = 0;
02141
02142 if (frame_pointer_needed)
02143 {
02144 if (infp->local_size % STACK_BYTES != 0)
02145 infp->pad_local = STACK_BYTES - (infp->local_size % STACK_BYTES);
02146
02147 infp->growth[growths++] = infp->local_size + infp->pad_local;
02148 infp->local_growth = growths;
02149
02150 infp->growth[growths++] = outbounds;
02151 }
02152 else
02153 {
02154 if ((infp->local_size + outbounds) % STACK_BYTES != 0)
02155 infp->pad_local = STACK_BYTES - ((infp->local_size + outbounds) % STACK_BYTES);
02156
02157 infp->growth[growths++] = infp->local_size + infp->pad_local + outbounds;
02158 infp->local_growth = growths;
02159 }
02160
02161
02162 finish:
02163 assert (infp->reg_offset >= 0);
02164 assert (growths <= MAX_STACK_GROWS);
02165
02166 for (i = 0; i < growths; i++)
02167 {
02168 if (infp->growth[i] % STACK_BYTES)
02169 {
02170 fprintf (stderr,"stack growth of %d is not %d aligned\n",
02171 infp->growth[i], STACK_BYTES);
02172 abort ();
02173 }
02174 }
02175 }
02176
02177
02178
02179
02180 int
02181 mcore_initial_elimination_offset (int from, int to)
02182 {
02183 int above_frame;
02184 int below_frame;
02185 struct mcore_frame fi;
02186
02187 layout_mcore_frame (& fi);
02188
02189
02190 above_frame = fi.local_size + fi.pad_local + fi.reg_size + fi.pad_reg;
02191
02192 below_frame = fi.outbound_size + fi.pad_outbound;
02193
02194 if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
02195 return above_frame;
02196
02197 if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
02198 return above_frame + below_frame;
02199
02200 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
02201 return below_frame;
02202
02203 abort ();
02204
02205 return 0;
02206 }
02207
02208
02209
02210 static void
02211 mcore_setup_incoming_varargs (CUMULATIVE_ARGS *args_so_far,
02212 enum machine_mode mode, tree type,
02213 int * ptr_pretend_size ATTRIBUTE_UNUSED,
02214 int second_time ATTRIBUTE_UNUSED)
02215 {
02216 current_function_anonymous_args = 1;
02217
02218
02219
02220
02221 number_of_regs_before_varargs = *args_so_far + mcore_num_arg_regs (mode, type);
02222
02223
02224
02225
02226 number_of_regs_before_varargs = *args_so_far;
02227
02228
02229
02230 if (number_of_regs_before_varargs > NPARM_REGS)
02231 number_of_regs_before_varargs = NPARM_REGS;
02232 }
02233
02234 void
02235 mcore_expand_prolog (void)
02236 {
02237 struct mcore_frame fi;
02238 int space_allocated = 0;
02239 int growth = 0;
02240
02241
02242 layout_mcore_frame (&fi);
02243
02244 space_allocated = fi.arg_size + fi.reg_size + fi.local_size +
02245 fi.outbound_size + fi.pad_outbound + fi.pad_local + fi.pad_reg;
02246
02247 if (TARGET_CG_DATA)
02248 {
02249
02250 rtx x;
02251
02252 x = DECL_RTL (current_function_decl);
02253
02254 if (GET_CODE (x) != MEM)
02255 abort ();
02256
02257 x = XEXP (x, 0);
02258
02259 if (GET_CODE (x) != SYMBOL_REF)
02260 abort ();
02261
02262 if (mcore_current_function_name)
02263 free (mcore_current_function_name);
02264
02265 mcore_current_function_name = xstrdup (XSTR (x, 0));
02266
02267 ASM_OUTPUT_CG_NODE (asm_out_file, mcore_current_function_name, space_allocated);
02268
02269 if (current_function_calls_alloca)
02270 ASM_OUTPUT_CG_EDGE (asm_out_file, mcore_current_function_name, "alloca", 1);
02271
02272
02273
02274
02275
02276 fprintf (asm_out_file,
02277 "\t.equ\t__$frame$info$_%s_$_%d_%d_x%x_%d_%d_%d,0\n",
02278 mcore_current_function_name,
02279 fi.arg_size, fi.reg_size, fi.reg_mask,
02280 fi.local_size, fi.outbound_size,
02281 frame_pointer_needed);
02282 }
02283
02284 if (mcore_naked_function_p ())
02285 return;
02286
02287
02288 output_stack_adjust (-1, fi.growth[growth++]);
02289
02290
02291
02292
02293 if (fi.arg_size != 0 && current_function_pretend_args_size == 0)
02294 {
02295 int offset;
02296 int rn = FIRST_PARM_REG + NPARM_REGS - 1;
02297 int remaining = fi.arg_size;
02298
02299 for (offset = fi.arg_offset; remaining >= 4; offset -= 4, rn--, remaining -= 4)
02300 {
02301 emit_insn (gen_movsi
02302 (gen_rtx_MEM (SImode,
02303 plus_constant (stack_pointer_rtx, offset)),
02304 gen_rtx_REG (SImode, rn)));
02305 }
02306 }
02307
02308
02309 if (growth < fi.reg_growth)
02310 output_stack_adjust (-1, fi.growth[growth++]);
02311
02312 if (fi.reg_size != 0)
02313 {
02314 int i;
02315 int offs = fi.reg_offset;
02316
02317 for (i = 15; i >= 0; i--)
02318 {
02319 if (offs == 0 && i == 15 && ((fi.reg_mask & 0xc000) == 0xc000))
02320 {
02321 int first_reg = 15;
02322
02323 while (fi.reg_mask & (1 << first_reg))
02324 first_reg--;
02325 first_reg++;
02326
02327 emit_insn (gen_store_multiple (gen_rtx_MEM (SImode, stack_pointer_rtx),
02328 gen_rtx_REG (SImode, first_reg),
02329 GEN_INT (16 - first_reg)));
02330
02331 i -= (15 - first_reg);
02332 offs += (16 - first_reg) * 4;
02333 }
02334 else if (fi.reg_mask & (1 << i))
02335 {
02336 emit_insn (gen_movsi
02337 (gen_rtx_MEM (SImode,
02338 plus_constant (stack_pointer_rtx, offs)),
02339 gen_rtx_REG (SImode, i)));
02340 offs += 4;
02341 }
02342 }
02343 }
02344
02345
02346 if (frame_pointer_needed)
02347 {
02348
02349 if (growth < fi.local_growth)
02350 output_stack_adjust (-1, fi.growth[growth++]);
02351
02352 emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
02353
02354
02355 if (fi.growth[growth])
02356 output_stack_adjust (-1, fi.growth[growth++]);
02357 }
02358 else
02359 {
02360 if (growth < fi.local_growth)
02361 output_stack_adjust (-1, fi.growth[growth++]);
02362 if (fi.growth[growth])
02363 output_stack_adjust (-1, fi.growth[growth++]);
02364 }
02365 }
02366
02367 void
02368 mcore_expand_epilog (void)
02369 {
02370 struct mcore_frame fi;
02371 int i;
02372 int offs;
02373 int growth = MAX_STACK_GROWS - 1 ;
02374
02375
02376
02377 layout_mcore_frame(&fi);
02378
02379 if (mcore_naked_function_p ())
02380 return;
02381
02382
02383 if (frame_pointer_needed)
02384 {
02385 emit_insn (gen_movsi (stack_pointer_rtx, frame_pointer_rtx));
02386 growth = fi.local_growth - 1;
02387 }
02388 else
02389 {
02390
02391 while (growth >= fi.local_growth)
02392 {
02393 if (fi.growth[growth] != 0)
02394 output_stack_adjust (1, fi.growth[growth]);
02395 growth--;
02396 }
02397 }
02398
02399
02400
02401
02402 while (growth >= fi.reg_growth)
02403 output_stack_adjust ( 1, fi.growth[growth--]);
02404
02405 offs = fi.reg_offset;
02406
02407 for (i = 15; i >= 0; i--)
02408 {
02409 if (offs == 0 && i == 15 && ((fi.reg_mask & 0xc000) == 0xc000))
02410 {
02411 int first_reg;
02412
02413
02414 first_reg = 15;
02415
02416 while (fi.reg_mask & (1 << first_reg))
02417 first_reg--;
02418
02419 first_reg++;
02420
02421 emit_insn (gen_load_multiple (gen_rtx_REG (SImode, first_reg),
02422 gen_rtx_MEM (SImode, stack_pointer_rtx),
02423 GEN_INT (16 - first_reg)));
02424
02425 i -= (15 - first_reg);
02426 offs += (16 - first_reg) * 4;
02427 }
02428 else if (fi.reg_mask & (1 << i))
02429 {
02430 emit_insn (gen_movsi
02431 (gen_rtx_REG (SImode, i),
02432 gen_rtx_MEM (SImode,
02433 plus_constant (stack_pointer_rtx, offs))));
02434 offs += 4;
02435 }
02436 }
02437
02438
02439
02440 while (growth >= 0)
02441 output_stack_adjust ( 1, fi.growth[growth--]);
02442 }
02443
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487
02488
02489
02490
02491
02492
02493
02494
02495
02496 typedef struct
02497 {
02498 rtx value;
02499 rtx label;
02500 } pool_node;
02501
02502
02503
02504
02505
02506
02507 #define MAX_COUNT 1016
02508 #define MAX_POOL_SIZE (MAX_COUNT/4)
02509 static pool_node pool_vector[MAX_POOL_SIZE];
02510 static int pool_size;
02511
02512
02513
02514
02515 const char *
02516 mcore_output_jump_label_table (void)
02517 {
02518 int i;
02519
02520 if (pool_size)
02521 {
02522 fprintf (asm_out_file, "\t.align 2\n");
02523
02524 for (i = 0; i < pool_size; i++)
02525 {
02526 pool_node * p = pool_vector + i;
02527
02528 (*targetm.asm_out.internal_label) (asm_out_file, "L", CODE_LABEL_NUMBER (p->label));
02529
02530 output_asm_insn (".long %0", &p->value);
02531 }
02532
02533 pool_size = 0;
02534 }
02535
02536 return "";
02537 }
02538
02539
02540
02541 static cond_type
02542 is_cond_candidate (rtx insn)
02543 {
02544
02545
02546
02547
02548 if (GET_CODE (insn) == INSN)
02549 {
02550 rtx pat = PATTERN (insn);
02551 rtx src, dst;
02552
02553 if (GET_CODE (pat) != SET)
02554 return COND_NO;
02555
02556 dst = XEXP (pat, 0);
02557
02558 if ((GET_CODE (dst) != REG &&
02559 GET_CODE (dst) != SUBREG) ||
02560 GET_MODE (dst) != SImode)
02561 return COND_NO;
02562
02563 src = XEXP (pat, 1);
02564
02565 if ((GET_CODE (src) == REG ||
02566 (GET_CODE (src) == SUBREG &&
02567 GET_CODE (SUBREG_REG (src)) == REG)) &&
02568 GET_MODE (src) == SImode)
02569 return COND_MOV_INSN;
02570 else if (GET_CODE (src) == CONST_INT &&
02571 INTVAL (src) == 0)
02572 return COND_CLR_INSN;
02573 else if (GET_CODE (src) == PLUS &&
02574 (GET_CODE (XEXP (src, 0)) == REG ||
02575 (GET_CODE (XEXP (src, 0)) == SUBREG &&
02576 GET_CODE (SUBREG_REG (XEXP (src, 0))) == REG)) &&
02577 GET_MODE (XEXP (src, 0)) == SImode &&
02578 GET_CODE (XEXP (src, 1)) == CONST_INT &&
02579 INTVAL (XEXP (src, 1)) == 1)
02580 return COND_INC_INSN;
02581 else if (((GET_CODE (src) == MINUS &&
02582 GET_CODE (XEXP (src, 1)) == CONST_INT &&
02583 INTVAL( XEXP (src, 1)) == 1) ||
02584 (GET_CODE (src) == PLUS &&
02585 GET_CODE (XEXP (src, 1)) == CONST_INT &&
02586 INTVAL (XEXP (src, 1)) == -1)) &&
02587 (GET_CODE (XEXP (src, 0)) == REG ||
02588 (GET_CODE (XEXP (src, 0)) == SUBREG &&
02589 GET_CODE (SUBREG_REG (XEXP (src, 0))) == REG)) &&
02590 GET_MODE (XEXP (src, 0)) == SImode)
02591 return COND_DEC_INSN;
02592
02593
02594
02595
02596
02597
02598 }
02599 else if (GET_CODE (insn) == JUMP_INSN &&
02600 GET_CODE (PATTERN (insn)) == SET &&
02601 GET_CODE (XEXP (PATTERN (insn), 1)) == LABEL_REF)
02602 return COND_BRANCH_INSN;
02603
02604 return COND_NO;
02605 }
02606
02607
02608
02609
02610 static rtx
02611 emit_new_cond_insn (rtx insn, int cond)
02612 {
02613 rtx c_insn = 0;
02614 rtx pat, dst, src;
02615 cond_type num;
02616
02617 if ((num = is_cond_candidate (insn)) == COND_NO)
02618 return NULL;
02619
02620 pat = PATTERN (insn);
02621
02622 if (GET_CODE (insn) == INSN)
02623 {
02624 dst = SET_DEST (pat);
02625 src = SET_SRC (pat);
02626 }
02627 else
02628 {
02629 dst = JUMP_LABEL (insn);
02630 src = NULL_RTX;
02631 }
02632
02633 switch (num)
02634 {
02635 case COND_MOV_INSN:
02636 case COND_CLR_INSN:
02637 if (cond)
02638 c_insn = gen_movt0 (dst, src, dst);
02639 else
02640 c_insn = gen_movt0 (dst, dst, src);
02641 break;
02642
02643 case COND_INC_INSN:
02644 if (cond)
02645 c_insn = gen_incscc (dst, dst);
02646 else
02647 c_insn = gen_incscc_false (dst, dst);
02648 break;
02649
02650 case COND_DEC_INSN:
02651 if (cond)
02652 c_insn = gen_decscc (dst, dst);
02653 else
02654 c_insn = gen_decscc_false (dst, dst);
02655 break;
02656
02657 case COND_BRANCH_INSN:
02658 if (cond)
02659 c_insn = gen_branch_true (dst);
02660 else
02661 c_insn = gen_branch_false (dst);
02662 break;
02663
02664 default:
02665 return NULL;
02666 }
02667
02668
02669 if (rtx_length [GET_CODE (c_insn)] >= 7 && rtx_length [GET_CODE (insn)] >= 7)
02670 {
02671
02672
02673
02674
02675 REG_NOTES (c_insn) = REG_NOTES (insn);
02676 }
02677
02678 if (num == COND_BRANCH_INSN)
02679 {
02680
02681
02682
02683
02684 c_insn = emit_jump_insn_before (c_insn, insn);
02685
02686 ++ LABEL_NUSES (dst);
02687
02688 JUMP_LABEL (c_insn) = dst;
02689 }
02690 else
02691 c_insn = emit_insn_after (c_insn, insn);
02692
02693 delete_insn (insn);
02694
02695 return c_insn;
02696 }
02697
02698
02699
02700
02701
02702
02703
02704
02705
02706
02707
02708
02709
02710
02711
02712
02713
02714
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724
02725
02726
02727 static rtx
02728 conditionalize_block (rtx first)
02729 {
02730 rtx insn;
02731 rtx br_pat;
02732 rtx end_blk_1_br = 0;
02733 rtx end_blk_2_insn = 0;
02734 rtx start_blk_3_lab = 0;
02735 int cond;
02736 int br_lab_num;
02737 int blk_size = 0;
02738
02739
02740
02741
02742
02743 if (GET_CODE (first) != JUMP_INSN ||
02744 GET_CODE (PATTERN (first)) != SET ||
02745 GET_CODE (XEXP (PATTERN (first), 1)) != IF_THEN_ELSE)
02746 return NEXT_INSN (first);
02747
02748
02749 end_blk_1_br = first;
02750 br_pat = PATTERN (end_blk_1_br);
02751
02752
02753 cond = (GET_CODE (XEXP (XEXP (br_pat, 1), 0)) == EQ);
02754
02755
02756 if (GET_CODE (XEXP (XEXP (br_pat, 1), 1)) == LABEL_REF)
02757 {
02758
02759 br_lab_num = CODE_LABEL_NUMBER (XEXP (XEXP (XEXP (br_pat, 1), 1), 0));
02760 }
02761 else
02762 {
02763
02764
02765 cond = (cond == 0);
02766 br_lab_num = CODE_LABEL_NUMBER (XEXP (XEXP (XEXP (br_pat, 1), 2), 0));
02767 }
02768
02769
02770
02771
02772
02773
02774 for (insn = NEXT_INSN (first); insn; insn = NEXT_INSN (insn))
02775 {
02776 enum rtx_code code;
02777
02778 code = GET_CODE (insn);
02779
02780
02781 if (code == CODE_LABEL && CODE_LABEL_NUMBER (insn) == br_lab_num)
02782 break;
02783
02784
02785
02786
02787 if (code != BARRIER && code != NOTE && !is_cond_candidate (insn))
02788 return NEXT_INSN (insn);
02789
02790
02791 if (code == JUMP_INSN || code == INSN)
02792 {
02793 blk_size ++;
02794 end_blk_2_insn = insn;
02795 }
02796 }
02797
02798 if (!insn)
02799 return insn;
02800
02801
02802
02803
02804
02805
02806
02807
02808
02809
02810
02811 if (optimize > 1 && blk_size > 2)
02812 return insn;
02813
02814
02815
02816
02817
02818 start_blk_3_lab = insn;
02819
02820 for (insn = NEXT_INSN (end_blk_1_br); insn != start_blk_3_lab;
02821 insn = NEXT_INSN (insn))
02822 {
02823 rtx newinsn;
02824
02825 if (INSN_DELETED_P (insn))
02826 continue;
02827
02828
02829 if ((newinsn = emit_new_cond_insn (insn, cond)))
02830 {
02831 if (end_blk_2_insn == insn)
02832 end_blk_2_insn = newinsn;
02833
02834 insn = newinsn;
02835 }
02836 }
02837
02838
02839
02840
02841 if (LABEL_NUSES (start_blk_3_lab) == 1)
02842 {
02843 start_blk_3_lab = 0;
02844 }
02845
02846
02847
02848
02849
02850 delete_insn (end_blk_1_br);
02851
02852 if (! start_blk_3_lab)
02853 return end_blk_2_insn;
02854
02855
02856 return NEXT_INSN (start_blk_3_lab);
02857 }
02858
02859
02860
02861
02862
02863
02864
02865
02866
02867
02868 static void
02869 conditionalize_optimization (void)
02870 {
02871 rtx insn;
02872
02873 for (insn = get_insns (); insn; insn = conditionalize_block (insn))
02874 continue;
02875 }
02876
02877 static int saved_warn_return_type = -1;
02878 static int saved_warn_return_type_count = 0;
02879
02880
02881
02882 static void
02883 mcore_reorg (void)
02884 {
02885
02886 current_function_anonymous_args = 0;
02887
02888
02889 if (saved_warn_return_type != -1)
02890 {
02891
02892
02893
02894
02895
02896 if (--saved_warn_return_type_count == 0)
02897 {
02898 warn_return_type = saved_warn_return_type;
02899 saved_warn_return_type = -1;
02900 }
02901 }
02902
02903 if (optimize == 0)
02904 return;
02905
02906
02907 conditionalize_optimization ();
02908
02909
02910 }
02911
02912
02913
02914
02915 bool
02916 mcore_r15_operand_p (rtx x)
02917 {
02918 switch (GET_CODE (x))
02919 {
02920 case CONST_INT:
02921 return mcore_const_ok_for_inline (INTVAL (x));
02922
02923 case REG:
02924 case SUBREG:
02925 case MEM:
02926 return 1;
02927
02928 default:
02929 return 0;
02930 }
02931 }
02932
02933
02934
02935
02936 enum reg_class
02937 mcore_secondary_reload_class (enum reg_class class,
02938 enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
02939 {
02940 if (TEST_HARD_REG_BIT (reg_class_contents[class], 15)
02941 && !mcore_r15_operand_p (x))
02942 return LRW_REGS;
02943 return NO_REGS;
02944 }
02945
02946
02947
02948
02949
02950 enum reg_class
02951 mcore_reload_class (rtx x, enum reg_class class)
02952 {
02953 if (reg_class_subset_p (LRW_REGS, class) && !mcore_r15_operand_p (x))
02954 return LRW_REGS;
02955
02956 return class;
02957 }
02958
02959
02960
02961
02962
02963
02964
02965 int
02966 mcore_is_same_reg (rtx x, rtx y)
02967 {
02968
02969 while (GET_CODE (x) == SUBREG)
02970 x = SUBREG_REG (x);
02971
02972 while (GET_CODE (y) == SUBREG)
02973 y = SUBREG_REG (y);
02974
02975 if (GET_CODE(x) == REG && GET_CODE(y) == REG && REGNO(x) == REGNO(y))
02976 return 1;
02977
02978 return 0;
02979 }
02980
02981 void
02982 mcore_override_options (void)
02983 {
02984 if (mcore_stack_increment_string)
02985 {
02986 mcore_stack_increment = atoi (mcore_stack_increment_string);
02987
02988 if (mcore_stack_increment < 0
02989 || (mcore_stack_increment == 0
02990 && (mcore_stack_increment_string[0] != '0'
02991 || mcore_stack_increment_string[1] != 0)))
02992 error ("invalid option %<-mstack-increment=%s%>",
02993 mcore_stack_increment_string);
02994 }
02995
02996
02997 if (TARGET_LITTLE_END && ! TARGET_M340)
02998 target_flags |= M340_BIT;
02999 }
03000
03001
03002
03003
03004 int
03005 mcore_num_arg_regs (enum machine_mode mode, tree type)
03006 {
03007 int size;
03008
03009 if (targetm.calls.must_pass_in_stack (mode, type))
03010 return 0;
03011
03012 if (type && mode == BLKmode)
03013 size = int_size_in_bytes (type);
03014 else
03015 size = GET_MODE_SIZE (mode);
03016
03017 return ROUND_ADVANCE (size);
03018 }
03019
03020 static rtx
03021 handle_structs_in_regs (enum machine_mode mode, tree type, int reg)
03022 {
03023 int size;
03024
03025
03026
03027
03028
03029
03030
03031
03032 if (type
03033 && TYPE_MODE (type) == BLKmode
03034 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
03035 && (size = int_size_in_bytes (type)) > UNITS_PER_WORD
03036 && (size % UNITS_PER_WORD != 0)
03037 && (reg + mcore_num_arg_regs (mode, type) <= (FIRST_PARM_REG + NPARM_REGS)))
03038 {
03039 rtx arg_regs [NPARM_REGS];
03040 int nregs;
03041 rtx result;
03042 rtvec rtvec;
03043
03044 for (nregs = 0; size > 0; size -= UNITS_PER_WORD)
03045 {
03046 arg_regs [nregs] =
03047 gen_rtx_EXPR_LIST (SImode, gen_rtx_REG (SImode, reg ++),
03048 GEN_INT (nregs * UNITS_PER_WORD));
03049 nregs ++;
03050 }
03051
03052
03053 assert (ARRAY_SIZE (arg_regs) == 6);
03054 rtvec = gen_rtvec (nregs, arg_regs[0], arg_regs[1], arg_regs[2],
03055 arg_regs[3], arg_regs[4], arg_regs[5]);
03056
03057 result = gen_rtx_PARALLEL (mode, rtvec);
03058 return result;
03059 }
03060
03061 return gen_rtx_REG (mode, reg);
03062 }
03063
03064 rtx
03065 mcore_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
03066 {
03067 enum machine_mode mode;
03068 int unsigned_p;
03069
03070 mode = TYPE_MODE (valtype);
03071
03072 PROMOTE_MODE (mode, unsigned_p, NULL);
03073
03074 return handle_structs_in_regs (mode, valtype, FIRST_RET_REG);
03075 }
03076
03077
03078
03079
03080
03081
03082
03083
03084
03085
03086
03087
03088
03089
03090
03091
03092
03093
03094
03095 rtx
03096 mcore_function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode,
03097 tree type, int named)
03098 {
03099 int arg_reg;
03100
03101 if (! named || mode == VOIDmode)
03102 return 0;
03103
03104 if (targetm.calls.must_pass_in_stack (mode, type))
03105 return 0;
03106
03107 arg_reg = ROUND_REG (cum, mode);
03108
03109 if (arg_reg < NPARM_REGS)
03110 return handle_structs_in_regs (mode, type, FIRST_PARM_REG + arg_reg);
03111
03112 return 0;
03113 }
03114
03115
03116
03117
03118
03119
03120
03121
03122 static int
03123 mcore_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
03124 tree type, bool named)
03125 {
03126 int reg = ROUND_REG (*cum, mode);
03127
03128 if (named == 0)
03129 return 0;
03130
03131 if (targetm.calls.must_pass_in_stack (mode, type))
03132 return 0;
03133
03134
03135
03136
03137
03138
03139
03140
03141
03142 if (reg >= NPARM_REGS)
03143 return 0;
03144
03145
03146 if (reg + mcore_num_arg_regs (mode, type) <= NPARM_REGS)
03147 return 0;
03148
03149
03150
03151
03152 reg = NPARM_REGS - reg;
03153
03154
03155 return reg * UNITS_PER_WORD;
03156 }
03157
03158
03159
03160 int
03161 mcore_dllexport_name_p (const char * symbol)
03162 {
03163 return symbol[0] == '@' && symbol[1] == 'e' && symbol[2] == '.';
03164 }
03165
03166
03167
03168 int
03169 mcore_dllimport_name_p (const char * symbol)
03170 {
03171 return symbol[0] == '@' && symbol[1] == 'i' && symbol[2] == '.';
03172 }
03173
03174
03175
03176 static void
03177 mcore_mark_dllexport (tree decl)
03178 {
03179 const char * oldname;
03180 char * newname;
03181 rtx rtlname;
03182 tree idp;
03183
03184 rtlname = XEXP (DECL_RTL (decl), 0);
03185
03186 if (GET_CODE (rtlname) == SYMBOL_REF)
03187 oldname = XSTR (rtlname, 0);
03188 else if ( GET_CODE (rtlname) == MEM
03189 && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
03190 oldname = XSTR (XEXP (rtlname, 0), 0);
03191 else
03192 abort ();
03193
03194 if (mcore_dllexport_name_p (oldname))
03195 return;
03196
03197 newname = alloca (strlen (oldname) + 4);
03198 sprintf (newname, "@e.%s", oldname);
03199
03200
03201
03202
03203
03204
03205 idp = get_identifier (newname);
03206
03207 XEXP (DECL_RTL (decl), 0) =
03208 gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
03209 }
03210
03211
03212
03213 static void
03214 mcore_mark_dllimport (tree decl)
03215 {
03216 const char * oldname;
03217 char * newname;
03218 tree idp;
03219 rtx rtlname;
03220 rtx newrtl;
03221
03222 rtlname = XEXP (DECL_RTL (decl), 0);
03223
03224 if (GET_CODE (rtlname) == SYMBOL_REF)
03225 oldname = XSTR (rtlname, 0);
03226 else if ( GET_CODE (rtlname) == MEM
03227 && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
03228 oldname = XSTR (XEXP (rtlname, 0), 0);
03229 else
03230 abort ();
03231
03232 if (mcore_dllexport_name_p (oldname))
03233 abort ();
03234 else if (mcore_dllimport_name_p (oldname))
03235 return;
03236
03237
03238
03239
03240
03241 if (TREE_CODE (decl) == VAR_DECL
03242 && !DECL_VIRTUAL_P (decl)
03243 && DECL_INITIAL (decl))
03244 {
03245 error ("%Jinitialized variable '%D' is marked dllimport", decl, decl);
03246 return;
03247 }
03248
03249
03250
03251 if (TREE_CODE (decl) == VAR_DECL
03252
03253 && !DECL_VIRTUAL_P (decl))
03254 {
03255 DECL_EXTERNAL (decl) = 1;
03256 TREE_PUBLIC (decl) = 1;
03257 }
03258
03259 newname = alloca (strlen (oldname) + 11);
03260 sprintf (newname, "@i.__imp_%s", oldname);
03261
03262
03263
03264
03265
03266
03267 idp = get_identifier (newname);
03268
03269 newrtl = gen_rtx_MEM (Pmode,
03270 gen_rtx_SYMBOL_REF (Pmode,
03271 IDENTIFIER_POINTER (idp)));
03272 XEXP (DECL_RTL (decl), 0) = newrtl;
03273 }
03274
03275 static int
03276 mcore_dllexport_p (tree decl)
03277 {
03278 if ( TREE_CODE (decl) != VAR_DECL
03279 && TREE_CODE (decl) != FUNCTION_DECL)
03280 return 0;
03281
03282 return lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)) != 0;
03283 }
03284
03285 static int
03286 mcore_dllimport_p (tree decl)
03287 {
03288 if ( TREE_CODE (decl) != VAR_DECL
03289 && TREE_CODE (decl) != FUNCTION_DECL)
03290 return 0;
03291
03292 return lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)) != 0;
03293 }
03294
03295
03296
03297
03298 static void
03299 mcore_encode_section_info (tree decl, rtx rtl ATTRIBUTE_UNUSED, int first ATTRIBUTE_UNUSED)
03300 {
03301
03302
03303 if (mcore_dllexport_p (decl))
03304 mcore_mark_dllexport (decl);
03305 else if (mcore_dllimport_p (decl))
03306 mcore_mark_dllimport (decl);
03307
03308
03309
03310
03311 else if ((TREE_CODE (decl) == FUNCTION_DECL
03312 || TREE_CODE (decl) == VAR_DECL)
03313 && DECL_RTL (decl) != NULL_RTX
03314 && GET_CODE (DECL_RTL (decl)) == MEM
03315 && GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM
03316 && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF
03317 && mcore_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0)))
03318 {
03319 const char * oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0);
03320 tree idp = get_identifier (oldname + 9);
03321 rtx newrtl = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
03322
03323 XEXP (DECL_RTL (decl), 0) = newrtl;
03324
03325
03326
03327 }
03328 }
03329
03330
03331
03332 static const char *
03333 mcore_strip_name_encoding (const char * str)
03334 {
03335 return str + (str[0] == '@' ? 3 : 0);
03336 }
03337
03338
03339
03340
03341
03342
03343 const struct attribute_spec mcore_attribute_table[] =
03344 {
03345
03346 { "dllexport", 0, 0, true, false, false, NULL },
03347 { "dllimport", 0, 0, true, false, false, NULL },
03348 { "naked", 0, 0, true, false, false, mcore_handle_naked_attribute },
03349 { NULL, 0, 0, false, false, false, NULL }
03350 };
03351
03352
03353
03354
03355 static tree
03356 mcore_handle_naked_attribute (tree * node, tree name, tree args ATTRIBUTE_UNUSED,
03357 int flags ATTRIBUTE_UNUSED, bool * no_add_attrs)
03358 {
03359 if (TREE_CODE (*node) == FUNCTION_DECL)
03360 {
03361
03362
03363
03364
03365
03366
03367
03368 if (warn_return_type)
03369 {
03370 saved_warn_return_type = warn_return_type;
03371 warn_return_type = 0;
03372 saved_warn_return_type_count = 2;
03373 }
03374 else if (saved_warn_return_type_count)
03375 saved_warn_return_type_count = 2;
03376 }
03377 else
03378 {
03379 warning ("%qs attribute only applies to functions",
03380 IDENTIFIER_POINTER (name));
03381 *no_add_attrs = true;
03382 }
03383
03384 return NULL_TREE;
03385 }
03386
03387
03388
03389
03390 static void
03391 mcore_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED)
03392 {
03393 int len;
03394 const char * name;
03395 char * string;
03396 const char * prefix;
03397
03398 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
03399
03400
03401 name = (* targetm.strip_name_encoding) (name);
03402
03403
03404
03405
03406 if (TREE_CODE (decl) == FUNCTION_DECL)
03407 prefix = ".text$";
03408
03409
03410 else if (decl_readonly_section (decl, 0))
03411 prefix = ".rdata$";
03412 else
03413 prefix = ".data$";
03414
03415 len = strlen (name) + strlen (prefix);
03416 string = alloca (len + 1);
03417
03418 sprintf (string, "%s%s", prefix, name);
03419
03420 DECL_SECTION_NAME (decl) = build_string (len, string);
03421 }
03422
03423 int
03424 mcore_naked_function_p (void)
03425 {
03426 return lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE;
03427 }
03428
03429 #ifdef OBJECT_FORMAT_ELF
03430 static void
03431 mcore_asm_named_section (const char *name,
03432 unsigned int flags ATTRIBUTE_UNUSED,
03433 tree decl ATTRIBUTE_UNUSED)
03434 {
03435 fprintf (asm_out_file, "\t.section %s\n", name);
03436 }
03437 #endif
03438
03439
03440
03441 static void
03442 mcore_external_libcall (rtx fun)
03443 {
03444 fprintf (asm_out_file, "\t.import\t");
03445 assemble_name (asm_out_file, XSTR (fun, 0));
03446 fprintf (asm_out_file, "\n");
03447 }
03448
03449
03450
03451 static bool
03452 mcore_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
03453 {
03454 HOST_WIDE_INT size = int_size_in_bytes (type);
03455 return (size == -1 || size > 2 * UNITS_PER_WORD);
03456 }