<s> static bool ix86_expand_sse_fp_minmax ( rtx dest , enum rtx_code code , rtx cmp_op0 , rtx cmp_op1 , rtx if_true , rtx if_false ) { enum machine_mode mode ; bool is_min ; rtx tmp ; if ( code == LT ) ; else if ( code == UNGE ) { tmp = if_true ; if_true = if_false ; if_false = tmp ; } else return false ; if ( rtx_equal_p ( cmp_op0 , if_true ) && rtx_equal_p ( cmp_op1 , if_false ) ) is_min = true ; else if ( rtx_equal_p ( cmp_op1 , if_true ) && rtx_equal_p ( cmp_op0 , if_false ) ) is_min = false ; else return false ; mode = GET_MODE ( dest ) ; if ( ! flag_finite_math_only || ! flag_unsafe_math_optimizations ) { int u = is_min ? UNSPEC_IEEE_MIN : UNSPEC_IEEE_MAX ; rtvec v ; if_true = force_reg ( mode , if_true ) ; v = gen_rtvec ( 2 , if_true , if_false ) ; tmp = gen_rtx_UNSPEC ( mode , v , u ) ; } else { code = is_min ? SMIN : SMAX ; tmp = gen_rtx_fmt_ee ( code , mode , if_true , if_false ) ; } emit_insn ( gen_rtx_SET ( VOIDmode , dest , tmp ) ) ; return true ; } </s>

Detect conditional moves that exactly match min/max operational semantics . Note that this is IEEE safe , as long as we do n't interchange the operands . Returns FALSE if this conditional move does n't match a MIN/MAX , and TRUE if the operation is successful and instructions are emitted .


<s> static rtx ix86_expand_store_builtin ( enum insn_code icode , tree arglist ) { rtx pat ; tree arg0 = TREE_VALUE ( arglist ) ; tree arg1 = TREE_VALUE ( TREE_CHAIN ( arglist ) ) ; rtx op0 = expand_expr ( arg0 , NULL_RTX , VOIDmode , 0 ) ; rtx op1 = expand_expr ( arg1 , NULL_RTX , VOIDmode , 0 ) ; enum machine_mode mode0 = insn_data [ icode ] . operand [ 0 ] . mode ; enum machine_mode mode1 = insn_data [ icode ] . operand [ 1 ] . mode ; if ( VECTOR_MODE_P ( mode1 ) ) op1 = safe_vector_operand ( op1 , mode1 ) ; op0 = gen_rtx_MEM ( mode0 , copy_to_mode_reg ( Pmode , op0 ) ) ; op1 = copy_to_mode_reg ( mode1 , op1 ) ; pat = GEN_FCN ( icode ) ( op0 , op1 ) ; if ( pat ) emit_insn ( pat ) ; return 0 ; } </s>

Subroutine of ix86_expand_builtin to take care of stores .


<s> int ix86_expand_strlen ( rtx out , rtx src , rtx eoschar , rtx align ) { rtx addr , scratch1 , scratch2 , scratch3 , scratch4 ; if ( TARGET_UNROLL_STRLEN && eoschar == const0_rtx && optimize > 1 && ! TARGET_INLINE_ALL_STRINGOPS && ! optimize_size && ( GET_CODE ( align ) != CONST_INT || INTVAL ( align ) < 4 ) ) return 0 ; addr = force_reg ( Pmode , XEXP ( src , 0 ) ) ; scratch1 = gen_reg_rtx ( Pmode ) ; if ( TARGET_UNROLL_STRLEN && eoschar == const0_rtx && optimize > 1 && ! optimize_size ) { emit_move_insn ( out , addr ) ; ix86_expand_strlensi_unroll_1 ( out , src , align ) ; if ( TARGET_64BIT ) emit_insn ( gen_subdi3 ( out , out , addr ) ) ; else emit_insn ( gen_subsi3 ( out , out , addr ) ) ; } else { rtx unspec ; scratch2 = gen_reg_rtx ( Pmode ) ; scratch3 = gen_reg_rtx ( Pmode ) ; scratch4 = force_reg ( Pmode , constm1_rtx ) ; emit_move_insn ( scratch3 , addr ) ; eoschar = force_reg ( QImode , eoschar ) ; emit_insn ( gen_cld ( ) ) ; src = replace_equiv_address_nv ( src , scratch3 ) ; unspec = gen_rtx_UNSPEC ( Pmode , gen_rtvec ( 4 , src , eoschar , align , scratch4 ) , UNSPEC_SCAS ) ; emit_insn ( gen_strlenqi_1 ( scratch1 , scratch3 , unspec ) ) ; if ( TARGET_64BIT ) { emit_insn ( gen_one_cmpldi2 ( scratch2 , scratch1 ) ) ; emit_insn ( gen_adddi3 ( out , scratch2 , constm1_rtx ) ) ; } else { emit_insn ( gen_one_cmplsi2 ( scratch2 , scratch1 ) ) ; emit_insn ( gen_addsi3 ( out , scratch2 , constm1_rtx ) ) ; } } return 1 ; } </s>


<s> void ix86_expand_unary_operator ( enum rtx_code code , enum machine_mode mode , rtx operands [ ] ) { int matching_memory ; rtx src , dst , op , clob ; dst = operands [ 0 ] ; src = operands [ 1 ] ; matching_memory = 0 ; if ( MEM_P ( dst ) ) { if ( rtx_equal_p ( dst , src ) ) matching_memory = 1 ; else dst = gen_reg_rtx ( mode ) ; } if ( MEM_P ( src ) && ! matching_memory ) src = force_reg ( mode , src ) ; op = gen_rtx_SET ( VOIDmode , dst , gen_rtx_fmt_e ( code , mode , src ) ) ; if ( reload_in_progress || code == NOT ) { gcc_assert ( code == NOT ) ; emit_insn ( op ) ; } else { clob = gen_rtx_CLOBBER ( VOIDmode , gen_rtx_REG ( CCmode , FLAGS_REG ) ) ; emit_insn ( gen_rtx_PARALLEL ( VOIDmode , gen_rtvec ( 2 , op , clob ) ) ) ; } if ( dst != operands [ 0 ] ) emit_move_insn ( operands [ 0 ] , dst ) ; } </s>

Attempt to expand a unary operator . Make the expansion closer to the actual machine , then just general_operand , which will allow 2 separate memory references ( one output , one input ) in a single insn .


<s> static rtx ix86_expand_unop1_builtin ( enum insn_code icode , tree arglist , rtx target ) { rtx pat ; tree arg0 = TREE_VALUE ( arglist ) ; rtx op1 , op0 = expand_expr ( arg0 , NULL_RTX , VOIDmode , 0 ) ; enum machine_mode tmode = insn_data [ icode ] . operand [ 0 ] . mode ; enum machine_mode mode0 = insn_data [ icode ] . operand [ 1 ] . mode ; if ( optimize || ! target || GET_MODE ( target ) != tmode || ! ( * insn_data [ icode ] . operand [ 0 ] . predicate ) ( target , tmode ) ) target = gen_reg_rtx ( tmode ) ; if ( VECTOR_MODE_P ( mode0 ) ) op0 = safe_vector_operand ( op0 , mode0 ) ; if ( ( optimize && ! register_operand ( op0 , mode0 ) ) || ! ( * insn_data [ icode ] . operand [ 1 ] . predicate ) ( op0 , mode0 ) ) op0 = copy_to_mode_reg ( mode0 , op0 ) ; op1 = op0 ; if ( ! ( * insn_data [ icode ] . operand [ 2 ] . predicate ) ( op1 , mode0 ) ) op1 = copy_to_mode_reg ( mode0 , op1 ) ; pat = GEN_FCN ( icode ) ( target , op0 , op1 ) ; if ( ! pat ) return 0 ; emit_insn ( pat ) ; return target ; } </s>

Subroutine of ix86_expand_builtin to take care of three special unop insns : sqrtss , rsqrtss , rcpss .


<s> static rtx ix86_expand_unop_builtin ( enum insn_code icode , tree arglist , rtx target , int do_load ) { rtx pat ; tree arg0 = TREE_VALUE ( arglist ) ; rtx op0 = expand_expr ( arg0 , NULL_RTX , VOIDmode , 0 ) ; enum machine_mode tmode = insn_data [ icode ] . operand [ 0 ] . mode ; enum machine_mode mode0 = insn_data [ icode ] . operand [ 1 ] . mode ; if ( optimize || ! target || GET_MODE ( target ) != tmode || ! ( * insn_data [ icode ] . operand [ 0 ] . predicate ) ( target , tmode ) ) target = gen_reg_rtx ( tmode ) ; if ( do_load ) op0 = gen_rtx_MEM ( mode0 , copy_to_mode_reg ( Pmode , op0 ) ) ; else { if ( VECTOR_MODE_P ( mode0 ) ) op0 = safe_vector_operand ( op0 , mode0 ) ; if ( ( optimize && ! register_operand ( op0 , mode0 ) ) || ! ( * insn_data [ icode ] . operand [ 1 ] . predicate ) ( op0 , mode0 ) ) op0 = copy_to_mode_reg ( mode0 , op0 ) ; } pat = GEN_FCN ( icode ) ( target , op0 ) ; if ( ! pat ) return 0 ; emit_insn ( pat ) ; return target ; } </s>

Subroutine of ix86_expand_builtin to take care of unop insns .


<s> void ix86_expand_vector_init ( bool mmx_ok , rtx target , rtx vals ) { enum machine_mode mode = GET_MODE ( target ) ; enum machine_mode inner_mode = GET_MODE_INNER ( mode ) ; int n_elts = GET_MODE_NUNITS ( mode ) ; int n_var = 0 , one_var = - 1 ; bool all_same = true , all_const_zero = true ; int i ; rtx x ; for ( i = 0 ; i < n_elts ; ++ i ) { x = XVECEXP ( vals , 0 , i ) ; if ( ! CONSTANT_P ( x ) ) n_var ++ , one_var = i ; else if ( x != CONST0_RTX ( inner_mode ) ) all_const_zero = false ; if ( i > 0 && ! rtx_equal_p ( x , XVECEXP ( vals , 0 , 0 ) ) ) all_same = false ; } if ( n_var == 0 ) { emit_move_insn ( target , gen_rtx_CONST_VECTOR ( mode , XVEC ( vals , 0 ) ) ) ; return ; } if ( all_same && ix86_expand_vector_init_duplicate ( mmx_ok , mode , target , XVECEXP ( vals , 0 , 0 ) ) ) return ; if ( n_var == 1 ) { if ( all_const_zero && one_var == 0 && ix86_expand_vector_init_low_nonzero ( mmx_ok , mode , target , XVECEXP ( vals , 0 , 0 ) ) ) return ; if ( ix86_expand_vector_init_one_var ( mmx_ok , mode , target , vals , one_var ) ) return ; } ix86_expand_vector_init_general ( mmx_ok , mode , target , vals ) ; } </s>

Initialize vector TARGET via VALS . Suppress the use of MMX instructions unless MMX_OK is true .


<s> static bool ix86_expand_vector_init_duplicate ( bool mmx_ok , enum machine_mode mode , rtx target , rtx val ) { enum machine_mode smode , wsmode , wvmode ; rtx x ; switch ( mode ) { case V2SImode : case V2SFmode : if ( ! mmx_ok && ! TARGET_SSE ) return false ; case V2DFmode : case V2DImode : case V4SFmode : case V4SImode : val = force_reg ( GET_MODE_INNER ( mode ) , val ) ; x = gen_rtx_VEC_DUPLICATE ( mode , val ) ; emit_insn ( gen_rtx_SET ( VOIDmode , target , x ) ) ; return true ; case V4HImode : if ( ! mmx_ok ) return false ; if ( TARGET_SSE || TARGET_3DNOW_A ) { val = gen_lowpart ( SImode , val ) ; x = gen_rtx_TRUNCATE ( HImode , val ) ; x = gen_rtx_VEC_DUPLICATE ( mode , x ) ; emit_insn ( gen_rtx_SET ( VOIDmode , target , x ) ) ; return true ; } else { smode = HImode ; wsmode = SImode ; wvmode = V2SImode ; goto widen ; } case V8QImode : if ( ! mmx_ok ) return false ; smode = QImode ; wsmode = HImode ; wvmode = V4HImode ; goto widen ; case V8HImode : smode = HImode ; wsmode = SImode ; wvmode = V4SImode ; goto widen ; case V16QImode : smode = QImode ; wsmode = HImode ; wvmode = V8HImode ; goto widen ; widen : val = convert_modes ( wsmode , smode , val , true ) ; x = expand_simple_binop ( wsmode , ASHIFT , val , GEN_INT ( GET_MODE_BITSIZE ( smode ) ) , NULL_RTX , 1 , OPTAB_LIB_WIDEN ) ; val = expand_simple_binop ( wsmode , IOR , val , x , x , 1 , OPTAB_LIB_WIDEN ) ; x = gen_reg_rtx ( wvmode ) ; if ( ! ix86_expand_vector_init_duplicate ( mmx_ok , wvmode , x , val ) ) gcc_unreachable ( ) ; emit_move_insn ( target , gen_lowpart ( mode , x ) ) ; return true ; default : return false ; } } </s>

A subroutine of ix86_expand_vector_init . Store into TARGET a vector with all elements equal to VAR . Return true if successful .


<s> static bool ix86_expand_vector_init_low_nonzero ( bool mmx_ok , enum machine_mode mode , rtx target , rtx var ) { enum machine_mode vsimode ; rtx x ; switch ( mode ) { case V2SFmode : case V2SImode : if ( ! mmx_ok && ! TARGET_SSE ) return false ; case V2DFmode : case V2DImode : var = force_reg ( GET_MODE_INNER ( mode ) , var ) ; x = gen_rtx_VEC_CONCAT ( mode , var , CONST0_RTX ( GET_MODE_INNER ( mode ) ) ) ; emit_insn ( gen_rtx_SET ( VOIDmode , target , x ) ) ; return true ; case V4SFmode : case V4SImode : var = force_reg ( GET_MODE_INNER ( mode ) , var ) ; x = gen_rtx_VEC_DUPLICATE ( mode , var ) ; x = gen_rtx_VEC_MERGE ( mode , x , CONST0_RTX ( mode ) , const1_rtx ) ; emit_insn ( gen_rtx_SET ( VOIDmode , target , x ) ) ; return true ; case V8HImode : case V16QImode : vsimode = V4SImode ; goto widen ; case V4HImode : case V8QImode : if ( ! mmx_ok ) return false ; vsimode = V2SImode ; goto widen ; widen : var = convert_modes ( SImode , GET_MODE_INNER ( mode ) , var , true ) ; x = gen_reg_rtx ( vsimode ) ; if ( ! ix86_expand_vector_init_low_nonzero ( mmx_ok , vsimode , x , var ) ) gcc_unreachable ( ) ; emit_move_insn ( target , gen_lowpart ( mode , x ) ) ; return true ; default : return false ; } } </s>

A subroutine of ix86_expand_vector_init . Store into TARGET a vector whose low element is VAR , and other elements are zero . Return true if successful .


<s> static bool ix86_expand_vector_init_one_var ( bool mmx_ok , enum machine_mode mode , rtx target , rtx vals , int one_var ) { rtx var = XVECEXP ( vals , 0 , one_var ) ; enum machine_mode wmode ; rtx const_vec , x ; const_vec = copy_rtx ( vals ) ; XVECEXP ( const_vec , 0 , one_var ) = CONST0_RTX ( GET_MODE_INNER ( mode ) ) ; const_vec = gen_rtx_CONST_VECTOR ( mode , XVEC ( const_vec , 0 ) ) ; switch ( mode ) { case V2DFmode : case V2DImode : case V2SFmode : case V2SImode : return false ; case V4SFmode : case V4SImode : case V8HImode : case V4HImode : break ; case V16QImode : wmode = V8HImode ; goto widen ; case V8QImode : wmode = V4HImode ; goto widen ; widen : x = XVECEXP ( vals , 0 , one_var ^ 1 ) ; if ( one_var & 1 ) { var = convert_modes ( HImode , QImode , var , true ) ; var = expand_simple_binop ( HImode , ASHIFT , var , GEN_INT ( 8 ) , NULL_RTX , 1 , OPTAB_LIB_WIDEN ) ; x = GEN_INT ( INTVAL ( x ) & 0xff ) ; } else { var = convert_modes ( HImode , QImode , var , true ) ; x = gen_int_mode ( INTVAL ( x ) << 8 , HImode ) ; } if ( x != const0_rtx ) var = expand_simple_binop ( HImode , IOR , var , x , var , 1 , OPTAB_LIB_WIDEN ) ; x = gen_reg_rtx ( wmode ) ; emit_move_insn ( x , gen_lowpart ( wmode , const_vec ) ) ; ix86_expand_vector_set ( mmx_ok , x , var , one_var >> 1 ) ; emit_move_insn ( target , gen_lowpart ( mode , x ) ) ; return true ; default : return false ; } emit_move_insn ( target , const_vec ) ; ix86_expand_vector_set ( mmx_ok , target , var , one_var ) ; return true ; } </s>

A subroutine of ix86_expand_vector_init . Store into TARGET a vector consisting of the values in VALS . It is known that all elements except ONE_VAR are constants . Return true if successful .


<s> void ix86_expand_vector_move_misalign ( enum machine_mode mode , rtx operands [ ] ) { rtx op0 , op1 , m ; op0 = operands [ 0 ] ; op1 = operands [ 1 ] ; if ( MEM_P ( op1 ) ) { if ( optimize_size ) { op0 = gen_lowpart ( V4SFmode , op0 ) ; op1 = gen_lowpart ( V4SFmode , op1 ) ; emit_insn ( gen_sse_movups ( op0 , op1 ) ) ; return ; } if ( TARGET_SSE2 && GET_MODE_CLASS ( mode ) == MODE_VECTOR_INT ) { op0 = gen_lowpart ( V16QImode , op0 ) ; op1 = gen_lowpart ( V16QImode , op1 ) ; emit_insn ( gen_sse2_movdqu ( op0 , op1 ) ) ; return ; } if ( TARGET_SSE2 && mode == V2DFmode ) { rtx zero ; if ( TARGET_SSE_SPLIT_REGS ) { emit_insn ( gen_rtx_CLOBBER ( VOIDmode , op0 ) ) ; zero = op0 ; } else { zero = CONST0_RTX ( V2DFmode ) ; } m = adjust_address ( op1 , DFmode , 0 ) ; emit_insn ( gen_sse2_loadlpd ( op0 , zero , m ) ) ; m = adjust_address ( op1 , DFmode , 8 ) ; emit_insn ( gen_sse2_loadhpd ( op0 , op0 , m ) ) ; } else { if ( TARGET_SSE_PARTIAL_REG_DEPENDENCY ) emit_move_insn ( op0 , CONST0_RTX ( mode ) ) ; else emit_insn ( gen_rtx_CLOBBER ( VOIDmode , op0 ) ) ; if ( mode != V4SFmode ) op0 = gen_lowpart ( V4SFmode , op0 ) ; m = adjust_address ( op1 , V2SFmode , 0 ) ; emit_insn ( gen_sse_loadlps ( op0 , op0 , m ) ) ; m = adjust_address ( op1 , V2SFmode , 8 ) ; emit_insn ( gen_sse_loadhps ( op0 , op0 , m ) ) ; } } else if ( MEM_P ( op0 ) ) { if ( optimize_size ) { op0 = gen_lowpart ( V4SFmode , op0 ) ; op1 = gen_lowpart ( V4SFmode , op1 ) ; emit_insn ( gen_sse_movups ( op0 , op1 ) ) ; return ; } if ( TARGET_SSE2 && ! TARGET_SSE_TYPELESS_STORES && GET_MODE_CLASS ( mode ) == MODE_VECTOR_INT ) { op0 = gen_lowpart ( V16QImode , op0 ) ; op1 = gen_lowpart ( V16QImode , op1 ) ; emit_insn ( gen_sse2_movdqu ( op0 , op1 ) ) ; return ; } if ( TARGET_SSE2 && mode == V2DFmode ) { m = adjust_address ( op0 , DFmode , 0 ) ; emit_insn ( gen_sse2_storelpd ( m , op1 ) ) ; m = adjust_address ( op0 , DFmode , 8 ) ; emit_insn ( gen_sse2_storehpd ( m , op1 ) ) ; } else { if ( mode != V4SFmode ) op1 = gen_lowpart ( V4SFmode , op1 ) ; m = adjust_address ( op0 , V2SFmode , 0 ) ; emit_insn ( gen_sse_storelps ( m , op1 ) ) ; m = adjust_address ( op0 , V2SFmode , 8 ) ; emit_insn ( gen_sse_storehps ( m , op1 ) ) ; } } else gcc_unreachable ( ) ; } </s>

Implement the movmisalign patterns for SSE . Non-SSE modes go straight to ix86_expand_vector_move .


<s> static rtx ix86_expand_vec_ext_builtin ( tree arglist , rtx target ) { enum machine_mode tmode , mode0 ; tree arg0 , arg1 ; int elt ; rtx op0 ; arg0 = TREE_VALUE ( arglist ) ; arg1 = TREE_VALUE ( TREE_CHAIN ( arglist ) ) ; op0 = expand_expr ( arg0 , NULL_RTX , VOIDmode , 0 ) ; elt = get_element_number ( TREE_TYPE ( arg0 ) , arg1 ) ; tmode = TYPE_MODE ( TREE_TYPE ( TREE_TYPE ( arg0 ) ) ) ; mode0 = TYPE_MODE ( TREE_TYPE ( arg0 ) ) ; gcc_assert ( VECTOR_MODE_P ( mode0 ) ) ; op0 = force_reg ( mode0 , op0 ) ; if ( optimize || ! target || ! register_operand ( target , tmode ) ) target = gen_reg_rtx ( tmode ) ; ix86_expand_vector_extract ( true , target , op0 , elt ) ; return target ; } </s>

A subroutine of ix86_expand_builtin . These builtins are a wrapper around ix86_expand_vector_extract . They would be redundant ( for non-MMX ) if we had a language-level syntax for referencing vector elements .


<s> static rtx ix86_expand_vec_init_builtin ( tree type , tree arglist , rtx target ) { enum machine_mode tmode = TYPE_MODE ( type ) ; enum machine_mode inner_mode = GET_MODE_INNER ( tmode ) ; int i , n_elt = GET_MODE_NUNITS ( tmode ) ; rtvec v = rtvec_alloc ( n_elt ) ; gcc_assert ( VECTOR_MODE_P ( tmode ) ) ; for ( i = 0 ; i < n_elt ; ++ i , arglist = TREE_CHAIN ( arglist ) ) { rtx x = expand_expr ( TREE_VALUE ( arglist ) , NULL_RTX , VOIDmode , 0 ) ; RTVEC_ELT ( v , i ) = gen_lowpart ( inner_mode , x ) ; } gcc_assert ( arglist == NULL ) ; if ( ! target || ! register_operand ( target , tmode ) ) target = gen_reg_rtx ( tmode ) ; ix86_expand_vector_init ( true , target , gen_rtx_PARALLEL ( tmode , v ) ) ; return target ; } </s>

A subroutine of ix86_expand_builtin . These builtins are a wrapper around ix86_expand_vector_init . We DO have language-level syntax for this , in the form of ( type ) { init-list } . Except that since we ca n't place emms instructions from inside the compiler , we ca n't allow the use of MMX registers unless the user explicitly asks for it . So we do * not * define vec_set/vec_extract/vec_init patterns for MMX modes in mmx.md . Instead we have builtins invoked by mmintrin.h that gives us license to emit these sorts of instructions .


<s> static rtx ix86_expand_vec_set_builtin ( tree arglist ) { enum machine_mode tmode , mode1 ; tree arg0 , arg1 , arg2 ; int elt ; rtx op0 , op1 ; arg0 = TREE_VALUE ( arglist ) ; arg1 = TREE_VALUE ( TREE_CHAIN ( arglist ) ) ; arg2 = TREE_VALUE ( TREE_CHAIN ( TREE_CHAIN ( arglist ) ) ) ; tmode = TYPE_MODE ( TREE_TYPE ( arg0 ) ) ; mode1 = TYPE_MODE ( TREE_TYPE ( TREE_TYPE ( arg0 ) ) ) ; gcc_assert ( VECTOR_MODE_P ( tmode ) ) ; op0 = expand_expr ( arg0 , NULL_RTX , tmode , 0 ) ; op1 = expand_expr ( arg1 , NULL_RTX , mode1 , 0 ) ; elt = get_element_number ( TREE_TYPE ( arg0 ) , arg2 ) ; if ( GET_MODE ( op1 ) != mode1 && GET_MODE ( op1 ) != VOIDmode ) op1 = convert_modes ( mode1 , GET_MODE ( op1 ) , op1 , true ) ; op0 = force_reg ( tmode , op0 ) ; op1 = force_reg ( mode1 , op1 ) ; ix86_expand_vector_set ( true , op0 , op1 , elt ) ; return op0 ; } </s>

A subroutine of ix86_expand_builtin . These builtins are a wrapper around ix86_expand_vector_set . They would be redundant ( for non-MMX ) if we had a language-level syntax for referencing vector elements .


<s>
void
ix86_file_end
(
void
)
{
rtx
xops
[
2
]
;
int
regno
;
for
(
regno
=
0
;
regno
<
8
;
++
regno
)
{
char
name
[
32
]
;
if
(
!
(
(
pic_labels_used
>>
regno
)
&
1
)
)
continue
;
get_pc_thunk_name
(
name
,
regno
)
;
if
(
USE_HIDDEN_LINKONCE
)
{
tree
decl
;
decl
=
build_decl
(
FUNCTION_DECL
,
get_identifier
(
name
)
,
error_mark_node
)
;
TREE_PUBLIC
(
decl
)
=
1
;
TREE_STATIC
(
decl
)
=
1
;
DECL_ONE_ONLY
(
decl
)
=
1
;
(
*
targetm
.
asm_out
.
unique_section
)
(
decl
,
0
)
;
named_section
(
decl
,
,
0
)
;
(
*
targetm
.
asm_out
.
globalize_label
)
(
asm_out_file
,
name
)
;
fputs
(
"\t.hidden\t"
,
asm_out_file
)
;
assemble_name
(
asm_out_file
,
name
)
;
fputc
(
'\n'
,
asm_out_file
)
;
ASM_DECLARE_FUNCTION_NAME
(
asm_out_file
,
name
,
decl
)
;
}
else
{
text_section
(
)
;
ASM_OUTPUT_LABEL
(
asm_out_file
,
name
)
;
}
xops
[
0
]
=
gen_rtx_REG
(
SImode
,
regno
)
;
xops
[
1
]
=
gen_rtx_MEM
(
SImode
,
stack_pointer_rtx
)
;
output_asm_insn
(
"mov{l}\t{%1, %0|%0, %1}"
,
xops
)
;
output_asm_insn
(
"ret"
,
xops
)
;
}
if
(
NEED_INDICATE_EXEC_STACK
)
file_end_indicate_exec_stack
(
)
;
}
</s>

This function generates code for -fpic that loads % ebx with the return address of the caller and then returns .


<s> rtx ix86_find_base_term ( rtx x ) { rtx term ; if ( TARGET_64BIT ) { if ( GET_CODE ( x ) != CONST ) return x ; term = XEXP ( x , 0 ) ; if ( GET_CODE ( term ) == PLUS && ( GET_CODE ( XEXP ( term , 1 ) ) == CONST_INT || GET_CODE ( XEXP ( term , 1 ) ) == CONST_DOUBLE ) ) term = XEXP ( term , 0 ) ; if ( GET_CODE ( term ) != UNSPEC || XINT ( term , 1 ) != UNSPEC_GOTPCREL ) return x ; term = XVECEXP ( term , 0 , 0 ) ; if ( GET_CODE ( term ) != SYMBOL_REF && GET_CODE ( term ) != LABEL_REF ) return x ; return term ; } term = ix86_delegitimize_address ( x ) ; if ( GET_CODE ( term ) != SYMBOL_REF && GET_CODE ( term ) != LABEL_REF ) return x ; return term ; } </s>

If X is a machine specific address ( i.e . a symbol or label being referenced as a displacement from the GOT implemented using an UNSPEC ) , then return the base term . Otherwise return X .


<s> static bool ix86_fixed_condition_code_regs ( unsigned int * p1 , unsigned int * p2 ) { * p1 = FLAGS_REG ; * p2 = FPSR_REG ; return true ; } </s>

Return the fixed registers used for condition codes .


<s> rtx ix86_fixup_binary_operands ( enum rtx_code code , enum machine_mode mode , rtx operands [ ] ) { int matching_memory ; rtx src1 , src2 , dst ; dst = operands [ 0 ] ; src1 = operands [ 1 ] ; src2 = operands [ 2 ] ; if ( GET_RTX_CLASS ( code ) == RTX_COMM_ARITH && ( rtx_equal_p ( dst , src2 ) || immediate_operand ( src1 , mode ) ) ) { rtx temp = src1 ; src1 = src2 ; src2 = temp ; } matching_memory = 0 ; if ( GET_CODE ( dst ) == MEM ) { if ( rtx_equal_p ( dst , src1 ) ) matching_memory = 1 ; else if ( GET_RTX_CLASS ( code ) == RTX_COMM_ARITH && rtx_equal_p ( dst , src2 ) ) matching_memory = 2 ; else dst = gen_reg_rtx ( mode ) ; } if ( GET_CODE ( src1 ) == MEM && GET_CODE ( src2 ) == MEM ) { if ( matching_memory != 2 ) src2 = force_reg ( mode , src2 ) ; else src1 = force_reg ( mode , src1 ) ; } if ( ( CONSTANT_P ( src1 ) || ( ! matching_memory && GET_CODE ( src1 ) == MEM ) ) && GET_RTX_CLASS ( code ) != RTX_COMM_ARITH ) src1 = force_reg ( mode , src1 ) ; src1 = operands [ 1 ] = src1 ; src2 = operands [ 2 ] = src2 ; return dst ; } </s>

Fix up OPERANDS to satisfy ix86_binary_operator_ok . Return the destination to use for the operation . If different from the true destination in operands [ 0 ] , a copy operation will be required .


<s> void ix86_fixup_binary_operands_no_copy ( enum rtx_code code , enum machine_mode mode , rtx operands [ ] ) { rtx dst = ix86_fixup_binary_operands ( code , mode , operands ) ; gcc_assert ( dst == operands [ 0 ] ) ; } </s>

Similarly , but assume that the destination has already been set up properly .


<s> static int ix86_flags_dependant ( rtx insn , rtx dep_insn , enum attr_type insn_type ) { rtx set , set2 ; if ( insn_type != TYPE_SETCC && insn_type != TYPE_ICMOV && insn_type != TYPE_FCMOV && insn_type != TYPE_IBR ) return 0 ; if ( ( set = single_set ( dep_insn ) ) != 0 ) { set = SET_DEST ( set ) ; set2 = NULL_RTX ; } else if ( GET_CODE ( PATTERN ( dep_insn ) ) == PARALLEL && XVECLEN ( PATTERN ( dep_insn ) , 0 ) == 2 && GET_CODE ( XVECEXP ( PATTERN ( dep_insn ) , 0 , 0 ) ) == SET && GET_CODE ( XVECEXP ( PATTERN ( dep_insn ) , 0 , 1 ) ) == SET ) { set = SET_DEST ( XVECEXP ( PATTERN ( dep_insn ) , 0 , 0 ) ) ; set2 = SET_DEST ( XVECEXP ( PATTERN ( dep_insn ) , 0 , 0 ) ) ; } else return 0 ; if ( GET_CODE ( set ) != REG || REGNO ( set ) != FLAGS_REG ) return 0 ; if ( ! reg_overlap_mentioned_p ( set , PATTERN ( insn ) ) ) return 0 ; if ( set2 && reg_overlap_mentioned_p ( set2 , PATTERN ( insn ) ) ) return 0 ; return 1 ; } </s>

A subroutine of ix86_adjust_cost -- return true iff INSN reads flags set by DEP_INSN and nothing set by DEP_INSN .


<s> rtx ix86_force_to_memory ( enum machine_mode mode , rtx operand ) { rtx result ; gcc_assert ( reload_completed ) ; if ( TARGET_RED_ZONE ) { result = gen_rtx_MEM ( mode , gen_rtx_PLUS ( Pmode , stack_pointer_rtx , GEN_INT ( - RED_ZONE_SIZE ) ) ) ; emit_move_insn ( result , operand ) ; } else if ( ! TARGET_RED_ZONE && TARGET_64BIT ) { switch ( mode ) { case HImode : case SImode : operand = gen_lowpart ( DImode , operand ) ; case DImode : emit_insn ( gen_rtx_SET ( VOIDmode , gen_rtx_MEM ( DImode , gen_rtx_PRE_DEC ( DImode , stack_pointer_rtx ) ) , operand ) ) ; break ; default : gcc_unreachable ( ) ; } result = gen_rtx_MEM ( mode , stack_pointer_rtx ) ; } else { switch ( mode ) { case DImode : { rtx operands [ 2 ] ; split_di ( & operand , 1 , operands , operands + 1 ) ; emit_insn ( gen_rtx_SET ( VOIDmode , gen_rtx_MEM ( SImode , gen_rtx_PRE_DEC ( Pmode , stack_pointer_rtx ) ) , operands [ 1 ] ) ) ; emit_insn ( gen_rtx_SET ( VOIDmode , gen_rtx_MEM ( SImode , gen_rtx_PRE_DEC ( Pmode , stack_pointer_rtx ) ) , operands [ 0 ] ) ) ; } break ; case HImode : operand = gen_lowpart ( SImode , operand ) ; case SImode : emit_insn ( gen_rtx_SET ( VOIDmode , gen_rtx_MEM ( GET_MODE ( operand ) , gen_rtx_PRE_DEC ( SImode , stack_pointer_rtx ) ) , operand ) ) ; break ; default : gcc_unreachable ( ) ; } result = gen_rtx_MEM ( mode , stack_pointer_rtx ) ; } return result ; } </s>

Store OPERAND to the memory after reload is completed . This means that we ca n't easily use assign_stack_local .


<s> enum rtx_code ix86_fp_compare_code_to_integer ( enum rtx_code code ) { switch ( code ) { case GT : return GTU ; case GE : return GEU ; case ORDERED : case UNORDERED : return code ; break ; case UNEQ : return EQ ; break ; case UNLT : return LTU ; break ; case UNLE : return LEU ; break ; case LTGT : return NE ; break ; default : return UNKNOWN ; } } </s>

Convert comparison codes we use to represent FP comparison to integer code that will result in proper branch . Return UNKNOWN if no such code is available .


<s> enum machine_mode ix86_fp_compare_mode ( enum rtx_code code ATTRIBUTE_UNUSED ) { return TARGET_IEEE_FP ? CCFPUmode : CCFPmode ; } </s>

Figure out whether to use ordered or unordered fp comparisons . Return the appropriate mode to use .


<s> static int ix86_fp_comparison_arithmetics_cost ( enum rtx_code code ) { if ( ! TARGET_IEEE_FP ) return 4 ; switch ( code ) { case UNLE : case UNLT : case LTGT : case GT : case GE : case UNORDERED : case ORDERED : case UNEQ : return 4 ; break ; case LT : case NE : case EQ : case UNGE : return 5 ; break ; case LE : case UNGT : return 6 ; break ; default : gcc_unreachable ( ) ; } } </s>

Return cost of comparison done fcom + arithmetics operations on AX . All following functions do use number of instructions as a cost metrics . In future this should be tweaked to compute bytes for optimize_size and take into account performance of various instructions on various CPUs .


<s> void ix86_fp_comparison_codes ( enum rtx_code code , enum rtx_code * bypass_code , enum rtx_code * first_code , enum rtx_code * second_code ) { * first_code = code ; * bypass_code = UNKNOWN ; * second_code = UNKNOWN ; switch ( code ) { case GT : case GE : case ORDERED : case UNORDERED : case UNEQ : case UNLT : case UNLE : case LTGT : break ; case LT : * first_code = UNLT ; * bypass_code = UNORDERED ; break ; case LE : * first_code = UNLE ; * bypass_code = UNORDERED ; break ; case EQ : * first_code = UNEQ ; * bypass_code = UNORDERED ; break ; case NE : * first_code = LTGT ; * second_code = UNORDERED ; break ; case UNGE : * first_code = GE ; * second_code = UNORDERED ; break ; case UNGT : * first_code = GT ; * second_code = UNORDERED ; break ; default : gcc_unreachable ( ) ; } if ( ! TARGET_IEEE_FP ) { * second_code = UNKNOWN ; * bypass_code = UNKNOWN ; } } </s>

Split comparison code CODE into comparisons we can do using branch instructions . BYPASS_CODE is comparison code for branch that will branch around FIRST_CODE and SECOND_CODE . If some of branches is not required , set value to UNKNOWN . We never require more than two branches .


<s> static int ix86_fp_comparison_cost ( enum rtx_code code ) { int fcomi_cost , sahf_cost , arithmetics_cost = 1024 ; int min ; fcomi_cost = ix86_fp_comparison_fcomi_cost ( code ) ; sahf_cost = ix86_fp_comparison_sahf_cost ( code ) ; min = arithmetics_cost = ix86_fp_comparison_arithmetics_cost ( code ) ; if ( min > sahf_cost ) min = sahf_cost ; if ( min > fcomi_cost ) min = fcomi_cost ; return min ; } </s>

Compute cost of the comparison done using any method . See ix86_fp_comparison_arithmetics_cost for the metrics .


<s> static int ix86_fp_comparison_fcomi_cost ( enum rtx_code code ) { enum rtx_code bypass_code , first_code , second_code ; if ( ! TARGET_CMOVE ) return 1024 ; ix86_fp_comparison_codes ( code , & bypass_code , & first_code , & second_code ) ; return ( bypass_code != UNKNOWN || second_code != UNKNOWN ) + 2 ; } </s>

Return cost of comparison done using fcomi operation . See ix86_fp_comparison_arithmetics_cost for the metrics .


<s> static int ix86_fp_comparison_sahf_cost ( enum rtx_code code ) { enum rtx_code bypass_code , first_code , second_code ; if ( ! TARGET_USE_SAHF && ! optimize_size ) return 1024 ; ix86_fp_comparison_codes ( code , & bypass_code , & first_code , & second_code ) ; return ( bypass_code != UNKNOWN || second_code != UNKNOWN ) + 3 ; } </s>

Return cost of comparison done using sahf operation . See ix86_fp_comparison_arithmetics_cost for the metrics .


<s> bool ix86_fp_jump_nontrivial_p ( enum rtx_code code ) { enum rtx_code bypass_code , first_code , second_code ; if ( ! TARGET_CMOVE ) return true ; ix86_fp_comparison_codes ( code , & bypass_code , & first_code , & second_code ) ; return bypass_code != UNKNOWN || second_code != UNKNOWN ; } </s>

Return true if the CODE will result in nontrivial jump sequence .


<s> int ix86_frame_pointer_required ( void ) { if ( cfun -> machine -> accesses_prev_frame ) return 1 ; if ( SUBTARGET_FRAME_POINTER_REQUIRED ) return 1 ; if ( TARGET_OMIT_LEAF_FRAME_POINTER && ( ! current_function_is_leaf ) ) return 1 ; if ( current_function_profile ) return 1 ; return 0 ; } </s>

Value should be nonzero if functions must have frame pointers . Zero means the frame pointer need not be set up ( and parms may be accessed via the stack pointer ) in functions that seem suitable .


<s> void ix86_free_from_memory ( enum machine_mode mode ) { if ( ! TARGET_RED_ZONE ) { int size ; if ( mode == DImode || TARGET_64BIT ) size = 8 ; else size = 4 ; emit_insn ( gen_rtx_SET ( VOIDmode , stack_pointer_rtx , gen_rtx_PLUS ( Pmode , stack_pointer_rtx , GEN_INT ( size ) ) ) ) ; } } </s>


<s> bool ix86_function_arg_regno_p ( int regno ) { int i ; if ( ! TARGET_64BIT ) return ( regno < REGPARM_MAX || ( TARGET_MMX && MMX_REGNO_P ( regno ) && ( regno < FIRST_MMX_REG + MMX_REGPARM_MAX ) ) || ( TARGET_SSE && SSE_REGNO_P ( regno ) && ( regno < FIRST_SSE_REG + SSE_REGPARM_MAX ) ) ) ; if ( TARGET_SSE && SSE_REGNO_P ( regno ) && ( regno < FIRST_SSE_REG + SSE_REGPARM_MAX ) ) return true ; if ( ! regno ) return true ; for ( i = 0 ; i < REGPARM_MAX ; i ++ ) if ( regno == x86_64_int_parameter_registers [ i ] ) return true ; return false ; } </s>

Return true when register may be used to pass function parameters .


<s> static bool ix86_function_ok_for_sibcall ( tree decl , tree exp ) { tree func ; rtx a , b ; if ( ! TARGET_64BIT && flag_pic && ( ! decl || TREE_PUBLIC ( decl ) ) ) return false ; if ( decl ) func = decl ; else { func = TREE_TYPE ( TREE_OPERAND ( exp , 0 ) ) ; if ( POINTER_TYPE_P ( func ) ) func = TREE_TYPE ( func ) ; } a = ix86_function_value ( TREE_TYPE ( exp ) , func , false ) ; b = ix86_function_value ( TREE_TYPE ( DECL_RESULT ( cfun -> decl ) ) , cfun -> decl , false ) ; if ( STACK_REG_P ( a ) || STACK_REG_P ( b ) ) { if ( ! rtx_equal_p ( a , b ) ) return false ; } else if ( VOID_TYPE_P ( TREE_TYPE ( DECL_RESULT ( cfun -> decl ) ) ) ) ; else if ( ! rtx_equal_p ( a , b ) ) return false ; if ( ! decl && ! TARGET_64BIT ) { tree type ; type = TREE_OPERAND ( exp , 0 ) ; type = TREE_TYPE ( type ) ; type = TREE_TYPE ( type ) ; if ( ix86_function_regparm ( type , NULL ) >= 3 ) { return false ; } } if ( decl && DECL_DLLIMPORT_P ( decl ) && ix86_function_regparm ( TREE_TYPE ( decl ) , NULL ) >= 3 ) return false ; if ( cfun -> machine -> force_align_arg_pointer ) return false ; return true ; } </s>

Decide whether we can make a sibling call to a function . DECL is the declaration of the function being targeted by the call and EXP is the CALL_EXPR representing the call .


<s> static int ix86_function_regparm ( tree type , tree decl ) { tree attr ; int regparm = ix86_regparm ; bool user_convention = false ; if ( ! TARGET_64BIT ) { attr = lookup_attribute ( "regparm" , TYPE_ATTRIBUTES ( type ) ) ; if ( attr ) { regparm = TREE_INT_CST_LOW ( TREE_VALUE ( TREE_VALUE ( attr ) ) ) ; user_convention = true ; } if ( lookup_attribute ( "fastcall" , TYPE_ATTRIBUTES ( type ) ) ) { regparm = 2 ; user_convention = true ; } if ( ! TARGET_64BIT && ! user_convention && decl && flag_unit_at_a_time && ! profile_flag ) { struct cgraph_local_info * i = cgraph_local_info ( decl ) ; if ( i && i -> local ) { int local_regparm , globals = 0 , regno ; for ( local_regparm = 0 ; local_regparm < 3 ; local_regparm ++ ) if ( global_regs [ local_regparm ] ) break ; if ( local_regparm == 3 && decl_function_context ( decl ) && ! DECL_NO_STATIC_CHAIN ( decl ) ) local_regparm = 2 ; for ( regno = 0 ; regno < 6 ; regno ++ ) if ( global_regs [ regno ] ) globals ++ ; local_regparm = globals < local_regparm ? local_regparm - globals : 0 ; if ( local_regparm > regparm ) regparm = local_regparm ; } } } return regparm ; } </s>

Return the regparm value for a function with the indicated TYPE and DECL . DECL may be NULL when calling function indirectly or considering a libcall .


"Calling %qD with attribute sseregparm without "

"Calling %qT with attribute sseregparm without "

Return 1 or 2 , if we can pass up to SSE_REGPARM_MAX SFmode ( 1 ) and DFmode ( 2 ) arguments in SSE registers for a function with the indicated TYPE and DECL . DECL may be NULL when calling function indirectly or considering a libcall . Otherwise return 0 .


<s> rtx ix86_function_value ( tree valtype , tree fntype_or_decl , bool outgoing ATTRIBUTE_UNUSED ) { enum machine_mode natmode = type_natural_mode ( valtype ) ; if ( TARGET_64BIT ) { rtx ret = construct_container ( natmode , TYPE_MODE ( valtype ) , valtype , 1 , REGPARM_MAX , SSE_REGPARM_MAX , x86_64_int_return_registers , 0 ) ; if ( ! ret ) ret = gen_rtx_REG ( TYPE_MODE ( valtype ) , 0 ) ; return ret ; } else { tree fn = NULL_TREE , fntype ; if ( fntype_or_decl && DECL_P ( fntype_or_decl ) ) fn = fntype_or_decl ; fntype = fn ? TREE_TYPE ( fn ) : fntype_or_decl ; return gen_rtx_REG ( TYPE_MODE ( valtype ) , ix86_value_regno ( natmode , fn , fntype ) ) ; } } </s>

Define how to find the value returned by a function . VALTYPE is the data type of the value ( as a tree ) . If the precise function being called is known , FUNC is its FUNCTION_DECL ; otherwise , FUNC is 0 .


<s> bool ix86_function_value_regno_p ( int regno ) { if ( regno == 0 || ( regno == FIRST_FLOAT_REG && TARGET_FLOAT_RETURNS_IN_80387 ) || ( regno == FIRST_SSE_REG && TARGET_SSE ) ) return true ; if ( ! TARGET_64BIT && ( regno == FIRST_MMX_REG && TARGET_MMX ) ) return true ; return false ; } </s>

Return true if N is a possible register number of function value .


<s> static HOST_WIDE_INT ix86_GOT_alias_set ( void ) { static HOST_WIDE_INT set = - 1 ; if ( set == - 1 ) set = new_alias_set ( ) ; return set ; } </s>

Return an unique alias set for the GOT .


"%qs attribute only applies to functions"

"fastcall and regparm attributes are not compatible"

"%qs attribute requires an integer constant argument"

"argument to %qs attribute larger than %d"

"fastcall and cdecl attributes are not compatible"

"fastcall and stdcall attributes are not compatible"

"stdcall and cdecl attributes are not compatible"

"stdcall and fastcall attributes are not compatible"

Handle `` cdecl '' , `` stdcall '' , `` fastcall '' , `` regparm '' and `` sseregparm '' calling convention attributes ; arguments as in struct attribute_spec.handler .


<s> static bool ix86_handle_option ( size_t code , const char * arg ATTRIBUTE_UNUSED , int value ) { switch ( code ) { case OPT_m3dnow : if ( ! value ) { target_flags &= ~ MASK_3DNOW_A ; target_flags_explicit |= MASK_3DNOW_A ; } return true ; case OPT_mmmx : if ( ! value ) { target_flags &= ~ ( MASK_3DNOW | MASK_3DNOW_A ) ; target_flags_explicit |= MASK_3DNOW | MASK_3DNOW_A ; } return true ; case OPT_msse : if ( ! value ) { target_flags &= ~ ( MASK_SSE2 | MASK_SSE3 ) ; target_flags_explicit |= MASK_SSE2 | MASK_SSE3 ; } return true ; case OPT_msse2 : if ( ! value ) { target_flags &= ~ MASK_SSE3 ; target_flags_explicit |= MASK_SSE3 ; } return true ; default : return true ; } } </s>


<s>
static
tree
ix86_handle_struct_attribute
(
tree
*
node
,
tree
name
,
tree
args
ATTRIBUTE_UNUSED
,
int
flags
ATTRIBUTE_UNUSED
,
bool
*
no_add_attrs
)
{
tree
*
type
=
;
if
(
DECL_P
(
*
node
)
)
{
if
(
TREE_CODE
(
*
node
)
==
TYPE_DECL
)
type
=
&
TREE_TYPE
(
*
node
)
;
}
else
type
=
node
;
if
(
!
(
type
&&
(
TREE_CODE
(
*
type
)
==
RECORD_TYPE
||
TREE_CODE
(
*
type
)
==
UNION_TYPE
)
)
)
{
warning
(
OPT_Wattributes
,
"%qs attribute ignored"
,
IDENTIFIER_POINTER
(
name
)
)
;
*
no_add_attrs
=
true
;
}
else
if
(
(
is_attribute_p
(
"ms_struct"
,
name
)
&&
lookup_attribute
(
"gcc_struct"
,
TYPE_ATTRIBUTES
(
*
type
)
)
)
||
(
(
is_attribute_p
(
"gcc_struct"
,
name
)
&&
lookup_attribute
(
"ms_struct"
,
TYPE_ATTRIBUTES
(
*
type
)
)
)
)
)
{
warning
(
OPT_Wattributes
,
"%qs incompatible attribute ignored"
,
IDENTIFIER_POINTER
(
name
)
)
;
*
no_add_attrs
=
true
;
}
return
NULL_TREE
;
}
</s>

Handle a `` ms_struct '' or `` gcc_struct '' attribute ; arguments as in struct attribute_spec.handler .


<s> bool ix86_hard_regno_mode_ok ( int regno , enum machine_mode mode ) { if ( CC_REGNO_P ( regno ) ) return GET_MODE_CLASS ( mode ) == MODE_CC ; if ( GET_MODE_CLASS ( mode ) == MODE_CC || GET_MODE_CLASS ( mode ) == MODE_RANDOM || GET_MODE_CLASS ( mode ) == MODE_PARTIAL_INT ) return 0 ; if ( FP_REGNO_P ( regno ) ) return VALID_FP_MODE_P ( mode ) ; if ( SSE_REGNO_P ( regno ) ) { return ( VALID_SSE_REG_MODE ( mode ) || VALID_SSE2_REG_MODE ( mode ) || VALID_MMX_REG_MODE ( mode ) || VALID_MMX_REG_MODE_3DNOW ( mode ) ) ; } if ( MMX_REGNO_P ( regno ) ) { return ( VALID_MMX_REG_MODE ( mode ) || VALID_MMX_REG_MODE_3DNOW ( mode ) ) ; } if ( mode == QImode ) { if ( regno < 4 || TARGET_64BIT ) return 1 ; if ( ! TARGET_PARTIAL_REG_STALL ) return 1 ; return reload_in_progress || reload_completed ; } else if ( VALID_INT_MODE_P ( mode ) ) return 1 ; else if ( VALID_FP_MODE_P ( mode ) ) return 1 ; else if ( VALID_MMX_REG_MODE_3DNOW ( mode ) || VALID_MMX_REG_MODE ( mode ) ) return 1 ; return 0 ; } </s>

Return TRUE if hard register REGNO can hold a value of machine-mode MODE .


<s> HOST_WIDE_INT ix86_initial_elimination_offset ( int from , int to ) { struct ix86_frame frame ; ix86_compute_frame_layout ( & frame ) ; if ( from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM ) return frame . hard_frame_pointer_offset ; else if ( from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM ) return frame . hard_frame_pointer_offset - frame . frame_pointer_offset ; else { gcc_assert ( to == STACK_POINTER_REGNUM ) ; if ( from == ARG_POINTER_REGNUM ) return frame . stack_pointer_offset ; gcc_assert ( from == FRAME_POINTER_REGNUM ) ; return frame . stack_pointer_offset - frame . frame_pointer_offset ; } } </s>

Return the offset between two registers , one to be eliminated , and the other its replacement , at the start of a routine .


<s> static struct machine_function * ix86_init_machine_status ( void ) { struct machine_function * f ; f = ggc_alloc_cleared ( sizeof ( struct machine_function ) ) ; f -> use_fast_prologue_epilogue_nregs = - 1 ; return f ; } </s>

Clear stack slot assignments remembered from previous functions . This is called from INIT_EXPANDERS once before RTL is emitted for each function .


<s> static rtx ix86_internal_arg_pointer ( void ) { if ( FORCE_PREFERRED_STACK_BOUNDARY_IN_MAIN && DECL_NAME ( current_function_decl ) && MAIN_NAME_P ( DECL_NAME ( current_function_decl ) ) && DECL_FILE_SCOPE_P ( current_function_decl ) ) { cfun -> machine -> force_align_arg_pointer = gen_rtx_REG ( Pmode , 2 ) ; return copy_to_reg ( cfun -> machine -> force_align_arg_pointer ) ; } else return virtual_incoming_args_rtx ; } </s>

Handle the TARGET_INTERNAL_ARG_POINTER hook .


<s> static bool ix86_in_large_data_p ( tree exp ) { if ( ix86_cmodel != CM_MEDIUM && ix86_cmodel != CM_MEDIUM_PIC ) return false ; if ( TREE_CODE ( exp ) == FUNCTION_DECL ) return false ; if ( TREE_CODE ( exp ) == VAR_DECL && DECL_SECTION_NAME ( exp ) ) { const char * section = TREE_STRING_POINTER ( DECL_SECTION_NAME ( exp ) ) ; if ( strcmp ( section , ".ldata" ) == 0 || strcmp ( section , ".lbss" ) == 0 ) return true ; return false ; } else { HOST_WIDE_INT size = int_size_in_bytes ( TREE_TYPE ( exp ) ) ; if ( ! size || size > ix86_section_threshold ) return true ; } return false ; } </s>

Return true if this goes in small data/bss .


<s> static int ix86_issue_rate ( void ) { switch ( ix86_tune ) { case PROCESSOR_PENTIUM : case PROCESSOR_K6 : return 2 ; case PROCESSOR_PENTIUMPRO : case PROCESSOR_PENTIUM4 : case PROCESSOR_ATHLON : case PROCESSOR_K8 : case PROCESSOR_NOCONA : return 3 ; default : return 1 ; } } </s>

Return the maximum number of instructions a cpu can issue .


<s> rtx ix86_libcall_value ( enum machine_mode mode ) { if ( TARGET_64BIT ) { switch ( mode ) { case SFmode : case SCmode : case DFmode : case DCmode : case TFmode : return gen_rtx_REG ( mode , FIRST_SSE_REG ) ; case XFmode : case XCmode : return gen_rtx_REG ( mode , FIRST_FLOAT_REG ) ; case TCmode : return NULL ; default : return gen_rtx_REG ( mode , 0 ) ; } } else return gen_rtx_REG ( mode , ix86_value_regno ( mode , NULL , NULL ) ) ; } </s>

Define how to find the value returned by a library function assuming the value has mode MODE .


<s> int ix86_local_alignment ( tree type , int align ) { if ( TARGET_64BIT ) { if ( AGGREGATE_TYPE_P ( type ) && TYPE_SIZE ( type ) && TREE_CODE ( TYPE_SIZE ( type ) ) == INTEGER_CST && ( TREE_INT_CST_LOW ( TYPE_SIZE ( type ) ) >= 16 || TREE_INT_CST_HIGH ( TYPE_SIZE ( type ) ) ) && align < 128 ) return 128 ; } if ( TREE_CODE ( type ) == ARRAY_TYPE ) { if ( TYPE_MODE ( TREE_TYPE ( type ) ) == DFmode && align < 64 ) return 64 ; if ( ALIGN_MODE_128 ( TYPE_MODE ( TREE_TYPE ( type ) ) ) && align < 128 ) return 128 ; } else if ( TREE_CODE ( type ) == COMPLEX_TYPE ) { if ( TYPE_MODE ( type ) == DCmode && align < 64 ) return 64 ; if ( TYPE_MODE ( type ) == XCmode && align < 128 ) return 128 ; } else if ( ( TREE_CODE ( type ) == RECORD_TYPE || TREE_CODE ( type ) == UNION_TYPE || TREE_CODE ( type ) == QUAL_UNION_TYPE ) && TYPE_FIELDS ( type ) ) { if ( DECL_MODE ( TYPE_FIELDS ( type ) ) == DFmode && align < 64 ) return 64 ; if ( ALIGN_MODE_128 ( DECL_MODE ( TYPE_FIELDS ( type ) ) ) && align < 128 ) return 128 ; } else if ( TREE_CODE ( type ) == REAL_TYPE || TREE_CODE ( type ) == VECTOR_TYPE || TREE_CODE ( type ) == INTEGER_TYPE ) { if ( TYPE_MODE ( type ) == DFmode && align < 64 ) return 64 ; if ( ALIGN_MODE_128 ( TYPE_MODE ( type ) ) && align < 128 ) return 128 ; } return align ; } </s>

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 .


<s> static const char * ix86_mangle_fundamental_type ( tree type ) { switch ( TYPE_MODE ( type ) ) { case TFmode : return "g" ; case XFmode : return "e" ; default : return NULL ; } } </s>

Return the mangling of TYPE if it is an extended fundamental type .


<s> int ix86_match_ccmode ( rtx insn , enum machine_mode req_mode ) { rtx set ; enum machine_mode set_mode ; set = PATTERN ( insn ) ; if ( GET_CODE ( set ) == PARALLEL ) set = XVECEXP ( set , 0 , 0 ) ; gcc_assert ( GET_CODE ( set ) == SET ) ; gcc_assert ( GET_CODE ( SET_SRC ( set ) ) == COMPARE ) ; set_mode = GET_MODE ( SET_DEST ( set ) ) ; switch ( set_mode ) { case CCNOmode : if ( req_mode != CCNOmode && ( req_mode != CCmode || XEXP ( SET_SRC ( set ) , 1 ) != const0_rtx ) ) return 0 ; break ; case CCmode : if ( req_mode == CCGCmode ) return 0 ; case CCGCmode : if ( req_mode == CCGOCmode || req_mode == CCNOmode ) return 0 ; case CCGOCmode : if ( req_mode == CCZmode ) return 0 ; case CCZmode : break ; default : gcc_unreachable ( ) ; } return ( GET_MODE ( SET_SRC ( set ) ) == set_mode ) ; } </s>

Return TRUE or FALSE depending on whether the first SET in INSN has source and destination with matching CC modes , and that the CC mode is at least as constrained as REQ_MODE .


<s> static tree ix86_md_asm_clobbers ( tree outputs ATTRIBUTE_UNUSED , tree inputs ATTRIBUTE_UNUSED , tree clobbers ) { clobbers = tree_cons ( NULL_TREE , build_string ( 5 , "flags" ) , clobbers ) ; clobbers = tree_cons ( NULL_TREE , build_string ( 4 , "fpsr" ) , clobbers ) ; clobbers = tree_cons ( NULL_TREE , build_string ( 7 , "dirflag" ) , clobbers ) ; return clobbers ; } </s>

Worker function for TARGET_MD_ASM_CLOBBERS . We do this in the new i386 backend to maintain source compatibility with the old cc0-based compiler .


<s> int ix86_memory_move_cost ( enum machine_mode mode , enum reg_class class , int in ) { if ( FLOAT_CLASS_P ( class ) ) { int index ; switch ( mode ) { case SFmode : index = 0 ; break ; case DFmode : index = 1 ; break ; case XFmode : index = 2 ; break ; default : return 100 ; } return in ? ix86_cost -> fp_load [ index ] : ix86_cost -> fp_store [ index ] ; } if ( SSE_CLASS_P ( class ) ) { int index ; switch ( GET_MODE_SIZE ( mode ) ) { case 4 : index = 0 ; break ; case 8 : index = 1 ; break ; case 16 : index = 2 ; break ; default : return 100 ; } return in ? ix86_cost -> sse_load [ index ] : ix86_cost -> sse_store [ index ] ; } if ( MMX_CLASS_P ( class ) ) { int index ; switch ( GET_MODE_SIZE ( mode ) ) { case 4 : index = 0 ; break ; case 8 : index = 1 ; break ; default : return 100 ; } return in ? ix86_cost -> mmx_load [ index ] : ix86_cost -> mmx_store [ index ] ; } switch ( GET_MODE_SIZE ( mode ) ) { case 1 : if ( in ) return ( Q_CLASS_P ( class ) ? ix86_cost -> int_load [ 0 ] : ix86_cost -> movzbl_load ) ; else return ( Q_CLASS_P ( class ) ? ix86_cost -> int_store [ 0 ] : ix86_cost -> int_store [ 0 ] + 4 ) ; break ; case 2 : return in ? ix86_cost -> int_load [ 1 ] : ix86_cost -> int_store [ 1 ] ; default : if ( mode == TFmode ) mode = XFmode ; return ( ( in ? ix86_cost -> int_load [ 2 ] : ix86_cost -> int_store [ 2 ] ) * ( ( ( int ) GET_MODE_SIZE ( mode ) + UNITS_PER_WORD - 1 ) / UNITS_PER_WORD ) ) ; } } </s>

Return the cost of moving data of mode M between a register and memory . A value of 2 is the default ; this cost is relative to those in ` REGISTER_MOVE_COST ' . If moving between registers and memory is more expensive than between two registers , you should define this macro to express the relative cost . Model also increased moving costs of QImode registers in non Q_REGS classes .


<s> bool ix86_modes_tieable_p ( enum machine_mode mode1 , enum machine_mode mode2 ) { if ( mode1 == mode2 ) return true ; if ( ix86_tieable_integer_mode_p ( mode1 ) && ix86_tieable_integer_mode_p ( mode2 ) ) return true ; if ( mode2 == XFmode ) return mode1 == SFmode || mode1 == DFmode ; if ( mode2 == DFmode ) return mode1 == SFmode ; if ( GET_MODE_SIZE ( mode2 ) >= 8 && ix86_hard_regno_mode_ok ( FIRST_SSE_REG , mode2 ) ) return ix86_hard_regno_mode_ok ( FIRST_SSE_REG , mode1 ) ; if ( GET_MODE_SIZE ( mode2 ) == 8 && ix86_hard_regno_mode_ok ( FIRST_MMX_REG , mode2 ) ) return ix86_hard_regno_mode_ok ( FIRST_MMX_REG , mode1 ) ; return false ; } </s>

Return true if MODE1 is accessible in a register that can hold MODE2 without copying . That is , all register classes that can hold MODE2 can also hold MODE1 .


<s> int ix86_mode_needed ( int entity , rtx insn ) { enum attr_i387_cw mode ; if ( CALL_P ( insn ) || ( NONJUMP_INSN_P ( insn ) && ( asm_noperands ( PATTERN ( insn ) ) >= 0 || GET_CODE ( PATTERN ( insn ) ) == ASM_INPUT ) ) ) return I387_CW_UNINITIALIZED ; if ( recog_memoized ( insn ) < 0 ) return I387_CW_ANY ; mode = get_attr_i387_cw ( insn ) ; switch ( entity ) { case I387_TRUNC : if ( mode == I387_CW_TRUNC ) return mode ; break ; case I387_FLOOR : if ( mode == I387_CW_FLOOR ) return mode ; break ; case I387_CEIL : if ( mode == I387_CW_CEIL ) return mode ; break ; case I387_MASK_PM : if ( mode == I387_CW_MASK_PM ) return mode ; break ; default : gcc_unreachable ( ) ; } return I387_CW_ANY ; } </s>

Return needed mode for entity in optimize_mode_switching pass .


<s> static bool ix86_must_pass_in_stack ( enum machine_mode mode , tree type ) { if ( must_pass_in_stack_var_size_or_pad ( mode , type ) ) return true ; return ( ! TARGET_64BIT && mode == TImode && type && TREE_CODE ( type ) != VECTOR_TYPE ) ; } </s>

Return if we do not know how to pass TYPE solely in registers .


<s> static int ix86_nsaved_regs ( void ) { int nregs = 0 ; int regno ; for ( regno = FIRST_PSEUDO_REGISTER - 1 ; regno >= 0 ; regno -- ) if ( ix86_save_reg ( regno , true ) ) nregs ++ ; return nregs ; } </s>

Return number of registers to be saved on the stack .


<s> static void ix86_pad_returns ( void ) { edge e ; edge_iterator ei ; FOR_EACH_EDGE ( e , ei , EXIT_BLOCK_PTR -> preds ) { basic_block bb = e -> src ; rtx ret = BB_END ( bb ) ; rtx prev ; bool replace = false ; if ( GET_CODE ( ret ) != JUMP_INSN || GET_CODE ( PATTERN ( ret ) ) != RETURN || ! maybe_hot_bb_p ( bb ) ) continue ; for ( prev = PREV_INSN ( ret ) ; prev ; prev = PREV_INSN ( prev ) ) if ( active_insn_p ( prev ) || GET_CODE ( prev ) == CODE_LABEL ) break ; if ( prev && GET_CODE ( prev ) == CODE_LABEL ) { edge e ; edge_iterator ei ; FOR_EACH_EDGE ( e , ei , bb -> preds ) if ( EDGE_FREQUENCY ( e ) && e -> src -> index >= 0 && ! ( e -> flags & EDGE_FALLTHRU ) ) replace = true ; } if ( ! replace ) { prev = prev_active_insn ( ret ) ; if ( prev && ( ( GET_CODE ( prev ) == JUMP_INSN && any_condjump_p ( prev ) ) || GET_CODE ( prev ) == CALL_INSN ) ) replace = true ; if ( ! prev && cfun -> function_frequency > FUNCTION_FREQUENCY_UNLIKELY_EXECUTED ) replace = true ; } if ( replace ) { emit_insn_before ( gen_return_internal_long ( ) , ret ) ; delete_insn ( ret ) ; } } } </s>

AMD Athlon works faster when RET is not destination of conditional jump or directly preceded by other jump instruction . We avoid the penalty by inserting NOP just before the RET instructions in such cases .


<s> enum reg_class ix86_preferred_reload_class ( rtx x , enum reg_class class ) { if ( class == NO_REGS ) return NO_REGS ; if ( x == CONST0_RTX ( GET_MODE ( x ) ) ) return class ; if ( GET_CODE ( x ) == CONST_DOUBLE && GET_MODE ( x ) != VOIDmode ) { if ( reg_class_subset_p ( class , GENERAL_REGS ) ) return class ; if ( TARGET_80387 && ( TARGET_MIX_SSE_I387 || ! ( TARGET_SSE_MATH && SSE_FLOAT_MODE_P ( GET_MODE ( x ) ) ) ) && standard_80387_constant_p ( x ) ) { if ( class == FLOAT_SSE_REGS ) return FLOAT_REGS ; if ( class == FP_TOP_SSE_REGS ) return FP_TOP_REG ; if ( class == FP_SECOND_SSE_REGS ) return FP_SECOND_REG ; if ( class == FLOAT_INT_REGS || class == FLOAT_REGS ) return class ; } return NO_REGS ; } if ( MAYBE_MMX_CLASS_P ( class ) && CONSTANT_P ( x ) ) return NO_REGS ; if ( MAYBE_SSE_CLASS_P ( class ) && CONSTANT_P ( x ) ) return NO_REGS ; if ( GET_CODE ( x ) == PLUS ) return reg_class_subset_p ( class , GENERAL_REGS ) ? class : NO_REGS ; if ( GET_MODE ( x ) == QImode && ! CONSTANT_P ( x ) ) { if ( reg_class_subset_p ( class , Q_REGS ) ) return class ; if ( reg_class_subset_p ( Q_REGS , class ) ) return Q_REGS ; return NO_REGS ; } return class ; } </s>

Put float CONST_DOUBLE in the constant pool instead of fp regs . QImode must go into class Q_REGS . Narrow ALL_REGS to GENERAL_REGS . This supports allowing movsf and movdf to do mem-to-mem moves through integer regs .


<s> static enum rtx_code ix86_prepare_fp_compare_args ( enum rtx_code code , rtx * pop0 , rtx * pop1 ) { enum machine_mode fpcmp_mode = ix86_fp_compare_mode ( code ) ; rtx op0 = * pop0 , op1 = * pop1 ; enum machine_mode op_mode = GET_MODE ( op0 ) ; int is_sse = TARGET_SSE_MATH && SSE_FLOAT_MODE_P ( op_mode ) ; if ( ! is_sse && ( fpcmp_mode == CCFPUmode || ( op_mode == XFmode && ! ( standard_80387_constant_p ( op0 ) == 1 || standard_80387_constant_p ( op1 ) == 1 ) && GET_CODE ( op1 ) != FLOAT ) || ix86_use_fcomi_compare ( code ) ) ) { op0 = force_reg ( op_mode , op0 ) ; op1 = force_reg ( op_mode , op1 ) ; } else { if ( standard_80387_constant_p ( op0 ) == 0 || ( GET_CODE ( op0 ) == MEM && ! ( standard_80387_constant_p ( op1 ) == 0 || GET_CODE ( op1 ) == MEM ) ) ) { rtx tmp ; tmp = op0 , op0 = op1 , op1 = tmp ; code = swap_condition ( code ) ; } if ( GET_CODE ( op0 ) != REG ) op0 = force_reg ( op_mode , op0 ) ; if ( CONSTANT_P ( op1 ) ) { int tmp = standard_80387_constant_p ( op1 ) ; if ( tmp == 0 ) op1 = validize_mem ( force_const_mem ( op_mode , op1 ) ) ; else if ( tmp == 1 ) { if ( TARGET_CMOVE ) op1 = force_reg ( op_mode , op1 ) ; } else op1 = force_reg ( op_mode , op1 ) ; } } if ( ix86_fp_comparison_cost ( code ) > ix86_fp_comparison_cost ( swap_condition ( code ) ) && ( GET_CODE ( op1 ) == REG || ! no_new_pseudos ) ) { rtx tmp ; tmp = op0 , op0 = op1 , op1 = tmp ; code = swap_condition ( code ) ; if ( GET_CODE ( op0 ) != REG ) op0 = force_reg ( op_mode , op0 ) ; } * pop0 = op0 ; * pop1 = op1 ; return code ; } </s>

Swap , force into registers , or otherwise massage the two operands to a fp comparison . The operands are updated in place ; the new comparsion code is returned .


<s> static enum rtx_code ix86_prepare_sse_fp_compare_args ( rtx dest , enum rtx_code code , rtx * pop0 , rtx * pop1 ) { rtx tmp ; switch ( code ) { case LTGT : case UNEQ : return UNKNOWN ; case LT : case LE : case UNGT : case UNGE : break ; case EQ : case NE : case UNORDERED : case ORDERED : if ( ! dest || ! rtx_equal_p ( dest , * pop1 ) ) break ; case GE : case GT : case UNLE : case UNLT : tmp = * pop0 ; * pop0 = * pop1 ; * pop1 = tmp ; code = swap_condition ( code ) ; break ; default : gcc_unreachable ( ) ; } return code ; } </s>

Swap , force into registers , or otherwise massage the two operands to an sse comparison with a mask result . Thus we differ a bit from ix86_prepare_fp_compare_args which expects to produce a flags result . The DEST operand exists to help determine whether to commute commutative operators . The POP0/POP1 operands are updated in place . The new comparison code is returned , or UNKNOWN if not implementable .


<s> int ix86_register_move_cost ( enum machine_mode mode , enum reg_class class1 , enum reg_class class2 ) { if ( ix86_secondary_memory_needed ( class1 , class2 , mode , 0 ) ) { int cost = 1 ; cost += MAX ( MEMORY_MOVE_COST ( mode , class1 , 0 ) , MEMORY_MOVE_COST ( mode , class1 , 1 ) ) ; cost += MAX ( MEMORY_MOVE_COST ( mode , class2 , 0 ) , MEMORY_MOVE_COST ( mode , class2 , 1 ) ) ; if ( CLASS_MAX_NREGS ( class1 , mode ) > CLASS_MAX_NREGS ( class2 , mode ) ) cost += 20 ; if ( ( MMX_CLASS_P ( class1 ) && MAYBE_FLOAT_CLASS_P ( class2 ) ) || ( MMX_CLASS_P ( class2 ) && MAYBE_FLOAT_CLASS_P ( class1 ) ) ) cost += 20 ; return cost ; } if ( MMX_CLASS_P ( class1 ) != MMX_CLASS_P ( class2 ) || SSE_CLASS_P ( class1 ) != SSE_CLASS_P ( class2 ) ) return ix86_cost -> mmxsse_to_integer ; if ( MAYBE_FLOAT_CLASS_P ( class1 ) ) return ix86_cost -> fp_move ; if ( MAYBE_SSE_CLASS_P ( class1 ) ) return ix86_cost -> sse_move ; if ( MAYBE_MMX_CLASS_P ( class1 ) ) return ix86_cost -> mmx_move ; return 2 ; } </s>

Return the cost of moving data from a register in class CLASS1 to one in class CLASS2 . It is not required that the cost always equal 2 when FROM is the same as TO ; on some machines it is expensive to move between registers if they are not general registers .


<s> static void ix86_reorg ( void ) { if ( TARGET_ATHLON_K8 && optimize && ! optimize_size ) ix86_pad_returns ( ) ; if ( TARGET_FOUR_JUMP_LIMIT && optimize && ! optimize_size ) ix86_avoid_jump_misspredicts ( ) ; } </s>

Implement machine specific optimizations . We implement padding of returns for K8 CPUs and pass to avoid 4 jumps in the single 16 byte window .


<s> int ix86_return_in_memory ( tree type ) { int needed_intregs , needed_sseregs , size ; enum machine_mode mode = type_natural_mode ( type ) ; if ( TARGET_64BIT ) return ! examine_argument ( mode , type , 1 , & needed_intregs , & needed_sseregs ) ; if ( mode == BLKmode ) return 1 ; size = int_size_in_bytes ( type ) ; if ( MS_AGGREGATE_RETURN && AGGREGATE_TYPE_P ( type ) && size <= 8 ) return 0 ; if ( VECTOR_MODE_P ( mode ) || mode == TImode ) { if ( size < 8 ) return 0 ; if ( size == 8 ) return ( TARGET_MMX ? 0 : 1 ) ; if ( size == 16 ) return ( TARGET_SSE ? 0 : 1 ) ; } if ( mode == XFmode ) return 0 ; if ( size > 12 ) return 1 ; return 0 ; } </s>

Return false iff type is returned in memory .


<s> int ix86_return_pops_args ( tree fundecl , tree funtype , int size ) { int rtd = TARGET_RTD && ( ! fundecl || TREE_CODE ( fundecl ) != IDENTIFIER_NODE ) ; if ( ! lookup_attribute ( "cdecl" , TYPE_ATTRIBUTES ( funtype ) ) ) { if ( lookup_attribute ( "stdcall" , TYPE_ATTRIBUTES ( funtype ) ) || lookup_attribute ( "fastcall" , TYPE_ATTRIBUTES ( funtype ) ) ) rtd = 1 ; if ( rtd && ( TYPE_ARG_TYPES ( funtype ) == NULL_TREE || ( TREE_VALUE ( tree_last ( TYPE_ARG_TYPES ( funtype ) ) ) == void_type_node ) ) ) return size ; } if ( aggregate_value_p ( TREE_TYPE ( funtype ) , fundecl ) && ! TARGET_64BIT && ! KEEP_AGGREGATE_RETURN_POINTER ) { int nregs = ix86_function_regparm ( funtype , fundecl ) ; if ( ! nregs ) return GET_MODE_SIZE ( Pmode ) ; } return 0 ; } </s>

Value is the number of bytes of arguments automatically popped when returning from a subroutine call . FUNDECL is the declaration node of the function ( as a tree ) , FUNTYPE is the data type of the function ( as a tree ) , or for a library call it is an identifier node for the subroutine name . SIZE is the number of bytes of arguments passed on the stack . On the 80386 , the RTD insn may be used to pop them if the number of args is fixed , but if the number is variable then the caller must pop them all . RTD ca n't be used for library calls now because the library is compiled with the Unix compiler . Use of RTD is a selectable option , since it is incompatible with standard Unix calling sequences . If the option is not selected , the caller must always pop the args . The attribute stdcall is equivalent to RTD on a per module basis .


<s> enum rtx_code ix86_reverse_condition ( enum rtx_code code , enum machine_mode mode ) { return ( mode != CCFPmode && mode != CCFPUmode ? reverse_condition ( code ) : reverse_condition_maybe_unordered ( code ) ) ; } </s>


<s> static int ix86_save_reg ( unsigned int regno , int maybe_eh_return ) { if ( pic_offset_table_rtx && regno == REAL_PIC_OFFSET_TABLE_REGNUM && ( regs_ever_live [ REAL_PIC_OFFSET_TABLE_REGNUM ] || current_function_profile || current_function_calls_eh_return || current_function_uses_const_pool ) ) { if ( ix86_select_alt_pic_regnum ( ) != INVALID_REGNUM ) return 0 ; return 1 ; } if ( current_function_calls_eh_return && maybe_eh_return ) { unsigned i ; for ( i = 0 ; ; i ++ ) { unsigned test = EH_RETURN_DATA_REGNO ( i ) ; if ( test == INVALID_REGNUM ) break ; if ( test == regno ) return 1 ; } } if ( cfun -> machine -> force_align_arg_pointer && regno == REGNO ( cfun -> machine -> force_align_arg_pointer ) ) return 1 ; return ( regs_ever_live [ regno ] && ! call_used_regs [ regno ] && ! fixed_regs [ regno ] && ( regno != HARD_FRAME_POINTER_REGNUM || ! frame_pointer_needed ) ) ; } </s>


<s> int ix86_secondary_memory_needed ( enum reg_class class1 , enum reg_class class2 , enum machine_mode mode , int strict ) { if ( MAYBE_FLOAT_CLASS_P ( class1 ) != FLOAT_CLASS_P ( class1 ) || MAYBE_FLOAT_CLASS_P ( class2 ) != FLOAT_CLASS_P ( class2 ) || MAYBE_SSE_CLASS_P ( class1 ) != SSE_CLASS_P ( class1 ) || MAYBE_SSE_CLASS_P ( class2 ) != SSE_CLASS_P ( class2 ) || MAYBE_MMX_CLASS_P ( class1 ) != MMX_CLASS_P ( class1 ) || MAYBE_MMX_CLASS_P ( class2 ) != MMX_CLASS_P ( class2 ) ) { gcc_assert ( ! strict ) ; return true ; } if ( FLOAT_CLASS_P ( class1 ) != FLOAT_CLASS_P ( class2 ) ) return true ; if ( MMX_CLASS_P ( class1 ) != MMX_CLASS_P ( class2 ) ) return true ; if ( SSE_CLASS_P ( class1 ) != SSE_CLASS_P ( class2 ) ) { if ( ! TARGET_SSE2 ) return true ; if ( ! TARGET_INTER_UNIT_MOVES && ! optimize_size ) return true ; if ( GET_MODE_SIZE ( mode ) > UNITS_PER_WORD ) return true ; if ( mode == SFmode || mode == DFmode ) return true ; } return false ; } </s>

If we are copying between general and FP registers , we need a memory location . The same is true for SSE and MMX registers . The macro ca n't work reliably when one of the CLASSES is class containing registers from multiple units ( SSE , MMX , integer ) . We avoid this by never combining those units in single alternative in the machine description . Ensure that this constraint holds to avoid unexpected surprises . When STRICT is false , we are being called from REGISTER_MOVE_COST , so do not enforce these sanity checks .


<s> static unsigned int ix86_select_alt_pic_regnum ( void ) { if ( current_function_is_leaf && ! current_function_profile ) { int i ; for ( i = 2 ; i >= 0 ; -- i ) if ( ! regs_ever_live [ i ] ) return i ; } return INVALID_REGNUM ; } </s>

Return > = 0 if there is an unused call-clobbered register available for the entire function .


<s> static void ix86_setup_incoming_varargs ( CUMULATIVE_ARGS * cum , enum machine_mode mode , tree type , int * pretend_size ATTRIBUTE_UNUSED , int no_rtl ) { CUMULATIVE_ARGS next_cum ; rtx save_area = NULL_RTX , mem ; rtx label ; rtx label_ref ; rtx tmp_reg ; rtx nsse_reg ; int set ; tree fntype ; int stdarg_p ; int i ; if ( ! TARGET_64BIT ) return ; if ( ! cfun -> va_list_gpr_size && ! cfun -> va_list_fpr_size ) return ; ix86_save_varrargs_registers = 1 ; cfun -> stack_alignment_needed = 128 ; fntype = TREE_TYPE ( current_function_decl ) ; stdarg_p = ( TYPE_ARG_TYPES ( fntype ) != 0 && ( TREE_VALUE ( tree_last ( TYPE_ARG_TYPES ( fntype ) ) ) != void_type_node ) ) ; next_cum = * cum ; if ( stdarg_p ) function_arg_advance ( & next_cum , mode , type , 1 ) ; if ( ! no_rtl ) save_area = frame_pointer_rtx ; set = get_varargs_alias_set ( ) ; for ( i = next_cum . regno ; i < ix86_regparm && i < next_cum . regno + cfun -> va_list_gpr_size / UNITS_PER_WORD ; i ++ ) { mem = gen_rtx_MEM ( Pmode , plus_constant ( save_area , i * UNITS_PER_WORD ) ) ; MEM_NOTRAP_P ( mem ) = 1 ; set_mem_alias_set ( mem , set ) ; emit_move_insn ( mem , gen_rtx_REG ( Pmode , x86_64_int_parameter_registers [ i ] ) ) ; } if ( next_cum . sse_nregs && cfun -> va_list_fpr_size ) { label = gen_label_rtx ( ) ; label_ref = gen_rtx_LABEL_REF ( Pmode , label ) ; tmp_reg = gen_reg_rtx ( Pmode ) ; nsse_reg = gen_reg_rtx ( Pmode ) ; emit_insn ( gen_zero_extendqidi2 ( nsse_reg , gen_rtx_REG ( QImode , 0 ) ) ) ; emit_insn ( gen_rtx_SET ( VOIDmode , tmp_reg , gen_rtx_MULT ( Pmode , nsse_reg , GEN_INT ( 4 ) ) ) ) ; if ( next_cum . sse_regno ) emit_move_insn ( nsse_reg , gen_rtx_CONST ( DImode , gen_rtx_PLUS ( DImode , label_ref , GEN_INT ( next_cum . sse_regno * 4 ) ) ) ) ; else emit_move_insn ( nsse_reg , label_ref ) ; emit_insn ( gen_subdi3 ( nsse_reg , nsse_reg , tmp_reg ) ) ; tmp_reg = gen_reg_rtx ( Pmode ) ; emit_insn ( gen_rtx_SET ( VOIDmode , tmp_reg , plus_constant ( save_area , 8 * REGPARM_MAX + 127 ) ) ) ; mem = gen_rtx_MEM ( BLKmode , plus_constant ( tmp_reg , - 127 ) ) ; MEM_NOTRAP_P ( mem ) = 1 ; set_mem_alias_set ( mem , set ) ; set_mem_align ( mem , BITS_PER_WORD ) ; emit_insn ( gen_sse_prologue_save ( mem , nsse_reg , GEN_INT ( next_cum . sse_regno ) , label ) ) ; } } </s>

Worker function for TARGET_SETUP_INCOMING_VARARGS .


<s> void ix86_split_copysign_const ( rtx operands [ ] ) { enum machine_mode mode , vmode ; rtx dest , op0 , op1 , mask , x ; dest = operands [ 0 ] ; op0 = operands [ 1 ] ; op1 = operands [ 2 ] ; mask = operands [ 3 ] ; mode = GET_MODE ( dest ) ; vmode = GET_MODE ( mask ) ; dest = simplify_gen_subreg ( vmode , dest , mode , 0 ) ; x = gen_rtx_AND ( vmode , dest , mask ) ; emit_insn ( gen_rtx_SET ( VOIDmode , dest , x ) ) ; if ( op0 != CONST0_RTX ( vmode ) ) { x = gen_rtx_IOR ( vmode , dest , op0 ) ; emit_insn ( gen_rtx_SET ( VOIDmode , dest , x ) ) ; } } </s>

Deconstruct a copysign operation into bit masks . Operand 0 is known to be a constant , and so has already been expanded into a vector constant .


<s> void ix86_split_copysign_var ( rtx operands [ ] ) { enum machine_mode mode , vmode ; rtx dest , scratch , op0 , op1 , mask , nmask , x ; dest = operands [ 0 ] ; scratch = operands [ 1 ] ; op0 = operands [ 2 ] ; op1 = operands [ 3 ] ; nmask = operands [ 4 ] ; mask = operands [ 5 ] ; mode = GET_MODE ( dest ) ; vmode = GET_MODE ( mask ) ; if ( rtx_equal_p ( op0 , op1 ) ) { emit_move_insn ( dest , op0 ) ; return ; } if ( REG_P ( mask ) && REGNO ( dest ) == REGNO ( mask ) ) { gcc_assert ( REGNO ( op1 ) == REGNO ( scratch ) ) ; x = gen_rtx_AND ( vmode , scratch , mask ) ; emit_insn ( gen_rtx_SET ( VOIDmode , scratch , x ) ) ; dest = mask ; op0 = simplify_gen_subreg ( vmode , op0 , mode , 0 ) ; x = gen_rtx_NOT ( vmode , dest ) ; x = gen_rtx_AND ( vmode , x , op0 ) ; emit_insn ( gen_rtx_SET ( VOIDmode , dest , x ) ) ; } else { if ( REGNO ( op1 ) == REGNO ( scratch ) ) { x = gen_rtx_AND ( vmode , scratch , mask ) ; } else { gcc_assert ( REGNO ( mask ) == REGNO ( scratch ) ) ; op1 = simplify_gen_subreg ( vmode , op1 , mode , 0 ) ; x = gen_rtx_AND ( vmode , scratch , op1 ) ; } emit_insn ( gen_rtx_SET ( VOIDmode , scratch , x ) ) ; if ( REGNO ( op0 ) == REGNO ( dest ) ) { dest = simplify_gen_subreg ( vmode , op0 , mode , 0 ) ; x = gen_rtx_AND ( vmode , dest , nmask ) ; } else { gcc_assert ( REGNO ( nmask ) == REGNO ( dest ) ) ; dest = nmask ; op0 = simplify_gen_subreg ( vmode , op0 , mode , 0 ) ; x = gen_rtx_AND ( vmode , dest , op0 ) ; } emit_insn ( gen_rtx_SET ( VOIDmode , dest , x ) ) ; } x = gen_rtx_IOR ( vmode , dest , scratch ) ; emit_insn ( gen_rtx_SET ( VOIDmode , dest , x ) ) ; } </s>

Deconstruct a copysign operation into bit masks . Operand 0 is variable , so we have to do two masks .


<s> void ix86_split_fp_branch ( enum rtx_code code , rtx op1 , rtx op2 , rtx target1 , rtx target2 , rtx tmp , rtx pushed ) { rtx second , bypass ; rtx label = NULL_RTX ; rtx condition ; int bypass_probability = - 1 , second_probability = - 1 , probability = - 1 ; rtx i ; if ( target2 != pc_rtx ) { rtx tmp = target2 ; code = reverse_condition_maybe_unordered ( code ) ; target2 = target1 ; target1 = tmp ; } condition = ix86_expand_fp_compare ( code , op1 , op2 , tmp , & second , & bypass ) ; if ( pushed ) ix86_free_from_memory ( GET_MODE ( pushed ) ) ; if ( split_branch_probability >= 0 ) { probability = split_branch_probability ; if ( bypass ) bypass_probability = 1 ; if ( second ) second_probability = 1 ; } if ( bypass != NULL_RTX ) { label = gen_label_rtx ( ) ; i = emit_jump_insn ( gen_rtx_SET ( VOIDmode , pc_rtx , gen_rtx_IF_THEN_ELSE ( VOIDmode , bypass , gen_rtx_LABEL_REF ( VOIDmode , label ) , pc_rtx ) ) ) ; if ( bypass_probability >= 0 ) REG_NOTES ( i ) = gen_rtx_EXPR_LIST ( REG_BR_PROB , GEN_INT ( bypass_probability ) , REG_NOTES ( i ) ) ; } i = emit_jump_insn ( gen_rtx_SET ( VOIDmode , pc_rtx , gen_rtx_IF_THEN_ELSE ( VOIDmode , condition , target1 , target2 ) ) ) ; if ( probability >= 0 ) REG_NOTES ( i ) = gen_rtx_EXPR_LIST ( REG_BR_PROB , GEN_INT ( probability ) , REG_NOTES ( i ) ) ; if ( second != NULL_RTX ) { i = emit_jump_insn ( gen_rtx_SET ( VOIDmode , pc_rtx , gen_rtx_IF_THEN_ELSE ( VOIDmode , second , target1 , target2 ) ) ) ; if ( second_probability >= 0 ) REG_NOTES ( i ) = gen_rtx_EXPR_LIST ( REG_BR_PROB , GEN_INT ( second_probability ) , REG_NOTES ( i ) ) ; } if ( label != NULL_RTX ) emit_label ( label ) ; } </s>

Split branch based on floating point condition .


<s> static tree ix86_stack_protect_fail ( void ) { return TARGET_64BIT ? default_external_stack_protect_fail ( ) : default_hidden_stack_protect_fail ( ) ; } </s>

For 32-bit code we can save PIC register setup by using __stack_chk_fail_local hidden function instead of calling __stack_chk_fail directly . 64-bit code does n't need to setup any PIC register , so it is better to call __stack_chk_fail directly .


"SSE vector return without SSE enabled "

"MMX vector return without MMX enabled "

When returning SSE vector types , we have a choice of either ( 1 ) being abi incompatible with a -march switch , or ( 2 ) generating an error . Given no good solution , I think the safest thing is one warning . The user wo n't be able to use -Werror , but .... Choose the STRUCT_VALUE_RTX hook because that 's ( at present ) only called in response to actually generating a caller or callee that uses such a type . As opposed to RETURN_IN_MEMORY , which is called via aggregate_value_p for general type probing from tree-ssa .


<s> static bool ix86_tieable_integer_mode_p ( enum machine_mode mode ) { switch ( mode ) { case HImode : case SImode : return true ; case QImode : return TARGET_64BIT || ! TARGET_PARTIAL_REG_STALL ; case DImode : return TARGET_64BIT ; default : return false ; } } </s>

A subroutine of ix86_modes_tieable_p . Return true if MODE is a tieable integer mode .


<s> int ix86_unary_operator_ok ( enum rtx_code code ATTRIBUTE_UNUSED , enum machine_mode mode ATTRIBUTE_UNUSED , rtx operands [ 2 ] ATTRIBUTE_UNUSED ) { if ( ( GET_CODE ( operands [ 0 ] ) == MEM || GET_CODE ( operands [ 1 ] ) == MEM ) && ! rtx_equal_p ( operands [ 0 ] , operands [ 1 ] ) ) return FALSE ; return TRUE ; } </s>

Return TRUE or FALSE depending on whether the unary operator meets the appropriate constraints .


<s> int ix86_use_fcomi_compare ( enum rtx_code code ATTRIBUTE_UNUSED ) { enum rtx_code swapped_code = swap_condition ( code ) ; return ( ( ix86_fp_comparison_cost ( code ) == ix86_fp_comparison_fcomi_cost ( code ) ) || ( ix86_fp_comparison_cost ( swapped_code ) == ix86_fp_comparison_fcomi_cost ( swapped_code ) ) ) ; } </s>

Return true if we should use an FCOMI instruction for this fp comparison .


<s> static int ix86_value_regno ( enum machine_mode mode , tree func , tree fntype ) { gcc_assert ( ! TARGET_64BIT ) ; if ( ( VECTOR_MODE_P ( mode ) && GET_MODE_SIZE ( mode ) == 8 ) ) return FIRST_MMX_REG ; if ( mode == TImode || ( VECTOR_MODE_P ( mode ) && GET_MODE_SIZE ( mode ) == 16 ) ) return FIRST_SSE_REG ; if ( GET_MODE_CLASS ( mode ) != MODE_FLOAT || ! TARGET_FLOAT_RETURNS_IN_80387 ) return 0 ; if ( ( func || fntype ) && ( mode == SFmode || mode == DFmode ) ) { int sse_level = ix86_function_sseregparm ( fntype , func ) ; if ( ( sse_level >= 1 && mode == SFmode ) || ( sse_level == 2 && mode == DFmode ) ) return FIRST_SSE_REG ; } return FIRST_FLOAT_REG ; } </s>

Given a mode , return the register to use for a return value .


"va_start: words = %d, n_gpr = %d, n_fpr = %d\n"


<s> static bool ix86_vector_mode_supported_p ( enum machine_mode mode ) { if ( TARGET_SSE && VALID_SSE_REG_MODE ( mode ) ) return true ; if ( TARGET_SSE2 && VALID_SSE2_REG_MODE ( mode ) ) return true ; if ( TARGET_MMX && VALID_MMX_REG_MODE ( mode ) ) return true ; if ( TARGET_3DNOW && VALID_MMX_REG_MODE_3DNOW ( mode ) ) return true ; return false ; } </s>

Implements target hook vector_mode_supported_p .


<s> rtx ix86_zero_extend_to_Pmode ( rtx exp ) { rtx r ; if ( GET_MODE ( exp ) == VOIDmode ) return force_reg ( Pmode , exp ) ; if ( GET_MODE ( exp ) == Pmode ) return copy_to_mode_reg ( Pmode , exp ) ; r = gen_reg_rtx ( Pmode ) ; emit_insn ( gen_zero_extendsidi2 ( r , exp ) ) ; return r ; } </s>

Zero extend possibly SImode EXP to Pmode register .


<s> bool legitimate_constant_p ( rtx x ) { switch ( GET_CODE ( x ) ) { case CONST : x = XEXP ( x , 0 ) ; if ( GET_CODE ( x ) == PLUS ) { if ( GET_CODE ( XEXP ( x , 1 ) ) != CONST_INT ) return false ; x = XEXP ( x , 0 ) ; } if ( TARGET_MACHO && darwin_local_data_pic ( x ) ) return true ; if ( GET_CODE ( x ) == UNSPEC ) switch ( XINT ( x , 1 ) ) { case UNSPEC_GOTOFF : return TARGET_64BIT ; case UNSPEC_TPOFF : case UNSPEC_NTPOFF : x = XVECEXP ( x , 0 , 0 ) ; return ( GET_CODE ( x ) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL ( x ) == TLS_MODEL_LOCAL_EXEC ) ; case UNSPEC_DTPOFF : x = XVECEXP ( x , 0 , 0 ) ; return ( GET_CODE ( x ) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL ( x ) == TLS_MODEL_LOCAL_DYNAMIC ) ; default : return false ; } if ( GET_CODE ( x ) == LABEL_REF ) return true ; if ( GET_CODE ( x ) != SYMBOL_REF ) return false ; case SYMBOL_REF : if ( SYMBOL_REF_TLS_MODEL ( x ) ) return false ; break ; default : break ; } return true ; } </s>

Nonzero if the constant value X is a legitimate general operand . It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE .


<s> bool legitimate_pic_operand_p ( rtx x ) { rtx inner ; switch ( GET_CODE ( x ) ) { case CONST : inner = XEXP ( x , 0 ) ; if ( GET_CODE ( inner ) == PLUS && GET_CODE ( XEXP ( inner , 1 ) ) == CONST_INT ) inner = XEXP ( inner , 0 ) ; if ( GET_CODE ( inner ) == UNSPEC ) switch ( XINT ( inner , 1 ) ) { case UNSPEC_GOTOFF : return TARGET_64BIT ; case UNSPEC_TPOFF : x = XVECEXP ( inner , 0 , 0 ) ; return ( GET_CODE ( x ) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL ( x ) == TLS_MODEL_LOCAL_EXEC ) ; default : return false ; } case SYMBOL_REF : case LABEL_REF : return legitimate_pic_address_disp_p ( x ) ; default : return true ; } } </s>

Return true if OP is a legitimate general operand when generating PIC code . It is given that flag_pic is on and that OP satisfies CONSTANT_P or is a CONST_DOUBLE .


<s>
void
machopic_output_stub
(
FILE
*
file
,
const
char
*
symb
,
const
char
*
stub
)
{
unsigned
int
length
;
char
*
binder_name
,
*
symbol_name
,
lazy_ptr_name
[
32
]
;
int
label
=
++
current_machopic_label_num
;
symb
=
(
*
targetm
.
strip_name_encoding
)
(
symb
)
;
length
=
strlen
(
stub
)
;
binder_name
=
alloca
(
length
+
32
)
;
GEN_BINDER_NAME_FOR_STUB
(
binder_name
,
stub
,
length
)
;
length
=
strlen
(
symb
)
;
symbol_name
=
alloca
(
length
+
32
)
;
GEN_SYMBOL_NAME_FOR_SYMBOL
(
symbol_name
,
symb
,
length
)
;
sprintf
(
lazy_ptr_name
,
"L%d$lz"
,
label
)
;
if
(
MACHOPIC_PURE
)
machopic_picsymbol_stub_section
(
)
;
else
machopic_symbol_stub_section
(
)
;
fprintf
(
file
,
"%s:\n"
,
stub
)
;
fprintf
(
file
,
"\t.indirect_symbol %s\n"
,
symbol_name
)
;
if
(
MACHOPIC_PURE
)
{
fprintf
(
file
,
"\tcall LPC$%d\nLPC$%d:\tpopl %%eax\n"
,
label
,
label
)
;
fprintf
(
file
,
"\tmovl %s-LPC$%d(%%eax),%%edx\n"
,
lazy_ptr_name
,
label
)
;
fprintf
(
file
,
"\tjmp %%edx\n"
)
;
}
else
fprintf
(
file
,
"\tjmp *%s\n"
,
lazy_ptr_name
)
;
fprintf
(
file
,
"%s:\n"
,
binder_name
)
;
if
(
MACHOPIC_PURE
)
{
fprintf
(
file
,
"\tlea %s-LPC$%d(%%eax),%%eax\n"
,
lazy_ptr_name
,
label
)
;
fprintf
(
file
,
"\tpushl %%eax\n"
)
;
}
else
fprintf
(
file
,
"\t pushl $%s\n"
,
lazy_ptr_name
)
;
fprintf
(
file
,
"\tjmp dyld_stub_binding_helper\n"
)
;
machopic_lazy_symbol_ptr_section
(
)
;
fprintf
(
file
,
"%s:\n"
,
lazy_ptr_name
)
;
fprintf
(
file
,
"\t.indirect_symbol %s\n"
,
symbol_name
)
;
fprintf
(
file
,
"\t.long %s\n"
,
binder_name
)
;
}
</s>

Generate external symbol indirection stubs ( PIC and non-PIC ) .

i386
32
32
32
"L%d$lz"
"%s:\n"
"\t.indirect_symbol %s\n"
"\tcall LPC$%d\nLPC$%d:\tpopl %%eax\n"
"\tmovl %s-LPC$%d(%%eax),%%edx\n"
"\tjmp %%edx\n"
"\tjmp *%s\n"
"%s:\n"
"\tlea %s-LPC$%d(%%eax),%%eax\n"
"\tpushl %%eax\n"
"\t pushl $%s\n"
"\tjmp dyld_stub_binding_helper\n"
"%s:\n"
"\t.indirect_symbol %s\n"
"\t.long %s\n"


<s> rtx maybe_get_pool_constant ( rtx x ) { x = ix86_delegitimize_address ( XEXP ( x , 0 ) ) ; if ( GET_CODE ( x ) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P ( x ) ) return get_pool_constant ( x ) ; return NULL_RTX ; } </s>

X is an unchanging MEM . If it is a constant pool reference , return the constant pool rtx , else NULL .


<s> int memory_address_length ( rtx addr ) { struct ix86_address parts ; rtx base , index , disp ; int len ; int ok ; if ( GET_CODE ( addr ) == PRE_DEC || GET_CODE ( addr ) == POST_INC || GET_CODE ( addr ) == PRE_MODIFY || GET_CODE ( addr ) == POST_MODIFY ) return 0 ; ok = ix86_decompose_address ( addr , & parts ) ; gcc_assert ( ok ) ; if ( parts . base && GET_CODE ( parts . base ) == SUBREG ) parts . base = SUBREG_REG ( parts . base ) ; if ( parts . index && GET_CODE ( parts . index ) == SUBREG ) parts . index = SUBREG_REG ( parts . index ) ; base = parts . base ; index = parts . index ; disp = parts . disp ; len = 0 ; if ( base && ! index && ! disp ) { if ( addr == stack_pointer_rtx || addr == arg_pointer_rtx || addr == frame_pointer_rtx || addr == hard_frame_pointer_rtx ) len = 1 ; } else if ( disp && ! base && ! index ) len = 4 ; else { if ( disp ) { if ( GET_CODE ( disp ) == CONST_INT && CONST_OK_FOR_LETTER_P ( INTVAL ( disp ) , 'K' ) && base ) len = 1 ; else len = 4 ; } else if ( base == hard_frame_pointer_rtx ) len = 1 ; if ( index || base == stack_pointer_rtx || base == arg_pointer_rtx || base == frame_pointer_rtx ) len += 1 ; } return len ; } </s>

Calculate the length of the memory address in the instruction encoding . Does not include the one-byte modrm , opcode , or prefix .


<s> static int min_insn_size ( rtx insn ) { int l = 0 ; if ( ! INSN_P ( insn ) || ! active_insn_p ( insn ) ) return 0 ; if ( GET_CODE ( PATTERN ( insn ) ) == UNSPEC_VOLATILE && XINT ( PATTERN ( insn ) , 1 ) == UNSPECV_ALIGN ) return 0 ; if ( GET_CODE ( insn ) == JUMP_INSN && ( GET_CODE ( PATTERN ( insn ) ) == ADDR_VEC || GET_CODE ( PATTERN ( insn ) ) == ADDR_DIFF_VEC ) ) return 0 ; if ( GET_CODE ( insn ) == CALL_INSN && symbolic_reference_mentioned_p ( PATTERN ( insn ) ) && ! SIBLING_CALL_P ( insn ) ) return 5 ; if ( get_attr_length ( insn ) <= 1 ) return 1 ; if ( GET_CODE ( insn ) != JUMP_INSN ) { l = get_attr_length_address ( insn ) ; if ( l < 4 && symbolic_reference_mentioned_p ( PATTERN ( insn ) ) ) l = 4 ; } if ( l ) return 1 + l ; else return 2 ; } </s>

We do n't have exact information about the insn sizes , but we may assume quite safely that we are informed about all 1 byte insns and memory address sizes . This is enough to eliminate unnecessary padding in 99 % of cases .


<s> void optimization_options ( int level , int size ATTRIBUTE_UNUSED ) { if ( level > 1 ) flag_schedule_insns = 0 ; if ( TARGET_MACHO ) flag_errno_math = 0 ; if ( optimize >= 1 ) flag_omit_frame_pointer = 2 ; flag_pcc_struct_return = 2 ; flag_asynchronous_unwind_tables = 2 ; SUBTARGET_OPTIMIZATION_OPTIONS ; } </s>

Change optimizations to be performed , depending on the optimization level . LEVEL is the optimization level specified ; 2 if ` -O2 ' is specified , 1 if ` -O ' is specified , and 0 if neither is specified . SIZE is nonzero if ` -Os ' is specified and zero otherwise .


<s> const char * output_387_reg_move ( rtx insn , rtx * operands ) { if ( REG_P ( operands [ 1 ] ) && find_regno_note ( insn , REG_DEAD , REGNO ( operands [ 1 ] ) ) ) { if ( REGNO ( operands [ 0 ] ) == FIRST_STACK_REG && TARGET_USE_FFREEP ) return "ffreep\t%y0" ; return "fstp\t%y0" ; } if ( STACK_TOP_P ( operands [ 0 ] ) ) return "fld%z1\t%y1" ; return "fst\t%y0" ; } </s>

Output code to perform an x87 FP register move , from OPERANDS [ 1 ] to OPERANDS [ 0 ] .


<s> const char * output_fix_trunc ( rtx insn , rtx * operands , int fisttp ) { int stack_top_dies = find_regno_note ( insn , REG_DEAD , FIRST_STACK_REG ) != 0 ; int dimode_p = GET_MODE ( operands [ 0 ] ) == DImode ; int round_mode = get_attr_i387_cw ( insn ) ; if ( ( dimode_p || fisttp ) && ! stack_top_dies ) output_asm_insn ( "fld\t%y1" , operands ) ; gcc_assert ( STACK_TOP_P ( operands [ 1 ] ) ) ; gcc_assert ( GET_CODE ( operands [ 0 ] ) == MEM ) ; if ( fisttp ) output_asm_insn ( "fisttp%z0\t%0" , operands ) ; else { if ( round_mode != I387_CW_ANY ) output_asm_insn ( "fldcw\t%3" , operands ) ; if ( stack_top_dies || dimode_p ) output_asm_insn ( "fistp%z0\t%0" , operands ) ; else output_asm_insn ( "fist%z0\t%0" , operands ) ; if ( round_mode != I387_CW_ANY ) output_asm_insn ( "fldcw\t%2" , operands ) ; } return "" ; } </s>

Output code for INSN to convert a float to a signed int . OPERANDS are the insn operands . The output may be [ HSD ] Imode and the input operand may be [ SDX ] Fmode .


<s>
const
char
*
output_fp_compare
(
rtx
insn
,
rtx
*
operands
,
int
eflags_p
,
int
unordered_p
)
{
int
stack_top_dies
;
rtx
cmp_op0
,
cmp_op1
;
int
is_sse
=
SSE_REG_P
(
operands
[
0
]
)
||
SSE_REG_P
(
operands
[
1
]
)
;
if
(
eflags_p
)
{
cmp_op0
=
operands
[
0
]
;
cmp_op1
=
operands
[
1
]
;
}
else
{
cmp_op0
=
operands
[
1
]
;
cmp_op1
=
operands
[
2
]
;
}
if
(
is_sse
)
{
if
(
GET_MODE
(
operands
[
0
]
)
==
SFmode
)
if
(
unordered_p
)
return
"ucomiss\t{%1, %0|%0, %1}"
;
else
return
"comiss\t{%1, %0|%0, %1}"
;
else
if
(
unordered_p
)
return
"ucomisd\t{%1, %0|%0, %1}"
;
else
return
"comisd\t{%1, %0|%0, %1}"
;
}
gcc_assert
(
STACK_TOP_P
(
cmp_op0
)
)
;
stack_top_dies
=
find_regno_note
(
insn
,
REG_DEAD
,
FIRST_STACK_REG
)
!=
0
;
if
(
cmp_op1
==
CONST0_RTX
(
GET_MODE
(
cmp_op1
)
)
)
{
if
(
stack_top_dies
)
{
output_asm_insn
(
"ftst\n\tfnstsw\t%0"
,
operands
)
;
return
TARGET_USE_FFREEP
"ffreep\t%y1"
:
"fstp\t%y1"
;
}
else
return
"ftst\n\tfnstsw\t%0"
;
}
if
(
STACK_REG_P
(
cmp_op1
)
&&
stack_top_dies
&&
find_regno_note
(
insn
,
REG_DEAD
,
REGNO
(
cmp_op1
)
)
&&
REGNO
(
cmp_op1
)
!=
FIRST_STACK_REG
)
{
if
(
eflags_p
)
{
if
(
unordered_p
)
output_asm_insn
(
"fucomip\t{%y1, %0|%0, %y1}"
,
operands
)
;
else
output_asm_insn
(
"fcomip\t{%y1, %0|%0, %y1}"
,
operands
)
;
return
TARGET_USE_FFREEP
"ffreep\t%y0"
:
"fstp\t%y0"
;
}
else
{
if
(
unordered_p
)
return
"fucompp\n\tfnstsw\t%0"
;
else
return
"fcompp\n\tfnstsw\t%0"
;
}
}
else
{
static
const
char
*
const
alt
[
16
]
=
{
"fcom%z2\t%y2\n\tfnstsw\t%0"
,
"fcomp%z2\t%y2\n\tfnstsw\t%0"
,
"fucom%z2\t%y2\n\tfnstsw\t%0"
,
"fucomp%z2\t%y2\n\tfnstsw\t%0"
,
"ficom%z2\t%y2\n\tfnstsw\t%0"
,
"ficomp%z2\t%y2\n\tfnstsw\t%0"
,
,
,
"fcomi\t{%y1, %0|%0, %y1}"
,
"fcomip\t{%y1, %0|%0, %y1}"
,
"fucomi\t{%y1, %0|%0, %y1}"
,
"fucomip\t{%y1, %0|%0, %y1}"
,
,
,
,
}
;
int
mask
;
const
char
*
ret
;
mask
=
eflags_p
<<
3
;
mask
|=
(
GET_MODE_CLASS
(
GET_MODE
(
cmp_op1
)
)
==
MODE_INT
)
<<
2
;
mask
|=
unordered_p
<<
1
;
mask
|=
stack_top_dies
;
gcc_assert
(
mask
<
16
)
;
ret
=
alt
[
mask
]
;
gcc_assert
(
ret
)
;
return
ret
;
}
}
</s>

Output code for INSN to compare OPERANDS . EFLAGS_P is 1 when fcomi should be used and 2 when fnstsw should be used . UNORDERED_P is true when fucom should be used .


"extended registers have no high halves"

"unsupported operand size for extended register"


<s> static void pro_epilogue_adjust_stack ( rtx dest , rtx src , rtx offset , int style ) { rtx insn ; if ( ! TARGET_64BIT ) insn = emit_insn ( gen_pro_epilogue_adjust_stack_1 ( dest , src , offset ) ) ; else if ( x86_64_immediate_operand ( offset , DImode ) ) insn = emit_insn ( gen_pro_epilogue_adjust_stack_rex64 ( dest , src , offset ) ) ; else { rtx r11 ; gcc_assert ( style ) ; r11 = gen_rtx_REG ( DImode , FIRST_REX_INT_REG + 3 ) ; insn = emit_insn ( gen_rtx_SET ( DImode , r11 , offset ) ) ; if ( style < 0 ) RTX_FRAME_RELATED_P ( insn ) = 1 ; insn = emit_insn ( gen_pro_epilogue_adjust_stack_rex64_2 ( dest , src , r11 , offset ) ) ; } if ( style < 0 ) RTX_FRAME_RELATED_P ( insn ) = 1 ; } </s>

Expand prologue or epilogue stack adjustment . The pattern exist to put a dependency on all ebp-based memory accesses . STYLE should be negative if instructions should be marked as frame related , zero if % r11 register is live and can not be freely used and positive otherwise .


<s> static rtx safe_vector_operand ( rtx x , enum machine_mode mode ) { if ( x == const0_rtx ) x = CONST0_RTX ( mode ) ; return x ; } </s>

Errors in the source file can cause expand_expr to return const0_rtx where we expect a vector . To avoid crashing , use one of the vector clear instructions .


<s> void split_di ( rtx operands [ ] , int num , rtx lo_half [ ] , rtx hi_half [ ] ) { while ( num -- ) { rtx op = operands [ num ] ; if ( GET_CODE ( op ) == MEM ) { lo_half [ num ] = adjust_address ( op , SImode , 0 ) ; hi_half [ num ] = adjust_address ( op , SImode , 4 ) ; } else { lo_half [ num ] = simplify_gen_subreg ( SImode , op , GET_MODE ( op ) == VOIDmode ? DImode : GET_MODE ( op ) , 0 ) ; hi_half [ num ] = simplify_gen_subreg ( SImode , op , GET_MODE ( op ) == VOIDmode ? DImode : GET_MODE ( op ) , 4 ) ; } } } </s>

Split one or more DImode RTL references into pairs of SImode references . The RTL can be REG , offsettable MEM , integer constant , or CONST_DOUBLE . `` operands '' is a pointer to an array of DImode RTL to split and `` num '' is its length . lo_half and hi_half are output arrays that parallel `` operands '' .


<s> void split_ti ( rtx operands [ ] , int num , rtx lo_half [ ] , rtx hi_half [ ] ) { while ( num -- ) { rtx op = operands [ num ] ; if ( GET_CODE ( op ) == MEM ) { lo_half [ num ] = adjust_address ( op , DImode , 0 ) ; hi_half [ num ] = adjust_address ( op , DImode , 8 ) ; } else { lo_half [ num ] = simplify_gen_subreg ( DImode , op , TImode , 0 ) ; hi_half [ num ] = simplify_gen_subreg ( DImode , op , TImode , 8 ) ; } } } </s>

Split one or more TImode RTL references into pairs of DImode references . The RTL can be REG , offsettable MEM , integer constant , or CONST_DOUBLE . `` operands '' is a pointer to an array of DImode RTL to split and `` num '' is its length . lo_half and hi_half are output arrays that parallel `` operands '' .


<s> const char * standard_80387_constant_opcode ( rtx x ) { switch ( standard_80387_constant_p ( x ) ) { case 1 : return "fldz" ; case 2 : return "fld1" ; case 3 : return "fldlg2" ; case 4 : return "fldln2" ; case 5 : return "fldl2e" ; case 6 : return "fldl2t" ; case 7 : return "fldpi" ; default : gcc_unreachable ( ) ; } } </s>

Return the opcode of the special instruction to be used to load the constant X .


<s> int standard_80387_constant_p ( rtx x ) { if ( GET_CODE ( x ) != CONST_DOUBLE || ! FLOAT_MODE_P ( GET_MODE ( x ) ) ) return - 1 ; if ( x == CONST0_RTX ( GET_MODE ( x ) ) ) return 1 ; if ( x == CONST1_RTX ( GET_MODE ( x ) ) ) return 2 ; if ( GET_MODE ( x ) == XFmode && ( optimize_size || x86_ext_80387_constants & TUNEMASK ) ) { REAL_VALUE_TYPE r ; int i ; if ( ! ext_80387_constants_init ) init_ext_80387_constants ( ) ; REAL_VALUE_FROM_CONST_DOUBLE ( r , x ) ; for ( i = 0 ; i < 5 ; i ++ ) if ( real_identical ( & r , & ext_80387_constants_table [ i ] ) ) return i + 3 ; } return 0 ; } </s>

Return true if the constant is something that can be loaded with a special instruction .


<s> rtx standard_80387_constant_rtx ( int idx ) { int i ; if ( ! ext_80387_constants_init ) init_ext_80387_constants ( ) ; switch ( idx ) { case 3 : case 4 : case 5 : case 6 : case 7 : i = idx - 3 ; break ; default : gcc_unreachable ( ) ; } return CONST_DOUBLE_FROM_REAL_VALUE ( ext_80387_constants_table [ i ] , XFmode ) ; } </s>

Return the CONST_DOUBLE representing the 80387 constant that is loaded by the specified special instruction . The argument IDX matches the return value from standard_80387_constant_p .


<s> int standard_sse_constant_p ( rtx x ) { if ( x == const0_rtx ) return 1 ; return ( x == CONST0_RTX ( GET_MODE ( x ) ) ) ; } </s>

Return 1 if X is all 0s and 2 if x is all 1s in supported SSE/AVX vector mode .


<s> int symbolic_reference_mentioned_p ( rtx op ) { const char * fmt ; int i ; if ( GET_CODE ( op ) == SYMBOL_REF || GET_CODE ( op ) == LABEL_REF ) return 1 ; fmt = GET_RTX_FORMAT ( GET_CODE ( op ) ) ; for ( i = GET_RTX_LENGTH ( GET_CODE ( op ) ) - 1 ; i >= 0 ; i -- ) { if ( fmt [ i ] == 'E' ) { int j ; for ( j = XVECLEN ( op , i ) - 1 ; j >= 0 ; j -- ) if ( symbolic_reference_mentioned_p ( XVECEXP ( op , i , j ) ) ) return 1 ; } else if ( fmt [ i ] == 'e' && symbolic_reference_mentioned_p ( XEXP ( op , i ) ) ) return 1 ; } return 0 ; } </s>

Return true if OP contains a symbol reference


<s> static enum machine_mode type_natural_mode ( tree type ) { enum machine_mode mode = TYPE_MODE ( type ) ; if ( TREE_CODE ( type ) == VECTOR_TYPE && ! VECTOR_MODE_P ( mode ) ) { HOST_WIDE_INT size = int_size_in_bytes ( type ) ; if ( ( size == 8 || size == 16 ) && TYPE_VECTOR_SUBPARTS ( type ) > 1 ) { enum machine_mode innermode = TYPE_MODE ( TREE_TYPE ( type ) ) ; if ( TREE_CODE ( TREE_TYPE ( type ) ) == REAL_TYPE ) mode = MIN_MODE_VECTOR_FLOAT ; else mode = MIN_MODE_VECTOR_INT ; for ( ; mode != VOIDmode ; mode = GET_MODE_WIDER_MODE ( mode ) ) if ( GET_MODE_NUNITS ( mode ) == TYPE_VECTOR_SUBPARTS ( type ) && GET_MODE_INNER ( mode ) == innermode ) return mode ; gcc_unreachable ( ) ; } } return mode ; } </s>

Return the `` natural '' mode for TYPE . In most cases , this is just TYPE_MODE . But in the case of vector types , it is some vector mode . When we have only some of our vector isa extensions enabled , then there are some modes for which vector_mode_supported_p is false . For these modes , the generic vector support in gcc will choose some non-vector mode in order to implement the type . By computing the natural mode , we 'll select the proper ABI location for the operand and not depend on whatever the middle-end decides to do with these vector types .


<s> static void x86_64_elf_select_section ( tree decl , int reloc , unsigned HOST_WIDE_INT align ) { if ( ( ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_MEDIUM_PIC ) && ix86_in_large_data_p ( decl ) ) { const char * sname = NULL ; unsigned int flags = SECTION_WRITE ; switch ( categorize_decl_for_section ( decl , reloc , flag_pic ) ) { case SECCAT_DATA : sname = ".ldata" ; break ; case SECCAT_DATA_REL : sname = ".ldata.rel" ; break ; case SECCAT_DATA_REL_LOCAL : sname = ".ldata.rel.local" ; break ; case SECCAT_DATA_REL_RO : sname = ".ldata.rel.ro" ; break ; case SECCAT_DATA_REL_RO_LOCAL : sname = ".ldata.rel.ro.local" ; break ; case SECCAT_BSS : sname = ".lbss" ; flags |= SECTION_BSS ; break ; case SECCAT_RODATA : case SECCAT_RODATA_MERGE_STR : case SECCAT_RODATA_MERGE_STR_INIT : case SECCAT_RODATA_MERGE_CONST : sname = ".lrodata" ; flags = 0 ; break ; case SECCAT_SRODATA : case SECCAT_SDATA : case SECCAT_SBSS : gcc_unreachable ( ) ; case SECCAT_TEXT : case SECCAT_TDATA : case SECCAT_TBSS : break ; } if ( sname ) { if ( ! DECL_P ( decl ) ) named_section_flags ( sname , flags ) ; else named_section ( decl , sname , reloc ) ; return ; } } default_elf_select_section ( decl , reloc , align ) ; } </s>

switch to the appropriate section for output of DECL . DECL is either a ` VAR_DECL ' node or a constant of some sort . RELOC indicates whether forming the initial value of DECL requires link-time relocations .


<s> static void x86_64_elf_unique_section ( tree decl , int reloc ) { if ( ( ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_MEDIUM_PIC ) && ix86_in_large_data_p ( decl ) ) { const char * prefix = NULL ; bool one_only = DECL_ONE_ONLY ( decl ) && ! HAVE_COMDAT_GROUP ; switch ( categorize_decl_for_section ( decl , reloc , flag_pic ) ) { case SECCAT_DATA : case SECCAT_DATA_REL : case SECCAT_DATA_REL_LOCAL : case SECCAT_DATA_REL_RO : case SECCAT_DATA_REL_RO_LOCAL : prefix = one_only ? ".gnu.linkonce.ld." : ".ldata." ; break ; case SECCAT_BSS : prefix = one_only ? ".gnu.linkonce.lb." : ".lbss." ; break ; case SECCAT_RODATA : case SECCAT_RODATA_MERGE_STR : case SECCAT_RODATA_MERGE_STR_INIT : case SECCAT_RODATA_MERGE_CONST : prefix = one_only ? ".gnu.linkonce.lr." : ".lrodata." ; break ; case SECCAT_SRODATA : case SECCAT_SDATA : case SECCAT_SBSS : gcc_unreachable ( ) ; case SECCAT_TEXT : case SECCAT_TDATA : case SECCAT_TBSS : break ; } if ( prefix ) { const char * name ; size_t nlen , plen ; char * string ; plen = strlen ( prefix ) ; name = IDENTIFIER_POINTER ( DECL_ASSEMBLER_NAME ( decl ) ) ; name = targetm . strip_name_encoding ( name ) ; nlen = strlen ( name ) ; string = alloca ( nlen + plen + 1 ) ; memcpy ( string , prefix , plen ) ; memcpy ( string + plen , name , nlen + 1 ) ; DECL_SECTION_NAME ( decl ) = build_string ( nlen + plen , string ) ; return ; } } default_unique_section ( decl , reloc ) ; } </s>

Build up a unique section name , expressed as a STRING_CST node , and assign it to DECL_SECTION_NAME ( decl ) . RELOC indicates whether the initial value of EXP requires link-time relocations .


<s> static bool x86_can_output_mi_thunk ( tree thunk ATTRIBUTE_UNUSED , HOST_WIDE_INT delta ATTRIBUTE_UNUSED , HOST_WIDE_INT vcall_offset , tree function ) { if ( TARGET_64BIT ) return true ; if ( ix86_function_regparm ( TREE_TYPE ( function ) , function ) < 3 ) return true ; if ( vcall_offset ) return false ; if ( flag_pic && ! ( * targetm . binds_local_p ) ( function ) ) return false ; return true ; } </s>

Determine whether x86_output_mi_thunk can succeed .


<s> void x86_elf_aligned_common ( FILE * file , const char * name , unsigned HOST_WIDE_INT size , int align ) { if ( ( ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_MEDIUM_PIC ) && size > ( unsigned int ) ix86_section_threshold ) fprintf ( file , ".largecomm\t" ) ; else fprintf ( file , "%s" , COMMON_ASM_OP ) ; assemble_name ( file , name ) ; fprintf ( file , "," HOST_WIDE_INT_PRINT_UNSIGNED ",%u\n" , size , align / BITS_PER_UNIT ) ; } </s>

This says how to output assembler code to declare an uninitialized external linkage data object . For medium model x86-64 we need to use .largecomm opcode for large objects .


<s> void x86_emit_floatuns ( rtx operands [ 2 ] ) { rtx neglab , donelab , i0 , i1 , f0 , in , out ; enum machine_mode mode , inmode ; inmode = GET_MODE ( operands [ 1 ] ) ; gcc_assert ( inmode == SImode || inmode == DImode ) ; out = operands [ 0 ] ; in = force_reg ( inmode , operands [ 1 ] ) ; mode = GET_MODE ( out ) ; neglab = gen_label_rtx ( ) ; donelab = gen_label_rtx ( ) ; i1 = gen_reg_rtx ( Pmode ) ; f0 = gen_reg_rtx ( mode ) ; emit_cmp_and_jump_insns ( in , const0_rtx , LT , const0_rtx , Pmode , 0 , neglab ) ; emit_insn ( gen_rtx_SET ( VOIDmode , out , gen_rtx_FLOAT ( mode , in ) ) ) ; emit_jump_insn ( gen_jump ( donelab ) ) ; emit_barrier ( ) ; emit_label ( neglab ) ; i0 = expand_simple_binop ( Pmode , LSHIFTRT , in , const1_rtx , NULL , 1 , OPTAB_DIRECT ) ; i1 = expand_simple_binop ( Pmode , AND , in , const1_rtx , NULL , 1 , OPTAB_DIRECT ) ; i0 = expand_simple_binop ( Pmode , IOR , i0 , i1 , i0 , 1 , OPTAB_DIRECT ) ; expand_float ( f0 , i0 , 0 ) ; emit_insn ( gen_rtx_SET ( VOIDmode , out , gen_rtx_PLUS ( mode , f0 , f0 ) ) ) ; emit_label ( donelab ) ; } </s>

Generate an unsigned DImode/SImode to FP conversion . This is the same code optabs would emit if we did n't have TFmode patterns .


<s> bool x86_extended_QIreg_mentioned_p ( rtx insn ) { int i ; extract_insn_cached ( insn ) ; for ( i = 0 ; i < recog_data . n_operands ; i ++ ) if ( REG_P ( recog_data . operand [ i ] ) && REGNO ( recog_data . operand [ i ] ) >= 4 ) return true ; return false ; } </s>

Return nonzero when QImode register that must be represented via REX prefix is used .


<s> bool x86_extended_reg_mentioned_p ( rtx insn ) { return for_each_rtx ( & PATTERN ( insn ) , extended_reg_mentioned_1 , NULL ) ; } </s>

Return true when INSN mentions register that must be encoded using REX prefix .


<s> void x86_function_profiler ( FILE * file , int labelno ATTRIBUTE_UNUSED ) { if ( TARGET_64BIT ) if ( flag_pic ) { fprintf ( file , "\tleaq\t%sP%d@(%%rip),%%r11\n" , LPREFIX , labelno ) ; fprintf ( file , "\tcall\t*%s@GOTPCREL(%%rip)\n" , MCOUNT_NAME ) ; } else { fprintf ( file , "\tmovq\t$%sP%d,%%r11\n" , LPREFIX , labelno ) ; fprintf ( file , "\tcall\t%s\n" , MCOUNT_NAME ) ; } else if ( flag_pic ) { fprintf ( file , "\tleal\t%sP%d@GOTOFF(%%ebx),%%%s\n" , LPREFIX , labelno , PROFILE_COUNT_REGISTER ) ; fprintf ( file , "\tcall\t*%s@GOT(%%ebx)\n" , MCOUNT_NAME ) ; } else { fprintf ( file , "\tmovl\t$%sP%d,%%%s\n" , LPREFIX , labelno , PROFILE_COUNT_REGISTER ) ; fprintf ( file , "\tcall\t%s\n" , MCOUNT_NAME ) ; } } </s>

Output assembler code to FILE to increment profiler label # LABELNO for profiling a function entry .


<s> void x86_initialize_trampoline ( rtx tramp , rtx fnaddr , rtx cxt ) { if ( ! TARGET_64BIT ) { rtx disp = expand_binop ( SImode , sub_optab , fnaddr , plus_constant ( tramp , 10 ) , NULL_RTX , 1 , OPTAB_DIRECT ) ; emit_move_insn ( gen_rtx_MEM ( QImode , tramp ) , gen_int_mode ( 0xb9 , QImode ) ) ; emit_move_insn ( gen_rtx_MEM ( SImode , plus_constant ( tramp , 1 ) ) , cxt ) ; emit_move_insn ( gen_rtx_MEM ( QImode , plus_constant ( tramp , 5 ) ) , gen_int_mode ( 0xe9 , QImode ) ) ; emit_move_insn ( gen_rtx_MEM ( SImode , plus_constant ( tramp , 6 ) ) , disp ) ; } else { int offset = 0 ; if ( x86_64_zext_immediate_operand ( fnaddr , VOIDmode ) ) { fnaddr = copy_to_mode_reg ( DImode , fnaddr ) ; emit_move_insn ( gen_rtx_MEM ( HImode , plus_constant ( tramp , offset ) ) , gen_int_mode ( 0xbb41 , HImode ) ) ; emit_move_insn ( gen_rtx_MEM ( SImode , plus_constant ( tramp , offset + 2 ) ) , gen_lowpart ( SImode , fnaddr ) ) ; offset += 6 ; } else { emit_move_insn ( gen_rtx_MEM ( HImode , plus_constant ( tramp , offset ) ) , gen_int_mode ( 0xbb49 , HImode ) ) ; emit_move_insn ( gen_rtx_MEM ( DImode , plus_constant ( tramp , offset + 2 ) ) , fnaddr ) ; offset += 10 ; } emit_move_insn ( gen_rtx_MEM ( HImode , plus_constant ( tramp , offset ) ) , gen_int_mode ( 0xba49 , HImode ) ) ; emit_move_insn ( gen_rtx_MEM ( DImode , plus_constant ( tramp , offset + 2 ) ) , cxt ) ; offset += 10 ; emit_move_insn ( gen_rtx_MEM ( HImode , plus_constant ( tramp , offset ) ) , gen_int_mode ( 0xff49 , HImode ) ) ; emit_move_insn ( gen_rtx_MEM ( QImode , plus_constant ( tramp , offset + 2 ) ) , gen_int_mode ( 0xe3 , QImode ) ) ; offset += 3 ; gcc_assert ( offset <= TRAMPOLINE_SIZE ) ; } emit_library_call ( gen_rtx_SYMBOL_REF ( Pmode , "__enable_execute_stack" ) , LCT_NORMAL , VOIDmode , 1 , tramp , Pmode ) ; } </s>

Emit RTL insns to initialize the variable parts of a trampoline . FNADDR is an RTX for the address of the function 's pure code . CXT is an RTX for the static chain value for the function .


<s> void x86_order_regs_for_local_alloc ( void ) { int pos = 0 ; int i ; for ( i = 0 ; i < FIRST_PSEUDO_REGISTER ; i ++ ) if ( GENERAL_REGNO_P ( i ) && call_used_regs [ i ] ) reg_alloc_order [ pos ++ ] = i ; for ( i = 0 ; i < FIRST_PSEUDO_REGISTER ; i ++ ) if ( GENERAL_REGNO_P ( i ) && ! call_used_regs [ i ] ) reg_alloc_order [ pos ++ ] = i ; if ( ! TARGET_SSE_MATH ) for ( i = FIRST_STACK_REG ; i <= LAST_STACK_REG ; i ++ ) reg_alloc_order [ pos ++ ] = i ; for ( i = FIRST_SSE_REG ; i <= LAST_SSE_REG ; i ++ ) reg_alloc_order [ pos ++ ] = i ; for ( i = FIRST_REX_SSE_REG ; i <= LAST_REX_SSE_REG ; i ++ ) reg_alloc_order [ pos ++ ] = i ; if ( TARGET_SSE_MATH ) for ( i = FIRST_STACK_REG ; i <= LAST_STACK_REG ; i ++ ) reg_alloc_order [ pos ++ ] = i ; for ( i = FIRST_MMX_REG ; i <= LAST_MMX_REG ; i ++ ) reg_alloc_order [ pos ++ ] = i ; while ( pos < FIRST_PSEUDO_REGISTER ) reg_alloc_order [ pos ++ ] = 0 ; } </s>

Order the registers for register allocator .


<s> void x86_output_aligned_bss ( FILE * file , tree decl ATTRIBUTE_UNUSED , const char * name , unsigned HOST_WIDE_INT size , int align ) { if ( ( ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_MEDIUM_PIC ) && size > ( unsigned int ) ix86_section_threshold ) named_section ( decl , ".lbss" , 0 ) ; else bss_section ( ) ; ASM_OUTPUT_ALIGN ( file , floor_log2 ( align / BITS_PER_UNIT ) ) ; last_assemble_variable_decl = decl ; ASM_DECLARE_OBJECT_NAME ( file , name , decl ) ; ASM_OUTPUT_LABEL ( file , name ) ; ASM_OUTPUT_SKIP ( file , size ? size : 1 ) ; } </s>

Utility function for targets to use in implementing ASM_OUTPUT_ALIGNED_BSS .