* [PATCH] Fix _Unwind_Context backward compatibility issues @ 2006-12-28 20:46 Jakub Jelinek 2006-12-29 6:54 ` [PATCH]: for Score backend liqin 2007-01-03 18:07 ` [PATCH] Fix _Unwind_Context backward compatibility issues Richard Henderson 0 siblings, 2 replies; 5+ messages in thread From: Jakub Jelinek @ 2006-12-28 20:46 UTC (permalink / raw) To: gcc-patches Hi! The http://gcc.gnu.org/ml/gcc-patches/2006-02/msg01986.html http://gcc.gnu.org/ml/gcc-patches/2006-03/msg00208.html patches added 2 new fields at the end of struct _Unwind_Context. While that structure is only defined inside unwind-dw2.c, unfortunately it seems to be part of the ABI. That's because if some application or library has its own copy of some older version of GCC unwinder linked into it, the two unwinders don't play together nicely. It is arguably a bug to provide its own unwinder (except for statically linked apps), but unfortunately it seems quite a common bug. With older GCCs (before --as-needed was used in specs), all that was needed was link some C++ program or shared library with gcc -o foo *.o -lstdc++ rather than g++ -o foo *.o and with very old GCCs the libgcc_eh.a routines weren't even hidden in the executable. With contemporary GCCs one has to try harder, either use -static-libgcc switch or link with explicit -lgcc_eh (one example of the latter is e.g. libwvstreams). The scenarios in which things break: 1) unwinder in the executable, exported from it (i.e. before it was made .hidden in libgcc_eh.a), links against shared libstdc++.so and that links against shared libgcc_s.so. If something calls say _Unwind_RaiseException, it will be resolved to the copy in the executable, because it comes earlier in the search path. The old _Unwind_RaiseException sets up 2 struct _Unwind_Context variables, with the old layout (i.e. args_size as the last member). During unwinding __gxx_personality_v0 in the shared libstdc++.so is called and that calls _Unwind_GetIPInfo. A pointer to the small old struct _Unwind_Context in old _Unwind_RaiseException's stack frame is passed through. As this is a new function in GCC 4.2, it won't be in the unwinder in the executable, so the call jumps to _Unwind_GetIPInfo in GCC 4.2+ libgcc_s.so. But, this routine looks at context->signal_frame, i.e. depends on some uninitialized byte on the stack. 2) unwinder in the executable, not exported from it (slightly newer version, already .hidden), links against shared libstdc++.so which links against shared libgcc_s.so. When an exception is thrown (__cxa_throw), first the libgcc_s.so unwinder is used, but if there is some destructor within the executable, we can then call _Unwind_Resume hidden in the executable. This again sets up a small _Unwind_Context, then during unwinding calls __gxx_personality_v0. This can call _Unwind_SetGR to set the unwind arguments, in all cases passing around pointer to the small _Unwind_Context. But, as _Unwind_SetGR from the executable's unwinder is hidden in the executable, it calls _Unwind_SetGR in libgcc_s.so. This looks at context->by_value, thus again depends on uninitialized stack values. If non-zero happens to be there, it can set context->regs[i] directly to the value rather than store the value to *context->regs[i]. When in uw_install_context_1 of the executable's unwinder the program will likely crash though, because it expects context->regs[i] to be a valid pointer. Unfortunately, the old _Unwind_Context did not contain any zero initialized pad values nor any version field which would allow subsequent field additions. The following patch tries to stay backwards compatible with 99.999% of old programs out there. It will not work with functions on 32-bit arches which push 1GB or more of arguments to one function, use DW_CFA_GNU_args_size for that function and at least one other unwinder is used in the application in addition to libgcc_s.so.1's unwinder. I guess that is extremely rare to non-existent. args_size field is always used only within the same unwinder (set up in uw_frame_state_for and/or static functions it calls, read in uw_install_context_1, again static function called from within the same _Unwind_{RaiseException,ForcedUnwind,Resume}. The reason I'm not just using the topmost args_size bit for EXTENDED_CONTEXT_BIT is that we (Red Hat) unfortunately used the topmost bit in RHEL 4.4 and RHEL 3.8 when we found the signal_frame new field didn't fly. I'm terribly sorry about that. At that time we thought GCC 4.2+ doesn't need to worry about this, after all apps that have their own unwinder in addition to libgcc_s's are broken (e.g. when libc or some other library starts using new DW_CFA_* opcodes, the old statically linked unwinders are out of luck), but we didn't know about scenario 2) at that point and we didn't know how many buggy apps are out there. Perhaps to be even more compatible even with older GCC 4.2 (plus all the 4.1 branches where this has been backported) unwinders, _Unwind_Context could be: struct _Unwind_Context { void *reg[DWARF_FRAME_REGISTERS+1]; void *cfa; void *ra; void *lsda; struct dwarf_eh_bases bases; /* Signal frame context. */ #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1) /* Context which has version/args_size/by_value fields. */ #define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1) _Unwind_Word flags; char old_signal_frame; /* Unused now, always 0. */ char by_value[DWARF_FRAME_REGISTERS+1]; /* 0 for now, can be increased when further fields are added to struct _Unwind_Context. */ _Unwind_Word version; _Unwind_Word args_size; }; and keep the rest of the patch the same, or alternatively drop SIGNAL_FRAME_BIT (but keep EXTENDED_CONTEXT_BIT the 2nd MSB) and use signal_frame only if _Unwind_IsExtendedContext (context). As args_size (see above) is only used within the same unwinder, we can IMHO move it to a different field, therefore support even extremely huge function arguments when only the new under is used. The struct now includes also a version field which can be used for further extensions of struct _Unwind_Context, so that we don't have to fight this bit battle again. Bootstrapped/regtested on 7 linux arches. Thoughts? 2006-12-28 Jakub Jelinek <jakub@redhat.com> * unwind-dw2.c (SIGNAL_FRAME_BIT, EXTENDED_CONTEXT_BIT): Define. (struct _Unwind_Context): Rename args_size to flags, remove signal_frame field, add a new args_size field and version field. (_Unwind_IsSignalFrame, _Unwind_SetSignalFrame, _Unwind_IsExtendedContext): New inline functions. (_Unwind_GetGR, _Unwind_SetGR, _Unwind_GetGRPtr, _Unwind_SetGRPtr): Assume by_value array is only present if _Unwind_IsExtendedContext. (_Unwind_GetIPInfo, execute_cfa_program, uw_frame_state_for): Use _Unwind_IsSignalFrame. (__frame_state_for): Initialize context.flags to EXTENDED_CONTEXT_BIT. (uw_update_context_1): Use _Unwind_SetSignalFrame. (uw_init_context_1): Initialize context->flags to EXTENDED_CONTEXT_BIT. * config/rs6000/linux-unwind.h (frob_update_context): Use _Unwind_SetSignalFrame. --- gcc/unwind-dw2.c.jj 2006-12-08 15:57:44.000000000 +0100 +++ gcc/unwind-dw2.c 2006-12-27 17:16:12.000000000 +0100 @@ -70,8 +70,15 @@ struct _Unwind_Context void *ra; void *lsda; struct dwarf_eh_bases bases; + /* Signal frame context. */ +#define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1) + /* Context which has version/args_size/by_value fields. */ +#define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1) + _Unwind_Word flags; + /* 0 for now, can be increased when further fields are added to + struct _Unwind_Context. */ + _Unwind_Word version; _Unwind_Word args_size; - char signal_frame; char by_value[DWARF_FRAME_REGISTERS+1]; }; @@ -123,6 +130,27 @@ read_8u (const void *p) { const union un static inline unsigned long read_8s (const void *p) { const union unaligned *up = p; return up->s8; } \f +static inline _Unwind_Word +_Unwind_IsSignalFrame (struct _Unwind_Context *context) +{ + return (context->flags & SIGNAL_FRAME_BIT) ? 1 : 0; +} + +static inline void +_Unwind_SetSignalFrame (struct _Unwind_Context *context, int val) +{ + if (val) + context->flags |= SIGNAL_FRAME_BIT; + else + context->flags &= ~SIGNAL_FRAME_BIT; +} + +static inline _Unwind_Word +_Unwind_IsExtendedContext (struct _Unwind_Context *context) +{ + return context->flags & EXTENDED_CONTEXT_BIT; +} +\f /* Get the value of register INDEX as saved in CONTEXT. */ inline _Unwind_Word @@ -141,7 +169,7 @@ _Unwind_GetGR (struct _Unwind_Context *c size = dwarf_reg_size_table[index]; ptr = context->reg[index]; - if (context->by_value[index]) + if (_Unwind_IsExtendedContext (context) && context->by_value[index]) return (_Unwind_Word) (_Unwind_Internal_Ptr) ptr; /* This will segfault if the register hasn't been saved. */ @@ -180,7 +208,7 @@ _Unwind_SetGR (struct _Unwind_Context *c gcc_assert (index < (int) sizeof(dwarf_reg_size_table)); size = dwarf_reg_size_table[index]; - if (context->by_value[index]) + if (_Unwind_IsExtendedContext (context) && context->by_value[index]) { context->reg[index] = (void *) (_Unwind_Internal_Ptr) val; return; @@ -203,7 +231,7 @@ static inline void * _Unwind_GetGRPtr (struct _Unwind_Context *context, int index) { index = DWARF_REG_TO_UNWIND_COLUMN (index); - if (context->by_value[index]) + if (_Unwind_IsExtendedContext (context) && context->by_value[index]) return &context->reg[index]; return context->reg[index]; } @@ -214,7 +242,8 @@ static inline void _Unwind_SetGRPtr (struct _Unwind_Context *context, int index, void *p) { index = DWARF_REG_TO_UNWIND_COLUMN (index); - context->by_value[index] = 0; + if (_Unwind_IsExtendedContext (context)) + context->by_value[index] = 0; context->reg[index] = p; } @@ -256,7 +285,7 @@ _Unwind_GetIP (struct _Unwind_Context *c inline _Unwind_Ptr _Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn) { - *ip_before_insn = context->signal_frame != 0; + *ip_before_insn = _Unwind_IsSignalFrame (context); return (_Unwind_Ptr) context->ra; } @@ -824,7 +853,8 @@ execute_cfa_program (const unsigned char reflected at the point immediately before the call insn. In signal frames, return address is after last completed instruction, so we add 1 to return address to make the comparison <=. */ - while (insn_ptr < insn_end && fs->pc < context->ra + context->signal_frame) + while (insn_ptr < insn_end + && fs->pc < context->ra + _Unwind_IsSignalFrame (context)) { unsigned char insn = *insn_ptr++; _Unwind_Word reg, utmp; @@ -1063,7 +1093,7 @@ uw_frame_state_for (struct _Unwind_Conte if (context->ra == 0) return _URC_END_OF_STACK; - fde = _Unwind_Find_FDE (context->ra + context->signal_frame - 1, + fde = _Unwind_Find_FDE (context->ra + _Unwind_IsSignalFrame (context) - 1, &context->bases); if (fde == NULL) { @@ -1142,6 +1172,7 @@ __frame_state_for (void *pc_target, stru int reg; memset (&context, 0, sizeof (struct _Unwind_Context)); + context.flags = EXTENDED_CONTEXT_BIT; context.ra = pc_target + 1; if (uw_frame_state_for (&context, &fs) != _URC_NO_REASON) @@ -1306,7 +1337,7 @@ uw_update_context_1 (struct _Unwind_Cont break; } - context->signal_frame = fs->signal_frame; + _Unwind_SetSignalFrame (context, fs->signal_frame); #ifdef MD_FROB_UPDATE_CONTEXT MD_FROB_UPDATE_CONTEXT (context, fs); @@ -1366,6 +1397,7 @@ uw_init_context_1 (struct _Unwind_Contex memset (context, 0, sizeof (struct _Unwind_Context)); context->ra = ra; + context->flags = EXTENDED_CONTEXT_BIT; code = uw_frame_state_for (context, &fs); gcc_assert (code == _URC_NO_REASON); --- gcc/config/rs6000/linux-unwind.h.jj 2006-10-29 21:49:21.000000000 +0100 +++ gcc/config/rs6000/linux-unwind.h 2006-12-28 10:40:19.000000000 +0100 @@ -319,7 +319,7 @@ frob_update_context (struct _Unwind_Cont if (pc[0] == 0x38210000 + SIGNAL_FRAMESIZE && (pc[1] == 0x38000077 || pc[1] == 0x380000AC) && pc[2] == 0x44000002) - context->signal_frame = 1; + _Unwind_SetSignalFrame (context, 1); #else /* li r0, 0x7777; sc (sigreturn old) */ /* li r0, 0x0077; sc (sigreturn new) */ @@ -328,7 +328,7 @@ frob_update_context (struct _Unwind_Cont if ((pc[0] == 0x38007777 || pc[0] == 0x38000077 || pc[0] == 0x38006666 || pc[0] == 0x380000AC) && pc[1] == 0x44000002) - context->signal_frame = 1; + _Unwind_SetSignalFrame (context, 1); #endif #ifdef __powerpc64__ Jakub ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH]: for Score backend 2006-12-28 20:46 [PATCH] Fix _Unwind_Context backward compatibility issues Jakub Jelinek @ 2006-12-29 6:54 ` liqin 2007-01-04 1:30 ` liqin 2007-01-03 18:07 ` [PATCH] Fix _Unwind_Context backward compatibility issues Richard Henderson 1 sibling, 1 reply; 5+ messages in thread From: liqin @ 2006-12-29 6:54 UTC (permalink / raw) To: gcc-patches [-- Attachment #1: Type: text/plain, Size: 1325 bytes --] Hi, this patch did many changes for Score backend. Changelog: * config/score/predicates.md (const_uimm5, sr0_operand, const_simm12, const_simm15, const_pow2, const_npow2): Added. * config/score/misc.md (insv, extv, extzv, movmemsi, move_lbu_a/b, mov_lhu_a/b etc): Added and fix some bug. * config/score/score.c (score_address_cost, score_select_cc_mode): Added. Change CONST_OK_FOR_LETTER_P/EXTRA_CONSTRAINT define. Update score_rtx_costs for MACRO TARGET_RTX_COSTS. Update score_print_operand. * config/score/score.h (DATA_ALIGNMENT, SELECT_CC_MODE): Added. Adjust register allocate order and update some macro define. * config/score/score-mdaux.c (mdx_unaligned_load, mdx_unsigned_store, mdx_block_move_straight, mdx_block_move_loop_head, mdx_block_move_loop_body, mdx_block_move_loop_foot, mdx_block_move_loop mdx_block_move): Added. (mdx_movsicc, mdp_select_add_imm, mdp_select, mds_zero_extract_andi, mdp_limm): Updated and fix some bug and typo. * config/score/score.md (movqi/hi/si, add/sub/zero/ext): Updated. (movsf, movdf, doloop_end): Added. * config/score/t-score-elf (MULTILIB_OPTIONS): Change. Rgds Liqin [-- Attachment #2: score-20061229.patch --] [-- Type: application/octet-stream, Size: 99711 bytes --] Index: gcc/config/score/t-score-elf =================================================================== --- gcc/config/score/t-score-elf (revision 120252) +++ gcc/config/score/t-score-elf (working copy) @@ -35,7 +35,7 @@ dp-bit.c: $(srcdir)/config/fp-bit.c # without the $gp register. TARGET_LIBGCC2_CFLAGS = -G 0 -MULTILIB_OPTIONS = fPIC mel mscore7 +MULTILIB_OPTIONS = mmac mel fPIC MULTILIB_MATCHES = fPIC=fpic EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o @@ -43,4 +43,3 @@ EXTRA_MULTILIB_PARTS = crtbegin.o crtend LIBGCC = stmp-multilib INSTALL_LIBGCC = install-multilib - Index: gcc/config/score/crti.asm =================================================================== --- gcc/config/score/crti.asm (revision 120252) +++ gcc/config/score/crti.asm (working copy) @@ -43,8 +43,8 @@ .mask 0x00000000, 0 _start: la r28, _gp - la r8, __bss_start - la r9, __bss_end__ + la r8, _bss_start + la r9, _bss_end__ sub! r9, r8 srli! r9, 2 addi r9, -1 @@ -91,8 +91,8 @@ _fini: .mask 0x00000000,0 _start: la r28, _gp - la r8, __bss_start - la r9, __bss_end__ + la r8, _bss_start + la r9, _bss_end__ sub! r9, r8 srli! r9, 2 addi r9, -1 @@ -102,15 +102,10 @@ _start: sw r9, [r8]+, 4 bcnz 1b la r0, _stack -# jl _init -# la r4, _end -# jl _init_argv ldiu! r4, 0 ldiu! r5, 0 -# jl main la r29, main brl r29 -# jl exit la r29, exit brl r29 .end _start Index: gcc/config/score/predicates.md =================================================================== --- gcc/config/score/predicates.md (revision 120252) +++ gcc/config/score/predicates.md (working copy) @@ -35,13 +35,11 @@ (ior (match_operand 0 "const_call_insn_operand") (match_operand 0 "register_operand"))) -(define_predicate "const_bi_operand" - (and (match_code "const_int") - (match_test "CONST_OK_FOR_LETTER_P (INTVAL (op), 'J')"))) - -(define_predicate "pindex_off_operand" - (and (match_code "const_int") - (match_test "CONST_OK_FOR_LETTER_P (INTVAL (op), 'P')"))) +(define_predicate "const_uimm5" + (match_code "const_int") +{ + return IMM_IN_RANGE (INTVAL (op), 5, 0); +}) (define_predicate "hireg_operand" (and (match_code "reg") @@ -51,6 +49,10 @@ (and (match_code "reg") (match_test "REGNO (op) == LO_REGNUM"))) +(define_predicate "sr0_operand" + (and (match_code "reg") + (match_test "REGNO (op) == CN_REGNUM"))) + (define_predicate "g32reg_operand" (and (match_code "reg") (match_test "GP_REG_P (REGNO (op))"))) @@ -61,3 +63,26 @@ (define_predicate "branch_nz_operator" (match_code "eq,ne,lt,ge")) +(define_predicate "const_simm12" + (match_code "const_int") +{ + return IMM_IN_RANGE (INTVAL (op), 12, 1); +}) + +(define_predicate "const_simm15" + (match_code "const_int") +{ + return IMM_IN_RANGE (INTVAL (op), 15, 1); +}) + +(define_predicate "const_pow2" + (match_code "const_int") +{ + return IMM_IS_POW_OF_2 ((unsigned HOST_WIDE_INT) INTVAL (op), 0, 31); +}) + +(define_predicate "const_npow2" + (match_code "const_int") +{ + return IMM_IS_POW_OF_2 (~(unsigned HOST_WIDE_INT) INTVAL (op), 0, 31); +}) Index: gcc/config/score/score-version.h =================================================================== --- gcc/config/score/score-version.h (revision 120252) +++ gcc/config/score/score-version.h (working copy) @@ -18,4 +18,4 @@ the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#define SCORE_GCC_VERSION "1.1" +#define SCORE_GCC_VERSION "1.2" Index: gcc/config/score/crtn.asm =================================================================== --- gcc/config/score/crtn.asm (revision 120252) +++ gcc/config/score/crtn.asm (working copy) @@ -59,4 +59,3 @@ br r3 #endif - Index: gcc/config/score/score-protos.h =================================================================== --- gcc/config/score/score-protos.h (revision 120252) +++ gcc/config/score/score-protos.h (working copy) @@ -36,7 +36,7 @@ enum reg_class score_preferred_reload_cl enum reg_class score_secondary_reload_class (enum reg_class class, enum machine_mode mode, rtx x); -int score_const_ok_for_letter_p (int value, char c); +int score_const_ok_for_letter_p (HOST_WIDE_INT value, char c); int score_extra_constraint (rtx op, char c); Index: gcc/config/score/misc.md =================================================================== --- gcc/config/score/misc.md (revision 120252) +++ gcc/config/score/misc.md (working copy) @@ -84,8 +84,8 @@ [(set (match_operand:SI 0 "register_operand" "=d") (if_then_else:SI (match_operator 1 "comparison_operator" [(reg:CC CC_REGNUM) (const_int 0)]) - (match_operand:SI 2 "register_operand" "d") - (match_operand:SI 3 "register_operand" "0")))] + (match_operand:SI 2 "arith_operand" "d") + (match_operand:SI 3 "arith_operand" "0")))] "" "mv%C1 %0, %2" [(set_attr "type" "cndmv") @@ -95,7 +95,7 @@ [(set (reg:CC_NZ CC_REGNUM) (compare:CC_NZ (unspec:SI [(match_operand:SI 0 "register_operand" "*e,d") - (match_operand:SI 1 "const_bi_operand" "")] + (match_operand:SI 1 "const_uimm5" "")] BITTST) (const_int 0)))] "" @@ -106,3 +106,312 @@ (set_attr "up_c" "yes") (set_attr "mode" "SI")]) +(define_expand "extzv" + [(set (match_operand:SI 0 "register_operand" "") + (zero_extract (match_operand:SI 1 "memory_operand" "") + (match_operand:SI 2 "immediate_operand" "") + (match_operand:SI 3 "immediate_operand" "")))] + "!TARGET_SCORE5U && !TARGET_LITTLE_ENDIAN" +{ + if (mdx_unaligned_load (operands)) + DONE; + else + FAIL; +}) + +(define_expand "insv" + [(set (zero_extract (match_operand:SI 0 "memory_operand" "") + (match_operand:SI 1 "immediate_operand" "") + (match_operand:SI 2 "immediate_operand" "")) + (match_operand:SI 3 "register_operand" ""))] + "!TARGET_SCORE5U && !TARGET_LITTLE_ENDIAN" +{ + if (mdx_unaligned_store (operands)) + DONE; + else + FAIL; +}) + +(define_expand "extv" + [(set (match_operand:SI 0 "register_operand" "") + (sign_extract (match_operand:SI 1 "memory_operand" "") + (match_operand:SI 2 "immediate_operand" "") + (match_operand:SI 3 "immediate_operand" "")))] + "!TARGET_SCORE5U && !TARGET_LITTLE_ENDIAN" +{ + if (mdx_unaligned_load (operands)) + DONE; + else + FAIL; +}) + +(define_expand "movmemsi" + [(parallel [(set (match_operand:BLK 0 "general_operand") + (match_operand:BLK 1 "general_operand")) + (use (match_operand:SI 2 "")) + (use (match_operand:SI 3 "const_int_operand"))])] + "!TARGET_SCORE5U" +{ + if (mdx_block_move (operands)) + DONE; + else + FAIL; +}) + +(define_insn "move_lbu_a" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "const_simm12" ""))) + (set (match_operand:QI 3 "register_operand" "=d") + (mem:QI (match_dup 1)))] + "!TARGET_SCORE5U" + "lbu %3, [%1]+, %2" + [(set_attr "type" "load") + (set_attr "mode" "QI")]) + +(define_insn "move_lhu_a" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "const_simm12" ""))) + (set (match_operand:HI 3 "register_operand" "=d") + (mem:HI (match_dup 1)))] + "!TARGET_SCORE5U" + "lhu %3, [%1]+, %2" + [(set_attr "type" "load") + (set_attr "mode" "HI")]) + +(define_insn "move_lw_a" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "const_simm12" ""))) + (set (match_operand:SI 3 "register_operand" "=d") + (mem:SI (match_dup 1)))] + "!TARGET_SCORE5U" + "lw %3, [%1]+, %2" + [(set_attr "type" "load") + (set_attr "mode" "SI")]) + +(define_insn "move_sb_a" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "const_simm12" ""))) + (set (mem:QI (match_dup 1)) + (match_operand:QI 3 "register_operand" "d"))] + "!TARGET_SCORE5U" + "sb %3, [%1]+, %2" + [(set_attr "type" "store") + (set_attr "mode" "QI")]) + +(define_insn "move_sh_a" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "const_simm12" ""))) + (set (mem:HI (match_dup 1)) + (match_operand:HI 3 "register_operand" "d"))] + "!TARGET_SCORE5U" + "sh %3, [%1]+, %2" + [(set_attr "type" "store") + (set_attr "mode" "HI")]) + +(define_insn "move_sw_a" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "const_simm12" ""))) + (set (mem:SI (match_dup 1)) + (match_operand:SI 3 "register_operand" "d"))] + "!TARGET_SCORE5U" + "sw %3, [%1]+, %2" + [(set_attr "type" "store") + (set_attr "mode" "SI")]) + +(define_insn "move_lbu_b" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "const_simm12" ""))) + (set (match_operand:QI 3 "register_operand" "=d") + (mem:QI (plus:SI (match_dup 1) + (match_dup 2))))] + "!TARGET_SCORE5U" + "lbu %3, [%1, %2]+" + [(set_attr "type" "load") + (set_attr "mode" "QI")]) + +(define_insn "move_lhu_b" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "const_simm12" ""))) + (set (match_operand:HI 3 "register_operand" "=d") + (mem:HI (plus:SI (match_dup 1) + (match_dup 2))))] + "!TARGET_SCORE5U" + "lhu %3, [%1, %2]+" + [(set_attr "type" "load") + (set_attr "mode" "HI")]) + +(define_insn "move_lw_b" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "const_simm12" ""))) + (set (match_operand:SI 3 "register_operand" "=d") + (mem:SI (plus:SI (match_dup 1) + (match_dup 2))))] + "!TARGET_SCORE5U" + "lw %3, [%1, %2]+" + [(set_attr "type" "load") + (set_attr "mode" "SI")]) + +(define_insn "move_sb_b" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "const_simm12" ""))) + (set (mem:QI (plus:SI (match_dup 1) + (match_dup 2))) + (match_operand:QI 3 "register_operand" "d"))] + "!TARGET_SCORE5U" + "sb %3, [%1, %2]+" + [(set_attr "type" "store") + (set_attr "mode" "QI")]) + +(define_insn "move_sh_b" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "const_simm12" ""))) + (set (mem:HI (plus:SI (match_dup 1) + (match_dup 2))) + (match_operand:HI 3 "register_operand" "d"))] + "!TARGET_SCORE5U" + "sh %3, [%1, %2]+" + [(set_attr "type" "store") + (set_attr "mode" "HI")]) + +(define_insn "move_sw_b" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "const_simm12" ""))) + (set (mem:SI (plus:SI (match_dup 1) + (match_dup 2))) + (match_operand:SI 3 "register_operand" "d"))] + "!TARGET_SCORE5U" + "sw %3, [%1, %2]+" + [(set_attr "type" "store") + (set_attr "mode" "SI")]) + +(define_insn "move_lcb" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (const_int 4))) + (set (reg:SI LC_REGNUM) + (unspec:SI [(mem:BLK (match_dup 1))] LCB))] + "!TARGET_SCORE5U && !TARGET_LITTLE_ENDIAN" + "lcb [%1]+" + [(set_attr "type" "load") + (set_attr "mode" "SI")]) + +(define_insn "move_lcw" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (const_int 4))) + (set (match_operand:SI 2 "register_operand" "=d") + (unspec:SI [(mem:BLK (match_dup 1)) + (reg:SI LC_REGNUM)] LCW)) + (set (reg:SI LC_REGNUM) + (unspec:SI [(mem:BLK (match_dup 1))] LCB))] + "!TARGET_SCORE5U && !TARGET_LITTLE_ENDIAN" + "lcw %2, [%1]+" + [(set_attr "type" "load") + (set_attr "mode" "SI")]) + +(define_insn "move_lce" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (const_int 4))) + (set (match_operand:SI 2 "register_operand" "=d") + (unspec:SI [(mem:BLK (match_dup 1)) + (reg:SI LC_REGNUM)] LCE))] + "!TARGET_SCORE5U && !TARGET_LITTLE_ENDIAN" + "lce %2, [%1]+" + [(set_attr "type" "load") + (set_attr "mode" "SI")]) + +(define_insn "move_scb" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (const_int 4))) + (set (mem:BLK (match_dup 1)) + (unspec:BLK [(match_operand:SI 2 "register_operand" "d")] SCB)) + (set (reg:SI SC_REGNUM) + (unspec:SI [(match_dup 2)] SCLC))] + "!TARGET_SCORE5U && !TARGET_LITTLE_ENDIAN" + "scb %2, [%1]+" + [(set_attr "type" "store") + (set_attr "mode" "SI")]) + +(define_insn "move_scw" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (const_int 4))) + (set (mem:BLK (match_dup 1)) + (unspec:BLK [(match_operand:SI 2 "register_operand" "d") + (reg:SI SC_REGNUM)] SCW)) + (set (reg:SI SC_REGNUM) + (unspec:SI [(match_dup 2)] SCLC))] + "!TARGET_SCORE5U && !TARGET_LITTLE_ENDIAN" + "scw %2, [%1]+" + [(set_attr "type" "store") + (set_attr "mode" "SI")]) + +(define_insn "move_sce" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (const_int 4))) + (set (mem:BLK (match_dup 1)) + (unspec:BLK [(reg:SI SC_REGNUM)] SCE))] + "!TARGET_SCORE5U && !TARGET_LITTLE_ENDIAN" + "sce [%1]+" + [(set_attr "type" "store") + (set_attr "mode" "SI")]) + +(define_insn "andsi3_extzh" + [(set (match_operand:SI 0 "register_operand" "=d") + (and:SI (match_operand:SI 1 "register_operand" "d") + (const_int 65535)))] + "" + "extzh %0, %1" + [(set_attr "type" "arith") + (set_attr "mode" "SI")]) + +(define_insn "bitclr_c" + [(set (match_operand:SI 0 "register_operand" "=e,d") + (and:SI (match_operand:SI 1 "register_operand" "0,d") + (match_operand:SI 2 "const_npow2"))) + (clobber (reg:CC CC_REGNUM))] + "" + "@ + bitclr! %0, %F2 + bitclr.c %0, %1, %F2" + [(set_attr "type" "arith") + (set_attr "mode" "SI")]) + +(define_insn "bitset_c" + [(set (match_operand:SI 0 "register_operand" "=e,d") + (ior:SI (match_operand:SI 1 "register_operand" "0,d") + (match_operand:SI 2 "const_pow2"))) + (clobber (reg:CC CC_REGNUM))] + "" + "@ + bitset! %0, %E2 + bitset.c %0, %1, %E2" + [(set_attr "type" "arith") + (set_attr "mode" "SI")]) + +(define_insn "bittgl_c" + [(set (match_operand:SI 0 "register_operand" "=e,d") + (xor:SI (match_operand:SI 1 "register_operand" "0,d") + (match_operand:SI 2 "const_pow2"))) + (clobber (reg:CC CC_REGNUM))] + "" + "@ + bittgl! %0, %E2 + bittgl.c %0, %1, %E2" + [(set_attr "type" "arith") + (set_attr "mode" "SI")]) Index: gcc/config/score/score.c =================================================================== --- gcc/config/score/score.c (revision 120252) +++ gcc/config/score/score.c (working copy) @@ -67,7 +67,9 @@ static int score_symbol_insns (enum scor static int score_address_insns (rtx, enum machine_mode); -static bool score_rtx_costs (rtx, int, int, int *); +static bool score_rtx_costs (rtx, enum rtx_code, enum rtx_code, int *); + +static int score_address_cost (rtx); #undef TARGET_ASM_FILE_START #define TARGET_ASM_FILE_START th_asm_file_start @@ -126,6 +128,9 @@ static bool score_rtx_costs (rtx, int, i #undef TARGET_RTX_COSTS #define TARGET_RTX_COSTS score_rtx_costs +#undef TARGET_ADDRESS_COST +#define TARGET_ADDRESS_COST score_address_cost + #undef TARGET_DEFAULT_TARGET_FLAGS #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT @@ -154,7 +159,7 @@ score_pass_by_reference (CUMULATIVE_ARGS static rtx score_add_offset (rtx temp, rtx reg, HOST_WIDE_INT offset) { - if (!CONST_OK_FOR_LETTER_P (offset, 'O')) + if (!IMM_IN_RANGE (offset, 15, 1)) { reg = expand_simple_binop (GET_MODE (reg), PLUS, gen_int_mode (offset & 0xffffc000, @@ -499,12 +504,13 @@ enum reg_class score_char_to_class[256]; void score_override_options (void) { + flag_pic = false; if (!flag_pic) sdata_max = g_switch_set ? g_switch_value : DEFAULT_SDATA_MAX; else { sdata_max = 0; - if (g_switch_set) + if (g_switch_set && (g_switch_value != 0)) warning (0, "-fPIC and -G are incompatible"); } @@ -540,7 +546,7 @@ score_reg_class (int regno) || regno == ARG_POINTER_REGNUM) return ALL_REGS; - for (c = 0 ; c < N_REG_CLASSES ; c++) + for (c = 0; c < N_REG_CLASSES; c++) if (TEST_HARD_REG_BIT (reg_class_contents[c], regno)) return c; @@ -551,10 +557,10 @@ score_reg_class (int regno) enum reg_class score_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, enum reg_class class) { - if (reg_class_subset_p (G32_REGS, class)) - class = G32_REGS; if (reg_class_subset_p (G16_REGS, class)) - class = G16_REGS; + return G16_REGS; + if (reg_class_subset_p (G32_REGS, class)) + return G32_REGS; return class; } @@ -576,41 +582,34 @@ score_secondary_reload_class (enum reg_c /* Implement CONST_OK_FOR_LETTER_P macro. */ /* imm constraints - I IMM8 (i15-2-form) - J IMM5 (i15_1-form) - K IMM16 (i-form) - L IMM16s (i-form) - M IMM14 (ri-form) - N IMM14s (ri-form) - O IMM15s (ri-form) - P IMM12s (rix-form) / IMM10s(cop-form) << 2 */ + I imm16 << 16 + J uimm5 + K uimm16 + L simm16 + M uimm14 + N simm14 */ int -score_const_ok_for_letter_p (int value, char c) +score_const_ok_for_letter_p (HOST_WIDE_INT value, char c) { switch (c) { - case 'I': return IMM_IN_RANGE (value, 8, 0); + case 'I': return ((value & 0xffff) == 0); case 'J': return IMM_IN_RANGE (value, 5, 0); case 'K': return IMM_IN_RANGE (value, 16, 0); case 'L': return IMM_IN_RANGE (value, 16, 1); case 'M': return IMM_IN_RANGE (value, 14, 0); case 'N': return IMM_IN_RANGE (value, 14, 1); - case 'O': return IMM_IN_RANGE (value, 15, 1); - case 'P': return IMM_IN_RANGE (value, 12, 1); default : return 0; } } /* Implement EXTRA_CONSTRAINT macro. */ -/* Q const_hi imm - Z symbol_ref */ +/* Z symbol_ref */ int score_extra_constraint (rtx op, char c) { switch (c) { - case 'Q': - return (GET_CODE (op) == CONST_INT && (INTVAL (op) & 0xffff) == 0); case 'Z': return GET_CODE (op) == SYMBOL_REF; default: @@ -917,10 +916,8 @@ score_address_insns (rtx x, enum machine int factor; if (mode == BLKmode) - /* BLKmode is used for single unaligned loads and stores. */ factor = 1; else - /* Each word of a multi-word value will be accessed individually. */ factor = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; if (mda_classify_address (&addr, mode, x, false)) @@ -938,24 +935,53 @@ score_address_insns (rtx x, enum machine /* Implement TARGET_RTX_COSTS macro. */ static bool -score_rtx_costs (rtx x, int code, int outer_code, int *total) +score_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code, + int *total) { enum machine_mode mode = GET_MODE (x); switch (code) { case CONST_INT: - /* These can be used anywhere. */ - *total = 0; + if (outer_code == SET) + { + if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I') + || CONST_OK_FOR_LETTER_P (INTVAL (x), 'L')) + *total = COSTS_N_INSNS (1); + else + *total = COSTS_N_INSNS (2); + } + else if (outer_code == PLUS || outer_code == MINUS) + { + if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'N')) + *total = 0; + else if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I') + || CONST_OK_FOR_LETTER_P (INTVAL (x), 'L')) + *total = 1; + else + *total = COSTS_N_INSNS (2); + } + else if (outer_code == AND || outer_code == IOR) + { + if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'M')) + *total = 0; + else if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I') + || CONST_OK_FOR_LETTER_P (INTVAL (x), 'K')) + *total = 1; + else + *total = COSTS_N_INSNS (2); + } + else + { + *total = 0; + } return true; - /* Otherwise fall through to the handling below because - we'll need to construct the constant. */ case CONST: case SYMBOL_REF: case LABEL_REF: case CONST_DOUBLE: - *total = COSTS_N_INSNS (1); + *total = COSTS_N_INSNS (2); return true; case MEM: @@ -1011,7 +1037,8 @@ score_rtx_costs (rtx x, int code, int ou *total = COSTS_N_INSNS (4); return true; } - return false; + *total = COSTS_N_INSNS (1); + return true; case NEG: if (mode == DImode) @@ -1022,22 +1049,38 @@ score_rtx_costs (rtx x, int code, int ou return false; case MULT: - *total = COSTS_N_INSNS (12); + *total = optimize_size ? COSTS_N_INSNS (2) : COSTS_N_INSNS (12); return true; case DIV: case MOD: case UDIV: case UMOD: - *total = COSTS_N_INSNS (33); + *total = optimize_size ? COSTS_N_INSNS (2) : COSTS_N_INSNS (33); return true; case SIGN_EXTEND: - *total = COSTS_N_INSNS (2); - return true; - case ZERO_EXTEND: - *total = COSTS_N_INSNS (1); + switch (GET_MODE (XEXP (x, 0))) + { + case QImode: + case HImode: + if (GET_CODE (XEXP (x, 0)) == MEM) + { + *total = COSTS_N_INSNS (2); + + if (!TARGET_LITTLE_ENDIAN && + side_effects_p (XEXP (XEXP (x, 0), 0))) + *total = 100; + } + else + *total = COSTS_N_INSNS (1); + break; + + default: + *total = COSTS_N_INSNS (1); + break; + } return true; default: @@ -1045,6 +1088,13 @@ score_rtx_costs (rtx x, int code, int ou } } +/* Implement TARGET_ADDRESS_COST macro. */ +int +score_address_cost (rtx addr) +{ + return score_address_insns (addr, SImode); +} + /* Implement ASM_OUTPUT_EXTERNAL macro. */ int score_output_external (FILE *file ATTRIBUTE_UNUSED, @@ -1089,18 +1139,16 @@ score_return_addr (int count, rtx frame /* Implement PRINT_OPERAND macro. */ /* Score-specific operand codes: '[' print .set nor1 directive - ']' print .set r1 directive - + ']' print .set r1 directive 'U' print hi part of a CONST_INT rtx - 'D' print first part of const double - 'S' selectively print '!' if operand is 15bit instruction accessible - 'V' print "v!" if operand is 15bit instruction accessible, or - "lfh!" - + 'E' print log2(v) + 'F' print log2(~v) + 'D' print SFmode const double + 'S' selectively print "!" if operand is 15bit instruction accessible + 'V' print "v!" if operand is 15bit instruction accessible, or "lfh!" 'L' low part of DImode reg operand 'H' high part of DImode reg operand - - 'C' print part of opcode for a branch condition. */ + 'C' print part of opcode for a branch condition. */ void score_print_operand (FILE *file, rtx op, int c) { @@ -1125,9 +1173,11 @@ score_print_operand (FILE *file, rtx op, else if (c == 'D') { if (GET_CODE (op) == CONST_DOUBLE) - fprintf (file, HOST_WIDE_INT_PRINT_HEX, - TARGET_LITTLE_ENDIAN - ? CONST_DOUBLE_LOW (op) : CONST_DOUBLE_HIGH (op)); + { + rtx temp = gen_lowpart (SImode, op); + gcc_assert (GET_MODE (op) == SFmode); + fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (temp)); + } else output_addr_const (file, op); } @@ -1142,23 +1192,17 @@ score_print_operand (FILE *file, rtx op, gcc_assert (code == REG); fprintf (file, G16_REG_P (REGNO (op)) ? "v!" : "lfh!"); } - else if (code == REG) - { - int regnum = REGNO (op); - if ((c == 'H' && !WORDS_BIG_ENDIAN) - || (c == 'L' && WORDS_BIG_ENDIAN)) - regnum ++; - fprintf (file, "%s", reg_names[regnum]); - } else if (c == 'C') { + enum machine_mode mode = GET_MODE (XEXP (op, 0)); + switch (code) { case EQ: fputs ("eq", file); break; case NE: fputs ("ne", file); break; case GT: fputs ("gt", file); break; - case GE: fputs ("ge", file); break; - case LT: fputs ("lt", file); break; + case GE: fputs (mode != CCmode ? "pl" : "ge", file); break; + case LT: fputs (mode != CCmode ? "mi" : "lt", file); break; case LE: fputs ("le", file); break; case GTU: fputs ("gtu", file); break; case GEU: fputs ("cs", file); break; @@ -1168,6 +1212,46 @@ score_print_operand (FILE *file, rtx op, output_operand_lossage ("invalid operand for code: '%c'", code); } } + else if (c == 'E') + { + unsigned HOST_WIDE_INT i; + unsigned HOST_WIDE_INT pow2mask = 1; + unsigned HOST_WIDE_INT val; + + val = INTVAL (op); + for (i = 0; i < 32; i++) + { + if (val == pow2mask) + break; + pow2mask <<= 1; + } + gcc_assert (i < 32); + fprintf (file, HOST_WIDE_INT_PRINT_HEX, i); + } + else if (c == 'F') + { + unsigned HOST_WIDE_INT i; + unsigned HOST_WIDE_INT pow2mask = 1; + unsigned HOST_WIDE_INT val; + + val = ~INTVAL (op); + for (i = 0; i < 32; i++) + { + if (val == pow2mask) + break; + pow2mask <<= 1; + } + gcc_assert (i < 32); + fprintf (file, HOST_WIDE_INT_PRINT_HEX, i); + } + else if (code == REG) + { + int regnum = REGNO (op); + if ((c == 'H' && !WORDS_BIG_ENDIAN) + || (c == 'L' && WORDS_BIG_ENDIAN)) + regnum ++; + fprintf (file, "%s", reg_names[regnum]); + } else { switch (code) @@ -1233,4 +1317,48 @@ score_print_operand_address (FILE *file, gcc_unreachable (); } +/* Implement SELECT_CC_MODE macro. */ +enum machine_mode +score_select_cc_mode (enum rtx_code op, rtx x, rtx y) +{ + if ((op == EQ || op == NE || op == LT || op == GE) + && y == const0_rtx + && GET_MODE (x) == SImode) + { + switch (GET_CODE (x)) + { + case PLUS: + case MINUS: + case NEG: + case AND: + case IOR: + case XOR: + case NOT: + case ASHIFT: + case LSHIFTRT: + case ASHIFTRT: + return CC_NZmode; + + case SIGN_EXTEND: + case ZERO_EXTEND: + case ROTATE: + case ROTATERT: + return (op == LT || op == GE) ? CC_Nmode : CCmode; + + default: + return CCmode; + } + } + + if ((op == EQ || op == NE) + && (GET_CODE (y) == NEG) + && register_operand (XEXP (y, 0), SImode) + && register_operand (x, SImode)) + { + return CC_NZmode; + } + + return CCmode; +} + struct gcc_target targetm = TARGET_INITIALIZER; Index: gcc/config/score/score.h =================================================================== --- gcc/config/score/score.h (revision 120252) +++ gcc/config/score/score.h (working copy) @@ -28,19 +28,20 @@ extern GTY(()) rtx cmp_op0; extern GTY(()) rtx cmp_op1; /* Controlling the Compilation Driver. */ +#undef SWITCH_TAKES_ARG #define SWITCH_TAKES_ARG(CHAR) \ (DEFAULT_SWITCH_TAKES_ARG (CHAR) || (CHAR) == 'G') /* CC1_SPEC is the set of arguments to pass to the compiler proper. */ #undef CC1_SPEC -#define CC1_SPEC "%{!mel:-meb}" +#define CC1_SPEC "%{G*} %{!mel:-meb}" #undef ASM_SPEC #define ASM_SPEC \ "%{!mel:-EB} %{mel:-EL} %{mscore5u:-SCORE5U} %{mscore7:-SCORE7} %{G*}" #undef LINK_SPEC -#define LINK_SPEC "%{!mel:-EB} %{mel:-EL} %{G*}" +#define LINK_SPEC "%{!mel:-EB} %{mel:-EL} %{G*}" /* Run-time Target Specification. */ #define TARGET_CPU_CPP_BUILTINS() \ @@ -96,7 +97,7 @@ extern GTY(()) rtx cmp_op1; /* Allocation boundary (in *bits*) for storing arguments in argument list. */ #define PARM_BOUNDARY BITS_PER_WORD -#define STACK_BOUNDARY 64 +#define STACK_BOUNDARY BITS_PER_WORD /* Allocation boundary (in *bits*) for the code of a function. */ #define FUNCTION_BOUNDARY BITS_PER_WORD @@ -115,12 +116,41 @@ extern GTY(()) rtx cmp_op1; data to make it all fit in fewer cache lines. Another is to cause character arrays to be word-aligned so that `strcpy' calls that copy constants to character arrays can be done inline. */ -#define DATA_ALIGNMENT(TYPE, ALIGN) \ - ((((ALIGN) < BITS_PER_WORD) \ - && (TREE_CODE (TYPE) == ARRAY_TYPE \ - || TREE_CODE (TYPE) == UNION_TYPE \ +#define DATA_ALIGNMENT(TYPE, ALIGN) \ + ((((ALIGN) < BITS_PER_WORD) \ + && (TREE_CODE (TYPE) == ARRAY_TYPE \ + || TREE_CODE (TYPE) == UNION_TYPE \ || TREE_CODE (TYPE) == RECORD_TYPE)) ? BITS_PER_WORD : (ALIGN)) +/* If defined, a C expression to compute the alignment given to a + constant that is being placed in memory. EXP is the constant + and ALIGN is the alignment that the object would ordinarily have. + The value of this macro is used instead of that alignment to align + the object. + + If this macro is not defined, then ALIGN is used. + + The typical use of this macro is to increase alignment for string + constants to be word aligned so that `strcpy' calls that copy + constants can be done inline. */ +#define CONSTANT_ALIGNMENT(EXP, ALIGN) \ + ((TREE_CODE (EXP) == STRING_CST || TREE_CODE (EXP) == CONSTRUCTOR) \ + && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) + +/* If defined, a C expression to compute the alignment for a local + variable. TYPE is the data type, and ALIGN is the alignment that + the object would ordinarily have. The value of this macro is used + instead of that alignment to align the object. + + If this macro is not defined, then ALIGN is used. + + One use of this macro is to increase alignment of medium-size + data to make it all fit in fewer cache lines. */ +#define LOCAL_ALIGNMENT(TYPE, ALIGN) \ + ((TREE_CODE (TYPE) == ARRAY_TYPE \ + && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \ + && (ALIGN) < BITS_PER_WORD) ? BITS_PER_WORD : (ALIGN)) + /* Alignment of field after `int : 0' in a structure. */ #define EMPTY_FIELD_BOUNDARY 32 @@ -209,7 +239,7 @@ extern GTY(()) rtx cmp_op1; { \ /* General Purpose Registers */ \ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, \ /* Control Registers */ \ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ /* CEH/ CEL/ CNT/ LCR/ SCR / ARG_POINTER_REGNUM/ FRAME_POINTER_REGNUM */\ @@ -245,8 +275,8 @@ extern GTY(()) rtx cmp_op1; } #define REG_ALLOC_ORDER \ -{ 0, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, \ - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 2, 3, \ +{ 0, 1, 6, 7, 8, 9, 10, 11, 4, 5, 22, 23, 24, 25, 26, 27, \ + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 28, 29, 30, 31, 2, 3, \ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, \ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, \ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, \ @@ -386,18 +416,18 @@ enum reg_class score_preferred_reload_class (X, CLASS) /* If we need to load shorts byte-at-a-time, then we need a scratch. */ -#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \ +#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \ score_secondary_reload_class (CLASS, MODE, X) /* Return the register class of a scratch register needed to copy IN into or out of a register in CLASS in MODE. If it can be done directly, NO_REGS is returned. */ -#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \ +#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \ score_secondary_reload_class (CLASS, MODE, X) /* Return the maximum number of consecutive registers needed to represent mode MODE in a register of class CLASS. */ -#define CLASS_MAX_NREGS(CLASS, MODE) \ +#define CLASS_MAX_NREGS(CLASS, MODE) \ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) #define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \ @@ -607,8 +637,8 @@ typedef struct score_args #define HAVE_PRE_DECREMENT 1 #define HAVE_POST_INCREMENT 1 #define HAVE_POST_DECREMENT 1 -#define HAVE_PRE_MODIFY_DISP 0 -#define HAVE_POST_MODIFY_DISP 0 +#define HAVE_PRE_MODIFY_DISP 1 +#define HAVE_POST_MODIFY_DISP 1 #define HAVE_PRE_MODIFY_REG 0 #define HAVE_POST_MODIFY_REG 0 @@ -660,6 +690,13 @@ typedef struct score_args #define LEGITIMATE_CONSTANT_P(X) 1 +/* Condition Code Status. */ +#define SELECT_CC_MODE(OP, X, Y) score_select_cc_mode (OP, X, Y) + +/* Return nonzero if SELECT_CC_MODE will never return MODE for a + floating point inequality comparison. */ +#define REVERSIBLE_CC_MODE(MODE) 1 + /* Describing Relative Costs of Operations */ /* Compute extra cost of moving data between one register class and another. */ #define REGISTER_MOVE_COST(MODE, FROM, TO) \ @@ -753,32 +790,32 @@ typedef struct score_args sprintf ((LABEL), "*%s%s%ld", (LOCAL_LABEL_PREFIX), (PREFIX), (long) (NUM)) /* Output of Assembler Instructions. */ -#define REGISTER_NAMES \ -{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \ - "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \ - "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", \ - \ - "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ - "cr8", "cr9", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15", \ - \ - "ceh", "cel", "sr0", "sr1", "sr2", "_arg", "_frame", "", \ - "cr24", "cr25", "cr26", "cr27", "cr28", "cr29", "cr30", "cr31", \ - \ - "c1r0", "c1r1", "c1r2", "c1r3", "c1r4", "c1r5", "c1r6", "c1r7", \ - "c1r8", "c1r9", "c1r10", "c1r11", "c1r12", "c1r13", "c1r14", "c1r15", \ - "c1r16", "c1r17", "c1r18", "c1r19", "c1r20", "c1r21", "c1r22", "c1r23",\ - "c1r24", "c1r25", "c1r26", "c1r27", "c1r28", "c1r29", "c1r30", "c1r31",\ - \ - "c2r0", "c2r1", "c2r2", "c2r3", "c2r4", "c2r5", "c2r6", "c2r7", \ - "c2r8", "c2r9", "c2r10", "c2r11", "c2r12", "c2r13", "c2r14", "c2r15", \ - "c2r16", "c2r17", "c2r18", "c2r19", "c2r20", "c2r21", "c2r22", "c2r23",\ - "c2r24", "c2r25", "c2r26", "c2r27", "c2r28", "c2r29", "c2r30", "c2r31",\ - \ - "c3r0", "c3r1", "c3r2", "c3r3", "c3r4", "c3r5", "c3r6", "c3r7", \ - "c3r8", "c3r9", "c3r10", "c3r11", "c3r12", "c3r13", "c3r14", "c3r15", \ - "c3r16", "c3r17", "c3r18", "c3r19", "c3r20", "c3r21", "c3r22", "c3r23",\ - "c3r24", "c3r25", "c3r26", "c3r27", "c3r28", "c3r29", "c3r30", "c3r31",\ +#define REGISTER_NAMES \ +{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \ + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \ + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", \ + \ + "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ + "cr8", "cr9", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15", \ + \ + "ceh", "cel", "sr0", "sr1", "sr2", "_arg", "_frame", "", \ + "cr24", "cr25", "cr26", "cr27", "cr28", "cr29", "cr30", "cr31", \ + \ + "c1r0", "c1r1", "c1r2", "c1r3", "c1r4", "c1r5", "c1r6", "c1r7", \ + "c1r8", "c1r9", "c1r10", "c1r11", "c1r12", "c1r13", "c1r14", "c1r15", \ + "c1r16", "c1r17", "c1r18", "c1r19", "c1r20", "c1r21", "c1r22", "c1r23", \ + "c1r24", "c1r25", "c1r26", "c1r27", "c1r28", "c1r29", "c1r30", "c1r31", \ + \ + "c2r0", "c2r1", "c2r2", "c2r3", "c2r4", "c2r5", "c2r6", "c2r7", \ + "c2r8", "c2r9", "c2r10", "c2r11", "c2r12", "c2r13", "c2r14", "c2r15", \ + "c2r16", "c2r17", "c2r18", "c2r19", "c2r20", "c2r21", "c2r22", "c2r23", \ + "c2r24", "c2r25", "c2r26", "c2r27", "c2r28", "c2r29", "c2r30", "c2r31", \ + \ + "c3r0", "c3r1", "c3r2", "c3r3", "c3r4", "c3r5", "c3r6", "c3r7", \ + "c3r8", "c3r9", "c3r10", "c3r11", "c3r12", "c3r13", "c3r14", "c3r15", \ + "c3r16", "c3r17", "c3r18", "c3r19", "c3r20", "c3r21", "c3r22", "c3r23", \ + "c3r24", "c3r25", "c3r26", "c3r27", "c3r28", "c3r29", "c3r30", "c3r31", \ } /* Print operand X (an rtx) in assembler syntax to file FILE. */ @@ -907,4 +944,4 @@ struct extern_list GTY ((chain_next ("%h int size; /* size in bytes */ }; -extern GTY (()) struct extern_list *extern_head ; +extern GTY (()) struct extern_list *extern_head; Index: gcc/config/score/score-conv.h =================================================================== --- gcc/config/score/score-conv.h (revision 120252) +++ gcc/config/score/score-conv.h (working copy) @@ -45,7 +45,7 @@ extern int target_flags; #define CE_REG_P(REGNO) REG_CONTAIN (REGNO, CE_REG_FIRST, CE_REG_NUM) -#define UIMM_IN_RANGE(V, W) ((V) >= 0 && (V) < ((HOST_WIDE_INT)1 << (W))) +#define UIMM_IN_RANGE(V, W) ((V) >= 0 && (V) < ((HOST_WIDE_INT) 1 << (W))) #define SIMM_IN_RANGE(V, W) \ ((V) >= (-1 * ((HOST_WIDE_INT) 1 << ((W) - 1))) \ @@ -54,6 +54,11 @@ extern int target_flags; #define IMM_IN_RANGE(V, W, S) \ ((S) ? SIMM_IN_RANGE (V, W) : UIMM_IN_RANGE (V, W)) +#define IMM_IS_POW_OF_2(V, E1, E2) \ + ((V) >= ((unsigned HOST_WIDE_INT) 1 << (E1)) \ + && (V) <= ((unsigned HOST_WIDE_INT) 1 << (E2)) \ + && ((V) & ((V) - 1)) == 0) + #define SCORE_STACK_ALIGN(LOC) (((LOC) + 3) & ~3) #define SCORE_MAX_FIRST_STACK_STEP (0x3ff0) Index: gcc/config/score/score-mdaux.c =================================================================== --- gcc/config/score/score-mdaux.c (revision 120252) +++ gcc/config/score/score-mdaux.c (working copy) @@ -108,10 +108,9 @@ score_symbol_type score_classify_symbol if (GET_CODE (x) == LABEL_REF) return SYMBOL_GENERAL; - if (GET_CODE (x) != SYMBOL_REF) - gcc_unreachable (); + gcc_assert (GET_CODE (x) == SYMBOL_REF); - if (CONSTANT_POOL_ADDRESS_P(x)) + if (CONSTANT_POOL_ADDRESS_P (x)) { if (GET_MODE_SIZE (get_pool_mode (x)) <= SCORE_SDATA_MAX) return SYMBOL_SMALL_DATA; @@ -185,14 +184,14 @@ mda_compute_frame_size (HOST_WIDE_INT si f->mask = 0; f->var_size = SCORE_STACK_ALIGN (size); f->args_size = current_function_outgoing_args_size; - f->cprestore_size = SCORE_STACK_ALIGN (STARTING_FRAME_OFFSET) - f->args_size; + f->cprestore_size = flag_pic ? UNITS_PER_WORD : 0; if (f->var_size == 0 && current_function_is_leaf) f->args_size = f->cprestore_size = 0; if (f->args_size == 0 && current_function_calls_alloca) f->args_size = UNITS_PER_WORD; - f->total_size = f->var_size + f->args_size; + f->total_size = f->var_size + f->args_size + f->cprestore_size; for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) { if (score_save_reg_p (regno)) @@ -205,7 +204,7 @@ mda_compute_frame_size (HOST_WIDE_INT si if (current_function_calls_eh_return) { unsigned int i; - for (i = 0; ; ++i) + for (i = 0;; ++i) { regno = EH_RETURN_DATA_REGNO (i); if (regno == INVALID_REGNUM) @@ -215,7 +214,7 @@ mda_compute_frame_size (HOST_WIDE_INT si } } - f->total_size += SCORE_STACK_ALIGN (f->gp_reg_size); + f->total_size += f->gp_reg_size; f->num_gp = f->gp_reg_size / UNITS_PER_WORD; if (f->mask) @@ -226,12 +225,7 @@ mda_compute_frame_size (HOST_WIDE_INT si f->gp_sp_offset = offset; } else - { - f->gp_sp_offset = 0; - } - - if ((f->total_size == f->gp_reg_size) && flag_pic) - f->total_size += 8; + f->gp_sp_offset = 0; return f; } @@ -294,8 +288,13 @@ mdx_prologue (void) if (frame_pointer_needed) EMIT_PL (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx)); - if (flag_pic) - emit_insn (gen_cprestore (GEN_INT (size + 4))); + if (flag_pic && f->cprestore_size) + { + if (frame_pointer_needed) + emit_insn (gen_cprestore_use_fp (GEN_INT (size - f->cprestore_size))); + else + emit_insn (gen_cprestore_use_sp (GEN_INT (size - f->cprestore_size))); + } #undef EMIT_PL } @@ -392,7 +391,7 @@ mda_classify_address (struct score_addre info->offset = XEXP (x, 1); return (mda_valid_base_register_p (info->reg, strict) && GET_CODE (info->offset) == CONST_INT - && CONST_OK_FOR_LETTER_P (INTVAL (info->offset), 'O')); + && IMM_IN_RANGE (INTVAL (info->offset), 15, 1)); case PRE_DEC: case POST_DEC: case PRE_INC: @@ -405,7 +404,7 @@ mda_classify_address (struct score_addre return mda_valid_base_register_p (info->reg, strict); case CONST_INT: info->type = ADD_CONST_INT; - return CONST_OK_FOR_LETTER_P (INTVAL (x), 'O'); + return IMM_IN_RANGE (INTVAL (x), 15, 1); case CONST: case LABEL_REF: case SYMBOL_REF: @@ -443,7 +442,7 @@ mda_symbolic_constant_p (rtx x, enum sco return 1; /* if offset > 15bit, must reload */ - if (!CONST_OK_FOR_LETTER_P (offset, 'O')) + if (!IMM_IN_RANGE (offset, 15, 1)) return 0; switch (*symbol_type) @@ -459,11 +458,9 @@ mda_symbolic_constant_p (rtx x, enum sco void mdx_movsicc (rtx *ops) { - enum machine_mode mode = CCmode; - - if (GET_CODE (ops[1]) == EQ || GET_CODE (ops[1]) == NE) - mode = CC_NZmode; + enum machine_mode mode; + mode = score_select_cc_mode (GET_CODE (ops[1]), ops[2], ops[3]); emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (mode, CC_REGNUM), gen_rtx_COMPARE (mode, cmp_op0, cmp_op1))); } @@ -533,14 +530,15 @@ mds_movdi (rtx *ops) void mds_zero_extract_andi (rtx *ops) { - if (INTVAL (ops[1]) == 1 && const_bi_operand (ops[2], SImode)) + if (INTVAL (ops[1]) == 1 && const_uimm5 (ops[2], SImode)) emit_insn (gen_zero_extract_bittst (ops[0], ops[2])); else { unsigned HOST_WIDE_INT mask; mask = (0xffffffffU & ((1U << INTVAL (ops[1])) - 1U)); mask = mask << INTVAL (ops[2]); - emit_insn (gen_andsi3_cmp (ops[0], gen_int_mode (mask, SImode))); + emit_insn (gen_andsi3_cmp (ops[3], ops[0], + gen_int_mode (mask, SImode))); } } @@ -637,17 +635,20 @@ mdp_sinsn (rtx *ops, enum mda_mem_unit u const char * mdp_limm (rtx *ops) { + HOST_WIDE_INT v; + gcc_assert (GET_CODE (ops[0]) == REG); + gcc_assert (GET_CODE (ops[1]) == CONST_INT); - if (G16_REG_P (REGNO (ops[0])) - && CONST_OK_FOR_LETTER_P (INTVAL (ops[1]), 'I')) + v = INTVAL (ops[1]); + if (G16_REG_P (REGNO (ops[0])) && IMM_IN_RANGE (v, 8, 0)) return "ldiu! %0, %c1"; - else if (CONST_OK_FOR_LETTER_P (INTVAL (ops[1]), 'L')) + else if (IMM_IN_RANGE (v, 16, 1)) return "ldi %0, %c1"; - else if (EXTRA_CONSTRAINT (ops[1], 'Q')) + else if ((v & 0xffff) == 0) return "ldis %0, %U1"; else - return "li %0, %D1"; + return "li %0, %c1"; } /* Output asm insn for move. */ @@ -670,69 +671,389 @@ mdp_move (rtx *ops) return "mv %0, %1"; } -/* Score support add/sub with exponent immediate insn, - use to judge imm condition. */ -static unsigned int -num_bits1 (unsigned HOST_WIDE_INT v) +/* Emit lcb/lce insns. */ +bool +mdx_unaligned_load (rtx *ops) +{ + rtx dst = ops[0]; + rtx src = ops[1]; + rtx len = ops[2]; + rtx off = ops[3]; + rtx addr_reg; + + if (INTVAL (len) != BITS_PER_WORD + || (INTVAL (off) % BITS_PER_UNIT) != 0) + return false; + + gcc_assert (GET_MODE_SIZE (GET_MODE (dst)) == GET_MODE_SIZE (SImode)); + + addr_reg = copy_addr_to_reg (XEXP (src, 0)); + emit_insn (gen_move_lcb (addr_reg, addr_reg)); + emit_insn (gen_move_lce (addr_reg, addr_reg, dst)); + + return true; +} + +/* Emit scb/sce insns. */ +bool +mdx_unaligned_store (rtx *ops) +{ + rtx dst = ops[0]; + rtx len = ops[1]; + rtx off = ops[2]; + rtx src = ops[3]; + rtx addr_reg; + + if (INTVAL(len) != BITS_PER_WORD + || (INTVAL(off) % BITS_PER_UNIT) != 0) + return false; + + gcc_assert (GET_MODE_SIZE (GET_MODE (src)) == GET_MODE_SIZE (SImode)); + + addr_reg = copy_addr_to_reg (XEXP (dst, 0)); + emit_insn (gen_move_scb (addr_reg, addr_reg, src)); + emit_insn (gen_move_sce (addr_reg, addr_reg)); + + return true; +} + +/* If length is short, generate move insns straight. */ +static void +mdx_block_move_straight (rtx dst, rtx src, HOST_WIDE_INT length) +{ + HOST_WIDE_INT leftover; + int i, reg_count; + rtx *regs; + + leftover = length % UNITS_PER_WORD; + length -= leftover; + reg_count = length / UNITS_PER_WORD; + + regs = alloca (sizeof (rtx) * reg_count); + for (i = 0; i < reg_count; i++) + regs[i] = gen_reg_rtx (SImode); + + /* Load from src to regs. */ + if (MEM_ALIGN (src) >= BITS_PER_WORD) + { + HOST_WIDE_INT offset = 0; + for (i = 0; i < reg_count; offset += UNITS_PER_WORD, i++) + emit_move_insn (regs[i], adjust_address (src, SImode, offset)); + } + else if (reg_count >= 1) + { + rtx src_reg = copy_addr_to_reg (XEXP (src, 0)); + + emit_insn (gen_move_lcb (src_reg, src_reg)); + for (i = 0; i < (reg_count - 1); i++) + emit_insn (gen_move_lcw (src_reg, src_reg, regs[i])); + emit_insn (gen_move_lce (src_reg, src_reg, regs[i])); + } + + /* Store regs to dest. */ + if (MEM_ALIGN (dst) >= BITS_PER_WORD) + { + HOST_WIDE_INT offset = 0; + for (i = 0; i < reg_count; offset += UNITS_PER_WORD, i++) + emit_move_insn (adjust_address (dst, SImode, offset), regs[i]); + } + else if (reg_count >= 1) + { + rtx dst_reg = copy_addr_to_reg (XEXP (dst, 0)); + + emit_insn (gen_move_scb (dst_reg, dst_reg, regs[0])); + for (i = 1; i < reg_count; i++) + emit_insn (gen_move_scw (dst_reg, dst_reg, regs[i])); + emit_insn (gen_move_sce (dst_reg, dst_reg)); + } + + /* Mop up any left-over bytes. */ + if (leftover > 0) + { + src = adjust_address (src, BLKmode, length); + dst = adjust_address (dst, BLKmode, length); + move_by_pieces (dst, src, leftover, + MIN (MEM_ALIGN (src), MEM_ALIGN (dst)), 0); + } +} + +/* Generate loop head when dst or src is unaligned. */ +static void +mdx_block_move_loop_head (rtx dst_reg, HOST_WIDE_INT dst_align, + rtx src_reg, HOST_WIDE_INT src_align, + HOST_WIDE_INT length) { - int i, n = 0; + bool src_unaligned = (src_align < BITS_PER_WORD); + bool dst_unaligned = (dst_align < BITS_PER_WORD); + + rtx temp = gen_reg_rtx (SImode); - for (i = 0; i < BITS_PER_WORD; i++) - n += BITSET_P (v, i) ? 1 : 0; - return n; + gcc_assert (length == UNITS_PER_WORD); + + if (src_unaligned) + { + emit_insn (gen_move_lcb (src_reg, src_reg)); + emit_insn (gen_move_lcw (src_reg, src_reg, temp)); + } + else + emit_insn (gen_move_lw_a (src_reg, + src_reg, gen_int_mode (4, SImode), temp)); + + if (dst_unaligned) + emit_insn (gen_move_scb (dst_reg, dst_reg, temp)); + else + emit_insn (gen_move_sw_a (dst_reg, + dst_reg, gen_int_mode (4, SImode), temp)); } -/* Generate add insn, insn will affect condition flag. Optimize used. */ +/* Generate loop body, copy length bytes per iteration. */ +static void +mdx_block_move_loop_body (rtx dst_reg, HOST_WIDE_INT dst_align, + rtx src_reg, HOST_WIDE_INT src_align, + HOST_WIDE_INT length) +{ + int reg_count = length / UNITS_PER_WORD; + rtx *regs = alloca (sizeof (rtx) * reg_count); + int i; + bool src_unaligned = (src_align < BITS_PER_WORD); + bool dst_unaligned = (dst_align < BITS_PER_WORD); + + for (i = 0; i < reg_count; i++) + regs[i] = gen_reg_rtx (SImode); + + if (src_unaligned) + { + for (i = 0; i < reg_count; i++) + emit_insn (gen_move_lcw (src_reg, src_reg, regs[i])); + } + else + { + for (i = 0; i < reg_count; i++) + emit_insn (gen_move_lw_a (src_reg, + src_reg, gen_int_mode (4, SImode), regs[i])); + } + + if (dst_unaligned) + { + for (i = 0; i < reg_count; i++) + emit_insn (gen_move_scw (dst_reg, dst_reg, regs[i])); + } + else + { + for (i = 0; i < reg_count; i++) + emit_insn (gen_move_sw_a (dst_reg, + dst_reg, gen_int_mode (4, SImode), regs[i])); + } +} + +/* Generate loop foot, copy the leftover bytes. */ +static void +mdx_block_move_loop_foot (rtx dst_reg, HOST_WIDE_INT dst_align, + rtx src_reg, HOST_WIDE_INT src_align, + HOST_WIDE_INT length) +{ + bool src_unaligned = (src_align < BITS_PER_WORD); + bool dst_unaligned = (dst_align < BITS_PER_WORD); + + HOST_WIDE_INT leftover; + + leftover = length % UNITS_PER_WORD; + length -= leftover; + + if (length > 0) + mdx_block_move_loop_body (dst_reg, dst_align, + src_reg, src_align, length); + + if (dst_unaligned) + emit_insn (gen_move_sce (dst_reg, dst_reg)); + + if (leftover > 0) + { + HOST_WIDE_INT src_adj = src_unaligned ? -4 : 0; + HOST_WIDE_INT dst_adj = dst_unaligned ? -4 : 0; + rtx temp; + + gcc_assert (leftover < UNITS_PER_WORD); + + if (leftover >= UNITS_PER_WORD / 2 + && src_align >= BITS_PER_WORD / 2 + && dst_align >= BITS_PER_WORD / 2) + { + temp = gen_reg_rtx (HImode); + emit_insn (gen_move_lhu_b (src_reg, src_reg, + gen_int_mode (src_adj, SImode), temp)); + emit_insn (gen_move_sh_b (dst_reg, dst_reg, + gen_int_mode (dst_adj, SImode), temp)); + leftover -= UNITS_PER_WORD / 2; + src_adj = UNITS_PER_WORD / 2; + dst_adj = UNITS_PER_WORD / 2; + } + + while (leftover > 0) + { + temp = gen_reg_rtx (QImode); + emit_insn (gen_move_lbu_b (src_reg, src_reg, + gen_int_mode (src_adj, SImode), temp)); + emit_insn (gen_move_sb_b (dst_reg, dst_reg, + gen_int_mode (dst_adj, SImode), temp)); + leftover--; + src_adj = 1; + dst_adj = 1; + } + } +} + +#define MIN_MOVE_REGS 3 +#define MIN_MOVE_BYTES (MIN_MOVE_REGS * UNITS_PER_WORD) +#define MAX_MOVE_REGS 4 +#define MAX_MOVE_BYTES (MAX_MOVE_REGS * UNITS_PER_WORD) + +/* The length is large, generate a loop if necessary. + The loop is consisted by loop head/body/foot. */ +static void +mdx_block_move_loop (rtx dst, rtx src, HOST_WIDE_INT length) +{ + HOST_WIDE_INT src_align = MEM_ALIGN (src); + HOST_WIDE_INT dst_align = MEM_ALIGN (dst); + HOST_WIDE_INT loop_mov_bytes; + HOST_WIDE_INT iteration = 0; + HOST_WIDE_INT head_length = 0, leftover; + rtx label, src_reg, dst_reg, final_dst; + + bool gen_loop_head = (src_align < BITS_PER_WORD + || dst_align < BITS_PER_WORD); + + if (gen_loop_head) + head_length += UNITS_PER_WORD; + + for (loop_mov_bytes = MAX_MOVE_BYTES; + loop_mov_bytes >= MIN_MOVE_BYTES; + loop_mov_bytes -= UNITS_PER_WORD) + { + iteration = (length - head_length) / loop_mov_bytes; + if (iteration > 1) + break; + } + if (iteration <= 1) + { + mdx_block_move_straight (dst, src, length); + return; + } + + leftover = (length - head_length) % loop_mov_bytes; + length -= leftover; + + src_reg = copy_addr_to_reg (XEXP (src, 0)); + dst_reg = copy_addr_to_reg (XEXP (dst, 0)); + final_dst = expand_simple_binop (Pmode, PLUS, dst_reg, GEN_INT (length), + 0, 0, OPTAB_WIDEN); + + if (gen_loop_head) + mdx_block_move_loop_head (dst_reg, dst_align, + src_reg, src_align, head_length); + + label = gen_label_rtx (); + emit_label (label); + + mdx_block_move_loop_body (dst_reg, dst_align, + src_reg, src_align, loop_mov_bytes); + + emit_insn (gen_cmpsi (dst_reg, final_dst)); + emit_jump_insn (gen_bne (label)); + + mdx_block_move_loop_foot (dst_reg, dst_align, + src_reg, src_align, leftover); +} + +/* Generate block move, for misc.md: "movmemsi". */ +bool +mdx_block_move (rtx *ops) +{ + rtx dst = ops[0]; + rtx src = ops[1]; + rtx length = ops[2]; + + if (TARGET_LITTLE_ENDIAN + && (MEM_ALIGN (src) < BITS_PER_WORD || MEM_ALIGN (dst) < BITS_PER_WORD) + && INTVAL (length) >= UNITS_PER_WORD) + return false; + + if (GET_CODE (length) == CONST_INT) + { + if (INTVAL (length) <= 2 * MAX_MOVE_BYTES) + { + mdx_block_move_straight (dst, src, INTVAL (length)); + return true; + } + else if (optimize && + !(flag_unroll_loops || flag_unroll_all_loops)) + { + mdx_block_move_loop (dst, src, INTVAL (length)); + return true; + } + } + return false; +} + +/* Generate add insn. */ const char * -mdp_add_imm_ucc (rtx *ops) +mdp_select_add_imm (rtx *ops, bool set_cc) { HOST_WIDE_INT v = INTVAL (ops[2]); gcc_assert (GET_CODE (ops[2]) == CONST_INT); gcc_assert (REGNO (ops[0]) == REGNO (ops[1])); - if (G16_REG_P (REGNO (ops[0]))) + if (set_cc && G16_REG_P (REGNO (ops[0]))) { - if (v > 0 && num_bits1 (v) == 1 && IMM_IN_RANGE (ffs (v) - 1, 4, 0)) + if (v > 0 && IMM_IS_POW_OF_2 ((unsigned HOST_WIDE_INT) v, 0, 15)) { ops[2] = GEN_INT (ffs (v) - 1); return "addei! %0, %c2"; } - if (v < 0 && num_bits1 (-v) == 1 && IMM_IN_RANGE (ffs (-v) - 1, 4, 0)) + if (v < 0 && IMM_IS_POW_OF_2 ((unsigned HOST_WIDE_INT) (-v), 0, 15)) { ops[2] = GEN_INT (ffs (-v) - 1); return "subei! %0, %c2"; } } + + if (set_cc) return "addi.c %0, %c2"; + else + return "addi %0, %c2"; } -/* Output arith insn, insn will update condition flag. */ +/* Output arith insn. */ const char * -mdp_select (rtx *ops, const char *inst_pre, bool commu, const char *let) +mdp_select (rtx *ops, const char *inst_pre, + bool commu, const char *letter, bool set_cc) { gcc_assert (GET_CODE (ops[0]) == REG); gcc_assert (GET_CODE (ops[1]) == REG); - if (G16_REG_P (REGNO (ops[0])) + if (set_cc && G16_REG_P (REGNO (ops[0])) && (GET_CODE (ops[2]) == REG ? G16_REG_P (REGNO (ops[2])) : 1) && REGNO (ops[0]) == REGNO (ops[1])) { - snprintf (ins, INS_BUF_SZ, "%s! %%0, %%%s2", inst_pre, let); + snprintf (ins, INS_BUF_SZ, "%s! %%0, %%%s2", inst_pre, letter); return ins; } - if (commu && G16_REG_P (REGNO (ops[0])) + if (commu && set_cc && G16_REG_P (REGNO (ops[0])) && G16_REG_P (REGNO (ops[1])) && REGNO (ops[0]) == REGNO (ops[2])) { gcc_assert (GET_CODE (ops[2]) == REG); - snprintf (ins, INS_BUF_SZ, "%s! %%0, %%%s1", inst_pre, let); + snprintf (ins, INS_BUF_SZ, "%s! %%0, %%%s1", inst_pre, letter); return ins; } - snprintf (ins, INS_BUF_SZ, "%s.c %%0, %%1, %%%s2", inst_pre, let); + if (set_cc) + snprintf (ins, INS_BUF_SZ, "%s.c %%0, %%1, %%%s2", inst_pre, letter); + else + snprintf (ins, INS_BUF_SZ, "%s %%0, %%1, %%%s2", inst_pre, letter); return ins; } Index: gcc/config/score/score.md =================================================================== --- gcc/config/score/score.md (revision 120252) +++ gcc/config/score/score.md (working copy) @@ -59,8 +59,8 @@ (define_constants [(BITTST 0) - (LOAD_ADD 1) - (STORE_ADD 2) + (CPLOAD 1) + (CPRESTORE 2) (SCB 3) (SCW 4) @@ -88,10 +88,22 @@ (include "misc.md") (include "mac.md") -(define_insn "movqi" +(define_expand "movqi" + [(set (match_operand:QI 0 "nonimmediate_operand") + (match_operand:QI 1 "general_operand"))] + "" +{ + if (MEM_P (operands[0]) + && !register_operand (operands[1], QImode)) + { + operands[1] = force_reg (QImode, operands[1]); + } +}) + +(define_insn "*movqi_insns" [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,m,d,*x,d,*a") (match_operand:QI 1 "general_operand" "i,d,m,d,*x,d,*a,d"))] - "" + "!MEM_P (operands[0]) || register_operand (operands[1], QImode)" { switch (which_alternative) { @@ -109,10 +121,22 @@ [(set_attr "type" "arith,move,load,store,fce,tce,fsr,tsr") (set_attr "mode" "QI")]) -(define_insn "movhi" +(define_expand "movhi" + [(set (match_operand:HI 0 "nonimmediate_operand") + (match_operand:HI 1 "general_operand"))] + "" +{ + if (MEM_P (operands[0]) + && !register_operand (operands[1], HImode)) + { + operands[1] = force_reg (HImode, operands[1]); + } +}) + +(define_insn "*movhi_insns" [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,m,d,*x,d,*a") (match_operand:HI 1 "general_operand" "i,d,m,d,*x,d,*a,d"))] - "" + "!MEM_P (operands[0]) || register_operand (operands[1], HImode)" { switch (which_alternative) { @@ -130,11 +154,23 @@ [(set_attr "type" "arith,move,load,store,fce,tce,fsr,tsr") (set_attr "mode" "HI")]) -(define_insn "movsi" - [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,m,d,*x,d,*a,d,c") - (match_operand:SI 1 "general_operand" "i,d,m,d,*x,d,*a,d,c,d"))] +(define_expand "movsi" + [(set (match_operand:SI 0 "nonimmediate_operand") + (match_operand:SI 1 "general_operand"))] "" { + if (MEM_P (operands[0]) + && !register_operand (operands[1], SImode)) + { + operands[1] = force_reg (SImode, operands[1]); + } +}) + +(define_insn "*movsi_insns" + [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,m,d,*x,d,*a,d,*c") + (match_operand:SI 1 "general_operand" "i,d,m,d,*x,d,*a,d,*c,d"))] + "!MEM_P (operands[0]) || register_operand (operands[1], SImode)" +{ switch (which_alternative) { case 0: @@ -169,46 +205,103 @@ DONE; }) +(define_expand "movsf" + [(set (match_operand:SF 0 "nonimmediate_operand") + (match_operand:SF 1 "general_operand"))] + "" +{ + if (MEM_P (operands[0]) + && !register_operand (operands[1], SFmode)) + { + operands[1] = force_reg (SFmode, operands[1]); + } +}) + +(define_insn "*movsf_insns" + [(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,d,m") + (match_operand:SF 1 "general_operand" "i,d,m,d"))] + "!MEM_P (operands[0]) || register_operand (operands[1], SFmode)" +{ + switch (which_alternative) + { + case 0: return \"li %0, %D1\";; + case 1: return mdp_move (operands); + case 2: return mdp_linsn (operands, MDA_WORD, false); + case 3: return mdp_sinsn (operands, MDA_WORD); + default: gcc_unreachable (); + } +} + [(set_attr "type" "arith,move,load,store") + (set_attr "mode" "SI")]) + +(define_insn_and_split "movdf" + [(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,d,m") + (match_operand:DF 1 "general_operand" "i,d,m,d"))] + "" + "#" + "reload_completed" + [(const_int 0)] +{ + mds_movdi (operands); + DONE; +}) + (define_insn "addsi3" - [(set (match_operand:SI 0 "register_operand" "=d,d,d") - (plus:SI (match_operand:SI 1 "register_operand" "0,d,%d") - (match_operand:SI 2 "arith_operand" "L,N,d")))] + [(set (match_operand:SI 0 "register_operand" "=d,d,d,d") + (plus:SI (match_operand:SI 1 "register_operand" "0,0,d,d") + (match_operand:SI 2 "arith_operand" "I,L,N,d")))] "" - "@ - addi %0, %c2 - addri %0, %1, %c2 - add %0, %1, %2" +{ + switch (which_alternative) + { + case 0: return \"addis %0, %U2\"; + case 1: return mdp_select_add_imm (operands, false); + case 2: return \"addri %0, %1, %c2\"; + case 3: return mdp_select (operands, "add", true, "", false); + default: gcc_unreachable (); + } +} [(set_attr "type" "arith") (set_attr "mode" "SI")]) (define_insn "*addsi3_cmp" [(set (reg:CC_NZ CC_REGNUM) - (compare:CC_NZ (plus:SI (match_operand:SI 0 "register_operand" "d,d,d") - (match_operand:SI 1 "arith_operand" "N,L,d")) - (const_int 0)))] + (compare:CC_NZ (plus:SI + (match_operand:SI 1 "register_operand" "0,0,d,d") + (match_operand:SI 2 "arith_operand" "I,L,N,d")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=d,d,d,d"))] "" - "@ - %[ addri.c r1, %0, %c1 %] - %[ m%V0 r1, %0\;addi.c r1, %2 %] - %[ add.c r1, %0, %1 %]" +{ + switch (which_alternative) + { + case 0: return \"addis.c %0, %U2\"; + case 1: return mdp_select_add_imm (operands, true); + case 2: return \"addri.c %0, %1, %c2\"; + case 3: return mdp_select (operands, "add", true, "", true); + default: gcc_unreachable (); + } +} [(set_attr "type" "arith") (set_attr "up_c" "yes") (set_attr "mode" "SI")]) -(define_insn "addsi3_ucc" +(define_insn "*addsi3_ucc" [(set (reg:CC_NZ CC_REGNUM) - (compare:CC_NZ (plus:SI (match_operand:SI 1 "register_operand" "0,d,d") - (match_operand:SI 2 "arith_operand" "L,N,d")) + (compare:CC_NZ (plus:SI + (match_operand:SI 1 "register_operand" "0,0,d,d") + (match_operand:SI 2 "arith_operand" "I,L,N,d")) (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=d,d,d") + (set (match_operand:SI 0 "register_operand" "=d,d,d,d") (plus:SI (match_dup 1) (match_dup 2)))] "" { switch (which_alternative) { - case 0: return mdp_add_imm_ucc (operands); - case 1: return \"addri.c %0, %1, %c2\"; - case 2: return mdp_select (operands, "add", true, ""); + case 0: return \"addis.c %0, %U2\"; + case 1: return mdp_select_add_imm (operands, true); + case 2: return \"addri.c %0, %1, %c2\"; + case 3: return mdp_select (operands, "add", true, "", true); default: gcc_unreachable (); } } @@ -217,9 +310,9 @@ (set_attr "mode" "SI")]) (define_insn "adddi3" - [(set (match_operand:DI 0 "register_operand" "=*e,d") - (plus:DI (match_operand:DI 1 "register_operand" "*0,d") - (match_operand:DI 2 "register_operand" "*e,d"))) + [(set (match_operand:DI 0 "register_operand" "=e,d") + (plus:DI (match_operand:DI 1 "register_operand" "0,d") + (match_operand:DI 2 "register_operand" "e,d"))) (clobber (reg:CC CC_REGNUM))] "" "@ @@ -233,17 +326,22 @@ (minus:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d")))] "" - "sub %0, %1, %2" +{ + return mdp_select (operands, "sub", false, "", false); +} [(set_attr "type" "arith") (set_attr "mode" "SI")]) (define_insn "*subsi3_cmp" [(set (reg:CC_NZ CC_REGNUM) - (compare:CC_NZ (minus:SI (match_operand:SI 0 "register_operand" "d") - (match_operand:SI 1 "register_operand" "d")) - (const_int 0)))] + (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "d") + (match_operand:SI 2 "register_operand" "d")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=d"))] "" - "%[ sub.c r1, %0, %1 %]" +{ + return mdp_select (operands, "sub", false, "", true); +} [(set_attr "type" "arith") (set_attr "up_c" "yes") (set_attr "mode" "SI")]) @@ -255,11 +353,10 @@ (set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (match_dup 2)))] "" - [(parallel - [(set (reg:CC CC_REGNUM) - (compare:CC (match_dup 1) (match_dup 2))) - (set (match_dup 0) - (minus:SI (match_dup 1) (match_dup 2)))])]) + [(set (reg:CC CC_REGNUM) + (compare:CC (match_dup 1) (match_dup 2))) + (set (match_dup 0) + (minus:SI (match_dup 1) (match_dup 2)))]) (define_insn "subsi3_ucc_pcmp" [(parallel @@ -270,7 +367,7 @@ (minus:SI (match_dup 1) (match_dup 2)))])] "" { - return mdp_select (operands, "sub", false, ""); + return mdp_select (operands, "sub", false, "", true); } [(set_attr "type" "arith") (set_attr "up_c" "yes") @@ -285,16 +382,16 @@ (minus:SI (match_dup 1) (match_dup 2)))] "" { - return mdp_select (operands, "sub", false, ""); + return mdp_select (operands, "sub", false, "", true); } [(set_attr "type" "arith") (set_attr "up_c" "yes") (set_attr "mode" "SI")]) (define_insn "subdi3" - [(set (match_operand:DI 0 "register_operand" "=*e,d") - (minus:DI (match_operand:DI 1 "register_operand" "*0,d") - (match_operand:DI 2 "register_operand" "*e,d"))) + [(set (match_operand:DI 0 "register_operand" "=e,d") + (minus:DI (match_operand:DI 1 "register_operand" "0,d") + (match_operand:DI 2 "register_operand" "e,d"))) (clobber (reg:CC CC_REGNUM))] "" "@ @@ -306,36 +403,47 @@ (define_insn "andsi3" [(set (match_operand:SI 0 "register_operand" "=d,d,d,d") (and:SI (match_operand:SI 1 "register_operand" "0,0,d,d") - (match_operand:SI 2 "arith_operand" "K,Q,M,d")))] + (match_operand:SI 2 "arith_operand" "I,K,M,d")))] "" - "@ - andi %0, %c2 - andis %0, %U2 - andri %0, %1, %c2 - and %0, %1, %2" +{ + switch (which_alternative) + { + case 0: return \"andis %0, %U2\"; + case 1: return \"andi %0, %c2"; + case 2: return \"andri %0, %1, %c2\"; + case 3: return mdp_select (operands, "and", true, "", false); + default: gcc_unreachable (); + } +} [(set_attr "type" "arith") (set_attr "mode" "SI")]) (define_insn "andsi3_cmp" [(set (reg:CC_NZ CC_REGNUM) - (compare:CC_NZ (and:SI (match_operand:SI 0 "register_operand" "d,d,d,d") - (match_operand:SI 1 "arith_operand" "M,K,Q,d")) - (const_int 0)))] + (compare:CC_NZ (and:SI (match_operand:SI 1 "register_operand" "0,0,0,d") + (match_operand:SI 2 "arith_operand" "I,K,M,d")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=d,d,d,d"))] "" - "@ - %[ andri.c r1, %0, %c1 %] - %[ m%V0 r1, %0\;andi.c r1, %c1 %] - %[ m%V0 r1, %0\;andis.c r1, %U1 %] - %[ and.c r1, %0, %1 %]" +{ + switch (which_alternative) + { + case 0: return \"andis.c %0, %U2\"; + case 1: return \"andi.c %0, %c2"; + case 2: return \"andri.c %0, %1, %c2\"; + case 3: return mdp_select (operands, "and", true, "", true); + default: gcc_unreachable (); + } +} [(set_attr "type" "arith") (set_attr "up_c" "yes") (set_attr "mode" "SI")]) -(define_insn "andsi3_ucc" +(define_insn "*andsi3_ucc" [(set (reg:CC_NZ CC_REGNUM) (compare:CC_NZ (and:SI (match_operand:SI 1 "register_operand" "0,0,d,d") - (match_operand:SI 2 "arith_operand" "K,Q,M,d")) + (match_operand:SI 2 "arith_operand" "I,K,M,d")) (const_int 0))) (set (match_operand:SI 0 "register_operand" "=d,d,d,d") (and:SI (match_dup 1) (match_dup 2)))] @@ -343,10 +451,10 @@ { switch (which_alternative) { - case 0: return \"andi.c %0, %c2\"; - case 1: return \"andis.c %0, %U2\"; - case 2: return \"andri.c %0, %1, %c2\"; - case 3: return mdp_select (operands, "and", true, ""); + case 0: return \"andis.c %0, %U2\"; + case 1: return \"andi.c %0, %c2"; + case 2: return \"andri.c %0, %1, %c2\"; + case 3: return mdp_select (operands, "and", true, "", true); default: gcc_unreachable (); } } @@ -355,12 +463,12 @@ (set_attr "mode" "SI")]) (define_insn_and_split "*zero_extract_andi" - [(set (reg:CC_NZ CC_REGNUM) - (compare:CC_NZ (zero_extract:SI - (match_operand:SI 0 "register_operand" "d") - (match_operand:SI 1 "const_bi_operand" "") - (match_operand:SI 2 "const_bi_operand" "")) - (const_int 0)))] + [(set (reg:CC CC_REGNUM) + (compare:CC (zero_extract:SI + (match_operand:SI 0 "register_operand" "d") + (match_operand:SI 1 "const_uimm5" "") + (match_operand:SI 2 "const_uimm5" "")) + (const_int 0)))] "" "#" "" @@ -373,26 +481,39 @@ (define_insn "iorsi3" [(set (match_operand:SI 0 "register_operand" "=d,d,d,d") (ior:SI (match_operand:SI 1 "register_operand" "0,0,d,d") - (match_operand:SI 2 "arith_operand" "K,Q,M,d")))] + (match_operand:SI 2 "arith_operand" "I,K,M,d")))] "" - "@ - ori %0, %c2 - oris %0, %U2 - orri %0, %1, %c2 - or %0, %1, %2" +{ + switch (which_alternative) + { + case 0: return \"oris %0, %U2\"; + case 1: return \"ori %0, %c2\"; + case 2: return \"orri %0, %1, %c2\"; + case 3: return mdp_select (operands, "or", true, "", false); + default: gcc_unreachable (); + } +} [(set_attr "type" "arith") (set_attr "mode" "SI")]) (define_insn "iorsi3_ucc" [(set (reg:CC_NZ CC_REGNUM) - (compare:CC_NZ (ior:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d")) + (compare:CC_NZ (ior:SI + (match_operand:SI 1 "register_operand" "0,0,d,d") + (match_operand:SI 2 "arith_operand" "I,K,M,d")) (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=d") + (set (match_operand:SI 0 "register_operand" "=d,d,d,d") (ior:SI (match_dup 1) (match_dup 2)))] "" { - return mdp_select (operands, "or", true, ""); + switch (which_alternative) + { + case 0: return \"oris.c %0, %U2\"; + case 1: return \"ori.c %0, %c2\"; + case 2: return \"orri.c %0, %1, %c2\"; + case 3: return mdp_select (operands, "or", true, "", true); + default: gcc_unreachable (); + } } [(set_attr "type" "arith") (set_attr "up_c" "yes") @@ -400,11 +521,22 @@ (define_insn "iorsi3_cmp" [(set (reg:CC_NZ CC_REGNUM) - (compare:CC_NZ (ior:SI (match_operand:SI 0 "register_operand" "d") - (match_operand:SI 1 "register_operand" "d")) - (const_int 0)))] + (compare:CC_NZ (ior:SI + (match_operand:SI 1 "register_operand" "0,0,d,d") + (match_operand:SI 2 "arith_operand" "I,K,M,d")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=d,d,d,d"))] "" - "%[ or.c r1, %0, %1 %]" +{ + switch (which_alternative) + { + case 0: return \"oris.c %0, %U2\"; + case 1: return \"ori.c %0, %c2\"; + case 2: return \"orri.c %0, %1, %c2\"; + case 3: return mdp_select (operands, "or", true, "", true); + default: gcc_unreachable (); + } +} [(set_attr "type" "arith") (set_attr "up_c" "yes") (set_attr "mode" "SI")]) @@ -414,7 +546,9 @@ (xor:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d")))] "" - "xor %0, %1, %2" +{ + return mdp_select (operands, "xor", true, "", false); +} [(set_attr "type" "arith") (set_attr "mode" "SI")]) @@ -427,7 +561,7 @@ (xor:SI (match_dup 1) (match_dup 2)))] "" { - return mdp_select (operands, "xor", true, ""); + return mdp_select (operands, "xor", true, "", true); } [(set_attr "type" "arith") (set_attr "up_c" "yes") @@ -435,11 +569,14 @@ (define_insn "xorsi3_cmp" [(set (reg:CC_NZ CC_REGNUM) - (compare:CC_NZ (xor:SI (match_operand:SI 0 "register_operand" "d") - (match_operand:SI 1 "register_operand" "d")) - (const_int 0)))] + (compare:CC_NZ (xor:SI (match_operand:SI 1 "register_operand" "d") + (match_operand:SI 2 "register_operand" "d")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=d"))] "" - "%[ xor.c r1, %0, %1 %]" +{ + return mdp_select (operands, "xor", true, "", true); +} [(set_attr "type" "arith") (set_attr "up_c" "yes") (set_attr "mode" "SI")]) @@ -459,49 +596,35 @@ [(set_attr "type" "arith,load") (set_attr "mode" "SI")]) -(define_insn "extendqisi2_cmp" +(define_insn "*extendqisi2_ucc" [(set (reg:CC_N CC_REGNUM) (compare:CC_N (ashiftrt:SI - (ashift:SI (match_operand:SI 0 "register_operand" "d") + (ashift:SI (match_operand:SI 1 "register_operand" "d") (const_int 24)) (const_int 24)) - (const_int 0)))] + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=d") + (sign_extend:SI (match_operand:QI 2 "register_operand" "0")))] "" - "%[ extsb.c r1, %0 %]" + "extsb.c %0, %1" [(set_attr "type" "arith") (set_attr "up_c" "yes") (set_attr "mode" "SI")]) -(define_insn "extendqisi2_ucc" +(define_insn "*extendqisi2_cmp" [(set (reg:CC_N CC_REGNUM) (compare:CC_N (ashiftrt:SI (ashift:SI (match_operand:SI 1 "register_operand" "d") (const_int 24)) (const_int 24)) (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=d") - (sign_extend:SI (match_operand:QI 2 "register_operand" "0")))] + (clobber (match_scratch:SI 0 "=d"))] "" "extsb.c %0, %1" [(set_attr "type" "arith") (set_attr "up_c" "yes") (set_attr "mode" "SI")]) -(define_insn "zero_extendqisi2" - [(set (match_operand:SI 0 "register_operand""=d,d") - (zero_extend:SI (match_operand:QI 1 "register_operand" "d,m")))] - "" -{ - switch (which_alternative) - { - case 0: return \"extzb %0, %1\"; - case 1: return mdp_linsn (operands, MDA_BYTE, false); - default: gcc_unreachable (); - } -} - [(set_attr "type" "arith, load") - (set_attr "mode" "SI")]) - (define_insn "extendhisi2" [(set (match_operand:SI 0 "register_operand" "=d,d") (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "d,m")))] @@ -517,34 +640,79 @@ [(set_attr "type" "arith, load") (set_attr "mode" "SI")]) -(define_insn "extendhisi2_cmp" +(define_insn "*extendhisi2_ucc" [(set (reg:CC_N CC_REGNUM) (compare:CC_N (ashiftrt:SI - (ashift:SI (match_operand:SI 0 "register_operand" "d") + (ashift:SI (match_operand:SI 1 "register_operand" "d") (const_int 16)) (const_int 16)) - (const_int 0)))] + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=d") + (sign_extend:SI (match_operand:HI 2 "register_operand" "0")))] "" - "%[ extsh.c r1, %0 %]" + "extsh.c %0, %1" [(set_attr "type" "arith") (set_attr "up_c" "yes") (set_attr "mode" "SI")]) -(define_insn "extendhisi2_ucc" +(define_insn "*extendhisi2_cmp" [(set (reg:CC_N CC_REGNUM) (compare:CC_N (ashiftrt:SI (ashift:SI (match_operand:SI 1 "register_operand" "d") (const_int 16)) (const_int 16)) (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=d") - (sign_extend:SI (match_operand:HI 2 "register_operand" "0")))] + (clobber (match_scratch:SI 0 "=d"))] "" "extsh.c %0, %1" [(set_attr "type" "arith") (set_attr "up_c" "yes") (set_attr "mode" "SI")]) +(define_insn "zero_extendqisi2" + [(set (match_operand:SI 0 "register_operand" "=d,d") + (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "d,m")))] + "" +{ + switch (which_alternative) + { + case 0: return \"extzb %0, %1\"; + case 1: return mdp_linsn (operands, MDA_BYTE, false); + default: gcc_unreachable (); + } + } + [(set_attr "type" "arith, load") + (set_attr "mode" "SI")]) + +(define_insn "*zero_extendqisi2_ucc" + [(set (reg:CC_N CC_REGNUM) + (compare:CC_N (lshiftrt:SI + (ashift:SI (match_operand:SI 1 "register_operand" "d") + (const_int 24)) + (const_int 24)) + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=d") + (zero_extend:SI (match_operand:QI 2 "register_operand" "0")))] + "" + "extzb.c %0, %1" + [(set_attr "type" "arith") + (set_attr "up_c" "yes") + (set_attr "mode" "SI")]) + +(define_insn "*zero_extendqisi2_cmp" + [(set (reg:CC_N CC_REGNUM) + (compare:CC_N (lshiftrt:SI + (ashift:SI (match_operand:SI 1 "register_operand" "d") + (const_int 24)) + (const_int 24)) + (const_int 0))) + (clobber (match_scratch:SI 0 "=d"))] + "" + "extzb.c %0, %1" + [(set_attr "type" "arith") + (set_attr "up_c" "yes") + (set_attr "mode" "SI")]) + (define_insn "zero_extendhisi2" [(set (match_operand:SI 0 "register_operand" "=d,d") (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "d,m")))] @@ -560,6 +728,35 @@ [(set_attr "type" "arith, load") (set_attr "mode" "SI")]) +(define_insn "*zero_extendhisi2_ucc" + [(set (reg:CC_N CC_REGNUM) + (compare:CC_N (lshiftrt:SI + (ashift:SI (match_operand:SI 1 "register_operand" "d") + (const_int 16)) + (const_int 16)) + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=d") + (zero_extend:SI (match_operand:HI 2 "register_operand" "0")))] + "" + "extzh.c %0, %1" + [(set_attr "type" "arith") + (set_attr "up_c" "yes") + (set_attr "mode" "SI")]) + +(define_insn "*zero_extendhisi2_cmp" + [(set (reg:CC_N CC_REGNUM) + (compare:CC_N (lshiftrt:SI + (ashift:SI (match_operand:SI 1 "register_operand" "d") + (const_int 16)) + (const_int 16)) + (const_int 0))) + (clobber (match_scratch:SI 0 "=d"))] + "" + "extzh.c %0, %1" + [(set_attr "type" "arith") + (set_attr "up_c" "yes") + (set_attr "mode" "SI")]) + (define_insn "mulsi3" [(set (match_operand:SI 0 "register_operand" "=l") (mult:SI (match_operand:SI 1 "register_operand" "d") @@ -572,7 +769,8 @@ (define_insn "mulsidi3" [(set (match_operand:DI 0 "register_operand" "=x") - (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d")) + (mult:DI (sign_extend:DI + (match_operand:SI 1 "register_operand" "d")) (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))] "!TARGET_SCORE5U" @@ -582,7 +780,8 @@ (define_insn "umulsidi3" [(set (match_operand:DI 0 "register_operand" "=x") - (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d")) + (mult:DI (zero_extend:DI + (match_operand:SI 1 "register_operand" "d")) (zero_extend:DI (match_operand:SI 2 "register_operand" "d"))))] "!TARGET_SCORE5U" @@ -635,8 +834,8 @@ { switch (which_alternative) { - case 0: return mdp_select (operands, "slli", false, "c"); - case 1: return mdp_select (operands, "sll", false, ""); + case 0: return mdp_select (operands, "slli", false, "c", true); + case 1: return mdp_select (operands, "sll", false, "", true); default: gcc_unreachable (); } } @@ -647,13 +846,19 @@ (define_insn "ashlsi3_cmp" [(set (reg:CC_NZ CC_REGNUM) (compare:CC_NZ (ashift:SI - (match_operand:SI 0 "register_operand" "d,d") - (match_operand:SI 1 "arith_operand" "J,d")) - (const_int 0)))] + (match_operand:SI 1 "register_operand" "d,d") + (match_operand:SI 2 "arith_operand" "J,d")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=d,d"))] "" - "@ - %[ slli.c r1, %0, %c1 %] - %[ sll.c r1, %0, %1 %]" +{ + switch (which_alternative) + { + case 0: return mdp_select (operands, "slli", false, "c", true); + case 1: return mdp_select (operands, "sll", false, "", true); + default: gcc_unreachable (); + } +} [(set_attr "type" "arith") (set_attr "up_c" "yes") (set_attr "mode" "SI")]) @@ -682,7 +887,7 @@ switch (which_alternative) { case 0: return \"srai.c %0, %1, %c2\"; - case 1: return mdp_select (operands, "sra", false, ""); + case 1: return mdp_select (operands, "sra", false, "", true); default: gcc_unreachable (); } } @@ -693,31 +898,16 @@ (define_insn "ashrsi3_cmp" [(set (reg:CC_NZ CC_REGNUM) (compare:CC_NZ (ashiftrt:SI - (match_operand:SI 0 "register_operand" "d,d") - (match_operand:SI 1 "arith_operand" "J,d")) - (const_int 0)))] - "" - "@ - %[ srai.c r1, %0, %c1 %] - %[ sra.c r1, %0, %1 %]" - [(set_attr "type" "arith") - (set_attr "up_c" "yes") - (set_attr "mode" "SI")]) - -(define_insn "ashrsi3_ucc_n" - [(set (reg:CC_N CC_REGNUM) - (compare:CC_N (ashiftrt:SI - (match_operand:SI 1 "register_operand" "d,d") - (match_operand:SI 2 "arith_operand" "J,d")) - (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=d,d") - (ashiftrt:SI (match_dup 1) (match_dup 2)))] + (match_operand:SI 1 "register_operand" "d,d") + (match_operand:SI 2 "arith_operand" "J,d")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=d,d"))] "" { switch (which_alternative) { case 0: return \"srai.c %0, %1, %c2\"; - case 1: return mdp_select (operands, "sra", false, ""); + case 1: return mdp_select (operands, "sra", false, "", true); default: gcc_unreachable (); } } @@ -725,20 +915,6 @@ (set_attr "up_c" "yes") (set_attr "mode" "SI")]) -(define_insn "ashrsi3_cmp_n" - [(set (reg:CC_N CC_REGNUM) - (compare:CC_N (ashiftrt:SI - (match_operand:SI 0 "register_operand" "d,d") - (match_operand:SI 1 "arith_operand" "J,d")) - (const_int 0)))] - "" - "@ - %[ srai.c r1, %0, %c1 %] - %[ sra.c r1, %0, %1 %]" - [(set_attr "type" "arith") - (set_attr "up_c" "yes") - (set_attr "mode" "SI")]) - (define_insn "lshrsi3" [(set (match_operand:SI 0 "register_operand" "=d,d") (lshiftrt:SI (match_operand:SI 1 "register_operand" "d,d") @@ -762,8 +938,8 @@ { switch (which_alternative) { - case 0: return mdp_select (operands, "srli", false, "c"); - case 1: return mdp_select (operands, "srl", false, ""); + case 0: return mdp_select (operands, "srli", false, "c", true); + case 1: return mdp_select (operands, "srl", false, "", true); default: gcc_unreachable (); } } @@ -774,13 +950,19 @@ (define_insn "lshrsi3_cmp" [(set (reg:CC_NZ CC_REGNUM) (compare:CC_NZ (lshiftrt:SI - (match_operand:SI 0 "register_operand" "d,d") - (match_operand:SI 1 "arith_operand" "J,d")) - (const_int 0)))] + (match_operand:SI 1 "register_operand" "d,d") + (match_operand:SI 2 "arith_operand" "J,d")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=d,d"))] "" - "@ - %[ srli.c r1, %0, %c1 %] - %[ srl.c r1, %0, %1 %]" +{ + switch (which_alternative) + { + case 0: return mdp_select (operands, "srli", false, "c", true); + case 1: return mdp_select (operands, "srl", false, "", true); + default: gcc_unreachable (); + } +} [(set_attr "type" "arith") (set_attr "up_c" "yes") (set_attr "mode" "SI")]) @@ -793,11 +975,24 @@ [(set_attr "type" "arith") (set_attr "mode" "SI")]) +(define_insn "*negsi2_cmp" + [(set (reg:CC_NZ CC_REGNUM) + (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "e,d")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=e,d"))] + "" + "@ + neg! %0, %1 + neg.c %0, %1" + [(set_attr "type" "arith") + (set_attr "up_c" "yes") + (set_attr "mode" "SI")]) + (define_insn "negsi2_ucc" - [(set (reg:CC CC_REGNUM) - (compare:CC (neg:SI (match_operand:SI 1 "register_operand" "*e,d")) - (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=*e,d") + [(set (reg:CC_NZ CC_REGNUM) + (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "e,d")) + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=e,d") (neg:SI (match_dup 1)))] "" "@ @@ -817,9 +1012,9 @@ (define_insn "one_cmplsi2_ucc" [(set (reg:CC_NZ CC_REGNUM) - (compare:CC_NZ (not:SI (match_operand:SI 1 "register_operand" "*e,d")) + (compare:CC_NZ (not:SI (match_operand:SI 1 "register_operand" "e,d")) (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=*e,d") + (set (match_operand:SI 0 "register_operand" "=e,d") (not:SI (match_dup 1)))] "" "@ @@ -831,12 +1026,13 @@ (define_insn "one_cmplsi2_cmp" [(set (reg:CC_NZ CC_REGNUM) - (compare:CC_NZ (not:SI (match_operand:SI 0 "register_operand" "*e,d")) - (const_int 0)))] + (compare:CC_NZ (not:SI (match_operand:SI 1 "register_operand" "e,d")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=e,d"))] "" "@ - %[ not! r1, %0 %] - %[ not.c r1, %0 %]" + not! %0, %1 + not.c %0, %1" [(set_attr "type" "arith") (set_attr "up_c" "yes") (set_attr "mode" "SI")]) @@ -877,8 +1073,8 @@ (define_insn "cmpsi_nz" [(set (reg:CC_NZ CC_REGNUM) - (compare:CC_NZ (match_operand:SI 0 "register_operand" "d,*e,d") - (match_operand:SI 1 "arith_operand" "L,*e,d")))] + (compare:CC_NZ (match_operand:SI 0 "register_operand" "d,e,d") + (match_operand:SI 1 "arith_operand" "L,e,d")))] "" "@ cmpi.c %0, %c1 @@ -890,8 +1086,8 @@ (define_insn "cmpsi_n" [(set (reg:CC_N CC_REGNUM) - (compare:CC_N (match_operand:SI 0 "register_operand" "d,*e,d") - (match_operand:SI 1 "arith_operand" "L,*e,d")))] + (compare:CC_N (match_operand:SI 0 "register_operand" "d,e,d") + (match_operand:SI 1 "arith_operand" "L,e,d")))] "" "@ cmpi.c %0, %c1 @@ -901,10 +1097,23 @@ (set_attr "up_c" "yes") (set_attr "mode" "SI")]) +(define_insn "*cmpsi_to_addsi" + [(set (reg:CC_NZ CC_REGNUM) + (compare:CC_NZ (match_operand:SI 1 "register_operand" "0,d") + (neg:SI (match_operand:SI 2 "register_operand" "e,d")))) + (clobber (match_scratch:SI 0 "=e,d"))] + "" + "@ + add! %0, %2 + add.c %0, %1, %2" + [(set_attr "type" "cmp") + (set_attr "up_c" "yes") + (set_attr "mode" "SI")]) + (define_insn "cmpsi_cc" [(set (reg:CC CC_REGNUM) - (compare:CC (match_operand:SI 0 "register_operand" "d,*e,d") - (match_operand:SI 1 "arith_operand" "L,*e,d")))] + (compare:CC (match_operand:SI 0 "register_operand" "d,e,d") + (match_operand:SI 1 "arith_operand" "L,e,d")))] "" "@ cmpi.c %0, %c1 @@ -1078,17 +1287,17 @@ (clobber (reg:SI RT_REGNUM))] "SIBLING_CALL_P (insn)" { - if (!flag_pic) - switch (which_alternative) + if (!flag_pic) + switch (which_alternative) { case 0: return \"br%S0 %0\"; case 1: return \"j %0\"; default: gcc_unreachable (); } else - switch (which_alternative) + switch (which_alternative) { - case 0: return \"mv r29, %0\;.cpadd r29\;br r29\"; + case 0: return \"mv r29, %0\;br r29\"; case 1: return \"la r29, %0\;br r29\"; default: gcc_unreachable (); } @@ -1112,17 +1321,17 @@ (clobber (reg:SI RT_REGNUM))] "SIBLING_CALL_P (insn)" { - if (!flag_pic) - switch (which_alternative) + if (!flag_pic) + switch (which_alternative) { case 0: return \"br%S1 %1\"; case 1: return \"j %1\"; default: gcc_unreachable (); } else - switch (which_alternative) + switch (which_alternative) { - case 0: return \"mv r29, %1\;.cpadd r29\;br r29\"; + case 0: return \"mv r29, %1\;br r29\"; case 1: return \"la r29, %1\;br r29\"; default: gcc_unreachable (); } @@ -1154,7 +1363,7 @@ else switch (which_alternative) { - case 0: return \"mv r29, %0\;.cpadd r29\;brl r29\"; + case 0: return \"mv r29, %0\;brl r29\"; case 1: return \"la r29, %0\;brl r29\"; default: gcc_unreachable (); } @@ -1163,7 +1372,7 @@ (define_expand "call_value" [(parallel [(set (match_operand 0 "" "") - (call (match_operand 1 "" "") (match_operand 2 "" ""))) + (call (match_operand 1 "" "") (match_operand 2 "" ""))) (use (match_operand 3 "" ""))])] "" { @@ -1188,7 +1397,7 @@ else switch (which_alternative) { - case 0: return \"mv r29, %1\;.cpadd r29\;brl r29\"; + case 0: return \"mv r29, %1\;brl r29\"; case 1: return \"la r29, %1\;brl r29\"; default: gcc_unreachable (); } @@ -1277,13 +1486,59 @@ ) (define_insn "cpload" - [(unspec:SI [(const_int 1)] 1)] + [(unspec_volatile:SI [(const_int 1)] CPLOAD)] "flag_pic" ".cpload r29" ) -(define_insn "cprestore" - [(unspec:SI [(match_operand:SI 0 "" "")] 2)] +(define_insn "cprestore_use_fp" + [(unspec_volatile:SI [(match_operand:SI 0 "" "")] CPRESTORE) + (use (reg:SI FP_REGNUM))] "flag_pic" - ".cprestore %0" + ".cprestore r2, %0" ) + +(define_insn "cprestore_use_sp" + [(unspec_volatile:SI [(match_operand:SI 0 "" "")] CPRESTORE) + (use (reg:SI SP_REGNUM))] + "flag_pic" + ".cprestore r0, %0" +) + +(define_expand "doloop_end" + [(use (match_operand 0 "" "")) ; loop pseudo + (use (match_operand 1 "" "")) ; iterations; zero if unknown + (use (match_operand 2 "" "")) ; max iterations + (use (match_operand 3 "" "")) ; loop level + (use (match_operand 4 "" ""))] ; label + "" + { + if (INTVAL (operands[3]) > 1) + FAIL; + + if (GET_MODE (operands[0]) == SImode) + { + rtx sr0 = gen_rtx_REG (SImode, CN_REGNUM); + emit_jump_insn (gen_doloop_end_si (sr0, operands[4])); + } + else + FAIL; + + DONE; + }) + +(define_insn "doloop_end_si" + [(set (pc) + (if_then_else + (ne (match_operand:SI 0 "sr0_operand" "") + (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int -1))) + (clobber (reg:CC CC_REGNUM)) +] + "" + "bcnz %1" + [(set_attr "type" "branch")]) Index: gcc/config/score/score-modes.def =================================================================== --- gcc/config/score/score-modes.def (revision 120252) +++ gcc/config/score/score-modes.def (working copy) @@ -21,6 +21,5 @@ /* CC_NZmode should be used if the N (sign) and Z (zero) flag is set correctly. CC_Nmode should be used if only the N flag is set correctly. */ -CC_MODE (CC_NZ); CC_MODE (CC_N); - +CC_MODE (CC_NZ); Index: gcc/config/score/score-mdaux.h =================================================================== --- gcc/config/score/score-mdaux.h (revision 120252) +++ gcc/config/score/score-mdaux.h (working copy) @@ -69,8 +69,6 @@ void mda_gen_cmp (enum machine_mode mode int mda_symbolic_constant_p (rtx x, enum score_symbol_type *symbol_type); -bool mda_pindex_mem (rtx addr); - int mda_bp (void); /* Machine Expand. */ @@ -87,8 +85,6 @@ void mdx_call_value (rtx *ops, bool sibc /* Machine Split. */ void mds_movdi (rtx *ops); -void mds_addsi (rtx *ops); - void mds_zero_extract_andi (rtx *ops); /* Machine Print. */ @@ -100,14 +96,21 @@ const char * mdp_linsn (rtx *ops, enum m const char * mdp_sinsn (rtx *ops, enum mda_mem_unit unit); -const char * mdp_add_imm_ucc (rtx *ops); +const char * mdp_select_add_imm (rtx *ops, bool set_cc); const char * mdp_select (rtx *ops, const char *inst_pre, - bool comu, const char *let); + bool commu, const char *letter, bool set_cc); const char * mdp_limm (rtx *ops); const char * mdp_move (rtx *ops); +/* Machine unaligned memory load/store. */ +bool mdx_unaligned_load (rtx* ops); + +bool mdx_unaligned_store (rtx* ops); + +bool mdx_block_move (rtx* ops); + #endif Index: gcc/config/score/mul-div.S =================================================================== --- gcc/config/score/mul-div.S (revision 120252) +++ gcc/config/score/mul-div.S (working copy) @@ -242,7 +242,7 @@ _flush_cache: #nop! addi r8, 16 bcnz 2b - .cprestore 12 # pic used + .cprestore r0, 12 # pic used addi r0, 8 # pic used br r3 #endif @@ -278,7 +278,7 @@ __mulsi3_loop2: cmpi.c a1, 0 bne __mulsi3_loop mv r4, t1 - .cprestore 12 # pic used + .cprestore r0, 12 # pic used addi r0, 8 # pic used br ra .end __mulsi3 @@ -334,7 +334,7 @@ __uds_loop3: __uds_exit: mv a1, a0 mv r4, t4 - .cprestore 12 # pic used + .cprestore r0, 12 # pic used addi r0, 8 # pic used br ra .end __udivsi3 @@ -350,7 +350,7 @@ __umodsi3: la r29, __udivsi3 brl r29 mv r4, a1 - .cprestore 12 # pic used + .cprestore r0, 12 # pic used addi r0, 8 # pic used br t3 .end __umodsi3 @@ -383,7 +383,7 @@ __divsi3_adjust: bge __divsi3_exit neg r4, r4 __divsi3_exit: - .cprestore 12 # pic used + .cprestore r0, 12 # pic used addi r0, 8 # pic used br t3 .end __divsi3 ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH]: for Score backend 2006-12-29 6:54 ` [PATCH]: for Score backend liqin @ 2007-01-04 1:30 ` liqin 2007-01-08 4:53 ` liqin 0 siblings, 1 reply; 5+ messages in thread From: liqin @ 2007-01-04 1:30 UTC (permalink / raw) To: gcc-patches [-- Attachment #1: Type: text/plain, Size: 1601 bytes --] Can I commit this patch to gcc-4.2.0/gcc-trunk repository, because I had put it here for one week, and not get any response. Rgds Liqin gcc-patches-owner@gcc.gnu.org 写于 2006-12-29 14:53:32: > Hi, > this patch did many changes for Score backend. > > Changelog: > * config/score/predicates.md (const_uimm5, sr0_operand, > const_simm12, > const_simm15, const_pow2, const_npow2): Added. > * config/score/misc.md (insv, extv, extzv, movmemsi, > move_lbu_a/b, mov_lhu_a/b etc): Added and fix some bug. > * config/score/score.c (score_address_cost, score_select_cc_mode): > > Added. > Change CONST_OK_FOR_LETTER_P/EXTRA_CONSTRAINT define. > Update score_rtx_costs for MACRO TARGET_RTX_COSTS. > Update score_print_operand. > * config/score/score.h (DATA_ALIGNMENT, SELECT_CC_MODE): Added. > Adjust register allocate order and update some macro define. > * config/score/score-mdaux.c (mdx_unaligned_load, > mdx_unsigned_store, > mdx_block_move_straight, mdx_block_move_loop_head, > mdx_block_move_loop_body, > mdx_block_move_loop_foot, mdx_block_move_loop mdx_block_move): > Added. > (mdx_movsicc, mdp_select_add_imm, mdp_select, > mds_zero_extract_andi, mdp_limm): > Updated and fix some bug and typo. > * config/score/score.md (movqi/hi/si, add/sub/zero/ext): Updated. > (movsf, movdf, doloop_end): Added. > * config/score/t-score-elf (MULTILIB_OPTIONS): Change. > > Rgds > Liqin [-- Attachment #2: score-20061229.patch --] [-- Type: application/octet-stream, Size: 99711 bytes --] Index: gcc/config/score/t-score-elf =================================================================== --- gcc/config/score/t-score-elf (revision 120252) +++ gcc/config/score/t-score-elf (working copy) @@ -35,7 +35,7 @@ dp-bit.c: $(srcdir)/config/fp-bit.c # without the $gp register. TARGET_LIBGCC2_CFLAGS = -G 0 -MULTILIB_OPTIONS = fPIC mel mscore7 +MULTILIB_OPTIONS = mmac mel fPIC MULTILIB_MATCHES = fPIC=fpic EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o @@ -43,4 +43,3 @@ EXTRA_MULTILIB_PARTS = crtbegin.o crtend LIBGCC = stmp-multilib INSTALL_LIBGCC = install-multilib - Index: gcc/config/score/crti.asm =================================================================== --- gcc/config/score/crti.asm (revision 120252) +++ gcc/config/score/crti.asm (working copy) @@ -43,8 +43,8 @@ .mask 0x00000000, 0 _start: la r28, _gp - la r8, __bss_start - la r9, __bss_end__ + la r8, _bss_start + la r9, _bss_end__ sub! r9, r8 srli! r9, 2 addi r9, -1 @@ -91,8 +91,8 @@ _fini: .mask 0x00000000,0 _start: la r28, _gp - la r8, __bss_start - la r9, __bss_end__ + la r8, _bss_start + la r9, _bss_end__ sub! r9, r8 srli! r9, 2 addi r9, -1 @@ -102,15 +102,10 @@ _start: sw r9, [r8]+, 4 bcnz 1b la r0, _stack -# jl _init -# la r4, _end -# jl _init_argv ldiu! r4, 0 ldiu! r5, 0 -# jl main la r29, main brl r29 -# jl exit la r29, exit brl r29 .end _start Index: gcc/config/score/predicates.md =================================================================== --- gcc/config/score/predicates.md (revision 120252) +++ gcc/config/score/predicates.md (working copy) @@ -35,13 +35,11 @@ (ior (match_operand 0 "const_call_insn_operand") (match_operand 0 "register_operand"))) -(define_predicate "const_bi_operand" - (and (match_code "const_int") - (match_test "CONST_OK_FOR_LETTER_P (INTVAL (op), 'J')"))) - -(define_predicate "pindex_off_operand" - (and (match_code "const_int") - (match_test "CONST_OK_FOR_LETTER_P (INTVAL (op), 'P')"))) +(define_predicate "const_uimm5" + (match_code "const_int") +{ + return IMM_IN_RANGE (INTVAL (op), 5, 0); +}) (define_predicate "hireg_operand" (and (match_code "reg") @@ -51,6 +49,10 @@ (and (match_code "reg") (match_test "REGNO (op) == LO_REGNUM"))) +(define_predicate "sr0_operand" + (and (match_code "reg") + (match_test "REGNO (op) == CN_REGNUM"))) + (define_predicate "g32reg_operand" (and (match_code "reg") (match_test "GP_REG_P (REGNO (op))"))) @@ -61,3 +63,26 @@ (define_predicate "branch_nz_operator" (match_code "eq,ne,lt,ge")) +(define_predicate "const_simm12" + (match_code "const_int") +{ + return IMM_IN_RANGE (INTVAL (op), 12, 1); +}) + +(define_predicate "const_simm15" + (match_code "const_int") +{ + return IMM_IN_RANGE (INTVAL (op), 15, 1); +}) + +(define_predicate "const_pow2" + (match_code "const_int") +{ + return IMM_IS_POW_OF_2 ((unsigned HOST_WIDE_INT) INTVAL (op), 0, 31); +}) + +(define_predicate "const_npow2" + (match_code "const_int") +{ + return IMM_IS_POW_OF_2 (~(unsigned HOST_WIDE_INT) INTVAL (op), 0, 31); +}) Index: gcc/config/score/score-version.h =================================================================== --- gcc/config/score/score-version.h (revision 120252) +++ gcc/config/score/score-version.h (working copy) @@ -18,4 +18,4 @@ the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#define SCORE_GCC_VERSION "1.1" +#define SCORE_GCC_VERSION "1.2" Index: gcc/config/score/crtn.asm =================================================================== --- gcc/config/score/crtn.asm (revision 120252) +++ gcc/config/score/crtn.asm (working copy) @@ -59,4 +59,3 @@ br r3 #endif - Index: gcc/config/score/score-protos.h =================================================================== --- gcc/config/score/score-protos.h (revision 120252) +++ gcc/config/score/score-protos.h (working copy) @@ -36,7 +36,7 @@ enum reg_class score_preferred_reload_cl enum reg_class score_secondary_reload_class (enum reg_class class, enum machine_mode mode, rtx x); -int score_const_ok_for_letter_p (int value, char c); +int score_const_ok_for_letter_p (HOST_WIDE_INT value, char c); int score_extra_constraint (rtx op, char c); Index: gcc/config/score/misc.md =================================================================== --- gcc/config/score/misc.md (revision 120252) +++ gcc/config/score/misc.md (working copy) @@ -84,8 +84,8 @@ [(set (match_operand:SI 0 "register_operand" "=d") (if_then_else:SI (match_operator 1 "comparison_operator" [(reg:CC CC_REGNUM) (const_int 0)]) - (match_operand:SI 2 "register_operand" "d") - (match_operand:SI 3 "register_operand" "0")))] + (match_operand:SI 2 "arith_operand" "d") + (match_operand:SI 3 "arith_operand" "0")))] "" "mv%C1 %0, %2" [(set_attr "type" "cndmv") @@ -95,7 +95,7 @@ [(set (reg:CC_NZ CC_REGNUM) (compare:CC_NZ (unspec:SI [(match_operand:SI 0 "register_operand" "*e,d") - (match_operand:SI 1 "const_bi_operand" "")] + (match_operand:SI 1 "const_uimm5" "")] BITTST) (const_int 0)))] "" @@ -106,3 +106,312 @@ (set_attr "up_c" "yes") (set_attr "mode" "SI")]) +(define_expand "extzv" + [(set (match_operand:SI 0 "register_operand" "") + (zero_extract (match_operand:SI 1 "memory_operand" "") + (match_operand:SI 2 "immediate_operand" "") + (match_operand:SI 3 "immediate_operand" "")))] + "!TARGET_SCORE5U && !TARGET_LITTLE_ENDIAN" +{ + if (mdx_unaligned_load (operands)) + DONE; + else + FAIL; +}) + +(define_expand "insv" + [(set (zero_extract (match_operand:SI 0 "memory_operand" "") + (match_operand:SI 1 "immediate_operand" "") + (match_operand:SI 2 "immediate_operand" "")) + (match_operand:SI 3 "register_operand" ""))] + "!TARGET_SCORE5U && !TARGET_LITTLE_ENDIAN" +{ + if (mdx_unaligned_store (operands)) + DONE; + else + FAIL; +}) + +(define_expand "extv" + [(set (match_operand:SI 0 "register_operand" "") + (sign_extract (match_operand:SI 1 "memory_operand" "") + (match_operand:SI 2 "immediate_operand" "") + (match_operand:SI 3 "immediate_operand" "")))] + "!TARGET_SCORE5U && !TARGET_LITTLE_ENDIAN" +{ + if (mdx_unaligned_load (operands)) + DONE; + else + FAIL; +}) + +(define_expand "movmemsi" + [(parallel [(set (match_operand:BLK 0 "general_operand") + (match_operand:BLK 1 "general_operand")) + (use (match_operand:SI 2 "")) + (use (match_operand:SI 3 "const_int_operand"))])] + "!TARGET_SCORE5U" +{ + if (mdx_block_move (operands)) + DONE; + else + FAIL; +}) + +(define_insn "move_lbu_a" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "const_simm12" ""))) + (set (match_operand:QI 3 "register_operand" "=d") + (mem:QI (match_dup 1)))] + "!TARGET_SCORE5U" + "lbu %3, [%1]+, %2" + [(set_attr "type" "load") + (set_attr "mode" "QI")]) + +(define_insn "move_lhu_a" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "const_simm12" ""))) + (set (match_operand:HI 3 "register_operand" "=d") + (mem:HI (match_dup 1)))] + "!TARGET_SCORE5U" + "lhu %3, [%1]+, %2" + [(set_attr "type" "load") + (set_attr "mode" "HI")]) + +(define_insn "move_lw_a" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "const_simm12" ""))) + (set (match_operand:SI 3 "register_operand" "=d") + (mem:SI (match_dup 1)))] + "!TARGET_SCORE5U" + "lw %3, [%1]+, %2" + [(set_attr "type" "load") + (set_attr "mode" "SI")]) + +(define_insn "move_sb_a" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "const_simm12" ""))) + (set (mem:QI (match_dup 1)) + (match_operand:QI 3 "register_operand" "d"))] + "!TARGET_SCORE5U" + "sb %3, [%1]+, %2" + [(set_attr "type" "store") + (set_attr "mode" "QI")]) + +(define_insn "move_sh_a" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "const_simm12" ""))) + (set (mem:HI (match_dup 1)) + (match_operand:HI 3 "register_operand" "d"))] + "!TARGET_SCORE5U" + "sh %3, [%1]+, %2" + [(set_attr "type" "store") + (set_attr "mode" "HI")]) + +(define_insn "move_sw_a" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "const_simm12" ""))) + (set (mem:SI (match_dup 1)) + (match_operand:SI 3 "register_operand" "d"))] + "!TARGET_SCORE5U" + "sw %3, [%1]+, %2" + [(set_attr "type" "store") + (set_attr "mode" "SI")]) + +(define_insn "move_lbu_b" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "const_simm12" ""))) + (set (match_operand:QI 3 "register_operand" "=d") + (mem:QI (plus:SI (match_dup 1) + (match_dup 2))))] + "!TARGET_SCORE5U" + "lbu %3, [%1, %2]+" + [(set_attr "type" "load") + (set_attr "mode" "QI")]) + +(define_insn "move_lhu_b" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "const_simm12" ""))) + (set (match_operand:HI 3 "register_operand" "=d") + (mem:HI (plus:SI (match_dup 1) + (match_dup 2))))] + "!TARGET_SCORE5U" + "lhu %3, [%1, %2]+" + [(set_attr "type" "load") + (set_attr "mode" "HI")]) + +(define_insn "move_lw_b" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "const_simm12" ""))) + (set (match_operand:SI 3 "register_operand" "=d") + (mem:SI (plus:SI (match_dup 1) + (match_dup 2))))] + "!TARGET_SCORE5U" + "lw %3, [%1, %2]+" + [(set_attr "type" "load") + (set_attr "mode" "SI")]) + +(define_insn "move_sb_b" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "const_simm12" ""))) + (set (mem:QI (plus:SI (match_dup 1) + (match_dup 2))) + (match_operand:QI 3 "register_operand" "d"))] + "!TARGET_SCORE5U" + "sb %3, [%1, %2]+" + [(set_attr "type" "store") + (set_attr "mode" "QI")]) + +(define_insn "move_sh_b" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "const_simm12" ""))) + (set (mem:HI (plus:SI (match_dup 1) + (match_dup 2))) + (match_operand:HI 3 "register_operand" "d"))] + "!TARGET_SCORE5U" + "sh %3, [%1, %2]+" + [(set_attr "type" "store") + (set_attr "mode" "HI")]) + +(define_insn "move_sw_b" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "const_simm12" ""))) + (set (mem:SI (plus:SI (match_dup 1) + (match_dup 2))) + (match_operand:SI 3 "register_operand" "d"))] + "!TARGET_SCORE5U" + "sw %3, [%1, %2]+" + [(set_attr "type" "store") + (set_attr "mode" "SI")]) + +(define_insn "move_lcb" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (const_int 4))) + (set (reg:SI LC_REGNUM) + (unspec:SI [(mem:BLK (match_dup 1))] LCB))] + "!TARGET_SCORE5U && !TARGET_LITTLE_ENDIAN" + "lcb [%1]+" + [(set_attr "type" "load") + (set_attr "mode" "SI")]) + +(define_insn "move_lcw" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (const_int 4))) + (set (match_operand:SI 2 "register_operand" "=d") + (unspec:SI [(mem:BLK (match_dup 1)) + (reg:SI LC_REGNUM)] LCW)) + (set (reg:SI LC_REGNUM) + (unspec:SI [(mem:BLK (match_dup 1))] LCB))] + "!TARGET_SCORE5U && !TARGET_LITTLE_ENDIAN" + "lcw %2, [%1]+" + [(set_attr "type" "load") + (set_attr "mode" "SI")]) + +(define_insn "move_lce" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (const_int 4))) + (set (match_operand:SI 2 "register_operand" "=d") + (unspec:SI [(mem:BLK (match_dup 1)) + (reg:SI LC_REGNUM)] LCE))] + "!TARGET_SCORE5U && !TARGET_LITTLE_ENDIAN" + "lce %2, [%1]+" + [(set_attr "type" "load") + (set_attr "mode" "SI")]) + +(define_insn "move_scb" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (const_int 4))) + (set (mem:BLK (match_dup 1)) + (unspec:BLK [(match_operand:SI 2 "register_operand" "d")] SCB)) + (set (reg:SI SC_REGNUM) + (unspec:SI [(match_dup 2)] SCLC))] + "!TARGET_SCORE5U && !TARGET_LITTLE_ENDIAN" + "scb %2, [%1]+" + [(set_attr "type" "store") + (set_attr "mode" "SI")]) + +(define_insn "move_scw" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (const_int 4))) + (set (mem:BLK (match_dup 1)) + (unspec:BLK [(match_operand:SI 2 "register_operand" "d") + (reg:SI SC_REGNUM)] SCW)) + (set (reg:SI SC_REGNUM) + (unspec:SI [(match_dup 2)] SCLC))] + "!TARGET_SCORE5U && !TARGET_LITTLE_ENDIAN" + "scw %2, [%1]+" + [(set_attr "type" "store") + (set_attr "mode" "SI")]) + +(define_insn "move_sce" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "register_operand" "0") + (const_int 4))) + (set (mem:BLK (match_dup 1)) + (unspec:BLK [(reg:SI SC_REGNUM)] SCE))] + "!TARGET_SCORE5U && !TARGET_LITTLE_ENDIAN" + "sce [%1]+" + [(set_attr "type" "store") + (set_attr "mode" "SI")]) + +(define_insn "andsi3_extzh" + [(set (match_operand:SI 0 "register_operand" "=d") + (and:SI (match_operand:SI 1 "register_operand" "d") + (const_int 65535)))] + "" + "extzh %0, %1" + [(set_attr "type" "arith") + (set_attr "mode" "SI")]) + +(define_insn "bitclr_c" + [(set (match_operand:SI 0 "register_operand" "=e,d") + (and:SI (match_operand:SI 1 "register_operand" "0,d") + (match_operand:SI 2 "const_npow2"))) + (clobber (reg:CC CC_REGNUM))] + "" + "@ + bitclr! %0, %F2 + bitclr.c %0, %1, %F2" + [(set_attr "type" "arith") + (set_attr "mode" "SI")]) + +(define_insn "bitset_c" + [(set (match_operand:SI 0 "register_operand" "=e,d") + (ior:SI (match_operand:SI 1 "register_operand" "0,d") + (match_operand:SI 2 "const_pow2"))) + (clobber (reg:CC CC_REGNUM))] + "" + "@ + bitset! %0, %E2 + bitset.c %0, %1, %E2" + [(set_attr "type" "arith") + (set_attr "mode" "SI")]) + +(define_insn "bittgl_c" + [(set (match_operand:SI 0 "register_operand" "=e,d") + (xor:SI (match_operand:SI 1 "register_operand" "0,d") + (match_operand:SI 2 "const_pow2"))) + (clobber (reg:CC CC_REGNUM))] + "" + "@ + bittgl! %0, %E2 + bittgl.c %0, %1, %E2" + [(set_attr "type" "arith") + (set_attr "mode" "SI")]) Index: gcc/config/score/score.c =================================================================== --- gcc/config/score/score.c (revision 120252) +++ gcc/config/score/score.c (working copy) @@ -67,7 +67,9 @@ static int score_symbol_insns (enum scor static int score_address_insns (rtx, enum machine_mode); -static bool score_rtx_costs (rtx, int, int, int *); +static bool score_rtx_costs (rtx, enum rtx_code, enum rtx_code, int *); + +static int score_address_cost (rtx); #undef TARGET_ASM_FILE_START #define TARGET_ASM_FILE_START th_asm_file_start @@ -126,6 +128,9 @@ static bool score_rtx_costs (rtx, int, i #undef TARGET_RTX_COSTS #define TARGET_RTX_COSTS score_rtx_costs +#undef TARGET_ADDRESS_COST +#define TARGET_ADDRESS_COST score_address_cost + #undef TARGET_DEFAULT_TARGET_FLAGS #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT @@ -154,7 +159,7 @@ score_pass_by_reference (CUMULATIVE_ARGS static rtx score_add_offset (rtx temp, rtx reg, HOST_WIDE_INT offset) { - if (!CONST_OK_FOR_LETTER_P (offset, 'O')) + if (!IMM_IN_RANGE (offset, 15, 1)) { reg = expand_simple_binop (GET_MODE (reg), PLUS, gen_int_mode (offset & 0xffffc000, @@ -499,12 +504,13 @@ enum reg_class score_char_to_class[256]; void score_override_options (void) { + flag_pic = false; if (!flag_pic) sdata_max = g_switch_set ? g_switch_value : DEFAULT_SDATA_MAX; else { sdata_max = 0; - if (g_switch_set) + if (g_switch_set && (g_switch_value != 0)) warning (0, "-fPIC and -G are incompatible"); } @@ -540,7 +546,7 @@ score_reg_class (int regno) || regno == ARG_POINTER_REGNUM) return ALL_REGS; - for (c = 0 ; c < N_REG_CLASSES ; c++) + for (c = 0; c < N_REG_CLASSES; c++) if (TEST_HARD_REG_BIT (reg_class_contents[c], regno)) return c; @@ -551,10 +557,10 @@ score_reg_class (int regno) enum reg_class score_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, enum reg_class class) { - if (reg_class_subset_p (G32_REGS, class)) - class = G32_REGS; if (reg_class_subset_p (G16_REGS, class)) - class = G16_REGS; + return G16_REGS; + if (reg_class_subset_p (G32_REGS, class)) + return G32_REGS; return class; } @@ -576,41 +582,34 @@ score_secondary_reload_class (enum reg_c /* Implement CONST_OK_FOR_LETTER_P macro. */ /* imm constraints - I IMM8 (i15-2-form) - J IMM5 (i15_1-form) - K IMM16 (i-form) - L IMM16s (i-form) - M IMM14 (ri-form) - N IMM14s (ri-form) - O IMM15s (ri-form) - P IMM12s (rix-form) / IMM10s(cop-form) << 2 */ + I imm16 << 16 + J uimm5 + K uimm16 + L simm16 + M uimm14 + N simm14 */ int -score_const_ok_for_letter_p (int value, char c) +score_const_ok_for_letter_p (HOST_WIDE_INT value, char c) { switch (c) { - case 'I': return IMM_IN_RANGE (value, 8, 0); + case 'I': return ((value & 0xffff) == 0); case 'J': return IMM_IN_RANGE (value, 5, 0); case 'K': return IMM_IN_RANGE (value, 16, 0); case 'L': return IMM_IN_RANGE (value, 16, 1); case 'M': return IMM_IN_RANGE (value, 14, 0); case 'N': return IMM_IN_RANGE (value, 14, 1); - case 'O': return IMM_IN_RANGE (value, 15, 1); - case 'P': return IMM_IN_RANGE (value, 12, 1); default : return 0; } } /* Implement EXTRA_CONSTRAINT macro. */ -/* Q const_hi imm - Z symbol_ref */ +/* Z symbol_ref */ int score_extra_constraint (rtx op, char c) { switch (c) { - case 'Q': - return (GET_CODE (op) == CONST_INT && (INTVAL (op) & 0xffff) == 0); case 'Z': return GET_CODE (op) == SYMBOL_REF; default: @@ -917,10 +916,8 @@ score_address_insns (rtx x, enum machine int factor; if (mode == BLKmode) - /* BLKmode is used for single unaligned loads and stores. */ factor = 1; else - /* Each word of a multi-word value will be accessed individually. */ factor = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; if (mda_classify_address (&addr, mode, x, false)) @@ -938,24 +935,53 @@ score_address_insns (rtx x, enum machine /* Implement TARGET_RTX_COSTS macro. */ static bool -score_rtx_costs (rtx x, int code, int outer_code, int *total) +score_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code, + int *total) { enum machine_mode mode = GET_MODE (x); switch (code) { case CONST_INT: - /* These can be used anywhere. */ - *total = 0; + if (outer_code == SET) + { + if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I') + || CONST_OK_FOR_LETTER_P (INTVAL (x), 'L')) + *total = COSTS_N_INSNS (1); + else + *total = COSTS_N_INSNS (2); + } + else if (outer_code == PLUS || outer_code == MINUS) + { + if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'N')) + *total = 0; + else if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I') + || CONST_OK_FOR_LETTER_P (INTVAL (x), 'L')) + *total = 1; + else + *total = COSTS_N_INSNS (2); + } + else if (outer_code == AND || outer_code == IOR) + { + if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'M')) + *total = 0; + else if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I') + || CONST_OK_FOR_LETTER_P (INTVAL (x), 'K')) + *total = 1; + else + *total = COSTS_N_INSNS (2); + } + else + { + *total = 0; + } return true; - /* Otherwise fall through to the handling below because - we'll need to construct the constant. */ case CONST: case SYMBOL_REF: case LABEL_REF: case CONST_DOUBLE: - *total = COSTS_N_INSNS (1); + *total = COSTS_N_INSNS (2); return true; case MEM: @@ -1011,7 +1037,8 @@ score_rtx_costs (rtx x, int code, int ou *total = COSTS_N_INSNS (4); return true; } - return false; + *total = COSTS_N_INSNS (1); + return true; case NEG: if (mode == DImode) @@ -1022,22 +1049,38 @@ score_rtx_costs (rtx x, int code, int ou return false; case MULT: - *total = COSTS_N_INSNS (12); + *total = optimize_size ? COSTS_N_INSNS (2) : COSTS_N_INSNS (12); return true; case DIV: case MOD: case UDIV: case UMOD: - *total = COSTS_N_INSNS (33); + *total = optimize_size ? COSTS_N_INSNS (2) : COSTS_N_INSNS (33); return true; case SIGN_EXTEND: - *total = COSTS_N_INSNS (2); - return true; - case ZERO_EXTEND: - *total = COSTS_N_INSNS (1); + switch (GET_MODE (XEXP (x, 0))) + { + case QImode: + case HImode: + if (GET_CODE (XEXP (x, 0)) == MEM) + { + *total = COSTS_N_INSNS (2); + + if (!TARGET_LITTLE_ENDIAN && + side_effects_p (XEXP (XEXP (x, 0), 0))) + *total = 100; + } + else + *total = COSTS_N_INSNS (1); + break; + + default: + *total = COSTS_N_INSNS (1); + break; + } return true; default: @@ -1045,6 +1088,13 @@ score_rtx_costs (rtx x, int code, int ou } } +/* Implement TARGET_ADDRESS_COST macro. */ +int +score_address_cost (rtx addr) +{ + return score_address_insns (addr, SImode); +} + /* Implement ASM_OUTPUT_EXTERNAL macro. */ int score_output_external (FILE *file ATTRIBUTE_UNUSED, @@ -1089,18 +1139,16 @@ score_return_addr (int count, rtx frame /* Implement PRINT_OPERAND macro. */ /* Score-specific operand codes: '[' print .set nor1 directive - ']' print .set r1 directive - + ']' print .set r1 directive 'U' print hi part of a CONST_INT rtx - 'D' print first part of const double - 'S' selectively print '!' if operand is 15bit instruction accessible - 'V' print "v!" if operand is 15bit instruction accessible, or - "lfh!" - + 'E' print log2(v) + 'F' print log2(~v) + 'D' print SFmode const double + 'S' selectively print "!" if operand is 15bit instruction accessible + 'V' print "v!" if operand is 15bit instruction accessible, or "lfh!" 'L' low part of DImode reg operand 'H' high part of DImode reg operand - - 'C' print part of opcode for a branch condition. */ + 'C' print part of opcode for a branch condition. */ void score_print_operand (FILE *file, rtx op, int c) { @@ -1125,9 +1173,11 @@ score_print_operand (FILE *file, rtx op, else if (c == 'D') { if (GET_CODE (op) == CONST_DOUBLE) - fprintf (file, HOST_WIDE_INT_PRINT_HEX, - TARGET_LITTLE_ENDIAN - ? CONST_DOUBLE_LOW (op) : CONST_DOUBLE_HIGH (op)); + { + rtx temp = gen_lowpart (SImode, op); + gcc_assert (GET_MODE (op) == SFmode); + fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (temp)); + } else output_addr_const (file, op); } @@ -1142,23 +1192,17 @@ score_print_operand (FILE *file, rtx op, gcc_assert (code == REG); fprintf (file, G16_REG_P (REGNO (op)) ? "v!" : "lfh!"); } - else if (code == REG) - { - int regnum = REGNO (op); - if ((c == 'H' && !WORDS_BIG_ENDIAN) - || (c == 'L' && WORDS_BIG_ENDIAN)) - regnum ++; - fprintf (file, "%s", reg_names[regnum]); - } else if (c == 'C') { + enum machine_mode mode = GET_MODE (XEXP (op, 0)); + switch (code) { case EQ: fputs ("eq", file); break; case NE: fputs ("ne", file); break; case GT: fputs ("gt", file); break; - case GE: fputs ("ge", file); break; - case LT: fputs ("lt", file); break; + case GE: fputs (mode != CCmode ? "pl" : "ge", file); break; + case LT: fputs (mode != CCmode ? "mi" : "lt", file); break; case LE: fputs ("le", file); break; case GTU: fputs ("gtu", file); break; case GEU: fputs ("cs", file); break; @@ -1168,6 +1212,46 @@ score_print_operand (FILE *file, rtx op, output_operand_lossage ("invalid operand for code: '%c'", code); } } + else if (c == 'E') + { + unsigned HOST_WIDE_INT i; + unsigned HOST_WIDE_INT pow2mask = 1; + unsigned HOST_WIDE_INT val; + + val = INTVAL (op); + for (i = 0; i < 32; i++) + { + if (val == pow2mask) + break; + pow2mask <<= 1; + } + gcc_assert (i < 32); + fprintf (file, HOST_WIDE_INT_PRINT_HEX, i); + } + else if (c == 'F') + { + unsigned HOST_WIDE_INT i; + unsigned HOST_WIDE_INT pow2mask = 1; + unsigned HOST_WIDE_INT val; + + val = ~INTVAL (op); + for (i = 0; i < 32; i++) + { + if (val == pow2mask) + break; + pow2mask <<= 1; + } + gcc_assert (i < 32); + fprintf (file, HOST_WIDE_INT_PRINT_HEX, i); + } + else if (code == REG) + { + int regnum = REGNO (op); + if ((c == 'H' && !WORDS_BIG_ENDIAN) + || (c == 'L' && WORDS_BIG_ENDIAN)) + regnum ++; + fprintf (file, "%s", reg_names[regnum]); + } else { switch (code) @@ -1233,4 +1317,48 @@ score_print_operand_address (FILE *file, gcc_unreachable (); } +/* Implement SELECT_CC_MODE macro. */ +enum machine_mode +score_select_cc_mode (enum rtx_code op, rtx x, rtx y) +{ + if ((op == EQ || op == NE || op == LT || op == GE) + && y == const0_rtx + && GET_MODE (x) == SImode) + { + switch (GET_CODE (x)) + { + case PLUS: + case MINUS: + case NEG: + case AND: + case IOR: + case XOR: + case NOT: + case ASHIFT: + case LSHIFTRT: + case ASHIFTRT: + return CC_NZmode; + + case SIGN_EXTEND: + case ZERO_EXTEND: + case ROTATE: + case ROTATERT: + return (op == LT || op == GE) ? CC_Nmode : CCmode; + + default: + return CCmode; + } + } + + if ((op == EQ || op == NE) + && (GET_CODE (y) == NEG) + && register_operand (XEXP (y, 0), SImode) + && register_operand (x, SImode)) + { + return CC_NZmode; + } + + return CCmode; +} + struct gcc_target targetm = TARGET_INITIALIZER; Index: gcc/config/score/score.h =================================================================== --- gcc/config/score/score.h (revision 120252) +++ gcc/config/score/score.h (working copy) @@ -28,19 +28,20 @@ extern GTY(()) rtx cmp_op0; extern GTY(()) rtx cmp_op1; /* Controlling the Compilation Driver. */ +#undef SWITCH_TAKES_ARG #define SWITCH_TAKES_ARG(CHAR) \ (DEFAULT_SWITCH_TAKES_ARG (CHAR) || (CHAR) == 'G') /* CC1_SPEC is the set of arguments to pass to the compiler proper. */ #undef CC1_SPEC -#define CC1_SPEC "%{!mel:-meb}" +#define CC1_SPEC "%{G*} %{!mel:-meb}" #undef ASM_SPEC #define ASM_SPEC \ "%{!mel:-EB} %{mel:-EL} %{mscore5u:-SCORE5U} %{mscore7:-SCORE7} %{G*}" #undef LINK_SPEC -#define LINK_SPEC "%{!mel:-EB} %{mel:-EL} %{G*}" +#define LINK_SPEC "%{!mel:-EB} %{mel:-EL} %{G*}" /* Run-time Target Specification. */ #define TARGET_CPU_CPP_BUILTINS() \ @@ -96,7 +97,7 @@ extern GTY(()) rtx cmp_op1; /* Allocation boundary (in *bits*) for storing arguments in argument list. */ #define PARM_BOUNDARY BITS_PER_WORD -#define STACK_BOUNDARY 64 +#define STACK_BOUNDARY BITS_PER_WORD /* Allocation boundary (in *bits*) for the code of a function. */ #define FUNCTION_BOUNDARY BITS_PER_WORD @@ -115,12 +116,41 @@ extern GTY(()) rtx cmp_op1; data to make it all fit in fewer cache lines. Another is to cause character arrays to be word-aligned so that `strcpy' calls that copy constants to character arrays can be done inline. */ -#define DATA_ALIGNMENT(TYPE, ALIGN) \ - ((((ALIGN) < BITS_PER_WORD) \ - && (TREE_CODE (TYPE) == ARRAY_TYPE \ - || TREE_CODE (TYPE) == UNION_TYPE \ +#define DATA_ALIGNMENT(TYPE, ALIGN) \ + ((((ALIGN) < BITS_PER_WORD) \ + && (TREE_CODE (TYPE) == ARRAY_TYPE \ + || TREE_CODE (TYPE) == UNION_TYPE \ || TREE_CODE (TYPE) == RECORD_TYPE)) ? BITS_PER_WORD : (ALIGN)) +/* If defined, a C expression to compute the alignment given to a + constant that is being placed in memory. EXP is the constant + and ALIGN is the alignment that the object would ordinarily have. + The value of this macro is used instead of that alignment to align + the object. + + If this macro is not defined, then ALIGN is used. + + The typical use of this macro is to increase alignment for string + constants to be word aligned so that `strcpy' calls that copy + constants can be done inline. */ +#define CONSTANT_ALIGNMENT(EXP, ALIGN) \ + ((TREE_CODE (EXP) == STRING_CST || TREE_CODE (EXP) == CONSTRUCTOR) \ + && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) + +/* If defined, a C expression to compute the alignment for a local + variable. TYPE is the data type, and ALIGN is the alignment that + the object would ordinarily have. The value of this macro is used + instead of that alignment to align the object. + + If this macro is not defined, then ALIGN is used. + + One use of this macro is to increase alignment of medium-size + data to make it all fit in fewer cache lines. */ +#define LOCAL_ALIGNMENT(TYPE, ALIGN) \ + ((TREE_CODE (TYPE) == ARRAY_TYPE \ + && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \ + && (ALIGN) < BITS_PER_WORD) ? BITS_PER_WORD : (ALIGN)) + /* Alignment of field after `int : 0' in a structure. */ #define EMPTY_FIELD_BOUNDARY 32 @@ -209,7 +239,7 @@ extern GTY(()) rtx cmp_op1; { \ /* General Purpose Registers */ \ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, \ /* Control Registers */ \ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ /* CEH/ CEL/ CNT/ LCR/ SCR / ARG_POINTER_REGNUM/ FRAME_POINTER_REGNUM */\ @@ -245,8 +275,8 @@ extern GTY(()) rtx cmp_op1; } #define REG_ALLOC_ORDER \ -{ 0, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, \ - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 2, 3, \ +{ 0, 1, 6, 7, 8, 9, 10, 11, 4, 5, 22, 23, 24, 25, 26, 27, \ + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 28, 29, 30, 31, 2, 3, \ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, \ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, \ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, \ @@ -386,18 +416,18 @@ enum reg_class score_preferred_reload_class (X, CLASS) /* If we need to load shorts byte-at-a-time, then we need a scratch. */ -#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \ +#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \ score_secondary_reload_class (CLASS, MODE, X) /* Return the register class of a scratch register needed to copy IN into or out of a register in CLASS in MODE. If it can be done directly, NO_REGS is returned. */ -#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \ +#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \ score_secondary_reload_class (CLASS, MODE, X) /* Return the maximum number of consecutive registers needed to represent mode MODE in a register of class CLASS. */ -#define CLASS_MAX_NREGS(CLASS, MODE) \ +#define CLASS_MAX_NREGS(CLASS, MODE) \ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) #define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \ @@ -607,8 +637,8 @@ typedef struct score_args #define HAVE_PRE_DECREMENT 1 #define HAVE_POST_INCREMENT 1 #define HAVE_POST_DECREMENT 1 -#define HAVE_PRE_MODIFY_DISP 0 -#define HAVE_POST_MODIFY_DISP 0 +#define HAVE_PRE_MODIFY_DISP 1 +#define HAVE_POST_MODIFY_DISP 1 #define HAVE_PRE_MODIFY_REG 0 #define HAVE_POST_MODIFY_REG 0 @@ -660,6 +690,13 @@ typedef struct score_args #define LEGITIMATE_CONSTANT_P(X) 1 +/* Condition Code Status. */ +#define SELECT_CC_MODE(OP, X, Y) score_select_cc_mode (OP, X, Y) + +/* Return nonzero if SELECT_CC_MODE will never return MODE for a + floating point inequality comparison. */ +#define REVERSIBLE_CC_MODE(MODE) 1 + /* Describing Relative Costs of Operations */ /* Compute extra cost of moving data between one register class and another. */ #define REGISTER_MOVE_COST(MODE, FROM, TO) \ @@ -753,32 +790,32 @@ typedef struct score_args sprintf ((LABEL), "*%s%s%ld", (LOCAL_LABEL_PREFIX), (PREFIX), (long) (NUM)) /* Output of Assembler Instructions. */ -#define REGISTER_NAMES \ -{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \ - "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \ - "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", \ - \ - "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ - "cr8", "cr9", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15", \ - \ - "ceh", "cel", "sr0", "sr1", "sr2", "_arg", "_frame", "", \ - "cr24", "cr25", "cr26", "cr27", "cr28", "cr29", "cr30", "cr31", \ - \ - "c1r0", "c1r1", "c1r2", "c1r3", "c1r4", "c1r5", "c1r6", "c1r7", \ - "c1r8", "c1r9", "c1r10", "c1r11", "c1r12", "c1r13", "c1r14", "c1r15", \ - "c1r16", "c1r17", "c1r18", "c1r19", "c1r20", "c1r21", "c1r22", "c1r23",\ - "c1r24", "c1r25", "c1r26", "c1r27", "c1r28", "c1r29", "c1r30", "c1r31",\ - \ - "c2r0", "c2r1", "c2r2", "c2r3", "c2r4", "c2r5", "c2r6", "c2r7", \ - "c2r8", "c2r9", "c2r10", "c2r11", "c2r12", "c2r13", "c2r14", "c2r15", \ - "c2r16", "c2r17", "c2r18", "c2r19", "c2r20", "c2r21", "c2r22", "c2r23",\ - "c2r24", "c2r25", "c2r26", "c2r27", "c2r28", "c2r29", "c2r30", "c2r31",\ - \ - "c3r0", "c3r1", "c3r2", "c3r3", "c3r4", "c3r5", "c3r6", "c3r7", \ - "c3r8", "c3r9", "c3r10", "c3r11", "c3r12", "c3r13", "c3r14", "c3r15", \ - "c3r16", "c3r17", "c3r18", "c3r19", "c3r20", "c3r21", "c3r22", "c3r23",\ - "c3r24", "c3r25", "c3r26", "c3r27", "c3r28", "c3r29", "c3r30", "c3r31",\ +#define REGISTER_NAMES \ +{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \ + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \ + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", \ + \ + "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ + "cr8", "cr9", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15", \ + \ + "ceh", "cel", "sr0", "sr1", "sr2", "_arg", "_frame", "", \ + "cr24", "cr25", "cr26", "cr27", "cr28", "cr29", "cr30", "cr31", \ + \ + "c1r0", "c1r1", "c1r2", "c1r3", "c1r4", "c1r5", "c1r6", "c1r7", \ + "c1r8", "c1r9", "c1r10", "c1r11", "c1r12", "c1r13", "c1r14", "c1r15", \ + "c1r16", "c1r17", "c1r18", "c1r19", "c1r20", "c1r21", "c1r22", "c1r23", \ + "c1r24", "c1r25", "c1r26", "c1r27", "c1r28", "c1r29", "c1r30", "c1r31", \ + \ + "c2r0", "c2r1", "c2r2", "c2r3", "c2r4", "c2r5", "c2r6", "c2r7", \ + "c2r8", "c2r9", "c2r10", "c2r11", "c2r12", "c2r13", "c2r14", "c2r15", \ + "c2r16", "c2r17", "c2r18", "c2r19", "c2r20", "c2r21", "c2r22", "c2r23", \ + "c2r24", "c2r25", "c2r26", "c2r27", "c2r28", "c2r29", "c2r30", "c2r31", \ + \ + "c3r0", "c3r1", "c3r2", "c3r3", "c3r4", "c3r5", "c3r6", "c3r7", \ + "c3r8", "c3r9", "c3r10", "c3r11", "c3r12", "c3r13", "c3r14", "c3r15", \ + "c3r16", "c3r17", "c3r18", "c3r19", "c3r20", "c3r21", "c3r22", "c3r23", \ + "c3r24", "c3r25", "c3r26", "c3r27", "c3r28", "c3r29", "c3r30", "c3r31", \ } /* Print operand X (an rtx) in assembler syntax to file FILE. */ @@ -907,4 +944,4 @@ struct extern_list GTY ((chain_next ("%h int size; /* size in bytes */ }; -extern GTY (()) struct extern_list *extern_head ; +extern GTY (()) struct extern_list *extern_head; Index: gcc/config/score/score-conv.h =================================================================== --- gcc/config/score/score-conv.h (revision 120252) +++ gcc/config/score/score-conv.h (working copy) @@ -45,7 +45,7 @@ extern int target_flags; #define CE_REG_P(REGNO) REG_CONTAIN (REGNO, CE_REG_FIRST, CE_REG_NUM) -#define UIMM_IN_RANGE(V, W) ((V) >= 0 && (V) < ((HOST_WIDE_INT)1 << (W))) +#define UIMM_IN_RANGE(V, W) ((V) >= 0 && (V) < ((HOST_WIDE_INT) 1 << (W))) #define SIMM_IN_RANGE(V, W) \ ((V) >= (-1 * ((HOST_WIDE_INT) 1 << ((W) - 1))) \ @@ -54,6 +54,11 @@ extern int target_flags; #define IMM_IN_RANGE(V, W, S) \ ((S) ? SIMM_IN_RANGE (V, W) : UIMM_IN_RANGE (V, W)) +#define IMM_IS_POW_OF_2(V, E1, E2) \ + ((V) >= ((unsigned HOST_WIDE_INT) 1 << (E1)) \ + && (V) <= ((unsigned HOST_WIDE_INT) 1 << (E2)) \ + && ((V) & ((V) - 1)) == 0) + #define SCORE_STACK_ALIGN(LOC) (((LOC) + 3) & ~3) #define SCORE_MAX_FIRST_STACK_STEP (0x3ff0) Index: gcc/config/score/score-mdaux.c =================================================================== --- gcc/config/score/score-mdaux.c (revision 120252) +++ gcc/config/score/score-mdaux.c (working copy) @@ -108,10 +108,9 @@ score_symbol_type score_classify_symbol if (GET_CODE (x) == LABEL_REF) return SYMBOL_GENERAL; - if (GET_CODE (x) != SYMBOL_REF) - gcc_unreachable (); + gcc_assert (GET_CODE (x) == SYMBOL_REF); - if (CONSTANT_POOL_ADDRESS_P(x)) + if (CONSTANT_POOL_ADDRESS_P (x)) { if (GET_MODE_SIZE (get_pool_mode (x)) <= SCORE_SDATA_MAX) return SYMBOL_SMALL_DATA; @@ -185,14 +184,14 @@ mda_compute_frame_size (HOST_WIDE_INT si f->mask = 0; f->var_size = SCORE_STACK_ALIGN (size); f->args_size = current_function_outgoing_args_size; - f->cprestore_size = SCORE_STACK_ALIGN (STARTING_FRAME_OFFSET) - f->args_size; + f->cprestore_size = flag_pic ? UNITS_PER_WORD : 0; if (f->var_size == 0 && current_function_is_leaf) f->args_size = f->cprestore_size = 0; if (f->args_size == 0 && current_function_calls_alloca) f->args_size = UNITS_PER_WORD; - f->total_size = f->var_size + f->args_size; + f->total_size = f->var_size + f->args_size + f->cprestore_size; for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) { if (score_save_reg_p (regno)) @@ -205,7 +204,7 @@ mda_compute_frame_size (HOST_WIDE_INT si if (current_function_calls_eh_return) { unsigned int i; - for (i = 0; ; ++i) + for (i = 0;; ++i) { regno = EH_RETURN_DATA_REGNO (i); if (regno == INVALID_REGNUM) @@ -215,7 +214,7 @@ mda_compute_frame_size (HOST_WIDE_INT si } } - f->total_size += SCORE_STACK_ALIGN (f->gp_reg_size); + f->total_size += f->gp_reg_size; f->num_gp = f->gp_reg_size / UNITS_PER_WORD; if (f->mask) @@ -226,12 +225,7 @@ mda_compute_frame_size (HOST_WIDE_INT si f->gp_sp_offset = offset; } else - { - f->gp_sp_offset = 0; - } - - if ((f->total_size == f->gp_reg_size) && flag_pic) - f->total_size += 8; + f->gp_sp_offset = 0; return f; } @@ -294,8 +288,13 @@ mdx_prologue (void) if (frame_pointer_needed) EMIT_PL (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx)); - if (flag_pic) - emit_insn (gen_cprestore (GEN_INT (size + 4))); + if (flag_pic && f->cprestore_size) + { + if (frame_pointer_needed) + emit_insn (gen_cprestore_use_fp (GEN_INT (size - f->cprestore_size))); + else + emit_insn (gen_cprestore_use_sp (GEN_INT (size - f->cprestore_size))); + } #undef EMIT_PL } @@ -392,7 +391,7 @@ mda_classify_address (struct score_addre info->offset = XEXP (x, 1); return (mda_valid_base_register_p (info->reg, strict) && GET_CODE (info->offset) == CONST_INT - && CONST_OK_FOR_LETTER_P (INTVAL (info->offset), 'O')); + && IMM_IN_RANGE (INTVAL (info->offset), 15, 1)); case PRE_DEC: case POST_DEC: case PRE_INC: @@ -405,7 +404,7 @@ mda_classify_address (struct score_addre return mda_valid_base_register_p (info->reg, strict); case CONST_INT: info->type = ADD_CONST_INT; - return CONST_OK_FOR_LETTER_P (INTVAL (x), 'O'); + return IMM_IN_RANGE (INTVAL (x), 15, 1); case CONST: case LABEL_REF: case SYMBOL_REF: @@ -443,7 +442,7 @@ mda_symbolic_constant_p (rtx x, enum sco return 1; /* if offset > 15bit, must reload */ - if (!CONST_OK_FOR_LETTER_P (offset, 'O')) + if (!IMM_IN_RANGE (offset, 15, 1)) return 0; switch (*symbol_type) @@ -459,11 +458,9 @@ mda_symbolic_constant_p (rtx x, enum sco void mdx_movsicc (rtx *ops) { - enum machine_mode mode = CCmode; - - if (GET_CODE (ops[1]) == EQ || GET_CODE (ops[1]) == NE) - mode = CC_NZmode; + enum machine_mode mode; + mode = score_select_cc_mode (GET_CODE (ops[1]), ops[2], ops[3]); emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (mode, CC_REGNUM), gen_rtx_COMPARE (mode, cmp_op0, cmp_op1))); } @@ -533,14 +530,15 @@ mds_movdi (rtx *ops) void mds_zero_extract_andi (rtx *ops) { - if (INTVAL (ops[1]) == 1 && const_bi_operand (ops[2], SImode)) + if (INTVAL (ops[1]) == 1 && const_uimm5 (ops[2], SImode)) emit_insn (gen_zero_extract_bittst (ops[0], ops[2])); else { unsigned HOST_WIDE_INT mask; mask = (0xffffffffU & ((1U << INTVAL (ops[1])) - 1U)); mask = mask << INTVAL (ops[2]); - emit_insn (gen_andsi3_cmp (ops[0], gen_int_mode (mask, SImode))); + emit_insn (gen_andsi3_cmp (ops[3], ops[0], + gen_int_mode (mask, SImode))); } } @@ -637,17 +635,20 @@ mdp_sinsn (rtx *ops, enum mda_mem_unit u const char * mdp_limm (rtx *ops) { + HOST_WIDE_INT v; + gcc_assert (GET_CODE (ops[0]) == REG); + gcc_assert (GET_CODE (ops[1]) == CONST_INT); - if (G16_REG_P (REGNO (ops[0])) - && CONST_OK_FOR_LETTER_P (INTVAL (ops[1]), 'I')) + v = INTVAL (ops[1]); + if (G16_REG_P (REGNO (ops[0])) && IMM_IN_RANGE (v, 8, 0)) return "ldiu! %0, %c1"; - else if (CONST_OK_FOR_LETTER_P (INTVAL (ops[1]), 'L')) + else if (IMM_IN_RANGE (v, 16, 1)) return "ldi %0, %c1"; - else if (EXTRA_CONSTRAINT (ops[1], 'Q')) + else if ((v & 0xffff) == 0) return "ldis %0, %U1"; else - return "li %0, %D1"; + return "li %0, %c1"; } /* Output asm insn for move. */ @@ -670,69 +671,389 @@ mdp_move (rtx *ops) return "mv %0, %1"; } -/* Score support add/sub with exponent immediate insn, - use to judge imm condition. */ -static unsigned int -num_bits1 (unsigned HOST_WIDE_INT v) +/* Emit lcb/lce insns. */ +bool +mdx_unaligned_load (rtx *ops) +{ + rtx dst = ops[0]; + rtx src = ops[1]; + rtx len = ops[2]; + rtx off = ops[3]; + rtx addr_reg; + + if (INTVAL (len) != BITS_PER_WORD + || (INTVAL (off) % BITS_PER_UNIT) != 0) + return false; + + gcc_assert (GET_MODE_SIZE (GET_MODE (dst)) == GET_MODE_SIZE (SImode)); + + addr_reg = copy_addr_to_reg (XEXP (src, 0)); + emit_insn (gen_move_lcb (addr_reg, addr_reg)); + emit_insn (gen_move_lce (addr_reg, addr_reg, dst)); + + return true; +} + +/* Emit scb/sce insns. */ +bool +mdx_unaligned_store (rtx *ops) +{ + rtx dst = ops[0]; + rtx len = ops[1]; + rtx off = ops[2]; + rtx src = ops[3]; + rtx addr_reg; + + if (INTVAL(len) != BITS_PER_WORD + || (INTVAL(off) % BITS_PER_UNIT) != 0) + return false; + + gcc_assert (GET_MODE_SIZE (GET_MODE (src)) == GET_MODE_SIZE (SImode)); + + addr_reg = copy_addr_to_reg (XEXP (dst, 0)); + emit_insn (gen_move_scb (addr_reg, addr_reg, src)); + emit_insn (gen_move_sce (addr_reg, addr_reg)); + + return true; +} + +/* If length is short, generate move insns straight. */ +static void +mdx_block_move_straight (rtx dst, rtx src, HOST_WIDE_INT length) +{ + HOST_WIDE_INT leftover; + int i, reg_count; + rtx *regs; + + leftover = length % UNITS_PER_WORD; + length -= leftover; + reg_count = length / UNITS_PER_WORD; + + regs = alloca (sizeof (rtx) * reg_count); + for (i = 0; i < reg_count; i++) + regs[i] = gen_reg_rtx (SImode); + + /* Load from src to regs. */ + if (MEM_ALIGN (src) >= BITS_PER_WORD) + { + HOST_WIDE_INT offset = 0; + for (i = 0; i < reg_count; offset += UNITS_PER_WORD, i++) + emit_move_insn (regs[i], adjust_address (src, SImode, offset)); + } + else if (reg_count >= 1) + { + rtx src_reg = copy_addr_to_reg (XEXP (src, 0)); + + emit_insn (gen_move_lcb (src_reg, src_reg)); + for (i = 0; i < (reg_count - 1); i++) + emit_insn (gen_move_lcw (src_reg, src_reg, regs[i])); + emit_insn (gen_move_lce (src_reg, src_reg, regs[i])); + } + + /* Store regs to dest. */ + if (MEM_ALIGN (dst) >= BITS_PER_WORD) + { + HOST_WIDE_INT offset = 0; + for (i = 0; i < reg_count; offset += UNITS_PER_WORD, i++) + emit_move_insn (adjust_address (dst, SImode, offset), regs[i]); + } + else if (reg_count >= 1) + { + rtx dst_reg = copy_addr_to_reg (XEXP (dst, 0)); + + emit_insn (gen_move_scb (dst_reg, dst_reg, regs[0])); + for (i = 1; i < reg_count; i++) + emit_insn (gen_move_scw (dst_reg, dst_reg, regs[i])); + emit_insn (gen_move_sce (dst_reg, dst_reg)); + } + + /* Mop up any left-over bytes. */ + if (leftover > 0) + { + src = adjust_address (src, BLKmode, length); + dst = adjust_address (dst, BLKmode, length); + move_by_pieces (dst, src, leftover, + MIN (MEM_ALIGN (src), MEM_ALIGN (dst)), 0); + } +} + +/* Generate loop head when dst or src is unaligned. */ +static void +mdx_block_move_loop_head (rtx dst_reg, HOST_WIDE_INT dst_align, + rtx src_reg, HOST_WIDE_INT src_align, + HOST_WIDE_INT length) { - int i, n = 0; + bool src_unaligned = (src_align < BITS_PER_WORD); + bool dst_unaligned = (dst_align < BITS_PER_WORD); + + rtx temp = gen_reg_rtx (SImode); - for (i = 0; i < BITS_PER_WORD; i++) - n += BITSET_P (v, i) ? 1 : 0; - return n; + gcc_assert (length == UNITS_PER_WORD); + + if (src_unaligned) + { + emit_insn (gen_move_lcb (src_reg, src_reg)); + emit_insn (gen_move_lcw (src_reg, src_reg, temp)); + } + else + emit_insn (gen_move_lw_a (src_reg, + src_reg, gen_int_mode (4, SImode), temp)); + + if (dst_unaligned) + emit_insn (gen_move_scb (dst_reg, dst_reg, temp)); + else + emit_insn (gen_move_sw_a (dst_reg, + dst_reg, gen_int_mode (4, SImode), temp)); } -/* Generate add insn, insn will affect condition flag. Optimize used. */ +/* Generate loop body, copy length bytes per iteration. */ +static void +mdx_block_move_loop_body (rtx dst_reg, HOST_WIDE_INT dst_align, + rtx src_reg, HOST_WIDE_INT src_align, + HOST_WIDE_INT length) +{ + int reg_count = length / UNITS_PER_WORD; + rtx *regs = alloca (sizeof (rtx) * reg_count); + int i; + bool src_unaligned = (src_align < BITS_PER_WORD); + bool dst_unaligned = (dst_align < BITS_PER_WORD); + + for (i = 0; i < reg_count; i++) + regs[i] = gen_reg_rtx (SImode); + + if (src_unaligned) + { + for (i = 0; i < reg_count; i++) + emit_insn (gen_move_lcw (src_reg, src_reg, regs[i])); + } + else + { + for (i = 0; i < reg_count; i++) + emit_insn (gen_move_lw_a (src_reg, + src_reg, gen_int_mode (4, SImode), regs[i])); + } + + if (dst_unaligned) + { + for (i = 0; i < reg_count; i++) + emit_insn (gen_move_scw (dst_reg, dst_reg, regs[i])); + } + else + { + for (i = 0; i < reg_count; i++) + emit_insn (gen_move_sw_a (dst_reg, + dst_reg, gen_int_mode (4, SImode), regs[i])); + } +} + +/* Generate loop foot, copy the leftover bytes. */ +static void +mdx_block_move_loop_foot (rtx dst_reg, HOST_WIDE_INT dst_align, + rtx src_reg, HOST_WIDE_INT src_align, + HOST_WIDE_INT length) +{ + bool src_unaligned = (src_align < BITS_PER_WORD); + bool dst_unaligned = (dst_align < BITS_PER_WORD); + + HOST_WIDE_INT leftover; + + leftover = length % UNITS_PER_WORD; + length -= leftover; + + if (length > 0) + mdx_block_move_loop_body (dst_reg, dst_align, + src_reg, src_align, length); + + if (dst_unaligned) + emit_insn (gen_move_sce (dst_reg, dst_reg)); + + if (leftover > 0) + { + HOST_WIDE_INT src_adj = src_unaligned ? -4 : 0; + HOST_WIDE_INT dst_adj = dst_unaligned ? -4 : 0; + rtx temp; + + gcc_assert (leftover < UNITS_PER_WORD); + + if (leftover >= UNITS_PER_WORD / 2 + && src_align >= BITS_PER_WORD / 2 + && dst_align >= BITS_PER_WORD / 2) + { + temp = gen_reg_rtx (HImode); + emit_insn (gen_move_lhu_b (src_reg, src_reg, + gen_int_mode (src_adj, SImode), temp)); + emit_insn (gen_move_sh_b (dst_reg, dst_reg, + gen_int_mode (dst_adj, SImode), temp)); + leftover -= UNITS_PER_WORD / 2; + src_adj = UNITS_PER_WORD / 2; + dst_adj = UNITS_PER_WORD / 2; + } + + while (leftover > 0) + { + temp = gen_reg_rtx (QImode); + emit_insn (gen_move_lbu_b (src_reg, src_reg, + gen_int_mode (src_adj, SImode), temp)); + emit_insn (gen_move_sb_b (dst_reg, dst_reg, + gen_int_mode (dst_adj, SImode), temp)); + leftover--; + src_adj = 1; + dst_adj = 1; + } + } +} + +#define MIN_MOVE_REGS 3 +#define MIN_MOVE_BYTES (MIN_MOVE_REGS * UNITS_PER_WORD) +#define MAX_MOVE_REGS 4 +#define MAX_MOVE_BYTES (MAX_MOVE_REGS * UNITS_PER_WORD) + +/* The length is large, generate a loop if necessary. + The loop is consisted by loop head/body/foot. */ +static void +mdx_block_move_loop (rtx dst, rtx src, HOST_WIDE_INT length) +{ + HOST_WIDE_INT src_align = MEM_ALIGN (src); + HOST_WIDE_INT dst_align = MEM_ALIGN (dst); + HOST_WIDE_INT loop_mov_bytes; + HOST_WIDE_INT iteration = 0; + HOST_WIDE_INT head_length = 0, leftover; + rtx label, src_reg, dst_reg, final_dst; + + bool gen_loop_head = (src_align < BITS_PER_WORD + || dst_align < BITS_PER_WORD); + + if (gen_loop_head) + head_length += UNITS_PER_WORD; + + for (loop_mov_bytes = MAX_MOVE_BYTES; + loop_mov_bytes >= MIN_MOVE_BYTES; + loop_mov_bytes -= UNITS_PER_WORD) + { + iteration = (length - head_length) / loop_mov_bytes; + if (iteration > 1) + break; + } + if (iteration <= 1) + { + mdx_block_move_straight (dst, src, length); + return; + } + + leftover = (length - head_length) % loop_mov_bytes; + length -= leftover; + + src_reg = copy_addr_to_reg (XEXP (src, 0)); + dst_reg = copy_addr_to_reg (XEXP (dst, 0)); + final_dst = expand_simple_binop (Pmode, PLUS, dst_reg, GEN_INT (length), + 0, 0, OPTAB_WIDEN); + + if (gen_loop_head) + mdx_block_move_loop_head (dst_reg, dst_align, + src_reg, src_align, head_length); + + label = gen_label_rtx (); + emit_label (label); + + mdx_block_move_loop_body (dst_reg, dst_align, + src_reg, src_align, loop_mov_bytes); + + emit_insn (gen_cmpsi (dst_reg, final_dst)); + emit_jump_insn (gen_bne (label)); + + mdx_block_move_loop_foot (dst_reg, dst_align, + src_reg, src_align, leftover); +} + +/* Generate block move, for misc.md: "movmemsi". */ +bool +mdx_block_move (rtx *ops) +{ + rtx dst = ops[0]; + rtx src = ops[1]; + rtx length = ops[2]; + + if (TARGET_LITTLE_ENDIAN + && (MEM_ALIGN (src) < BITS_PER_WORD || MEM_ALIGN (dst) < BITS_PER_WORD) + && INTVAL (length) >= UNITS_PER_WORD) + return false; + + if (GET_CODE (length) == CONST_INT) + { + if (INTVAL (length) <= 2 * MAX_MOVE_BYTES) + { + mdx_block_move_straight (dst, src, INTVAL (length)); + return true; + } + else if (optimize && + !(flag_unroll_loops || flag_unroll_all_loops)) + { + mdx_block_move_loop (dst, src, INTVAL (length)); + return true; + } + } + return false; +} + +/* Generate add insn. */ const char * -mdp_add_imm_ucc (rtx *ops) +mdp_select_add_imm (rtx *ops, bool set_cc) { HOST_WIDE_INT v = INTVAL (ops[2]); gcc_assert (GET_CODE (ops[2]) == CONST_INT); gcc_assert (REGNO (ops[0]) == REGNO (ops[1])); - if (G16_REG_P (REGNO (ops[0]))) + if (set_cc && G16_REG_P (REGNO (ops[0]))) { - if (v > 0 && num_bits1 (v) == 1 && IMM_IN_RANGE (ffs (v) - 1, 4, 0)) + if (v > 0 && IMM_IS_POW_OF_2 ((unsigned HOST_WIDE_INT) v, 0, 15)) { ops[2] = GEN_INT (ffs (v) - 1); return "addei! %0, %c2"; } - if (v < 0 && num_bits1 (-v) == 1 && IMM_IN_RANGE (ffs (-v) - 1, 4, 0)) + if (v < 0 && IMM_IS_POW_OF_2 ((unsigned HOST_WIDE_INT) (-v), 0, 15)) { ops[2] = GEN_INT (ffs (-v) - 1); return "subei! %0, %c2"; } } + + if (set_cc) return "addi.c %0, %c2"; + else + return "addi %0, %c2"; } -/* Output arith insn, insn will update condition flag. */ +/* Output arith insn. */ const char * -mdp_select (rtx *ops, const char *inst_pre, bool commu, const char *let) +mdp_select (rtx *ops, const char *inst_pre, + bool commu, const char *letter, bool set_cc) { gcc_assert (GET_CODE (ops[0]) == REG); gcc_assert (GET_CODE (ops[1]) == REG); - if (G16_REG_P (REGNO (ops[0])) + if (set_cc && G16_REG_P (REGNO (ops[0])) && (GET_CODE (ops[2]) == REG ? G16_REG_P (REGNO (ops[2])) : 1) && REGNO (ops[0]) == REGNO (ops[1])) { - snprintf (ins, INS_BUF_SZ, "%s! %%0, %%%s2", inst_pre, let); + snprintf (ins, INS_BUF_SZ, "%s! %%0, %%%s2", inst_pre, letter); return ins; } - if (commu && G16_REG_P (REGNO (ops[0])) + if (commu && set_cc && G16_REG_P (REGNO (ops[0])) && G16_REG_P (REGNO (ops[1])) && REGNO (ops[0]) == REGNO (ops[2])) { gcc_assert (GET_CODE (ops[2]) == REG); - snprintf (ins, INS_BUF_SZ, "%s! %%0, %%%s1", inst_pre, let); + snprintf (ins, INS_BUF_SZ, "%s! %%0, %%%s1", inst_pre, letter); return ins; } - snprintf (ins, INS_BUF_SZ, "%s.c %%0, %%1, %%%s2", inst_pre, let); + if (set_cc) + snprintf (ins, INS_BUF_SZ, "%s.c %%0, %%1, %%%s2", inst_pre, letter); + else + snprintf (ins, INS_BUF_SZ, "%s %%0, %%1, %%%s2", inst_pre, letter); return ins; } Index: gcc/config/score/score.md =================================================================== --- gcc/config/score/score.md (revision 120252) +++ gcc/config/score/score.md (working copy) @@ -59,8 +59,8 @@ (define_constants [(BITTST 0) - (LOAD_ADD 1) - (STORE_ADD 2) + (CPLOAD 1) + (CPRESTORE 2) (SCB 3) (SCW 4) @@ -88,10 +88,22 @@ (include "misc.md") (include "mac.md") -(define_insn "movqi" +(define_expand "movqi" + [(set (match_operand:QI 0 "nonimmediate_operand") + (match_operand:QI 1 "general_operand"))] + "" +{ + if (MEM_P (operands[0]) + && !register_operand (operands[1], QImode)) + { + operands[1] = force_reg (QImode, operands[1]); + } +}) + +(define_insn "*movqi_insns" [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,m,d,*x,d,*a") (match_operand:QI 1 "general_operand" "i,d,m,d,*x,d,*a,d"))] - "" + "!MEM_P (operands[0]) || register_operand (operands[1], QImode)" { switch (which_alternative) { @@ -109,10 +121,22 @@ [(set_attr "type" "arith,move,load,store,fce,tce,fsr,tsr") (set_attr "mode" "QI")]) -(define_insn "movhi" +(define_expand "movhi" + [(set (match_operand:HI 0 "nonimmediate_operand") + (match_operand:HI 1 "general_operand"))] + "" +{ + if (MEM_P (operands[0]) + && !register_operand (operands[1], HImode)) + { + operands[1] = force_reg (HImode, operands[1]); + } +}) + +(define_insn "*movhi_insns" [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,m,d,*x,d,*a") (match_operand:HI 1 "general_operand" "i,d,m,d,*x,d,*a,d"))] - "" + "!MEM_P (operands[0]) || register_operand (operands[1], HImode)" { switch (which_alternative) { @@ -130,11 +154,23 @@ [(set_attr "type" "arith,move,load,store,fce,tce,fsr,tsr") (set_attr "mode" "HI")]) -(define_insn "movsi" - [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,m,d,*x,d,*a,d,c") - (match_operand:SI 1 "general_operand" "i,d,m,d,*x,d,*a,d,c,d"))] +(define_expand "movsi" + [(set (match_operand:SI 0 "nonimmediate_operand") + (match_operand:SI 1 "general_operand"))] "" { + if (MEM_P (operands[0]) + && !register_operand (operands[1], SImode)) + { + operands[1] = force_reg (SImode, operands[1]); + } +}) + +(define_insn "*movsi_insns" + [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,m,d,*x,d,*a,d,*c") + (match_operand:SI 1 "general_operand" "i,d,m,d,*x,d,*a,d,*c,d"))] + "!MEM_P (operands[0]) || register_operand (operands[1], SImode)" +{ switch (which_alternative) { case 0: @@ -169,46 +205,103 @@ DONE; }) +(define_expand "movsf" + [(set (match_operand:SF 0 "nonimmediate_operand") + (match_operand:SF 1 "general_operand"))] + "" +{ + if (MEM_P (operands[0]) + && !register_operand (operands[1], SFmode)) + { + operands[1] = force_reg (SFmode, operands[1]); + } +}) + +(define_insn "*movsf_insns" + [(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,d,m") + (match_operand:SF 1 "general_operand" "i,d,m,d"))] + "!MEM_P (operands[0]) || register_operand (operands[1], SFmode)" +{ + switch (which_alternative) + { + case 0: return \"li %0, %D1\";; + case 1: return mdp_move (operands); + case 2: return mdp_linsn (operands, MDA_WORD, false); + case 3: return mdp_sinsn (operands, MDA_WORD); + default: gcc_unreachable (); + } +} + [(set_attr "type" "arith,move,load,store") + (set_attr "mode" "SI")]) + +(define_insn_and_split "movdf" + [(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,d,m") + (match_operand:DF 1 "general_operand" "i,d,m,d"))] + "" + "#" + "reload_completed" + [(const_int 0)] +{ + mds_movdi (operands); + DONE; +}) + (define_insn "addsi3" - [(set (match_operand:SI 0 "register_operand" "=d,d,d") - (plus:SI (match_operand:SI 1 "register_operand" "0,d,%d") - (match_operand:SI 2 "arith_operand" "L,N,d")))] + [(set (match_operand:SI 0 "register_operand" "=d,d,d,d") + (plus:SI (match_operand:SI 1 "register_operand" "0,0,d,d") + (match_operand:SI 2 "arith_operand" "I,L,N,d")))] "" - "@ - addi %0, %c2 - addri %0, %1, %c2 - add %0, %1, %2" +{ + switch (which_alternative) + { + case 0: return \"addis %0, %U2\"; + case 1: return mdp_select_add_imm (operands, false); + case 2: return \"addri %0, %1, %c2\"; + case 3: return mdp_select (operands, "add", true, "", false); + default: gcc_unreachable (); + } +} [(set_attr "type" "arith") (set_attr "mode" "SI")]) (define_insn "*addsi3_cmp" [(set (reg:CC_NZ CC_REGNUM) - (compare:CC_NZ (plus:SI (match_operand:SI 0 "register_operand" "d,d,d") - (match_operand:SI 1 "arith_operand" "N,L,d")) - (const_int 0)))] + (compare:CC_NZ (plus:SI + (match_operand:SI 1 "register_operand" "0,0,d,d") + (match_operand:SI 2 "arith_operand" "I,L,N,d")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=d,d,d,d"))] "" - "@ - %[ addri.c r1, %0, %c1 %] - %[ m%V0 r1, %0\;addi.c r1, %2 %] - %[ add.c r1, %0, %1 %]" +{ + switch (which_alternative) + { + case 0: return \"addis.c %0, %U2\"; + case 1: return mdp_select_add_imm (operands, true); + case 2: return \"addri.c %0, %1, %c2\"; + case 3: return mdp_select (operands, "add", true, "", true); + default: gcc_unreachable (); + } +} [(set_attr "type" "arith") (set_attr "up_c" "yes") (set_attr "mode" "SI")]) -(define_insn "addsi3_ucc" +(define_insn "*addsi3_ucc" [(set (reg:CC_NZ CC_REGNUM) - (compare:CC_NZ (plus:SI (match_operand:SI 1 "register_operand" "0,d,d") - (match_operand:SI 2 "arith_operand" "L,N,d")) + (compare:CC_NZ (plus:SI + (match_operand:SI 1 "register_operand" "0,0,d,d") + (match_operand:SI 2 "arith_operand" "I,L,N,d")) (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=d,d,d") + (set (match_operand:SI 0 "register_operand" "=d,d,d,d") (plus:SI (match_dup 1) (match_dup 2)))] "" { switch (which_alternative) { - case 0: return mdp_add_imm_ucc (operands); - case 1: return \"addri.c %0, %1, %c2\"; - case 2: return mdp_select (operands, "add", true, ""); + case 0: return \"addis.c %0, %U2\"; + case 1: return mdp_select_add_imm (operands, true); + case 2: return \"addri.c %0, %1, %c2\"; + case 3: return mdp_select (operands, "add", true, "", true); default: gcc_unreachable (); } } @@ -217,9 +310,9 @@ (set_attr "mode" "SI")]) (define_insn "adddi3" - [(set (match_operand:DI 0 "register_operand" "=*e,d") - (plus:DI (match_operand:DI 1 "register_operand" "*0,d") - (match_operand:DI 2 "register_operand" "*e,d"))) + [(set (match_operand:DI 0 "register_operand" "=e,d") + (plus:DI (match_operand:DI 1 "register_operand" "0,d") + (match_operand:DI 2 "register_operand" "e,d"))) (clobber (reg:CC CC_REGNUM))] "" "@ @@ -233,17 +326,22 @@ (minus:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d")))] "" - "sub %0, %1, %2" +{ + return mdp_select (operands, "sub", false, "", false); +} [(set_attr "type" "arith") (set_attr "mode" "SI")]) (define_insn "*subsi3_cmp" [(set (reg:CC_NZ CC_REGNUM) - (compare:CC_NZ (minus:SI (match_operand:SI 0 "register_operand" "d") - (match_operand:SI 1 "register_operand" "d")) - (const_int 0)))] + (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "d") + (match_operand:SI 2 "register_operand" "d")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=d"))] "" - "%[ sub.c r1, %0, %1 %]" +{ + return mdp_select (operands, "sub", false, "", true); +} [(set_attr "type" "arith") (set_attr "up_c" "yes") (set_attr "mode" "SI")]) @@ -255,11 +353,10 @@ (set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (match_dup 2)))] "" - [(parallel - [(set (reg:CC CC_REGNUM) - (compare:CC (match_dup 1) (match_dup 2))) - (set (match_dup 0) - (minus:SI (match_dup 1) (match_dup 2)))])]) + [(set (reg:CC CC_REGNUM) + (compare:CC (match_dup 1) (match_dup 2))) + (set (match_dup 0) + (minus:SI (match_dup 1) (match_dup 2)))]) (define_insn "subsi3_ucc_pcmp" [(parallel @@ -270,7 +367,7 @@ (minus:SI (match_dup 1) (match_dup 2)))])] "" { - return mdp_select (operands, "sub", false, ""); + return mdp_select (operands, "sub", false, "", true); } [(set_attr "type" "arith") (set_attr "up_c" "yes") @@ -285,16 +382,16 @@ (minus:SI (match_dup 1) (match_dup 2)))] "" { - return mdp_select (operands, "sub", false, ""); + return mdp_select (operands, "sub", false, "", true); } [(set_attr "type" "arith") (set_attr "up_c" "yes") (set_attr "mode" "SI")]) (define_insn "subdi3" - [(set (match_operand:DI 0 "register_operand" "=*e,d") - (minus:DI (match_operand:DI 1 "register_operand" "*0,d") - (match_operand:DI 2 "register_operand" "*e,d"))) + [(set (match_operand:DI 0 "register_operand" "=e,d") + (minus:DI (match_operand:DI 1 "register_operand" "0,d") + (match_operand:DI 2 "register_operand" "e,d"))) (clobber (reg:CC CC_REGNUM))] "" "@ @@ -306,36 +403,47 @@ (define_insn "andsi3" [(set (match_operand:SI 0 "register_operand" "=d,d,d,d") (and:SI (match_operand:SI 1 "register_operand" "0,0,d,d") - (match_operand:SI 2 "arith_operand" "K,Q,M,d")))] + (match_operand:SI 2 "arith_operand" "I,K,M,d")))] "" - "@ - andi %0, %c2 - andis %0, %U2 - andri %0, %1, %c2 - and %0, %1, %2" +{ + switch (which_alternative) + { + case 0: return \"andis %0, %U2\"; + case 1: return \"andi %0, %c2"; + case 2: return \"andri %0, %1, %c2\"; + case 3: return mdp_select (operands, "and", true, "", false); + default: gcc_unreachable (); + } +} [(set_attr "type" "arith") (set_attr "mode" "SI")]) (define_insn "andsi3_cmp" [(set (reg:CC_NZ CC_REGNUM) - (compare:CC_NZ (and:SI (match_operand:SI 0 "register_operand" "d,d,d,d") - (match_operand:SI 1 "arith_operand" "M,K,Q,d")) - (const_int 0)))] + (compare:CC_NZ (and:SI (match_operand:SI 1 "register_operand" "0,0,0,d") + (match_operand:SI 2 "arith_operand" "I,K,M,d")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=d,d,d,d"))] "" - "@ - %[ andri.c r1, %0, %c1 %] - %[ m%V0 r1, %0\;andi.c r1, %c1 %] - %[ m%V0 r1, %0\;andis.c r1, %U1 %] - %[ and.c r1, %0, %1 %]" +{ + switch (which_alternative) + { + case 0: return \"andis.c %0, %U2\"; + case 1: return \"andi.c %0, %c2"; + case 2: return \"andri.c %0, %1, %c2\"; + case 3: return mdp_select (operands, "and", true, "", true); + default: gcc_unreachable (); + } +} [(set_attr "type" "arith") (set_attr "up_c" "yes") (set_attr "mode" "SI")]) -(define_insn "andsi3_ucc" +(define_insn "*andsi3_ucc" [(set (reg:CC_NZ CC_REGNUM) (compare:CC_NZ (and:SI (match_operand:SI 1 "register_operand" "0,0,d,d") - (match_operand:SI 2 "arith_operand" "K,Q,M,d")) + (match_operand:SI 2 "arith_operand" "I,K,M,d")) (const_int 0))) (set (match_operand:SI 0 "register_operand" "=d,d,d,d") (and:SI (match_dup 1) (match_dup 2)))] @@ -343,10 +451,10 @@ { switch (which_alternative) { - case 0: return \"andi.c %0, %c2\"; - case 1: return \"andis.c %0, %U2\"; - case 2: return \"andri.c %0, %1, %c2\"; - case 3: return mdp_select (operands, "and", true, ""); + case 0: return \"andis.c %0, %U2\"; + case 1: return \"andi.c %0, %c2"; + case 2: return \"andri.c %0, %1, %c2\"; + case 3: return mdp_select (operands, "and", true, "", true); default: gcc_unreachable (); } } @@ -355,12 +463,12 @@ (set_attr "mode" "SI")]) (define_insn_and_split "*zero_extract_andi" - [(set (reg:CC_NZ CC_REGNUM) - (compare:CC_NZ (zero_extract:SI - (match_operand:SI 0 "register_operand" "d") - (match_operand:SI 1 "const_bi_operand" "") - (match_operand:SI 2 "const_bi_operand" "")) - (const_int 0)))] + [(set (reg:CC CC_REGNUM) + (compare:CC (zero_extract:SI + (match_operand:SI 0 "register_operand" "d") + (match_operand:SI 1 "const_uimm5" "") + (match_operand:SI 2 "const_uimm5" "")) + (const_int 0)))] "" "#" "" @@ -373,26 +481,39 @@ (define_insn "iorsi3" [(set (match_operand:SI 0 "register_operand" "=d,d,d,d") (ior:SI (match_operand:SI 1 "register_operand" "0,0,d,d") - (match_operand:SI 2 "arith_operand" "K,Q,M,d")))] + (match_operand:SI 2 "arith_operand" "I,K,M,d")))] "" - "@ - ori %0, %c2 - oris %0, %U2 - orri %0, %1, %c2 - or %0, %1, %2" +{ + switch (which_alternative) + { + case 0: return \"oris %0, %U2\"; + case 1: return \"ori %0, %c2\"; + case 2: return \"orri %0, %1, %c2\"; + case 3: return mdp_select (operands, "or", true, "", false); + default: gcc_unreachable (); + } +} [(set_attr "type" "arith") (set_attr "mode" "SI")]) (define_insn "iorsi3_ucc" [(set (reg:CC_NZ CC_REGNUM) - (compare:CC_NZ (ior:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d")) + (compare:CC_NZ (ior:SI + (match_operand:SI 1 "register_operand" "0,0,d,d") + (match_operand:SI 2 "arith_operand" "I,K,M,d")) (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=d") + (set (match_operand:SI 0 "register_operand" "=d,d,d,d") (ior:SI (match_dup 1) (match_dup 2)))] "" { - return mdp_select (operands, "or", true, ""); + switch (which_alternative) + { + case 0: return \"oris.c %0, %U2\"; + case 1: return \"ori.c %0, %c2\"; + case 2: return \"orri.c %0, %1, %c2\"; + case 3: return mdp_select (operands, "or", true, "", true); + default: gcc_unreachable (); + } } [(set_attr "type" "arith") (set_attr "up_c" "yes") @@ -400,11 +521,22 @@ (define_insn "iorsi3_cmp" [(set (reg:CC_NZ CC_REGNUM) - (compare:CC_NZ (ior:SI (match_operand:SI 0 "register_operand" "d") - (match_operand:SI 1 "register_operand" "d")) - (const_int 0)))] + (compare:CC_NZ (ior:SI + (match_operand:SI 1 "register_operand" "0,0,d,d") + (match_operand:SI 2 "arith_operand" "I,K,M,d")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=d,d,d,d"))] "" - "%[ or.c r1, %0, %1 %]" +{ + switch (which_alternative) + { + case 0: return \"oris.c %0, %U2\"; + case 1: return \"ori.c %0, %c2\"; + case 2: return \"orri.c %0, %1, %c2\"; + case 3: return mdp_select (operands, "or", true, "", true); + default: gcc_unreachable (); + } +} [(set_attr "type" "arith") (set_attr "up_c" "yes") (set_attr "mode" "SI")]) @@ -414,7 +546,9 @@ (xor:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d")))] "" - "xor %0, %1, %2" +{ + return mdp_select (operands, "xor", true, "", false); +} [(set_attr "type" "arith") (set_attr "mode" "SI")]) @@ -427,7 +561,7 @@ (xor:SI (match_dup 1) (match_dup 2)))] "" { - return mdp_select (operands, "xor", true, ""); + return mdp_select (operands, "xor", true, "", true); } [(set_attr "type" "arith") (set_attr "up_c" "yes") @@ -435,11 +569,14 @@ (define_insn "xorsi3_cmp" [(set (reg:CC_NZ CC_REGNUM) - (compare:CC_NZ (xor:SI (match_operand:SI 0 "register_operand" "d") - (match_operand:SI 1 "register_operand" "d")) - (const_int 0)))] + (compare:CC_NZ (xor:SI (match_operand:SI 1 "register_operand" "d") + (match_operand:SI 2 "register_operand" "d")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=d"))] "" - "%[ xor.c r1, %0, %1 %]" +{ + return mdp_select (operands, "xor", true, "", true); +} [(set_attr "type" "arith") (set_attr "up_c" "yes") (set_attr "mode" "SI")]) @@ -459,49 +596,35 @@ [(set_attr "type" "arith,load") (set_attr "mode" "SI")]) -(define_insn "extendqisi2_cmp" +(define_insn "*extendqisi2_ucc" [(set (reg:CC_N CC_REGNUM) (compare:CC_N (ashiftrt:SI - (ashift:SI (match_operand:SI 0 "register_operand" "d") + (ashift:SI (match_operand:SI 1 "register_operand" "d") (const_int 24)) (const_int 24)) - (const_int 0)))] + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=d") + (sign_extend:SI (match_operand:QI 2 "register_operand" "0")))] "" - "%[ extsb.c r1, %0 %]" + "extsb.c %0, %1" [(set_attr "type" "arith") (set_attr "up_c" "yes") (set_attr "mode" "SI")]) -(define_insn "extendqisi2_ucc" +(define_insn "*extendqisi2_cmp" [(set (reg:CC_N CC_REGNUM) (compare:CC_N (ashiftrt:SI (ashift:SI (match_operand:SI 1 "register_operand" "d") (const_int 24)) (const_int 24)) (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=d") - (sign_extend:SI (match_operand:QI 2 "register_operand" "0")))] + (clobber (match_scratch:SI 0 "=d"))] "" "extsb.c %0, %1" [(set_attr "type" "arith") (set_attr "up_c" "yes") (set_attr "mode" "SI")]) -(define_insn "zero_extendqisi2" - [(set (match_operand:SI 0 "register_operand""=d,d") - (zero_extend:SI (match_operand:QI 1 "register_operand" "d,m")))] - "" -{ - switch (which_alternative) - { - case 0: return \"extzb %0, %1\"; - case 1: return mdp_linsn (operands, MDA_BYTE, false); - default: gcc_unreachable (); - } -} - [(set_attr "type" "arith, load") - (set_attr "mode" "SI")]) - (define_insn "extendhisi2" [(set (match_operand:SI 0 "register_operand" "=d,d") (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "d,m")))] @@ -517,34 +640,79 @@ [(set_attr "type" "arith, load") (set_attr "mode" "SI")]) -(define_insn "extendhisi2_cmp" +(define_insn "*extendhisi2_ucc" [(set (reg:CC_N CC_REGNUM) (compare:CC_N (ashiftrt:SI - (ashift:SI (match_operand:SI 0 "register_operand" "d") + (ashift:SI (match_operand:SI 1 "register_operand" "d") (const_int 16)) (const_int 16)) - (const_int 0)))] + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=d") + (sign_extend:SI (match_operand:HI 2 "register_operand" "0")))] "" - "%[ extsh.c r1, %0 %]" + "extsh.c %0, %1" [(set_attr "type" "arith") (set_attr "up_c" "yes") (set_attr "mode" "SI")]) -(define_insn "extendhisi2_ucc" +(define_insn "*extendhisi2_cmp" [(set (reg:CC_N CC_REGNUM) (compare:CC_N (ashiftrt:SI (ashift:SI (match_operand:SI 1 "register_operand" "d") (const_int 16)) (const_int 16)) (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=d") - (sign_extend:SI (match_operand:HI 2 "register_operand" "0")))] + (clobber (match_scratch:SI 0 "=d"))] "" "extsh.c %0, %1" [(set_attr "type" "arith") (set_attr "up_c" "yes") (set_attr "mode" "SI")]) +(define_insn "zero_extendqisi2" + [(set (match_operand:SI 0 "register_operand" "=d,d") + (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "d,m")))] + "" +{ + switch (which_alternative) + { + case 0: return \"extzb %0, %1\"; + case 1: return mdp_linsn (operands, MDA_BYTE, false); + default: gcc_unreachable (); + } + } + [(set_attr "type" "arith, load") + (set_attr "mode" "SI")]) + +(define_insn "*zero_extendqisi2_ucc" + [(set (reg:CC_N CC_REGNUM) + (compare:CC_N (lshiftrt:SI + (ashift:SI (match_operand:SI 1 "register_operand" "d") + (const_int 24)) + (const_int 24)) + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=d") + (zero_extend:SI (match_operand:QI 2 "register_operand" "0")))] + "" + "extzb.c %0, %1" + [(set_attr "type" "arith") + (set_attr "up_c" "yes") + (set_attr "mode" "SI")]) + +(define_insn "*zero_extendqisi2_cmp" + [(set (reg:CC_N CC_REGNUM) + (compare:CC_N (lshiftrt:SI + (ashift:SI (match_operand:SI 1 "register_operand" "d") + (const_int 24)) + (const_int 24)) + (const_int 0))) + (clobber (match_scratch:SI 0 "=d"))] + "" + "extzb.c %0, %1" + [(set_attr "type" "arith") + (set_attr "up_c" "yes") + (set_attr "mode" "SI")]) + (define_insn "zero_extendhisi2" [(set (match_operand:SI 0 "register_operand" "=d,d") (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "d,m")))] @@ -560,6 +728,35 @@ [(set_attr "type" "arith, load") (set_attr "mode" "SI")]) +(define_insn "*zero_extendhisi2_ucc" + [(set (reg:CC_N CC_REGNUM) + (compare:CC_N (lshiftrt:SI + (ashift:SI (match_operand:SI 1 "register_operand" "d") + (const_int 16)) + (const_int 16)) + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=d") + (zero_extend:SI (match_operand:HI 2 "register_operand" "0")))] + "" + "extzh.c %0, %1" + [(set_attr "type" "arith") + (set_attr "up_c" "yes") + (set_attr "mode" "SI")]) + +(define_insn "*zero_extendhisi2_cmp" + [(set (reg:CC_N CC_REGNUM) + (compare:CC_N (lshiftrt:SI + (ashift:SI (match_operand:SI 1 "register_operand" "d") + (const_int 16)) + (const_int 16)) + (const_int 0))) + (clobber (match_scratch:SI 0 "=d"))] + "" + "extzh.c %0, %1" + [(set_attr "type" "arith") + (set_attr "up_c" "yes") + (set_attr "mode" "SI")]) + (define_insn "mulsi3" [(set (match_operand:SI 0 "register_operand" "=l") (mult:SI (match_operand:SI 1 "register_operand" "d") @@ -572,7 +769,8 @@ (define_insn "mulsidi3" [(set (match_operand:DI 0 "register_operand" "=x") - (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d")) + (mult:DI (sign_extend:DI + (match_operand:SI 1 "register_operand" "d")) (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))] "!TARGET_SCORE5U" @@ -582,7 +780,8 @@ (define_insn "umulsidi3" [(set (match_operand:DI 0 "register_operand" "=x") - (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d")) + (mult:DI (zero_extend:DI + (match_operand:SI 1 "register_operand" "d")) (zero_extend:DI (match_operand:SI 2 "register_operand" "d"))))] "!TARGET_SCORE5U" @@ -635,8 +834,8 @@ { switch (which_alternative) { - case 0: return mdp_select (operands, "slli", false, "c"); - case 1: return mdp_select (operands, "sll", false, ""); + case 0: return mdp_select (operands, "slli", false, "c", true); + case 1: return mdp_select (operands, "sll", false, "", true); default: gcc_unreachable (); } } @@ -647,13 +846,19 @@ (define_insn "ashlsi3_cmp" [(set (reg:CC_NZ CC_REGNUM) (compare:CC_NZ (ashift:SI - (match_operand:SI 0 "register_operand" "d,d") - (match_operand:SI 1 "arith_operand" "J,d")) - (const_int 0)))] + (match_operand:SI 1 "register_operand" "d,d") + (match_operand:SI 2 "arith_operand" "J,d")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=d,d"))] "" - "@ - %[ slli.c r1, %0, %c1 %] - %[ sll.c r1, %0, %1 %]" +{ + switch (which_alternative) + { + case 0: return mdp_select (operands, "slli", false, "c", true); + case 1: return mdp_select (operands, "sll", false, "", true); + default: gcc_unreachable (); + } +} [(set_attr "type" "arith") (set_attr "up_c" "yes") (set_attr "mode" "SI")]) @@ -682,7 +887,7 @@ switch (which_alternative) { case 0: return \"srai.c %0, %1, %c2\"; - case 1: return mdp_select (operands, "sra", false, ""); + case 1: return mdp_select (operands, "sra", false, "", true); default: gcc_unreachable (); } } @@ -693,31 +898,16 @@ (define_insn "ashrsi3_cmp" [(set (reg:CC_NZ CC_REGNUM) (compare:CC_NZ (ashiftrt:SI - (match_operand:SI 0 "register_operand" "d,d") - (match_operand:SI 1 "arith_operand" "J,d")) - (const_int 0)))] - "" - "@ - %[ srai.c r1, %0, %c1 %] - %[ sra.c r1, %0, %1 %]" - [(set_attr "type" "arith") - (set_attr "up_c" "yes") - (set_attr "mode" "SI")]) - -(define_insn "ashrsi3_ucc_n" - [(set (reg:CC_N CC_REGNUM) - (compare:CC_N (ashiftrt:SI - (match_operand:SI 1 "register_operand" "d,d") - (match_operand:SI 2 "arith_operand" "J,d")) - (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=d,d") - (ashiftrt:SI (match_dup 1) (match_dup 2)))] + (match_operand:SI 1 "register_operand" "d,d") + (match_operand:SI 2 "arith_operand" "J,d")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=d,d"))] "" { switch (which_alternative) { case 0: return \"srai.c %0, %1, %c2\"; - case 1: return mdp_select (operands, "sra", false, ""); + case 1: return mdp_select (operands, "sra", false, "", true); default: gcc_unreachable (); } } @@ -725,20 +915,6 @@ (set_attr "up_c" "yes") (set_attr "mode" "SI")]) -(define_insn "ashrsi3_cmp_n" - [(set (reg:CC_N CC_REGNUM) - (compare:CC_N (ashiftrt:SI - (match_operand:SI 0 "register_operand" "d,d") - (match_operand:SI 1 "arith_operand" "J,d")) - (const_int 0)))] - "" - "@ - %[ srai.c r1, %0, %c1 %] - %[ sra.c r1, %0, %1 %]" - [(set_attr "type" "arith") - (set_attr "up_c" "yes") - (set_attr "mode" "SI")]) - (define_insn "lshrsi3" [(set (match_operand:SI 0 "register_operand" "=d,d") (lshiftrt:SI (match_operand:SI 1 "register_operand" "d,d") @@ -762,8 +938,8 @@ { switch (which_alternative) { - case 0: return mdp_select (operands, "srli", false, "c"); - case 1: return mdp_select (operands, "srl", false, ""); + case 0: return mdp_select (operands, "srli", false, "c", true); + case 1: return mdp_select (operands, "srl", false, "", true); default: gcc_unreachable (); } } @@ -774,13 +950,19 @@ (define_insn "lshrsi3_cmp" [(set (reg:CC_NZ CC_REGNUM) (compare:CC_NZ (lshiftrt:SI - (match_operand:SI 0 "register_operand" "d,d") - (match_operand:SI 1 "arith_operand" "J,d")) - (const_int 0)))] + (match_operand:SI 1 "register_operand" "d,d") + (match_operand:SI 2 "arith_operand" "J,d")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=d,d"))] "" - "@ - %[ srli.c r1, %0, %c1 %] - %[ srl.c r1, %0, %1 %]" +{ + switch (which_alternative) + { + case 0: return mdp_select (operands, "srli", false, "c", true); + case 1: return mdp_select (operands, "srl", false, "", true); + default: gcc_unreachable (); + } +} [(set_attr "type" "arith") (set_attr "up_c" "yes") (set_attr "mode" "SI")]) @@ -793,11 +975,24 @@ [(set_attr "type" "arith") (set_attr "mode" "SI")]) +(define_insn "*negsi2_cmp" + [(set (reg:CC_NZ CC_REGNUM) + (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "e,d")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=e,d"))] + "" + "@ + neg! %0, %1 + neg.c %0, %1" + [(set_attr "type" "arith") + (set_attr "up_c" "yes") + (set_attr "mode" "SI")]) + (define_insn "negsi2_ucc" - [(set (reg:CC CC_REGNUM) - (compare:CC (neg:SI (match_operand:SI 1 "register_operand" "*e,d")) - (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=*e,d") + [(set (reg:CC_NZ CC_REGNUM) + (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "e,d")) + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=e,d") (neg:SI (match_dup 1)))] "" "@ @@ -817,9 +1012,9 @@ (define_insn "one_cmplsi2_ucc" [(set (reg:CC_NZ CC_REGNUM) - (compare:CC_NZ (not:SI (match_operand:SI 1 "register_operand" "*e,d")) + (compare:CC_NZ (not:SI (match_operand:SI 1 "register_operand" "e,d")) (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=*e,d") + (set (match_operand:SI 0 "register_operand" "=e,d") (not:SI (match_dup 1)))] "" "@ @@ -831,12 +1026,13 @@ (define_insn "one_cmplsi2_cmp" [(set (reg:CC_NZ CC_REGNUM) - (compare:CC_NZ (not:SI (match_operand:SI 0 "register_operand" "*e,d")) - (const_int 0)))] + (compare:CC_NZ (not:SI (match_operand:SI 1 "register_operand" "e,d")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=e,d"))] "" "@ - %[ not! r1, %0 %] - %[ not.c r1, %0 %]" + not! %0, %1 + not.c %0, %1" [(set_attr "type" "arith") (set_attr "up_c" "yes") (set_attr "mode" "SI")]) @@ -877,8 +1073,8 @@ (define_insn "cmpsi_nz" [(set (reg:CC_NZ CC_REGNUM) - (compare:CC_NZ (match_operand:SI 0 "register_operand" "d,*e,d") - (match_operand:SI 1 "arith_operand" "L,*e,d")))] + (compare:CC_NZ (match_operand:SI 0 "register_operand" "d,e,d") + (match_operand:SI 1 "arith_operand" "L,e,d")))] "" "@ cmpi.c %0, %c1 @@ -890,8 +1086,8 @@ (define_insn "cmpsi_n" [(set (reg:CC_N CC_REGNUM) - (compare:CC_N (match_operand:SI 0 "register_operand" "d,*e,d") - (match_operand:SI 1 "arith_operand" "L,*e,d")))] + (compare:CC_N (match_operand:SI 0 "register_operand" "d,e,d") + (match_operand:SI 1 "arith_operand" "L,e,d")))] "" "@ cmpi.c %0, %c1 @@ -901,10 +1097,23 @@ (set_attr "up_c" "yes") (set_attr "mode" "SI")]) +(define_insn "*cmpsi_to_addsi" + [(set (reg:CC_NZ CC_REGNUM) + (compare:CC_NZ (match_operand:SI 1 "register_operand" "0,d") + (neg:SI (match_operand:SI 2 "register_operand" "e,d")))) + (clobber (match_scratch:SI 0 "=e,d"))] + "" + "@ + add! %0, %2 + add.c %0, %1, %2" + [(set_attr "type" "cmp") + (set_attr "up_c" "yes") + (set_attr "mode" "SI")]) + (define_insn "cmpsi_cc" [(set (reg:CC CC_REGNUM) - (compare:CC (match_operand:SI 0 "register_operand" "d,*e,d") - (match_operand:SI 1 "arith_operand" "L,*e,d")))] + (compare:CC (match_operand:SI 0 "register_operand" "d,e,d") + (match_operand:SI 1 "arith_operand" "L,e,d")))] "" "@ cmpi.c %0, %c1 @@ -1078,17 +1287,17 @@ (clobber (reg:SI RT_REGNUM))] "SIBLING_CALL_P (insn)" { - if (!flag_pic) - switch (which_alternative) + if (!flag_pic) + switch (which_alternative) { case 0: return \"br%S0 %0\"; case 1: return \"j %0\"; default: gcc_unreachable (); } else - switch (which_alternative) + switch (which_alternative) { - case 0: return \"mv r29, %0\;.cpadd r29\;br r29\"; + case 0: return \"mv r29, %0\;br r29\"; case 1: return \"la r29, %0\;br r29\"; default: gcc_unreachable (); } @@ -1112,17 +1321,17 @@ (clobber (reg:SI RT_REGNUM))] "SIBLING_CALL_P (insn)" { - if (!flag_pic) - switch (which_alternative) + if (!flag_pic) + switch (which_alternative) { case 0: return \"br%S1 %1\"; case 1: return \"j %1\"; default: gcc_unreachable (); } else - switch (which_alternative) + switch (which_alternative) { - case 0: return \"mv r29, %1\;.cpadd r29\;br r29\"; + case 0: return \"mv r29, %1\;br r29\"; case 1: return \"la r29, %1\;br r29\"; default: gcc_unreachable (); } @@ -1154,7 +1363,7 @@ else switch (which_alternative) { - case 0: return \"mv r29, %0\;.cpadd r29\;brl r29\"; + case 0: return \"mv r29, %0\;brl r29\"; case 1: return \"la r29, %0\;brl r29\"; default: gcc_unreachable (); } @@ -1163,7 +1372,7 @@ (define_expand "call_value" [(parallel [(set (match_operand 0 "" "") - (call (match_operand 1 "" "") (match_operand 2 "" ""))) + (call (match_operand 1 "" "") (match_operand 2 "" ""))) (use (match_operand 3 "" ""))])] "" { @@ -1188,7 +1397,7 @@ else switch (which_alternative) { - case 0: return \"mv r29, %1\;.cpadd r29\;brl r29\"; + case 0: return \"mv r29, %1\;brl r29\"; case 1: return \"la r29, %1\;brl r29\"; default: gcc_unreachable (); } @@ -1277,13 +1486,59 @@ ) (define_insn "cpload" - [(unspec:SI [(const_int 1)] 1)] + [(unspec_volatile:SI [(const_int 1)] CPLOAD)] "flag_pic" ".cpload r29" ) -(define_insn "cprestore" - [(unspec:SI [(match_operand:SI 0 "" "")] 2)] +(define_insn "cprestore_use_fp" + [(unspec_volatile:SI [(match_operand:SI 0 "" "")] CPRESTORE) + (use (reg:SI FP_REGNUM))] "flag_pic" - ".cprestore %0" + ".cprestore r2, %0" ) + +(define_insn "cprestore_use_sp" + [(unspec_volatile:SI [(match_operand:SI 0 "" "")] CPRESTORE) + (use (reg:SI SP_REGNUM))] + "flag_pic" + ".cprestore r0, %0" +) + +(define_expand "doloop_end" + [(use (match_operand 0 "" "")) ; loop pseudo + (use (match_operand 1 "" "")) ; iterations; zero if unknown + (use (match_operand 2 "" "")) ; max iterations + (use (match_operand 3 "" "")) ; loop level + (use (match_operand 4 "" ""))] ; label + "" + { + if (INTVAL (operands[3]) > 1) + FAIL; + + if (GET_MODE (operands[0]) == SImode) + { + rtx sr0 = gen_rtx_REG (SImode, CN_REGNUM); + emit_jump_insn (gen_doloop_end_si (sr0, operands[4])); + } + else + FAIL; + + DONE; + }) + +(define_insn "doloop_end_si" + [(set (pc) + (if_then_else + (ne (match_operand:SI 0 "sr0_operand" "") + (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int -1))) + (clobber (reg:CC CC_REGNUM)) +] + "" + "bcnz %1" + [(set_attr "type" "branch")]) Index: gcc/config/score/score-modes.def =================================================================== --- gcc/config/score/score-modes.def (revision 120252) +++ gcc/config/score/score-modes.def (working copy) @@ -21,6 +21,5 @@ /* CC_NZmode should be used if the N (sign) and Z (zero) flag is set correctly. CC_Nmode should be used if only the N flag is set correctly. */ -CC_MODE (CC_NZ); CC_MODE (CC_N); - +CC_MODE (CC_NZ); Index: gcc/config/score/score-mdaux.h =================================================================== --- gcc/config/score/score-mdaux.h (revision 120252) +++ gcc/config/score/score-mdaux.h (working copy) @@ -69,8 +69,6 @@ void mda_gen_cmp (enum machine_mode mode int mda_symbolic_constant_p (rtx x, enum score_symbol_type *symbol_type); -bool mda_pindex_mem (rtx addr); - int mda_bp (void); /* Machine Expand. */ @@ -87,8 +85,6 @@ void mdx_call_value (rtx *ops, bool sibc /* Machine Split. */ void mds_movdi (rtx *ops); -void mds_addsi (rtx *ops); - void mds_zero_extract_andi (rtx *ops); /* Machine Print. */ @@ -100,14 +96,21 @@ const char * mdp_linsn (rtx *ops, enum m const char * mdp_sinsn (rtx *ops, enum mda_mem_unit unit); -const char * mdp_add_imm_ucc (rtx *ops); +const char * mdp_select_add_imm (rtx *ops, bool set_cc); const char * mdp_select (rtx *ops, const char *inst_pre, - bool comu, const char *let); + bool commu, const char *letter, bool set_cc); const char * mdp_limm (rtx *ops); const char * mdp_move (rtx *ops); +/* Machine unaligned memory load/store. */ +bool mdx_unaligned_load (rtx* ops); + +bool mdx_unaligned_store (rtx* ops); + +bool mdx_block_move (rtx* ops); + #endif Index: gcc/config/score/mul-div.S =================================================================== --- gcc/config/score/mul-div.S (revision 120252) +++ gcc/config/score/mul-div.S (working copy) @@ -242,7 +242,7 @@ _flush_cache: #nop! addi r8, 16 bcnz 2b - .cprestore 12 # pic used + .cprestore r0, 12 # pic used addi r0, 8 # pic used br r3 #endif @@ -278,7 +278,7 @@ __mulsi3_loop2: cmpi.c a1, 0 bne __mulsi3_loop mv r4, t1 - .cprestore 12 # pic used + .cprestore r0, 12 # pic used addi r0, 8 # pic used br ra .end __mulsi3 @@ -334,7 +334,7 @@ __uds_loop3: __uds_exit: mv a1, a0 mv r4, t4 - .cprestore 12 # pic used + .cprestore r0, 12 # pic used addi r0, 8 # pic used br ra .end __udivsi3 @@ -350,7 +350,7 @@ __umodsi3: la r29, __udivsi3 brl r29 mv r4, a1 - .cprestore 12 # pic used + .cprestore r0, 12 # pic used addi r0, 8 # pic used br t3 .end __umodsi3 @@ -383,7 +383,7 @@ __divsi3_adjust: bge __divsi3_exit neg r4, r4 __divsi3_exit: - .cprestore 12 # pic used + .cprestore r0, 12 # pic used addi r0, 8 # pic used br t3 .end __divsi3 ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH]: for Score backend 2007-01-04 1:30 ` liqin @ 2007-01-08 4:53 ` liqin 0 siblings, 0 replies; 5+ messages in thread From: liqin @ 2007-01-08 4:53 UTC (permalink / raw) To: gcc-patches Commit Score backend code to gcc-4.2.0 and gcc-trunk repository. -liqin gcc-patches-owner@gcc.gnu.org 写于 2007-01-04 09:29:30: > Can I commit this patch to gcc-4.2.0/gcc-trunk repository, > because I had put it here for one week, and not get > any response. > > Rgds > Liqin > > gcc-patches-owner@gcc.gnu.org 写于 2006-12-29 14:53:32: > > > Hi, > > this patch did many changes for Score backend. > > > > Changelog: > > * config/score/predicates.md (const_uimm5, sr0_operand, > > const_simm12, > > const_simm15, const_pow2, const_npow2): Added. > > * config/score/misc.md (insv, extv, extzv, movmemsi, > > move_lbu_a/b, mov_lhu_a/b etc): Added and fix some bug. > > * config/score/score.c (score_address_cost, > score_select_cc_mode): > > > > Added. > > Change CONST_OK_FOR_LETTER_P/EXTRA_CONSTRAINT define. > > Update score_rtx_costs for MACRO TARGET_RTX_COSTS. > > Update score_print_operand. > > * config/score/score.h (DATA_ALIGNMENT, SELECT_CC_MODE): Added. > > Adjust register allocate order and update some macro define. > > * config/score/score-mdaux.c (mdx_unaligned_load, > > mdx_unsigned_store, > > mdx_block_move_straight, mdx_block_move_loop_head, > > mdx_block_move_loop_body, > > mdx_block_move_loop_foot, mdx_block_move_loop mdx_block_move): > > Added. > > (mdx_movsicc, mdp_select_add_imm, mdp_select, > > mds_zero_extract_andi, mdp_limm): > > Updated and fix some bug and typo. > > * config/score/score.md (movqi/hi/si, add/sub/zero/ext): > Updated. > > (movsf, movdf, doloop_end): Added. > > * config/score/t-score-elf (MULTILIB_OPTIONS): Change. > > > > Rgds > > Liqin > > [附件 "score-20061229.patch" 被 liqin/Sunnorth 删除] ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] Fix _Unwind_Context backward compatibility issues 2006-12-28 20:46 [PATCH] Fix _Unwind_Context backward compatibility issues Jakub Jelinek 2006-12-29 6:54 ` [PATCH]: for Score backend liqin @ 2007-01-03 18:07 ` Richard Henderson 1 sibling, 0 replies; 5+ messages in thread From: Richard Henderson @ 2007-01-03 18:07 UTC (permalink / raw) To: Jakub Jelinek; +Cc: gcc-patches On Thu, Dec 28, 2006 at 03:40:41PM -0500, Jakub Jelinek wrote: > Perhaps to be even more compatible even with older GCC 4.2 (plus > all the 4.1 branches where this has been backported) unwinders, > _Unwind_Context could be... I'm ok with the first patch, where this is not done. While you're preserving the layout in the second patch, you're not preserving the values stuck into, or read from, those fields. Really, this is all being done to cater to A Well Known Commercial Program, whose authors ought to be hit with a clue bat. You've done an admirable job working around their brokenness. I think it would be a bit over the top to try to really preserve the field values as the second patch would have to do. Particularly since this doesn't seem to be necessary for a known case. r~ ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2007-01-08 4:53 UTC | newest] Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2006-12-28 20:46 [PATCH] Fix _Unwind_Context backward compatibility issues Jakub Jelinek 2006-12-29 6:54 ` [PATCH]: for Score backend liqin 2007-01-04 1:30 ` liqin 2007-01-08 4:53 ` liqin 2007-01-03 18:07 ` [PATCH] Fix _Unwind_Context backward compatibility issues Richard Henderson
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).