Change the defaults of some parameters and options.
* config/spu/spu-protos.h (spu_optimization_options): Declare.
* config/spu/spu.c (spu_optimization_options): Add.
(spu_override_options): Change params in spu_optimization_options.
* config/spu/spu.h (OPTIMIZATION_OPTIONS): Define.
Register 127 is only 16 byte aligned when used as a frame pointer.
* config/spu/spu-protos.h (spu_init_expanders): Declare.
* config/spu/spu.c (spu_expand_prologue): Set REGNO_POINTER_ALIGN for
HARD_FRAME_POINTER_REGNUM.
(spu_legitimate_address): Use regno_aligned_for_reload.
(regno_aligned_for_load): HARD_FRAME_POINTER_REGNUM is only 16 byte
aligned when frame_pointer_needed is true.
(spu_init_expanders): New. Set alignment of HARD_FRAME_POINTER_REGNUM
to 8 bits.
* config/spu/spu.h (INIT_EXPANDERS): Define.
Make sure shift and rotate instructions have valid immediate operands.
* config/spu/predicates.md (spu_shift_operand): Remove.
* config/spu/spu.c (print_operand): Add [efghEFGH] modifiers.
* config/spu/constraints.md (W, O): Extend range.
* config/spu/spu.md (umask, nmask): Define.
(ashl<mode>3, ashldi3, ashlti3_imm, shlqbybi_ti, shlqbi_ti, shlqby_ti,
lshr<mode>3, rotm_<mode>, lshr<mode>3_imm, rotqmbybi_<mode>,
rotqmbi_<mode>, rotqmby_<mode>, ashr<mode>3, rotma_<mode>,
rotl<mode>3, rotlti3, rotqbybi_ti, rotqby_ti, rotqbi_ti): Use
spu_nonmem_operand instead of spu_shift_operands. Use new modifiers.
(lshr<mode>3_reg): Fix rtl description.
Make sure mulhisi immediate operands are valid.
* config/spu/predicates.md (imm_K_operand): Add.
* config/spu/spu.md (mulhisi3_imm, umulhisi3_imm): Use imm_K_operand.
Generate constants using fsmbi and andi.
* config/spu/spu.c (enum immediate_class): Add IC_FSMBI2.
(print_operand, spu_split_immediate, classify_immediate,
fsmbi_const_p): Handle IC_FSMBI2.
Correctly handle a CONST_VECTOR containing symbols.
* config/spu/spu.c (print_operand): Handle HIGH correctly.
(spu_split_immediate): Split CONST_VECTORs with -mlarge-mem.
(immediate_load_p): Allow symbols that use 2 instructions to create.
(classify_immediate, spu_builtin_splats): Don't accept a CONST_VECTOR
with symbols when flag_pic is set.
(const_vector_immediate_p): New.
(logical_immediate_p, iohl_immediate_p, arith_immediate_p): Don't
accept a CONST_VECTOR with symbols.
(spu_legitimate_constant_p): Use const_vector_immediate_p. Don't
accept a CONST_VECTOR with symbols when flag_pic is set. Handle HIGH
correctly.
* config/spu/spu.md (high, low): Delete.
(low_<mode>): Define.
Remove INTRmode and INTR_REGNUM, which didn't work.
* config/spu/spu.c (spu_conditional_register_usage): Remove reference
of INTR_REGNUM.
* config/spu/spu-builtins.md (spu_idisable, spu_ienable, set_intr,
set_intr_pic, set_intr_cc, set_intr_cc_pic, set_intr_return, unnamed
peephole2 pattern): Don't use INTR or 131.
(movintrcc): Delete.
* config/spu/spu.h (FIRST_PSEUDO_REGISTER, FIXED_REGISTERS,
CALL_USED_REGISTERS, REGISTER_NAMES, INTR_REGNUM): Remove INTR_REGNUM.
* config/spu/spu.md (UNSPEC_IDISABLE, UNSPEC_IENABLE): Remove.
(UNSPEC_SET_INTR): Add.
* config/spu/spu-modes.def (INTR): Remove.
More accurate warnings about run-time relocations.
* config/spu/spu.c (reloc_diagnostic): Test in_section.
Correctly warn about immediate arguments to specific intrinsics.
* config/spu/spu.c (spu_check_builtin_parm): Handle CONST_VECTORs.
(spu_expand_builtin_1): Call spu_check_builtin_parm before checking
the instruction predicate.
Fix tree check errors with latest update.
* config/spu/spu.c (expand_builtin_args, spu_expand_builtin_1): Use
CALL_EXPR_ARG.
(spu_expand_builtin): Use CALL_EXPR_FN.
Add missing specific intrinsics.
* config/spu/spu-builtins.def: Add si_bisled, si_bisledd and
si_bislede.
* config/spu/spu_internals.h: Ditto.
Fix incorrect operand modifiers.
* config/spu/spu-builtins.md (spu_mpy, spu_mpyu): Remove use of %H.
* config/spu/spu.md (xor<mode>3): Change %S to %J.
Optimize one case of zero_extend of a vec_select.
* config/spu/spu.md (_vec_extractv8hi_ze): Add.
Accept any immediate for hbr.
* config/spu/spu.md (hbr): Change s constraints to i.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@122210
138bc75d-0d04-0410-961f-
82ee72b054a4
+2007-02-21 Trevor Smigiel <trevor_smigiel@playstation.sony.com>
+
+ Change the defaults of some parameters and options.
+ * config/spu/spu-protos.h (spu_optimization_options): Declare.
+ * config/spu/spu.c (spu_optimization_options): Add.
+ (spu_override_options): Change params in spu_optimization_options.
+ * config/spu/spu.h (OPTIMIZATION_OPTIONS): Define.
+
+ Register 127 is only 16 byte aligned when used as a frame pointer.
+ * config/spu/spu-protos.h (spu_init_expanders): Declare.
+ * config/spu/spu.c (spu_expand_prologue): Set REGNO_POINTER_ALIGN for
+ HARD_FRAME_POINTER_REGNUM.
+ (spu_legitimate_address): Use regno_aligned_for_reload.
+ (regno_aligned_for_load): HARD_FRAME_POINTER_REGNUM is only 16 byte
+ aligned when frame_pointer_needed is true.
+ (spu_init_expanders): New. Set alignment of HARD_FRAME_POINTER_REGNUM
+ to 8 bits.
+ * config/spu/spu.h (INIT_EXPANDERS): Define.
+
+ Make sure shift and rotate instructions have valid immediate operands.
+ * config/spu/predicates.md (spu_shift_operand): Remove.
+ * config/spu/spu.c (print_operand): Add [efghEFGH] modifiers.
+ * config/spu/constraints.md (W, O): Extend range.
+ * config/spu/spu.md (umask, nmask): Define.
+ (ashl<mode>3, ashldi3, ashlti3_imm, shlqbybi_ti, shlqbi_ti, shlqby_ti,
+ lshr<mode>3, rotm_<mode>, lshr<mode>3_imm, rotqmbybi_<mode>,
+ rotqmbi_<mode>, rotqmby_<mode>, ashr<mode>3, rotma_<mode>,
+ rotl<mode>3, rotlti3, rotqbybi_ti, rotqby_ti, rotqbi_ti): Use
+ spu_nonmem_operand instead of spu_shift_operands. Use new modifiers.
+ (lshr<mode>3_reg): Fix rtl description.
+
+ Make sure mulhisi immediate operands are valid.
+ * config/spu/predicates.md (imm_K_operand): Add.
+ * config/spu/spu.md (mulhisi3_imm, umulhisi3_imm): Use imm_K_operand.
+
+ Generate constants using fsmbi and andi.
+ * config/spu/spu.c (enum immediate_class): Add IC_FSMBI2.
+ (print_operand, spu_split_immediate, classify_immediate,
+ fsmbi_const_p): Handle IC_FSMBI2.
+
+ Correctly handle a CONST_VECTOR containing symbols.
+ * config/spu/spu.c (print_operand): Handle HIGH correctly.
+ (spu_split_immediate): Split CONST_VECTORs with -mlarge-mem.
+ (immediate_load_p): Allow symbols that use 2 instructions to create.
+ (classify_immediate, spu_builtin_splats): Don't accept a CONST_VECTOR
+ with symbols when flag_pic is set.
+ (const_vector_immediate_p): New.
+ (logical_immediate_p, iohl_immediate_p, arith_immediate_p): Don't
+ accept a CONST_VECTOR with symbols.
+ (spu_legitimate_constant_p): Use const_vector_immediate_p. Don't
+ accept a CONST_VECTOR with symbols when flag_pic is set. Handle HIGH
+ correctly.
+ * config/spu/spu.md (high, low): Delete.
+ (low_<mode>): Define.
+
+ Remove INTRmode and INTR_REGNUM, which didn't work.
+ * config/spu/spu.c (spu_conditional_register_usage): Remove reference
+ of INTR_REGNUM.
+ * config/spu/spu-builtins.md (spu_idisable, spu_ienable, set_intr,
+ set_intr_pic, set_intr_cc, set_intr_cc_pic, set_intr_return, unnamed
+ peephole2 pattern): Don't use INTR or 131.
+ (movintrcc): Delete.
+ * config/spu/spu.h (FIRST_PSEUDO_REGISTER, FIXED_REGISTERS,
+ CALL_USED_REGISTERS, REGISTER_NAMES, INTR_REGNUM): Remove INTR_REGNUM.
+ * config/spu/spu.md (UNSPEC_IDISABLE, UNSPEC_IENABLE): Remove.
+ (UNSPEC_SET_INTR): Add.
+ * config/spu/spu-modes.def (INTR): Remove.
+
+ More accurate warnings about run-time relocations.
+ * config/spu/spu.c (reloc_diagnostic): Test in_section.
+
+ Correctly warn about immediate arguments to specific intrinsics.
+ * config/spu/spu.c (spu_check_builtin_parm): Handle CONST_VECTORs.
+ (spu_expand_builtin_1): Call spu_check_builtin_parm before checking
+ the instruction predicate.
+
+ Fix tree check errors with latest update.
+ * config/spu/spu.c (expand_builtin_args, spu_expand_builtin_1): Use
+ CALL_EXPR_ARG.
+ (spu_expand_builtin): Use CALL_EXPR_FN.
+
+ Add missing specific intrinsics.
+ * config/spu/spu-builtins.def: Add si_bisled, si_bisledd and
+ si_bislede.
+ * config/spu/spu_internals.h: Ditto.
+
+ Fix incorrect operand modifiers.
+ * config/spu/spu-builtins.md (spu_mpy, spu_mpyu): Remove use of %H.
+ * config/spu/spu.md (xor<mode>3): Change %S to %J.
+
+ Optimize one case of zero_extend of a vec_select.
+ * config/spu/spu.md (_vec_extractv8hi_ze): Add.
+
+ Accept any immediate for hbr.
+ * config/spu/spu.md (hbr): Change s constraints to i.
+
2007-02-21 Paul Brook <paul@codesourcery.com>
* config/arm/arm.c (thumb2_final_prescan_insn): Don't incrememnt
(define_constraint "W"
"An immediate for shift and rotate instructions. const_int is treated as a 32-bit value."
(and (match_code "const_int,const_double,const_vector")
- (match_test "arith_immediate_p (op, SImode, -0x40, 0x3f)")))
+ (match_test "arith_immediate_p (op, SImode, -0x80000000ll, 0x7fffffffll)")))
(define_constraint "Y"
"An immediate for and/xor/or instructions. const_int is sign extended as a 128 bit."
(define_constraint "O"
"An unsigned 7-bit constant whose 3 least significant bits are 0."
(and (match_code "const_int")
- (match_test "ival >= 0 && ival <= 0x7f && (ival & 7) == 0")))
+ (match_test "(ival & 7) == 0")))
(define_constraint "P"
"An unsigned 3-bit constant for 16-byte rotates and shifts"
return 0;
})
-(define_predicate "spu_shift_operand"
- (match_code "reg,subreg,const_int,const_vector")
- {
- if (spu_reg_operand (op, mode))
- return 1;
- if (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_VECTOR)
- return arith_immediate_p (op, mode, -0x40, 0x3f);
- return 0;
- })
+(define_predicate "imm_K_operand"
+ (and (match_code "const_int")
+ (match_test "arith_immediate_p (op, mode, -0x200, 0x1ff)")))
;; Return 1 if OP is a comparison operation that is valid for a branch insn.
;; We only check the opcode against the mode of the register value here.
DEF_BUILTIN (SI_CLGTHI, CODE_FOR_clgt_v8hi, "si_clgthi", B_INSN, _A3(SPU_BTI_QUADWORD, SPU_BTI_QUADWORD, SPU_BTI_S10))
DEF_BUILTIN (SI_CLGT, CODE_FOR_clgt_v4si, "si_clgt", B_INSN, _A3(SPU_BTI_QUADWORD, SPU_BTI_QUADWORD, SPU_BTI_QUADWORD))
DEF_BUILTIN (SI_CLGTI, CODE_FOR_clgt_v4si, "si_clgti", B_INSN, _A3(SPU_BTI_QUADWORD, SPU_BTI_QUADWORD, SPU_BTI_S10))
+DEF_BUILTIN (SI_BISLED, CODE_FOR_spu_bisled, "si_bisled", B_BISLED, _A3(SPU_BTI_VOID, SPU_BTI_QUADWORD, SPU_BTI_PTR))
+DEF_BUILTIN (SI_BISLEDD, CODE_FOR_spu_bisledd, "si_bisledd", B_BISLED, _A3(SPU_BTI_VOID, SPU_BTI_QUADWORD, SPU_BTI_PTR))
+DEF_BUILTIN (SI_BISLEDE, CODE_FOR_spu_bislede, "si_bislede", B_BISLED, _A3(SPU_BTI_VOID, SPU_BTI_QUADWORD, SPU_BTI_PTR))
DEF_BUILTIN (SI_FA, CODE_FOR_addv4sf3, "si_fa", B_INSN, _A3(SPU_BTI_QUADWORD, SPU_BTI_QUADWORD, SPU_BTI_QUADWORD))
DEF_BUILTIN (SI_DFA, CODE_FOR_addv2df3, "si_dfa", B_INSN, _A3(SPU_BTI_QUADWORD, SPU_BTI_QUADWORD, SPU_BTI_QUADWORD))
DEF_BUILTIN (SI_FS, CODE_FOR_subv4sf3, "si_fs", B_INSN, _A3(SPU_BTI_QUADWORD, SPU_BTI_QUADWORD, SPU_BTI_QUADWORD))
""
"@
mpy\t%0,%1,%2
- mpyi\t%0,%1,%H2"
+ mpyi\t%0,%1,%2"
[(set_attr "type" "fp7")])
(define_insn "spu_mpyu"
""
"@
mpyu\t%0,%1,%2
- mpyui\t%0,%1,%H2"
+ mpyui\t%0,%1,%2"
[(set_attr "type" "fp7")])
(define_insn "spu_mpya"
[(set_attr "type" "br")])
;; interrupt disable/enable
-;; Register 131 is used exclusively for enabling/disabling interrupts.
-;; It is marked as a global reg and the instructions clobber mem, so it will
-;; not be incorrectly optimized.
(define_expand "spu_idisable"
[(parallel
- [(set (reg:INTR 131) (const_int 0))
+ [(unspec_volatile [(const_int 0)] UNSPEC_SET_INTR)
(clobber (match_dup:SI 0))
(clobber (mem:BLK (scratch)))])]
""
(define_expand "spu_ienable"
[(parallel
- [(set (reg:INTR 131) (const_int 1))
+ [(unspec_volatile [(const_int 1)] UNSPEC_SET_INTR)
(clobber (match_dup:SI 0))
(clobber (mem:BLK (scratch)))])]
""
"operands[0] = gen_reg_rtx (SImode);")
(define_insn "set_intr"
- [(set (reg:INTR 131) (match_operand 1 "const_int_operand" "i"))
+ [(unspec_volatile [(match_operand 1 "const_int_operand" "i")] UNSPEC_SET_INTR)
(clobber (match_operand:SI 0 "spu_reg_operand" "=&r"))
(clobber (mem:BLK (scratch)))]
"! flag_pic"
(set_attr "type" "multi0")])
(define_insn "set_intr_pic"
- [(set (reg:INTR 131) (match_operand 1 "const_int_operand" "i"))
+ [(unspec_volatile [(match_operand 1 "const_int_operand" "i")] UNSPEC_SET_INTR)
(clobber (match_operand:SI 0 "spu_reg_operand" "=&r"))
(clobber (mem:BLK (scratch)))]
"flag_pic"
[(set_attr "length" "12")
(set_attr "type" "multi1")])
-(define_expand "movintrcc"
- [(parallel
- [(set (match_operand:INTR 0 "spu_reg_operand" "")
- (if_then_else:INTR (match_operand 1 "branch_comparison_operator" "")
- (match_operand 3 "const_int_operand" "")
- (match_operand:INTR 2 "spu_reg_operand" "")))
- (clobber (match_dup:SI 4))
- (clobber (mem:BLK (scratch)))])]
- ""
- { /* We've swapped operands 2 and 3 in the pattern, reverse the
- condition code too. */
- PUT_CODE (operands[1], reverse_condition (GET_CODE (operands[1])));
- operands[4] = gen_reg_rtx (SImode);
- })
-
(define_insn "set_intr_cc"
- [(set (reg:INTR 131)
- (if_then_else:INTR
- (match_operator 1 "branch_comparison_operator"
- [(match_operand 2 "spu_reg_operand" "r")
- (const_int 0)])
- (match_operand:SI 3 "const_int_operand" "i")
- (reg:INTR 131)))
- (clobber (match_operand:SI 0 "spu_reg_operand" "=&r"))
- (clobber (mem:BLK (scratch)))]
+ [(cond_exec (match_operator 1 "branch_comparison_operator"
+ [(match_operand 2 "spu_reg_operand" "r")
+ (const_int 0)])
+ (parallel [(unspec_volatile [(match_operand:SI 3 "const_int_operand" "i")] UNSPEC_SET_INTR)
+ (clobber (match_operand:SI 0 "spu_reg_operand" "=&r"))
+ (clobber (mem:BLK (scratch)))]))]
"! flag_pic"
"ila\t%0,.+8\;bi%b2%b1z%I3\t%2,%0"
[(set_attr "length" "8")
(set_attr "type" "multi0")])
(define_insn "set_intr_cc_pic"
- [(set (reg:INTR 131)
- (if_then_else:INTR
- (match_operator 1 "branch_comparison_operator"
- [(match_operand 2 "spu_reg_operand" "r")
- (const_int 0)])
- (match_operand:SI 3 "const_int_operand" "i")
- (reg:INTR 131)))
- (clobber (match_operand:SI 0 "spu_reg_operand" "=&r"))
- (clobber (mem:BLK (scratch)))]
+ [(cond_exec (match_operator 1 "branch_comparison_operator"
+ [(match_operand 2 "spu_reg_operand" "r")
+ (const_int 0)])
+ (parallel [(unspec_volatile [(match_operand:SI 3 "const_int_operand" "i")] UNSPEC_SET_INTR)
+ (clobber (match_operand:SI 0 "spu_reg_operand" "=&r"))
+ (clobber (mem:BLK (scratch)))]))]
"flag_pic"
- "brsl\t%0,.+4\;ai\t%0,%0,8\;%b2%b1z%I3\t%2,%0"
+ "brsl\t%0,.+4\;ai\t%0,%0,8\;bi%b2%b1z%I3\t%2,%0"
[(set_attr "length" "12")
(set_attr "type" "multi1")])
(define_insn "set_intr_return"
- [(set (reg:INTR 131) (match_operand 0 "const_int_operand" "i"))
+ [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "i")] UNSPEC_SET_INTR)
(return)]
""
"bi%I0\t$lr"
(define_peephole2
[(parallel
- [(set (reg:INTR 131) (match_operand 0 "const_int_operand"))
+ [(unspec_volatile [(match_operand:SI 0 "const_int_operand")] UNSPEC_SET_INTR)
(clobber (match_operand:SI 1 "spu_reg_operand"))
(clobber (mem:BLK (scratch)))])
(use (reg:SI 0))
""
[(use (reg:SI 0))
(parallel
- [(set (reg:INTR 131) (match_dup 0))
+ [(unspec_volatile [(match_dup:SI 0)] UNSPEC_SET_INTR)
(return)])]
"")
VECTOR_MODES (FLOAT, 8); /* V4HF V2SF */
VECTOR_MODES (FLOAT, 16); /* V8HF V4SF V2DF */
-/* A special mode for the intr register so we can treat it differently
- for conditional moves. */
-RANDOM_MODE (INTR);
-
/* cse_insn needs an INT_MODE larger than WORD_MODE, otherwise some
parts of it will go into an infinite loop. */
INT_MODE (OI, 32);
extern enum machine_mode spu_eh_return_filter_mode (void);
extern void spu_cpu_cpp_builtins (struct cpp_reader * pfile);
extern void builtin_define_std (const char *);
+extern void spu_optimization_options (int level, int size);
extern void spu_override_options (void);
extern void spu_c_common_override_options (void);
extern int valid_subreg (rtx op);
extern void spu_initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt);
extern void spu_expand_sign_extend (rtx ops[]);
extern void spu_expand_vector_init (rtx target, rtx vals);
+extern void spu_init_expanders (void);
/* spu-c.c */
extern tree spu_resolve_overloaded_builtin (tree fndecl, tree fnargs);
IC_IL2s, /* both ilhu and iohl instructions */
IC_FSMBI, /* the fsmbi instruction */
IC_CPAT, /* one of the c*d instructions */
+ IC_FSMBI2 /* fsmbi plus 1 other instruction */
};
static enum spu_immediate which_immediate_load (HOST_WIDE_INT val);
struct gcc_target targetm = TARGET_INITIALIZER;
+void
+spu_optimization_options (int level ATTRIBUTE_UNUSED, int size ATTRIBUTE_UNUSED)
+{
+ /* Small loops will be unpeeled at -O3. For SPU it is more important
+ to keep code small by default. */
+ if (!flag_unroll_loops && !flag_peel_loops)
+ PARAM_VALUE (PARAM_MAX_COMPLETELY_PEEL_TIMES) = 1;
+
+ /* Override some of the default param values. With so many registers
+ larger values are better for these params. */
+ MAX_PENDING_LIST_LENGTH = 128;
+
+ /* With so many registers this is better on by default. */
+ flag_rename_registers = 1;
+}
+
/* Sometimes certain combinations of command options do not make sense
on a particular target machine. You can define a macro
OVERRIDE_OPTIONS to take account of this. This macro, if defined, is
void
spu_override_options (void)
{
- /* Override some of the default param values. With so many registers
- larger values are better for these params. */
- if (MAX_UNROLLED_INSNS == 100)
- MAX_UNROLLED_INSNS = 250;
- if (MAX_PENDING_LIST_LENGTH == 32)
- MAX_PENDING_LIST_LENGTH = 128;
-
flag_omit_frame_pointer = 1;
if (align_functions < 8)
fprintf (file, "hu");
break;
case IC_FSMBI:
+ case IC_FSMBI2:
case IC_IL2:
case IC_IL2s:
case IC_POOL:
fprintf (file, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)info);
break;
case IC_IL1s:
- if (xcode == CONST_VECTOR)
- {
- x = CONST_VECTOR_ELT (x, 0);
- xcode = GET_CODE (x);
- }
if (xcode == HIGH)
- {
- output_addr_const (file, XEXP (x, 0));
- fprintf (file, "@h");
- }
- else
- output_addr_const (file, x);
+ x = XEXP (x, 0);
+ if (GET_CODE (x) == CONST_VECTOR)
+ x = CONST_VECTOR_ELT (x, 0);
+ output_addr_const (file, x);
+ if (xcode == HIGH)
+ fprintf (file, "@h");
break;
case IC_IL2:
case IC_IL2s:
+ case IC_FSMBI2:
case IC_POOL:
abort ();
}
}
return;
+ case 'e':
+ val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
+ val &= 0x7;
+ output_addr_const (file, GEN_INT (val));
+ return;
+
+ case 'f':
+ val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
+ val &= 0x1f;
+ output_addr_const (file, GEN_INT (val));
+ return;
+
+ case 'g':
+ val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
+ val &= 0x3f;
+ output_addr_const (file, GEN_INT (val));
+ return;
+
+ case 'h':
+ val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
+ val = (val >> 3) & 0x1f;
+ output_addr_const (file, GEN_INT (val));
+ return;
+
+ case 'E':
+ val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
+ val = -val;
+ val &= 0x7;
+ output_addr_const (file, GEN_INT (val));
+ return;
+
+ case 'F':
+ val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
+ val = -val;
+ val &= 0x1f;
+ output_addr_const (file, GEN_INT (val));
+ return;
+
+ case 'G':
+ val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
+ val = -val;
+ val &= 0x3f;
+ output_addr_const (file, GEN_INT (val));
+ return;
+
+ case 'H':
+ val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
+ val = -(val & -8ll);
+ val = (val >> 3) & 0x1f;
+ output_addr_const (file, GEN_INT (val));
+ return;
+
case 0:
if (xcode == REG)
fprintf (file, "%s", reg_names[REGNO (x)]);
output_addr_const (file, x);
return;
+ /* unsed letters
+ o qr uvw yz
+ AB OPQR UVWXYZ */
default:
output_operand_lossage ("invalid %%xn code");
}
return pic_reg;
}
-/* Split constant addresses to handle cases that are too large. Also, add in
- the pic register when in PIC mode. */
+/* Split constant addresses to handle cases that are too large.
+ Add in the pic register when in PIC mode.
+ Split immediates that require more than 1 instruction. */
int
spu_split_immediate (rtx * ops)
{
(VOIDmode, ops[0], gen_rtx_IOR (mode, to, lo)));
return 1;
}
+ case IC_FSMBI2:
+ {
+ unsigned char arr_fsmbi[16];
+ unsigned char arr_andbi[16];
+ rtx to, reg_fsmbi, reg_and;
+ int i;
+ enum machine_mode imode = mode;
+ /* We need to do reals as ints because the constant used in the
+ * AND might not be a legitimate real constant. */
+ imode = int_mode_for_mode (mode);
+ constant_to_array (mode, ops[1], arr_fsmbi);
+ if (imode != mode)
+ to = simplify_gen_subreg(imode, ops[0], GET_MODE (ops[0]), 0);
+ else
+ to = ops[0];
+ for (i = 0; i < 16; i++)
+ if (arr_fsmbi[i] != 0)
+ {
+ arr_andbi[0] = arr_fsmbi[i];
+ arr_fsmbi[i] = 0xff;
+ }
+ for (i = 1; i < 16; i++)
+ arr_andbi[i] = arr_andbi[0];
+ reg_fsmbi = array_to_constant (imode, arr_fsmbi);
+ reg_and = array_to_constant (imode, arr_andbi);
+ emit_move_insn (to, reg_fsmbi);
+ emit_insn (gen_rtx_SET
+ (VOIDmode, to, gen_rtx_AND (imode, to, reg_and)));
+ return 1;
+ }
case IC_POOL:
if (reload_in_progress || reload_completed)
{
{
if (c == IC_IL2s)
{
- emit_insn (gen_high (ops[0], ops[1]));
- emit_insn (gen_low (ops[0], ops[0], ops[1]));
+ emit_move_insn (ops[0], gen_rtx_HIGH (mode, ops[1]));
+ emit_move_insn (ops[0], gen_rtx_LO_SUM (mode, ops[0], ops[1]));
}
else if (flag_pic)
emit_insn (gen_pic (ops[0], ops[1]));
REG_NOTES (insn) =
gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
real, REG_NOTES (insn));
+ REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = STACK_BOUNDARY;
}
}
if (CONSTANT_P (op))
{
enum immediate_class c = classify_immediate (op, mode);
- return c == IC_IL1 || (!flow2_completed && c == IC_IL2);
+ return c == IC_IL1 || c == IC_IL1s
+ || (!flow2_completed && (c == IC_IL2 || c == IC_IL2s));
}
return 0;
}
{
HOST_WIDE_INT val;
unsigned char arr[16];
- int i, j, repeated, fsmbi;
+ int i, j, repeated, fsmbi, repeat;
gcc_assert (CONSTANT_P (op));
mode = GET_MODE (op);
/* A V4SI const_vector with all identical symbols is ok. */
- if (mode == V4SImode
+ if (!flag_pic
+ && mode == V4SImode
&& GET_CODE (op) == CONST_VECTOR
&& GET_CODE (CONST_VECTOR_ELT (op, 0)) != CONST_INT
&& GET_CODE (CONST_VECTOR_ELT (op, 0)) != CONST_DOUBLE
gcc_assert (GET_MODE_SIZE (mode) > 2);
fsmbi = 1;
+ repeat = 0;
for (i = 0; i < 16 && fsmbi; i++)
- if (arr[i] != 0 && arr[i] != 0xff)
+ if (arr[i] != 0 && repeat == 0)
+ repeat = arr[i];
+ else if (arr[i] != 0 && arr[i] != repeat)
fsmbi = 0;
if (fsmbi)
- return IC_FSMBI;
+ return repeat == 0xff ? IC_FSMBI : IC_FSMBI2;
if (cpat_info (arr, GET_MODE_SIZE (mode), 0, 0))
return IC_CPAT;
return SPU_NONE;
}
+/* Return TRUE when X, a CONST_VECTOR, only contains CONST_INTs or
+ CONST_DOUBLEs. */
+static int
+const_vector_immediate_p (rtx x)
+{
+ int i;
+ gcc_assert (GET_CODE (x) == CONST_VECTOR);
+ for (i = 0; i < GET_MODE_NUNITS (GET_MODE (x)); i++)
+ if (GET_CODE (CONST_VECTOR_ELT (x, i)) != CONST_INT
+ && GET_CODE (CONST_VECTOR_ELT (x, i)) != CONST_DOUBLE)
+ return 0;
+ return 1;
+}
+
int
logical_immediate_p (rtx op, enum machine_mode mode)
{
gcc_assert (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE
|| GET_CODE (op) == CONST_VECTOR);
+ if (GET_CODE (op) == CONST_VECTOR
+ && !const_vector_immediate_p (op))
+ return 0;
+
if (GET_MODE (op) != VOIDmode)
mode = GET_MODE (op);
gcc_assert (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE
|| GET_CODE (op) == CONST_VECTOR);
+ if (GET_CODE (op) == CONST_VECTOR
+ && !const_vector_immediate_p (op))
+ return 0;
+
if (GET_MODE (op) != VOIDmode)
mode = GET_MODE (op);
gcc_assert (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE
|| GET_CODE (op) == CONST_VECTOR);
+ if (GET_CODE (op) == CONST_VECTOR
+ && !const_vector_immediate_p (op))
+ return 0;
+
if (GET_MODE (op) != VOIDmode)
mode = GET_MODE (op);
int
spu_legitimate_constant_p (rtx x)
{
- int i;
+ if (GET_CODE (x) == HIGH)
+ x = XEXP (x, 0);
/* V4SI with all identical symbols is valid. */
- if (GET_MODE (x) == V4SImode
+ if (!flag_pic
+ && GET_MODE (x) == V4SImode
&& (GET_CODE (CONST_VECTOR_ELT (x, 0)) == SYMBOL_REF
|| GET_CODE (CONST_VECTOR_ELT (x, 0)) == LABEL_REF
- || GET_CODE (CONST_VECTOR_ELT (x, 0)) == CONST
- || GET_CODE (CONST_VECTOR_ELT (x, 0)) == HIGH))
+ || GET_CODE (CONST_VECTOR_ELT (x, 0)) == CONST))
return CONST_VECTOR_ELT (x, 0) == CONST_VECTOR_ELT (x, 1)
&& CONST_VECTOR_ELT (x, 1) == CONST_VECTOR_ELT (x, 2)
&& CONST_VECTOR_ELT (x, 2) == CONST_VECTOR_ELT (x, 3);
- if (VECTOR_MODE_P (GET_MODE (x)))
- for (i = 0; i < GET_MODE_NUNITS (GET_MODE (x)); i++)
- if (GET_CODE (CONST_VECTOR_ELT (x, i)) != CONST_INT
- && GET_CODE (CONST_VECTOR_ELT (x, i)) != CONST_DOUBLE)
- return 0;
+ if (GET_CODE (x) == CONST_VECTOR
+ && !const_vector_immediate_p (x))
+ return 0;
return 1;
}
&& GET_CODE (op1) == CONST_INT
&& INTVAL (op1) >= -0x2000
&& INTVAL (op1) <= 0x1fff
- && (REGNO_PTR_FRAME_P (REGNO (op0)) || (INTVAL (op1) & 15) == 0))
+ && (regno_aligned_for_load (REGNO (op0)) || (INTVAL (op1) & 15) == 0))
return 1;
if (GET_CODE (op0) == REG
&& INT_REG_OK_FOR_BASE_P (op0, reg_ok_strict)
fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
}
- global_regs[INTR_REGNUM] = 1;
}
/* This is called to decide when we can simplify a load instruction. We
regno_aligned_for_load (int regno)
{
return regno == FRAME_POINTER_REGNUM
- || regno == HARD_FRAME_POINTER_REGNUM
+ || (frame_pointer_needed && regno == HARD_FRAME_POINTER_REGNUM)
|| regno == STACK_POINTER_REGNUM
- || (regno >= FIRST_VIRTUAL_REGISTER && regno <= LAST_VIRTUAL_REGISTER);
+ || (regno >= FIRST_VIRTUAL_REGISTER
+ && regno <= LAST_VIRTUAL_REGISTER);
}
/* Return TRUE when mem is known to be 16-byte aligned. */
{
if (CONSTANT_P (x))
{
- /* We can always choose DImode for CONST_INT because the high bits
+ /* We can always choose TImode for CONST_INT because the high bits
of an SImode will always be all 1s, i.e., valid for fsmbi. */
- enum immediate_class c = classify_immediate (x, DImode);
- return c == IC_FSMBI;
+ enum immediate_class c = classify_immediate (x, TImode);
+ return c == IC_FSMBI || (!flow2_completed && c == IC_FSMBI2);
}
return 0;
}
/* We use last_assemble_variable_decl to get line information. It's
not always going to be right and might not even be close, but will
be right for the more common cases. */
- if (!last_assemble_variable_decl)
+ if (!last_assemble_variable_decl || in_section == ctors_section)
loc_decl = decl;
else
loc_decl = last_assemble_variable_decl;
constant_to_array (GET_MODE_INNER (mode), ops[1], arr);
emit_move_insn (ops[0], array_to_constant (mode, arr));
}
- else if (GET_MODE (ops[0]) == V4SImode && CONSTANT_P (ops[1]))
+ else if (!flag_pic && GET_MODE (ops[0]) == V4SImode && CONSTANT_P (ops[1]))
{
rtvec v = rtvec_alloc (4);
RTVEC_ELT (v, 0) = ops[1];
if (p >= SPU_BTI_7 && p <= SPU_BTI_U18)
{
int range = p - SPU_BTI_7;
- if (!CONSTANT_P (op)
- || (GET_CODE (op) == CONST_INT
- && (INTVAL (op) < spu_builtin_range[range].low
- || INTVAL (op) > spu_builtin_range[range].high)))
+
+ if (!CONSTANT_P (op))
error ("%s expects an integer literal in the range [%d, %d].",
d->name,
spu_builtin_range[range].low, spu_builtin_range[range].high);
}
else if (GET_CODE (op) == CONST_INT)
v = INTVAL (op);
+ else if (GET_CODE (op) == CONST_VECTOR
+ && GET_CODE (CONST_VECTOR_ELT (op, 0)) == CONST_INT)
+ v = INTVAL (CONST_VECTOR_ELT (op, 0));
+
+ /* The default for v is 0 which is valid in every range. */
+ if (v < spu_builtin_range[range].low
+ || v > spu_builtin_range[range].high)
+ error ("%s expects an integer literal in the range [%d, %d]. ("
+ HOST_WIDE_INT_PRINT_DEC ")",
+ d->name,
+ spu_builtin_range[range].low, spu_builtin_range[range].high,
+ v);
switch (p)
{
if (GET_CODE (op) == LABEL_REF
|| (GET_CODE (op) == SYMBOL_REF
&& SYMBOL_REF_FUNCTION_P (op))
- || (INTVAL (op) & ((1 << lsbits) - 1)) != 0)
+ || (v & ((1 << lsbits) - 1)) != 0)
warning (0, "%d least significant bits of %s are ignored.", lsbits,
d->name);
}
static void
-expand_builtin_args (struct spu_builtin_description *d, tree arglist,
+expand_builtin_args (struct spu_builtin_description *d, tree exp,
rtx target, rtx ops[])
{
enum insn_code icode = d->icode;
- int i = 0;
+ int i = 0, a;
/* Expand the arguments into rtl. */
if (d->parm[0] != SPU_BTI_VOID)
ops[i++] = target;
- for (; i < insn_data[icode].n_operands; i++)
+ for (a = 0; i < insn_data[icode].n_operands; i++, a++)
{
- tree arg = TREE_VALUE (arglist);
+ tree arg = CALL_EXPR_ARG (exp, a);
if (arg == 0)
abort ();
ops[i] = expand_expr (arg, NULL_RTX, VOIDmode, 0);
- arglist = TREE_CHAIN (arglist);
}
}
static rtx
spu_expand_builtin_1 (struct spu_builtin_description *d,
- tree arglist, rtx target)
+ tree exp, rtx target)
{
rtx pat;
rtx ops[8];
tree return_type;
/* Set up ops[] with values from arglist. */
- expand_builtin_args (d, arglist, target, ops);
+ expand_builtin_args (d, exp, target, ops);
/* Handle the target operand which must be operand 0. */
i = 0;
rtx addr, op, pat;
/* get addr */
- arg = TREE_VALUE (arglist);
+ arg = CALL_EXPR_ARG (exp, 0);
gcc_assert (TREE_CODE (TREE_TYPE (arg)) == POINTER_TYPE);
op = expand_expr (arg, NULL_RTX, Pmode, EXPAND_NORMAL);
addr = memory_address (mode, op);
}
}
+ spu_check_builtin_parm (d, ops[i], d->parm[p]);
+
if (!(*insn_data[icode].operand[i].predicate) (ops[i], mode))
ops[i] = spu_force_reg (mode, ops[i]);
-
- spu_check_builtin_parm (d, ops[i], d->parm[p]);
}
switch (insn_data[icode].n_operands)
enum machine_mode mode ATTRIBUTE_UNUSED,
int ignore ATTRIBUTE_UNUSED)
{
- tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+ tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
unsigned int fcode = DECL_FUNCTION_CODE (fndecl) - END_BUILTINS;
- tree arglist = TREE_OPERAND (exp, 1);
struct spu_builtin_description *d;
if (fcode < NUM_SPU_BUILTINS)
{
d = &spu_builtins[fcode];
- return spu_expand_builtin_1 (d, arglist, target);
+ return spu_expand_builtin_1 (d, exp, target);
}
abort ();
}
gcc_assert (d);
return d->fndecl;
}
+
+void
+spu_init_expanders (void)
+{
+ /* HARD_FRAME_REGISTER is only 128 bit aligned when
+ * frame_pointer_needed is true. We don't know that until we're
+ * expanding the prologue. */
+ if (cfun)
+ REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = 8;
+}
#define OVERRIDE_OPTIONS spu_override_options()
#define C_COMMON_OVERRIDE_OPTIONS spu_c_common_override_options()
+#define OPTIMIZATION_OPTIONS(level,size) \
+ spu_optimization_options(level,size)
+
+#define INIT_EXPANDERS spu_init_expanders()
+
extern int target_flags;
extern const char *spu_fixed_range_string;
/* Register Basics */
/* 128-130 are special registers that never appear in assembly code. */
-#define FIRST_PSEUDO_REGISTER 132
+#define FIRST_PSEUDO_REGISTER 131
#define FIXED_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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
- 1, 1, 1, 1 \
+ 1, 1, 1 \
}
#define CALL_USED_REGISTERS { \
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, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
- 1, 1, 1, 1 \
+ 1, 1, 1 \
}
#define CONDITIONAL_REGISTER_USAGE \
* buffer. Users can also specify it in inline asm. */
#define HBR_REGNUM 130
-/* Used to keep track of enabling and disabling interrupts. */
-#define INTR_REGNUM 131
-
#define MAX_REGISTER_ARGS 72
#define FIRST_ARG_REGNUM 3
#define LAST_ARG_REGNUM (FIRST_ARG_REGNUM + MAX_REGISTER_ARGS - 1)
"$80", "$81", "$82", "$83", "$84", "$85", "$86", "$87", "$88", "$89", "$90", "$91", "$92", "$93", "$94", "$95", \
"$96", "$97", "$98", "$99", "$100", "$101", "$102", "$103", "$104", "$105", "$106", "$107", "$108", "$109", "$110", "$111", \
"$112", "$113", "$114", "$115", "$116", "$117", "$118", "$119", "$120", "$121", "$122", "$123", "$124", "$125", "$126", "$127", \
- "$vfp", "$vap", "hbr", "intr" \
+ "$vfp", "$vap", "hbr" \
}
#define PRINT_OPERAND(FILE, X, CODE) print_operand(FILE, X, CODE)
(UNSPEC_CFLTU 37)
(UNSPEC_STOP 38)
(UNSPEC_STOPD 39)
- (UNSPEC_IDISABLE 40)
- (UNSPEC_IENABLE 41)
+ (UNSPEC_SET_INTR 40)
(UNSPEC_FSCRRD 42)
(UNSPEC_FSCRWR 43)
(UNSPEC_MFSPR 44)
(define_mode_attr f2i [(SF "SI") (V4SF "V4SI")
(DF "DI") (V2DF "V2DI")])
+(define_mode_attr umask [(HI "f") (V8HI "f")
+ (SI "g") (V4SI "g")])
+(define_mode_attr nmask [(HI "F") (V8HI "F")
+ (SI "G") (V4SI "G")])
+
;; Used for carry and borrow instructions.
(define_mode_macro CBOP [SI DI V4SI V2DI])
stq%p0\t%1,%0"
[(set_attr "type" "fx2,fx2,shuf,shuf,load,store")])
-(define_insn "high"
- [(set (match_operand:SI 0 "spu_reg_operand" "=r")
- (high:SI (match_operand:SI 1 "immediate_operand" "i")))]
- ""
- "ilhu\t%0,%1@h")
-
-(define_insn "low"
- [(set (match_operand:SI 0 "spu_reg_operand" "=r")
- (lo_sum:SI (match_operand:SI 1 "spu_reg_operand" "0")
- (match_operand:SI 2 "immediate_operand" "i")))]
+(define_insn "low_<mode>"
+ [(set (match_operand:VSI 0 "spu_reg_operand" "=r")
+ (lo_sum:VSI (match_operand:VSI 1 "spu_reg_operand" "0")
+ (match_operand:VSI 2 "immediate_operand" "i")))]
""
"iohl\t%0,%2@l")
(define_insn "mulhisi3_imm"
[(set (match_operand:SI 0 "spu_reg_operand" "=r")
(mult:SI (sign_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
- (match_operand:SI 2 "immediate_operand" "K")))]
+ (match_operand:SI 2 "imm_K_operand" "K")))]
""
"mpyi\t%0,%1,%2"
[(set_attr "type" "fp7")])
(define_insn "umulhisi3_imm"
[(set (match_operand:SI 0 "spu_reg_operand" "=r")
(mult:SI (zero_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
- (and:SI (match_operand:SI 2 "immediate_operand" "K") (const_int 65535))))]
+ (and:SI (match_operand:SI 2 "imm_K_operand" "K") (const_int 65535))))]
""
"mpyui\t%0,%1,%2"
[(set_attr "type" "fp7")])
""
"@
xor\t%0,%1,%2
- xor%j2i\t%0,%1,%S2")
+ xor%j2i\t%0,%1,%J2")
(define_insn "xordi3"
[(set (match_operand:DI 0 "spu_reg_operand" "=r,r")
(define_insn "ashl<mode>3"
[(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
(ashift:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
- (match_operand:VHSI 2 "spu_shift_operand" "r,W")))]
+ (match_operand:VHSI 2 "spu_nonmem_operand" "r,W")))]
""
"@
shl<bh>\t%0,%1,%2
- shl<bh>i\t%0,%1,%2"
+ shl<bh>i\t%0,%1,%<umask>2"
[(set_attr "type" "fx3")])
(define_insn_and_split "ashldi3"
[(set (match_operand:DI 0 "spu_reg_operand" "=r,r")
(ashift:DI (match_operand:DI 1 "spu_reg_operand" "r,r")
- (match_operand:SI 2 "spu_shift_operand" "r,I")))
+ (match_operand:SI 2 "spu_nonmem_operand" "r,I")))
(clobber (match_scratch:SI 3 "=&r,X"))]
""
"#"
(match_operand:SI 2 "immediate_operand" "O,P")))]
""
"@
- shlqbyi\t%0,%1,%2/8
- shlqbii\t%0,%1,%2"
+ shlqbyi\t%0,%1,%h2
+ shlqbii\t%0,%1,%e2"
"!satisfies_constraint_O (operands[2]) && !satisfies_constraint_P (operands[2])"
[(set (match_dup:TI 0)
(ashift:TI (match_dup:TI 1)
{
HOST_WIDE_INT val = INTVAL(operands[2]);
operands[3] = GEN_INT (val&7);
- operands[4] = GEN_INT (val&0x78);
+ operands[4] = GEN_INT (val&-8);
}
[(set_attr "type" "shuf,shuf")])
""
"@
shlqbybi\t%0,%1,%2
- shlqbyi\t%0,%1,%2/8"
+ shlqbyi\t%0,%1,%h2"
[(set_attr "type" "shuf,shuf")])
(define_insn "shlqbi_ti"
""
"@
shlqbi\t%0,%1,%2
- shlqbii\t%0,%1,%2"
+ shlqbii\t%0,%1,%e2"
[(set_attr "type" "shuf,shuf")])
(define_insn "shlqby_ti"
""
"@
shlqby\t%0,%1,%2
- shlqbyi\t%0,%1,%2"
+ shlqbyi\t%0,%1,%f2"
[(set_attr "type" "shuf,shuf")])
\f
(define_insn_and_split "lshr<mode>3"
[(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
(lshiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
- (match_operand:VHSI 2 "spu_shift_operand" "r,W")))
+ (match_operand:VHSI 2 "spu_nonmem_operand" "r,W")))
(clobber (match_scratch:VHSI 3 "=&r,X"))]
""
"@
#
- rot<bh>mi\t%0,%1,%N2"
+ rot<bh>mi\t%0,%1,-%<umask>2"
"reload_completed && GET_CODE (operands[2]) == REG"
[(set (match_dup:VHSI 3)
(neg:VHSI (match_dup:VHSI 2)))
(define_insn "rotm_<mode>"
[(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
(lshiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
- (neg:VHSI (match_operand:VHSI 2 "spu_shift_operand" "r,W"))))]
+ (neg:VHSI (match_operand:VHSI 2 "spu_nonmem_operand" "r,W"))))]
""
"@
rot<bh>m\t%0,%1,%2
- rot<bh>mi\t%0,%1,%2"
+ rot<bh>mi\t%0,%1,-%<nmask>2"
[(set_attr "type" "fx3")])
(define_expand "lshr<mode>3"
(match_operand:SI 2 "immediate_operand" "O,P")))]
""
"@
- rotqmbyi\t%0,%1,%N2/8
- rotqmbii\t%0,%1,%N2"
+ rotqmbyi\t%0,%1,-%h2
+ rotqmbii\t%0,%1,-%e2"
"!satisfies_constraint_O (operands[2]) && !satisfies_constraint_P (operands[2])"
[(set (match_dup:DTI 0)
(lshiftrt:DTI (match_dup:DTI 1)
{
HOST_WIDE_INT val = INTVAL(operands[2]);
operands[4] = GEN_INT (val&7);
- operands[5] = GEN_INT (val&0x78);
+ operands[5] = GEN_INT (val&-8);
}
[(set_attr "type" "shuf,shuf")])
(const_int 7))))
(set (match_dup:DTI 0)
(lshiftrt:DTI (match_dup:DTI 3)
- (and:SI (neg:SI (match_dup:SI 5))
+ (and:SI (neg:SI (and:SI (match_dup:SI 5)
+ (const_int -8)))
(const_int -8))))]
{
emit_insn(gen_subsi3(operands[4], GEN_INT(0), operands[2]));
(define_insn "rotqmbybi_<mode>"
[(set (match_operand:DTI 0 "spu_reg_operand" "=r,r")
(lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r")
- (and:SI (neg:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I"))
+ (and:SI (neg:SI (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
+ (const_int -8)))
(const_int -8))))]
""
"@
rotqmbybi\t%0,%1,%2
- rotqmbyi\t%0,%1,%2/8"
+ rotqmbyi\t%0,%1,-%H2"
[(set_attr "type" "shuf")])
(define_insn "rotqmbi_<mode>"
""
"@
rotqmbi\t%0,%1,%2
- rotqmbii\t%0,%1,%2"
+ rotqmbii\t%0,%1,-%E2"
[(set_attr "type" "shuf")])
(define_insn "rotqmby_<mode>"
""
"@
rotqmby\t%0,%1,%2
- rotqmbyi\t%0,%1,%2"
+ rotqmbyi\t%0,%1,-%F2"
[(set_attr "type" "shuf")])
\f
(define_insn_and_split "ashr<mode>3"
[(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
(ashiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
- (match_operand:VHSI 2 "spu_shift_operand" "r,W")))
+ (match_operand:VHSI 2 "spu_nonmem_operand" "r,W")))
(clobber (match_scratch:VHSI 3 "=&r,X"))]
""
"@
#
- rotma<bh>i\t%0,%1,%N2"
+ rotma<bh>i\t%0,%1,-%<umask>2"
"reload_completed && GET_CODE (operands[2]) == REG"
[(set (match_dup:VHSI 3)
(neg:VHSI (match_dup:VHSI 2)))
(define_insn "rotma_<mode>"
[(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
(ashiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
- (neg:VHSI (match_operand:VHSI 2 "spu_shift_operand" "r,W"))))]
+ (neg:VHSI (match_operand:VHSI 2 "spu_nonmem_operand" "r,W"))))]
""
"@
rotma<bh>\t%0,%1,%2
- rotma<bh>i\t%0,%1,%2"
+ rotma<bh>i\t%0,%1,-%<nmask>2"
[(set_attr "type" "fx3")])
(define_insn_and_split "ashrdi3"
(define_insn "rotl<mode>3"
[(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
(rotate:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
- (match_operand:VHSI 2 "spu_shift_operand" "r,W")))]
+ (match_operand:VHSI 2 "spu_nonmem_operand" "r,W")))]
""
"@
rot<bh>\t%0,%1,%2
- rot<bh>i\t%0,%1,%2"
+ rot<bh>i\t%0,%1,%<umask>2"
[(set_attr "type" "fx3")])
(define_insn "rotlti3"
""
"@
rotqbybi\t%0,%1,%2\;rotqbi\t%0,%0,%2
- rotqbyi\t%0,%1,%2/8
- rotqbii\t%0,%1,%2
- rotqbyi\t%0,%1,%2/8\;rotqbii\t%0,%0,%2%%8"
+ rotqbyi\t%0,%1,%h2
+ rotqbii\t%0,%1,%e2
+ rotqbyi\t%0,%1,%h2\;rotqbii\t%0,%0,%e2"
[(set_attr "length" "8,4,4,8")
(set_attr "type" "multi1,shuf,shuf,multi1")])
""
"@
rotqbybi\t%0,%1,%2
- rotqbyi\t%0,%1,%2/8"
+ rotqbyi\t%0,%1,%h2"
[(set_attr "type" "shuf,shuf")])
(define_insn "rotqby_ti"
""
"@
rotqby\t%0,%1,%2
- rotqbyi\t%0,%1,%2"
+ rotqbyi\t%0,%1,%f2"
[(set_attr "type" "shuf,shuf")])
(define_insn "rotqbi_ti"
""
"@
rotqbi\t%0,%1,%2
- rotqbii\t%0,%1,%2%%8"
+ rotqbii\t%0,%1,%e2"
[(set_attr "type" "shuf,shuf")])
\f
[(unspec_volatile [(const_int 0)] UNSPEC_BLOCKAGE)]
""
""
- [(set_attr "length" "0")])
+ [(set_attr "type" "convert")
+ (set_attr "length" "0")])
(define_expand "epilogue"
[(const_int 2)]
"rotqbyi\t%0,%1,(%2*<vmult>+<voff>)%%16"
[(set_attr "type" "shuf")])
+(define_insn "_vec_extractv8hi_ze"
+ [(set (match_operand:SI 0 "spu_reg_operand" "=r")
+ (zero_extend:SI (vec_select:HI (match_operand:V8HI 1 "spu_reg_operand" "r")
+ (parallel [(const_int 0)]))))]
+ ""
+ "rotqmbyi\t%0,%1,-2"
+ [(set_attr "type" "shuf")])
+
\f
;; misc
(define_insn "hbr"
[(set (reg:SI 130)
- (unspec:SI [(match_operand:SI 0 "immediate_operand" "s,s,s")
+ (unspec:SI [(match_operand:SI 0 "immediate_operand" "i,i,i")
(match_operand:SI 1 "nonmemory_operand" "r,s,i")] UNSPEC_HBR))
(unspec [(const_int 0)] UNSPEC_HBR)]
""
#define si_clgthi(ra,imm) __builtin_si_clgthi(ra,imm)
#define si_clgt(ra,rb) __builtin_si_clgt(ra,rb)
#define si_clgti(ra,imm) __builtin_si_clgti(ra,imm)
+#define si_bisled(ra) __builtin_si_bisled(ra,0)
+#define si_bisledd(ra) __builtin_si_bisledd(ra,0)
+#define si_bislede(ra) __builtin_si_bislede(ra,0)
#define si_fa(ra,rb) __builtin_si_fa(ra,rb)
#define si_dfa(ra,rb) __builtin_si_dfa(ra,rb)
#define si_fs(ra,rb) __builtin_si_fs(ra,rb)