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