<s> static __inline__ struct quot_rem do_31div ( unsigned long a , unsigned long b ) { long extra = 0 ; int quot_digits = 0 ; if ( b == 0 ) { struct quot_rem ret ; ret . quot = 0xffffffff ; ret . rem = 0xffffffff ; return ret ; } if ( a < b ) return ( struct quot_rem ) { 0 , a } ; if ( b <= a ) { quot_digits = LZ ( b ) - LZ ( a ) ; quot_digits += ( a >= ( b << quot_digits ) ) ; b <<= quot_digits ; } while ( b <= a ) { b <<= 1 ; quot_digits ++ ; } if ( a & 0x40000000 ) { b >>= 1 ; if ( a >= b ) { a -= b ; extra = 1 << ( quot_digits - 1 ) ; } else { a -= b >> 1 ; extra = 1 << quot_digits ; } quot_digits -- ; } b -- ; switch ( quot_digits ) { case 32 : DS ; case 31 : DS ; case 30 : DS ; case 29 : DS ; case 28 : DS ; case 27 : DS ; case 26 : DS ; case 25 : DS ; case 24 : DS ; case 23 : DS ; case 22 : DS ; case 21 : DS ; case 20 : DS ; case 19 : DS ; case 18 : DS ; case 17 : DS ; case 16 : DS ; case 15 : DS ; case 14 : DS ; case 13 : DS ; case 12 : DS ; case 11 : DS ; case 10 : DS ; case 9 : DS ; case 8 : DS ; case 7 : DS ; case 6 : DS ; case 5 : DS ; case 4 : DS ; case 3 : DS ; case 2 : DS ; case 1 : DS ; case 0 : ; } { struct quot_rem ret ; ret . quot = ( a & ( ( 1 << quot_digits ) - 1 ) ) + extra ; ret . rem = a >> quot_digits ; return ret ; } } </s>

This is the worker function for div and mod . It is inlined into the respective library function .


<s> static rtx_insn * cris_md_asm_adjust ( vec < rtx > & outputs , vec < rtx > & inputs , vec < machine_mode > & , vec < const char * > & constraints , vec < rtx > & clobbers , HARD_REG_SET & clobbered_regs ) { clobbers . safe_push ( gen_rtx_REG ( CCmode , CRIS_CC0_REGNUM ) ) ; SET_HARD_REG_BIT ( clobbered_regs , CRIS_CC0_REGNUM ) ; for ( unsigned i = 0 , n = constraints . length ( ) ; i < n ; ++ i ) if ( strchr ( constraints [ i ] , 'h' ) != NULL ) return NULL ; rtx mof_reg = gen_rtx_REG ( SImode , CRIS_MOF_REGNUM ) ; for ( unsigned i = 0 , n = outputs . length ( ) ; i < n ; ++ i ) if ( reg_overlap_mentioned_p ( mof_reg , outputs [ i ] ) ) return NULL ; for ( unsigned i = 0 , n = inputs . length ( ) ; i < n ; ++ i ) if ( reg_overlap_mentioned_p ( mof_reg , inputs [ i ] ) ) return NULL ; clobbers . safe_push ( mof_reg ) ; SET_HARD_REG_BIT ( clobbered_regs , CRIS_MOF_REGNUM ) ; return NULL ; } </s>

Worker function for TARGET_MD_ASM_ADJUST .


"%<-max-stackframe=%d%> is not usable, "

"unknown CRIS version specification in %<-march=%> or "

"unknown CRIS cpu version specification in %<-mtune=%> : %s"

"%<-fPIC%> and %<-fpic%> are not supported on this target"

The TARGET_OPTION_OVERRIDE worker . As is the norm , this also parses -mfoo=bar type parameters .


<s> static unsigned int cris_postdbr_cmpelim ( ) { rtx_insn * insn ; rtx_insn * next ; rtx_insn * prev_cc_setter = 0 ; rtx_insn * prev_cc_outer = 0 ; rtx dccr = gen_rtx_REG ( CCmode , CRIS_CC0_REGNUM ) ; for ( insn = get_insns ( ) ; insn ; insn = next ) { rtx_insn * outer_insn = insn ; rtx pat = PATTERN ( insn ) ; next = NEXT_INSN ( outer_insn ) ; if ( LABEL_P ( insn ) ) { prev_cc_setter = 0 ; continue ; } if ( ! NONDEBUG_INSN_P ( insn ) ) continue ; if ( GET_CODE ( pat ) == SEQUENCE ) insn = as_a < rtx_insn * > XVECEXP ( pat , 0 , 1 ) ; else if ( prev_cc_setter != 0 && GET_CODE ( pat ) == SET ) { rtx dest = SET_DEST ( pat ) ; rtx src = SET_SRC ( pat ) ; rtx prev_set ; if ( REG_P ( dest ) && REGNO ( dest ) == CRIS_CC0_REGNUM && GET_CODE ( src ) == COMPARE && REG_P ( XEXP ( src , 0 ) ) && XEXP ( src , 1 ) == const0_rtx && ( prev_set = single_set ( prev_cc_setter ) ) != 0 ) { rtx reg = XEXP ( src , 0 ) ; rtx prev_dest = SET_DEST ( prev_set ) ; rtx prev_src = SET_SRC ( prev_set ) ; bool src_same = rtx_equal_p ( prev_src , reg ) ; if ( REG_P ( prev_dest ) && ! reg_set_p ( reg , prev_src ) && ! reg_set_between_p ( reg , prev_cc_outer , outer_insn ) && ( src_same || rtx_equal_p ( prev_dest , reg ) ) ) { machine_mode ccmode = GET_MODE ( src ) ; rtx modeadjusted_dccr = ( ccmode == CCmode ? dccr : gen_rtx_REG ( CCmode , CRIS_CC0_REGNUM ) ) ; rtx compare = ( src_same ? pat : gen_rtx_SET ( modeadjusted_dccr , gen_rtx_COMPARE ( ccmode , copy_rtx ( prev_src ) , const0_rtx ) ) ) ; validate_change ( prev_cc_setter , & XVECEXP ( PATTERN ( prev_cc_setter ) , 0 , 0 ) , compare , true ) ; validate_change ( prev_cc_setter , & XVECEXP ( PATTERN ( prev_cc_setter ) , 0 , 1 ) , prev_set , true ) ; if ( apply_change_group ( ) ) { delete_insn ( insn ) ; prev_cc_setter = 0 ; continue ; } } } } if ( reg_set_p ( dccr , insn ) ) { rtx pat = PATTERN ( insn ) ; prev_cc_setter = 0 ; if ( GET_CODE ( pat ) == PARALLEL && XVECLEN ( pat , 0 ) == 2 && GET_CODE ( XVECEXP ( pat , 0 , 1 ) ) == CLOBBER ) { prev_cc_setter = insn ; prev_cc_outer = outer_insn ; } } } return 0 ; } </s>

`` Cheap version '' of cmpelim , making use of the opportunities opened up by reorg . Go through the insns of a function and look at each actual compare insn ; considering only those that compare a register to 0 . If the previous CC-affecting insn sets the compared register or if a move reads from it , try to change that into a CC-setting move and try to have it recognized . Bail at labels or non-matching insns that clobber the compared register . If successful , delete the compare . Also , reorg is n't up to date regarding data-flow handling , so we ca n't go beyond classic RTL scanning .


"internal error: cris_side_effect_mode_ok with bad operands"

Check various objections to the side-effect . Used in the test-part of an anonymous insn describing an insn with a possible side-effect . Returns nonzero if the implied side-effect is ok. code : PLUS or MULT ops : An array of rtx : es . lreg , rreg , rval , The variables multop and other_op are indexes into this , or -1 if they are not applicable . lreg : The register that gets assigned in the side-effect . rreg : One register in the side-effect expression rval : The other register , or an int . multop : An integer to multiply rval with . other_op : One of the entities of the main effect , whose mode we must consider .


<s> int cris_cfun_uses_pic_table ( ) { return current_function_uses_pic_offset_table ; } </s>

Return current_function_uses_pic_offset_table . For use in cris.md , since some generated files do not include function.h .


<s> void cris_conditional_register_usage ( ) { if ( flag_pic ) fixed_regs [ PIC_OFFSET_TABLE_REGNUM ] = call_used_regs [ PIC_OFFSET_TABLE_REGNUM ] = 1 ; } </s>


<s> int cris_delay_slots_for_epilogue ( ) { if ( regs_ever_live [ CRIS_SRP_REGNUM ] || cfun -> machine -> needs_return_address_on_stack != 0 ) return 0 ; cris_target_asm_function_epilogue ( NULL , get_frame_size ( ) ) ; if ( * save_last ) return 1 ; return 0 ; } </s>

Return the number of delay-slots in the epilogue : return 1 if it contains `` ret '' , else 0 .


<s> static int cris_initial_frame_pointer_offset ( ) { int regno ; int offs = 0 ; for ( regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno ++ ) if ( ( ( ( regs_ever_live [ regno ] && ! call_used_regs [ regno ] ) || ( regno == ( int ) PIC_OFFSET_TABLE_REGNUM && ( current_function_uses_pic_offset_table || ( flag_pic && regs_ever_live [ regno + 1 ] && ! call_used_regs [ regno + 1 ] ) ) ) ) && ( regno != FRAME_POINTER_REGNUM || ! frame_pointer_needed ) && regno != CRIS_SRP_REGNUM ) || ( current_function_calls_eh_return && ( regno == EH_RETURN_DATA_REGNO ( 0 ) || regno == EH_RETURN_DATA_REGNO ( 1 ) || regno == EH_RETURN_DATA_REGNO ( 2 ) || regno == EH_RETURN_DATA_REGNO ( 3 ) ) ) ) offs += 4 ; offs += get_frame_size ( ) ; offs += current_function_outgoing_args_size ; if ( TARGET_STACK_ALIGN ) offs = TARGET_ALIGN_BY_32 ? ( offs + 3 ) & ~ 3 : ( offs + 1 ) & ~ 1 ; return offs ; } </s>

This used to be the INITIAL_FRAME_POINTER_OFFSET worker ; now only handles FP - > SP elimination offset .


<s> void cris_init_expanders ( ) { } </s>

The INIT_EXPANDERS worker sets the per-function-data initializer and mark functions .


"-max-stackframe=%d is not usable, not between 0 and %d"

"unknown CRIS version specification in -march= or -mcpu= : %s"

"unknown CRIS cpu version specification in -mtune= : %s"

"-fPIC and -fpic are not supported in this configuration"

"that particular -g option is invalid with -maout and -melinux"

The OVERRIDE_OPTIONS worker . As is the norm , this also parses -mfoo=bar type parameters .


<s> int cris_simple_epilogue ( ) { int regno ; int reglimit = STACK_POINTER_REGNUM ; int lastreg = - 1 ; if ( ! reload_completed || frame_pointer_needed || get_frame_size ( ) != 0 || current_function_pretend_args_size || current_function_args_size || current_function_outgoing_args_size || current_function_calls_eh_return || ! TARGET_PROLOGUE_EPILOGUE ) return 0 ; for ( regno = 0 ; regno < reglimit ; regno ++ ) if ( ( regs_ever_live [ regno ] && ! call_used_regs [ regno ] ) || ( regno == ( int ) PIC_OFFSET_TABLE_REGNUM && ( current_function_uses_pic_offset_table || ( flag_pic && regs_ever_live [ regno + 1 ] && ! call_used_regs [ regno + 1 ] ) ) ) ) { if ( lastreg != regno - 1 ) return 0 ; lastreg = regno ; } return 1 ; } </s>

Return ! = 0 if the return sequence for the current function is short , like `` ret '' or `` jump [ sp+ ] '' . Prior to reloading , we ca n't tell how many registers must be saved , so return 0 then .


<s> static int cris_address_cost ( rtx x ) { if ( BASE_OR_AUTOINCR_P ( x ) ) return 0 ; if ( GET_CODE ( x ) == MEM ) return ( 2 + 4 ) / 2 ; if ( CONSTANT_P ( x ) ) return ( 2 + 4 ) / 2 ; if ( GET_CODE ( x ) == PLUS ) { rtx tem1 = XEXP ( x , 0 ) ; rtx tem2 = XEXP ( x , 1 ) ; if ( ( GET_CODE ( tem1 ) == MULT && BIAP_INDEX_P ( tem1 ) ) || REG_P ( tem1 ) ) return 2 / 2 ; if ( GET_CODE ( tem2 ) == CONST_INT && INTVAL ( tem2 ) < 128 && INTVAL ( tem2 ) >= - 128 ) return 2 / 2 ; if ( GET_CODE ( tem2 ) == CONST_INT && CONST_OK_FOR_LETTER_P ( INTVAL ( tem2 ) , 'L' ) ) return ( 2 + 2 ) / 2 ; if ( CONSTANT_P ( tem2 ) ) return ( 2 + 2 + 2 ) / 2 ; return ( 2 + 2 + 2 ) / 2 ; } return 10 ; } </s>


"emitting PIC operand, but PIC register isn't set up"

Worker function for ASM_OUTPUT_LABEL_REF .


<s>
static
void
cris_asm_output_mi_thunk
(
FILE
*
stream
,
tree
thunkdecl
ATTRIBUTE_UNUSED
,
HOST_WIDE_INT
delta
,
HOST_WIDE_INT
vcall_offset
ATTRIBUTE_UNUSED
,
tree
funcdecl
)
{
if
(
delta
>
0
)
fprintf
(
stream
,
"\tadd%s "
HOST_WIDE_INT_PRINT_DEC
",$%s\n"
,
ADDITIVE_SIZE_MODIFIER
(
delta
)
,
delta
,
reg_names
[
CRIS_FIRST_ARG_REG
]
)
;
else
if
(
delta
<
0
)
fprintf
(
stream
,
"\tsub%s "
HOST_WIDE_INT_PRINT_DEC
",$%s\n"
,
ADDITIVE_SIZE_MODIFIER
(
delta
)
,
delta
,
reg_names
[
CRIS_FIRST_ARG_REG
]
)
;
if
(
flag_pic
)
{
const
char
*
name
=
XSTR
(
XEXP
(
DECL_RTL
(
funcdecl
)
,
0
)
,
0
)
;
name
=
(
*
targetm
.
strip_name_encoding
)
(
name
)
;
fprintf
(
stream
,
"add.d "
)
;
assemble_name
(
stream
,
name
)
;
fprintf
(
stream
,
"%s,$pc\n"
,
CRIS_PLT_PCOFFSET_SUFFIX
)
;
}
else
{
fprintf
(
stream
,
"jump "
)
;
assemble_name
(
stream
,
XSTR
(
XEXP
(
DECL_RTL
(
funcdecl
)
,
0
)
,
0
)
)
;
fprintf
(
stream
,
"\n"
)
;
}
}
</s>


<s>
void
cris_asm_output_symbol_ref
(
FILE
*
file
,
rtx
x
)
{
gcc_assert
(
GET_CODE
(
x
)
==
SYMBOL_REF
)
;
if
(
flag_pic
&&
in_code
>
0
)
{
const
char
*
origstr
=
XSTR
(
x
,
0
)
;
const
char
*
str
;
str
=
(
*
targetm
.
strip_name_encoding
)
(
origstr
)
;
assemble_name
(
file
,
str
)
;
if
(
!
current_function_uses_pic_offset_table
)
output_operand_lossage
(
"PIC register isn't set up"
)
;
}
else
assemble_name
(
file
,
XSTR
(
x
,
0
)
)
;
}
</s>

Worker function for ASM_OUTPUT_SYMBOL_REF .


<s> int cris_cfun_uses_pic_table ( void ) { return current_function_uses_pic_offset_table ; } </s>


<s> void cris_conditional_register_usage ( void ) { if ( flag_pic ) fixed_regs [ PIC_OFFSET_TABLE_REGNUM ] = call_used_regs [ PIC_OFFSET_TABLE_REGNUM ] = 1 ; if ( TARGET_HAS_MUL_INSNS ) fixed_regs [ CRIS_MOF_REGNUM ] = 0 ; if ( cris_cpu_version < 8 ) reg_names [ CRIS_CC0_REGNUM ] = "ccr" ; } </s>


<s>
void
cris_expand_pic_call_address
(
rtx
*
opp
)
{
rtx
op
=
*
opp
;
gcc_assert
(
MEM_P
(
op
)
)
;
op
=
XEXP
(
op
,
0
)
;
if
(
CONSTANT_ADDRESS_P
(
op
)
&&
GET_CODE
(
op
)
!=
CONST_INT
)
{
enum
cris_pic_symbol_type
t
=
cris_pic_symbol_type_of
(
op
)
;
CRIS_ASSERT
(
!
no_new_pseudos
)
;
if
(
t
==
cris_gotrel_symbol
)
op
=
force_reg
(
Pmode
,
op
)
;
else
if
(
t
==
cris_got_symbol
)
{
if
(
TARGET_AVOID_GOTPLT
)
{
rtx
tem
,
rm
,
ro
;
gcc_assert
(
!
no_new_pseudos
)
;
current_function_uses_pic_offset_table
=
1
;
tem
=
gen_rtx_UNSPEC
(
Pmode
,
gen_rtvec
(
1
,
op
)
,
CRIS_UNSPEC_PLT
)
;
rm
=
gen_reg_rtx
(
Pmode
)
;
emit_move_insn
(
rm
,
gen_rtx_CONST
(
Pmode
,
tem
)
)
;
ro
=
gen_reg_rtx
(
Pmode
)
;
if
(
expand_binop
(
Pmode
,
add_optab
,
rm
,
pic_offset_table_rtx
,
ro
,
0
,
OPTAB_LIB_WIDEN
)
!=
ro
)
internal_error
(
"expand_binop failed in movsi got"
)
;
op
=
ro
;
}
else
{
rtx
tem
,
mem
,
rm
,
ro
;
gcc_assert
(
!
no_new_pseudos
)
;
current_function_uses_pic_offset_table
=
1
;
tem
=
gen_rtx_UNSPEC
(
Pmode
,
gen_rtvec
(
1
,
op
)
,
CRIS_UNSPEC_PLTGOTREAD
)
;
rm
=
gen_reg_rtx
(
Pmode
)
;
emit_move_insn
(
rm
,
gen_rtx_CONST
(
Pmode
,
tem
)
)
;
ro
=
gen_reg_rtx
(
Pmode
)
;
if
(
expand_binop
(
Pmode
,
add_optab
,
rm
,
pic_offset_table_rtx
,
ro
,
0
,
OPTAB_LIB_WIDEN
)
!=
ro
)
internal_error
(
"expand_binop failed in movsi got"
)
;
mem
=
gen_rtx_MEM
(
Pmode
,
ro
)
;
set_mem_alias_set
(
mem
,
new_alias_set
(
)
)
;
MEM_NOTRAP_P
(
mem
)
=
1
;
op
=
mem
;
}
}
else
fatal_insn
(
"Unidentifiable call op"
,
op
)
;
*
opp
=
replace_equiv_address
(
*
opp
,
op
)
;
}
}
</s>

Worker function for expanding the address for PIC function calls .


<s> void cris_expand_return ( bool on_stack ) { emit_jump_insn ( gen_rtx_RETURN ( VOIDmode ) ) ; CRIS_ASSERT ( cfun -> machine -> return_type != CRIS_RETINSN_RET || ! on_stack ) ; CRIS_ASSERT ( cfun -> machine -> return_type != CRIS_RETINSN_JUMP || on_stack ) ; cfun -> machine -> return_type = on_stack ? CRIS_RETINSN_JUMP : CRIS_RETINSN_RET ; } </s>

Expand a return insn ( just one insn ) marked as using SRP or stack slot depending on parameter ON_STACK .


<s> static void cris_file_start ( void ) { targetm . file_start_app_off = ! ( TARGET_PDEBUG || flag_print_asm_name ) ; targetm . file_start_file_directive = TARGET_ELF ; default_file_start ( ) ; } </s>

Boilerplate emitted at start of file . NO_APP * only at file start * means faster assembly . It also means comments are not allowed . In some cases comments will be output for debugging purposes . Make sure they are allowed then . We want a .file directive only if TARGET_ELF .


<s> rtx cris_gen_movem_load ( rtx src , rtx nregs_rtx , int nprefix ) { int nregs = INTVAL ( nregs_rtx ) ; rtvec vec ; int eltno = 1 ; int i ; rtx srcreg = XEXP ( src , 0 ) ; unsigned int regno = nregs - 1 ; int regno_inc = - 1 ; if ( GET_CODE ( srcreg ) == POST_INC ) srcreg = XEXP ( srcreg , 0 ) ; CRIS_ASSERT ( REG_P ( srcreg ) ) ; if ( nregs == 1 ) return gen_movsi ( gen_rtx_REG ( SImode , 0 ) , src ) ; vec = rtvec_alloc ( nprefix + nregs + ( GET_CODE ( XEXP ( src , 0 ) ) == POST_INC ) ) ; if ( GET_CODE ( XEXP ( src , 0 ) ) == POST_INC ) { RTVEC_ELT ( vec , nprefix + 1 ) = gen_rtx_SET ( VOIDmode , srcreg , plus_constant ( srcreg , nregs * 4 ) ) ; eltno ++ ; } src = replace_equiv_address ( src , srcreg ) ; RTVEC_ELT ( vec , nprefix ) = gen_rtx_SET ( VOIDmode , gen_rtx_REG ( SImode , regno ) , src ) ; regno += regno_inc ; for ( i = 1 ; i < nregs ; i ++ , eltno ++ ) { RTVEC_ELT ( vec , nprefix + eltno ) = gen_rtx_SET ( VOIDmode , gen_rtx_REG ( SImode , regno ) , adjust_address_nv ( src , SImode , i * 4 ) ) ; regno += regno_inc ; } return gen_rtx_PARALLEL ( VOIDmode , vec ) ; } </s>

Worker function for generating movem from mem for load_multiple .


<s> static bool cris_handle_option ( size_t code , const char * arg ATTRIBUTE_UNUSED , int value ATTRIBUTE_UNUSED ) { switch ( code ) { case OPT_metrax100 : target_flags |= ( MASK_SVINTO + MASK_ETRAX4_ADD + MASK_ALIGN_BY_32 ) ; break ; case OPT_mno_etrax100 : target_flags &= ~ ( MASK_SVINTO + MASK_ETRAX4_ADD + MASK_ALIGN_BY_32 ) ; break ; case OPT_m32_bit : case OPT_m32bit : target_flags |= ( MASK_STACK_ALIGN + MASK_CONST_ALIGN + MASK_DATA_ALIGN + MASK_ALIGN_BY_32 ) ; break ; case OPT_m16_bit : case OPT_m16bit : target_flags |= ( MASK_STACK_ALIGN + MASK_CONST_ALIGN + MASK_DATA_ALIGN ) ; break ; case OPT_m8_bit : case OPT_m8bit : target_flags &= ~ ( MASK_STACK_ALIGN + MASK_CONST_ALIGN + MASK_DATA_ALIGN ) ; break ; default : break ; } CRIS_SUBTARGET_HANDLE_OPTION ( code , arg , value ) ; return true ; } </s>

TARGET_HANDLE_OPTION worker . We just store the values into local variables here . Checks for correct semantics are in cris_override_options .


<s> static int cris_initial_frame_pointer_offset ( void ) { int regno ; int offs = 0 ; bool got_really_used = false ; if ( current_function_uses_pic_offset_table ) { push_topmost_sequence ( ) ; got_really_used = reg_used_between_p ( pic_offset_table_rtx , get_insns ( ) , NULL_RTX ) ; pop_topmost_sequence ( ) ; } for ( regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno ++ ) if ( cris_reg_saved_in_regsave_area ( regno , got_really_used ) ) offs += 4 ; offs += get_frame_size ( ) ; offs += current_function_outgoing_args_size ; if ( TARGET_STACK_ALIGN ) offs = TARGET_ALIGN_BY_32 ? ( offs + 3 ) & ~ 3 : ( offs + 1 ) & ~ 1 ; return offs ; } </s>


<s> static void cris_init_libfuncs ( void ) { set_optab_libfunc ( smul_optab , SImode , "__Mul" ) ; set_optab_libfunc ( sdiv_optab , SImode , "__Div" ) ; set_optab_libfunc ( udiv_optab , SImode , "__Udiv" ) ; set_optab_libfunc ( smod_optab , SImode , "__Mod" ) ; set_optab_libfunc ( umod_optab , SImode , "__Umod" ) ; } </s>

Rename the function calls for integer multiply and divide .


<s> static struct machine_function * cris_init_machine_status ( void ) { return ggc_alloc_cleared ( sizeof ( struct machine_function ) ) ; } </s>

Zero initialization is OK for all current fields .


<s> int cris_legitimate_pic_operand ( rtx x ) { return cris_valid_pic_const ( x ) ; } </s>


<s> static tree cris_md_asm_clobbers ( tree outputs , tree inputs , tree in_clobbers ) { HARD_REG_SET mof_set ; tree clobbers ; tree t ; CLEAR_HARD_REG_SET ( mof_set ) ; SET_HARD_REG_BIT ( mof_set , CRIS_MOF_REGNUM ) ; clobbers = tree_cons ( NULL_TREE , build_string ( strlen ( reg_names [ CRIS_CC0_REGNUM ] ) , reg_names [ CRIS_CC0_REGNUM ] ) , in_clobbers ) ; for ( t = outputs ; t != NULL ; t = TREE_CHAIN ( t ) ) { tree val = TREE_VALUE ( t ) ; if ( strchr ( TREE_STRING_POINTER ( TREE_VALUE ( TREE_PURPOSE ( t ) ) ) , 'h' ) != NULL || tree_overlaps_hard_reg_set ( val , & mof_set ) != NULL_TREE ) return clobbers ; } for ( t = inputs ; t != NULL ; t = TREE_CHAIN ( t ) ) { tree val = TREE_VALUE ( t ) ; if ( strchr ( TREE_STRING_POINTER ( TREE_VALUE ( TREE_PURPOSE ( t ) ) ) , 'h' ) != NULL || tree_overlaps_hard_reg_set ( val , & mof_set ) != NULL_TREE ) return clobbers ; } return tree_cons ( NULL_TREE , build_string ( strlen ( reg_names [ CRIS_MOF_REGNUM ] ) , reg_names [ CRIS_MOF_REGNUM ] ) , clobbers ) ; } </s>

Worker function for TARGET_MD_ASM_CLOBBERS .


<s>
const
char
*
cris_op_str
(
rtx
x
)
{
cris_output_insn_is_bound
=
0
;
switch
(
GET_CODE
(
x
)
)
{
case
PLUS
:
return
"add"
;
break
;
case
MINUS
:
return
"sub"
;
break
;
case
MULT
:
internal_error
(
"MULT case in cris_op_str"
)
;
break
;
case
DIV
:
return
"div"
;
break
;
case
AND
:
return
"and"
;
break
;
case
IOR
:
return
"or"
;
break
;
case
XOR
:
return
"xor"
;
break
;
case
NOT
:
return
"not"
;
break
;
case
ASHIFT
:
return
"lsl"
;
break
;
case
LSHIFTRT
:
return
"lsr"
;
break
;
case
ASHIFTRT
:
return
"asr"
;
break
;
case
UMIN
:
cris_output_insn_is_bound
=
1
;
return
"bound"
;
break
;
default
:
return
"Unknown operator"
;
break
;
}
}
</s>

Given an rtx , return the text string corresponding to the CODE of X . Intended for use in the assembly language output section of a define_insn .

cris
0
"add"
"sub"
"MULT case in cris_op_str"
"div"
"and"
"or"
"xor"
"not"
"lsl"
"lsr"
"asr"
1
"bound"
"Unknown operator"


<s> void cris_order_for_addsi3 ( rtx * operands , int n ) { if ( MEM_P ( operands [ n ] ) ) { rtx tem = operands [ n ] ; operands [ n ] = operands [ n + 1 ] ; operands [ n + 1 ] = tem ; } } </s>

Make sure operands are in the right order for an addsi3 insn as generated by a define_split . A MEM as the first operand is n't recognized by addsi3 after reload . OPERANDS contains the operands , with the first at OPERANDS [ N ] and the second at OPERANDS [ N+1 ] .


<s> bool cris_output_addr_const_extra ( FILE * file , rtx xconst ) { switch ( GET_CODE ( xconst ) ) { rtx x ; case UNSPEC : x = XVECEXP ( xconst , 0 , 0 ) ; CRIS_ASSERT ( GET_CODE ( x ) == SYMBOL_REF || GET_CODE ( x ) == LABEL_REF || GET_CODE ( x ) == CONST ) ; output_addr_const ( file , x ) ; switch ( XINT ( xconst , 1 ) ) { case CRIS_UNSPEC_PLT : fprintf ( file , ":PLTG" ) ; break ; case CRIS_UNSPEC_GOTREL : fprintf ( file , ":GOTOFF" ) ; break ; case CRIS_UNSPEC_GOTREAD : if ( flag_pic == 1 ) fprintf ( file , ":GOT16" ) ; else fprintf ( file , ":GOT" ) ; break ; case CRIS_UNSPEC_PLTGOTREAD : if ( flag_pic == 1 ) fprintf ( file , CRIS_GOTPLT_SUFFIX "16" ) ; else fprintf ( file , CRIS_GOTPLT_SUFFIX ) ; break ; default : gcc_unreachable ( ) ; } return true ; default : return false ; } } </s>

Worker function for OUTPUT_ADDR_CONST_EXTRA .


"-max-stackframe=%d is not usable, not between 0 and %d"

"unknown CRIS version specification in -march= or -mcpu= : %s"

"unknown CRIS cpu version specification in -mtune= : %s"

"-fPIC and -fpic are not supported in this configuration"

"that particular -g option is invalid with -maout and -melinux"


<s>
enum
cris_pic_symbol_type
cris_pic_symbol_type_of
(
rtx
x
)
{
switch
(
GET_CODE
(
x
)
)
{
case
SYMBOL_REF
:
return
SYMBOL_REF_LOCAL_P
(
x
)
cris_gotrel_symbol
:
cris_got_symbol
;
case
LABEL_REF
:
return
cris_gotrel_symbol
;
case
CONST
:
return
cris_pic_symbol_type_of
(
XEXP
(
x
,
0
)
)
;
case
PLUS
:
case
MINUS
:
{
enum
cris_pic_symbol_type
t1
=
cris_pic_symbol_type_of
(
XEXP
(
x
,
0
)
)
;
enum
cris_pic_symbol_type
t2
=
cris_pic_symbol_type_of
(
XEXP
(
x
,
1
)
)
;
gcc_assert
(
t1
==
cris_no_symbol
||
t2
==
cris_no_symbol
)
;
if
(
t1
==
cris_got_symbol
||
t1
==
cris_got_symbol
)
return
cris_got_symbol_needing_fixup
;
return
t1
!=
cris_no_symbol
t1
:
t2
;
}
case
CONST_INT
:
case
CONST_DOUBLE
:
return
cris_no_symbol
;
case
UNSPEC
:
return
cris_invalid_pic_symbol
;
default
:
fatal_insn
(
"unrecognized supposed constant"
,
x
)
;
}
gcc_unreachable
(
)
;
}
</s>

Helper function to find the right PIC-type symbol to generate , given the original ( non-PIC ) representation .


"unexpected index-type in cris_print_index"

Print an index part of an address to file .


<s>
void
cris_print_operand_address
(
FILE
*
file
,
rtx
x
)
{
putc
(
'['
,
file
)
;
if
(
CONSTANT_ADDRESS_P
(
x
)
)
cris_output_addr_const
(
file
,
x
)
;
else
if
(
BASE_OR_AUTOINCR_P
(
x
)
)
cris_print_base
(
x
,
file
)
;
else
if
(
GET_CODE
(
x
)
==
PLUS
)
{
rtx
x1
,
x2
;
x1
=
XEXP
(
x
,
0
)
;
x2
=
XEXP
(
x
,
1
)
;
if
(
BASE_P
(
x1
)
)
{
cris_print_base
(
x1
,
file
)
;
cris_print_index
(
x2
,
file
)
;
}
else
if
(
BASE_P
(
x2
)
)
{
cris_print_base
(
x2
,
file
)
;
cris_print_index
(
x1
,
file
)
;
}
else
LOSE_AND_RETURN
(
"unrecognized address"
,
x
)
;
}
else
if
(
GET_CODE
(
x
)
==
MEM
)
{
putc
(
'['
,
file
)
;
cris_print_base
(
XEXP
(
x
,
0
)
,
file
)
;
putc
(
']'
,
file
)
;
}
else
LOSE_AND_RETURN
(
"unrecognized address"
,
x
)
;
putc
(
']'
,
file
)
;
}
</s>


<s> static int cris_reg_saved_in_regsave_area ( unsigned int regno , bool got_really_used ) { return ( ( ( regs_ever_live [ regno ] && ! call_used_regs [ regno ] ) || ( regno == PIC_OFFSET_TABLE_REGNUM && ( got_really_used || ( flag_pic && regs_ever_live [ regno + 1 ] && ! call_used_regs [ regno + 1 ] ) ) ) ) && ( regno != FRAME_POINTER_REGNUM || ! frame_pointer_needed ) && regno != CRIS_SRP_REGNUM ) || ( current_function_calls_eh_return && ( regno == EH_RETURN_DATA_REGNO ( 0 ) || regno == EH_RETURN_DATA_REGNO ( 1 ) || regno == EH_RETURN_DATA_REGNO ( 2 ) || regno == EH_RETURN_DATA_REGNO ( 3 ) ) ) ; } </s>

Return nonzero if REGNO is an ordinary register that * needs * to be saved together with other registers , possibly by a MOVEM instruction , or is saved for target-independent reasons . There may be target-dependent reasons to save the register anyway ; this is just a wrapper for a complicated conditional .


<s> bool cris_reload_address_legitimized ( rtx x , enum machine_mode mode ATTRIBUTE_UNUSED , int opnum ATTRIBUTE_UNUSED , int itype , int ind_levels ATTRIBUTE_UNUSED ) { enum reload_type type = itype ; rtx op0 , op1 ; rtx * op0p ; rtx * op1p ; if ( GET_CODE ( x ) != PLUS ) return false ; op0 = XEXP ( x , 0 ) ; op0p = & XEXP ( x , 0 ) ; op1 = XEXP ( x , 1 ) ; op1p = & XEXP ( x , 1 ) ; if ( ! REG_P ( op1 ) ) return false ; if ( GET_CODE ( op0 ) == SIGN_EXTEND && GET_CODE ( XEXP ( op0 , 0 ) ) == MEM ) { rtx op00 = XEXP ( op0 , 0 ) ; rtx op000 = XEXP ( op00 , 0 ) ; rtx * op000p = & XEXP ( op00 , 0 ) ; if ( ( GET_MODE ( op00 ) == HImode || GET_MODE ( op00 ) == QImode ) && ( REG_P ( op000 ) || ( GET_CODE ( op000 ) == POST_INC && REG_P ( XEXP ( op000 , 0 ) ) ) ) ) { bool something_reloaded = false ; if ( GET_CODE ( op000 ) == POST_INC && REG_P ( XEXP ( op000 , 0 ) ) && REGNO ( XEXP ( op000 , 0 ) ) > CRIS_LAST_GENERAL_REGISTER ) return false ; if ( ( REG_P ( op000 ) && REGNO ( op000 ) > CRIS_LAST_GENERAL_REGISTER ) ) { push_reload ( op000 , NULL_RTX , op000p , NULL , GENERAL_REGS , GET_MODE ( x ) , VOIDmode , 0 , 0 , opnum , type ) ; something_reloaded = true ; } if ( REGNO ( op1 ) > CRIS_LAST_GENERAL_REGISTER ) { push_reload ( op1 , NULL_RTX , op1p , NULL , GENERAL_REGS , GET_MODE ( x ) , VOIDmode , 0 , 0 , opnum , type ) ; something_reloaded = true ; } gcc_assert ( something_reloaded ) ; return true ; } } return false ; } </s>

Worker function for LEGITIMIZE_RELOAD_ADDRESS .


<s> bool cris_return_address_on_stack ( void ) { return regs_ever_live [ CRIS_SRP_REGNUM ] || cfun -> machine -> needs_return_address_on_stack ; } </s>

Accessor used in cris.md : return because cfun- > machine is n't available there .


<s> rtx cris_return_addr_rtx ( int count , rtx frameaddr ATTRIBUTE_UNUSED ) { cfun -> machine -> needs_return_address_on_stack = 1 ; return count == 0 ? gen_rtx_MEM ( Pmode , plus_constant ( virtual_incoming_args_rtx , - 4 ) ) : NULL_RTX ; } </s>

The RETURN_ADDR_RTX worker . We mark that the return address is used , either by EH or __builtin_return_address , for use by the function prologue and epilogue . FIXME : This is n't optimal ; we just use the mark in the prologue and epilogue to say that the return address is to be stored in the stack frame . We could return SRP for leaf-functions and use the initial-value machinery .


<s> static bool cris_rtx_costs ( rtx x , int code , int outer_code , int * total ) { switch ( code ) { case CONST_INT : { HOST_WIDE_INT val = INTVAL ( x ) ; if ( val == 0 ) * total = 0 ; else if ( val < 32 && val >= - 32 ) * total = 1 ; else if ( val <= 32767 && val >= - 32768 ) * total = 2 ; else * total = 4 ; return true ; } case LABEL_REF : * total = 6 ; return true ; case CONST : case SYMBOL_REF : * total = 6 ; return true ; case CONST_DOUBLE : if ( x != CONST0_RTX ( GET_MODE ( x ) == VOIDmode ? DImode : GET_MODE ( x ) ) ) * total = 12 ; else * total = 0 ; return true ; case MULT : if ( GET_CODE ( XEXP ( x , 1 ) ) != CONST_INT || exact_log2 ( INTVAL ( XEXP ( x , 1 ) ) < 0 ) ) { if ( TARGET_HAS_MUL_INSNS ) { * total = COSTS_N_INSNS ( 1 ) + COSTS_N_INSNS ( 1 ) / 2 ; return true ; } * total = COSTS_N_INSNS ( 132 ) ; return true ; } return false ; case UDIV : case MOD : case UMOD : case DIV : if ( GET_CODE ( XEXP ( x , 1 ) ) != CONST_INT || exact_log2 ( INTVAL ( XEXP ( x , 1 ) ) < 0 ) ) { * total = COSTS_N_INSNS ( 260 ) ; return true ; } return false ; case AND : if ( GET_CODE ( XEXP ( x , 1 ) ) == CONST_INT && GET_CODE ( XEXP ( x , 0 ) ) != CONST_INT && ! CONST_OK_FOR_LETTER_P ( INTVAL ( XEXP ( x , 1 ) ) , 'I' ) ) { * total = ( rtx_cost ( XEXP ( x , 0 ) , outer_code ) + 2 + 2 * GET_MODE_NUNITS ( GET_MODE ( XEXP ( x , 0 ) ) ) ) ; return true ; } return false ; case ZERO_EXTEND : case SIGN_EXTEND : * total = rtx_cost ( XEXP ( x , 0 ) , outer_code ) ; return true ; default : return false ; } } </s>

Compute a ( partial ) cost for rtx X . Return true if the complete cost has been computed , and false if subexpressions should be scanned . In either case , * TOTAL contains the cost result .


"\n; VA:: ANSI: %d args before, anon @ #%d, %dtime\n"

Worker function for TARGET_SETUP_INCOMING_VARARGS .


"internal error: cris_side_effect_mode_ok with bad operands"

Check various objections to the side-effect . Used in the test-part of an anonymous insn describing an insn with a possible side-effect . Returns nonzero if the implied side-effect is ok. code : PLUS or MULT ops : An array of rtx : es . lreg , rreg , rval , The variables multop and other_op are indexes into this , or -1 if they are not applicable . lreg : The register that gets assigned in the side-effect . rreg : One register in the side-effect expression rval : The other register , or an int . multop : An integer to multiply rval with . other_op : One of the entities of the main effect , whose mode we must consider .


<s> bool cris_simple_epilogue ( void ) { unsigned int regno ; unsigned int reglimit = STACK_POINTER_REGNUM ; bool got_really_used = false ; if ( ! reload_completed || frame_pointer_needed || get_frame_size ( ) != 0 || current_function_pretend_args_size || current_function_args_size || current_function_outgoing_args_size || current_function_calls_eh_return || ! TARGET_PROLOGUE_EPILOGUE ) return false ; if ( current_function_uses_pic_offset_table ) { push_topmost_sequence ( ) ; got_really_used = reg_used_between_p ( pic_offset_table_rtx , get_insns ( ) , NULL_RTX ) ; pop_topmost_sequence ( ) ; } for ( regno = 0 ; regno < reglimit ; regno ++ ) if ( cris_reg_saved_in_regsave_area ( regno , got_really_used ) ) return false ; return true ; } </s>

Return ! = 0 if the return sequence for the current function is short , like `` ret '' or `` jump [ sp+ ] '' . Prior to reloading , we ca n't tell how many registers must be saved , so return 0 then .


<s> void cris_target_asm_named_section ( const char * name , unsigned int flags , tree decl ) { if ( ! TARGET_ELF ) default_no_named_section ( name , flags , decl ) ; else default_elf_asm_named_section ( name , flags , decl ) ; } </s>

The TARGET_ASM_NAMED_SECTION worker . We just dispatch to the functions for ELF and a.out .


<s> bool cris_valid_pic_const ( rtx x ) { gcc_assert ( flag_pic ) ; switch ( GET_CODE ( x ) ) { case CONST_INT : case CONST_DOUBLE : return true ; default : ; } if ( GET_CODE ( x ) != CONST ) return false ; x = XEXP ( x , 0 ) ; if ( GET_CODE ( x ) == PLUS && GET_CODE ( XEXP ( x , 0 ) ) == UNSPEC && XINT ( XEXP ( x , 0 ) , 1 ) == CRIS_UNSPEC_GOTREL && GET_CODE ( XEXP ( x , 1 ) ) == CONST_INT ) x = XEXP ( x , 0 ) ; if ( GET_CODE ( x ) == UNSPEC ) switch ( XINT ( x , 1 ) ) { case CRIS_UNSPEC_PLT : case CRIS_UNSPEC_PLTGOTREAD : case CRIS_UNSPEC_GOTREAD : case CRIS_UNSPEC_GOTREL : return true ; default : gcc_unreachable ( ) ; } return cris_pic_symbol_type_of ( x ) == cris_no_symbol ; } </s>

Return TRUE iff X is a CONST valid for e.g . indexing .


<s> static int saved_regs_mentioned ( rtx x ) { int i ; const char * fmt ; RTX_CODE code ; code = GET_CODE ( x ) ; switch ( code ) { case REG : i = REGNO ( x ) ; return ! call_used_regs [ i ] ; case SUBREG : i = REGNO ( SUBREG_REG ( x ) ) ; return ! call_used_regs [ i ] ; default : ; } fmt = GET_RTX_FORMAT ( code ) ; for ( i = GET_RTX_LENGTH ( code ) - 1 ; i >= 0 ; i -- ) { if ( fmt [ i ] == 'e' ) { if ( saved_regs_mentioned ( XEXP ( x , i ) ) ) return 1 ; } else if ( fmt [ i ] == 'E' ) { int j ; for ( j = XVECLEN ( x , i ) - 1 ; j >= 0 ; j -- ) if ( saved_regs_mentioned ( XEXP ( x , i ) ) ) return 1 ; } } return 0 ; } </s>

Return nonzero if there are regs mentioned in the insn that are not all in the call_used regs . This is part of the decision whether an insn can be put in the epilogue .


<s>
void
cris_asm_output_case_end
(
FILE
*
stream
,
int
num
,
rtx
table
)
{
rtx
whole_jump_insn
=
prev_nonnote_nondebug_insn
(
table
)
;
gcc_assert
(
whole_jump_insn
!=
NULL_RTX
&&
LABEL_P
(
whole_jump_insn
)
)
;
whole_jump_insn
=
prev_nonnote_nondebug_insn
(
whole_jump_insn
)
;
gcc_assert
(
whole_jump_insn
!=
NULL_RTX
&&
(
JUMP_P
(
whole_jump_insn
)
||
(
TARGET_V32
&&
INSN_P
(
whole_jump_insn
)
&&
GET_CODE
(
PATTERN
(
whole_jump_insn
)
)
==
SEQUENCE
)
)
)
;
whole_jump_insn
=
PATTERN
(
whole_jump_insn
)
;
if
(
TARGET_V32
)
{
rtx
parallel_jump
=
(
GET_CODE
(
whole_jump_insn
)
==
SEQUENCE
PATTERN
(
XVECEXP
(
whole_jump_insn
,
0
,
0
)
)
:
whole_jump_insn
)
;
asm_fprintf
(
stream
,
"\t.word %LL%d-.%s\n"
,
CODE_LABEL_NUMBER
(
XEXP
(
XEXP
(
XEXP
(
XVECEXP
(
parallel_jump
,
0
,
0
)
,
1
)
,
2
)
,
0
)
)
,
(
TARGET_PDEBUG
"; default"
:
""
)
)
;
return
;
}
asm_fprintf
(
stream
,
"\t.word %LL%d-%LL%d%s\n"
,
CODE_LABEL_NUMBER
(
XEXP
(
XEXP
(
XEXP
(
XVECEXP
(
whole_jump_insn
,
0
,
0
)
,
1
)
,
2
)
,
0
)
)
,
num
,
(
TARGET_PDEBUG
"; default"
:
""
)
)
;
}
</s>


<s>
static
void
cris_asm_output_mi_thunk
(
FILE
*
stream
,
tree
thunkdecl
ATTRIBUTE_UNUSED
,
HOST_WIDE_INT
delta
,
HOST_WIDE_INT
vcall_offset
ATTRIBUTE_UNUSED
,
tree
funcdecl
)
{
final_start_function
(
emit_barrier
(
)
,
stream
,
1
)
;
if
(
delta
>
0
)
fprintf
(
stream
,
"\tadd%s "
HOST_WIDE_INT_PRINT_DEC
",$%s\n"
,
ADDITIVE_SIZE_MODIFIER
(
delta
)
,
delta
,
reg_names
[
CRIS_FIRST_ARG_REG
]
)
;
else
if
(
delta
<
0
)
fprintf
(
stream
,
"\tsub%s "
HOST_WIDE_INT_PRINT_DEC
",$%s\n"
,
ADDITIVE_SIZE_MODIFIER
(
delta
)
,
delta
,
reg_names
[
CRIS_FIRST_ARG_REG
]
)
;
if
(
flag_pic
)
{
const
char
*
name
=
XSTR
(
XEXP
(
DECL_RTL
(
funcdecl
)
,
0
)
,
0
)
;
name
=
(
*
targetm
.
strip_name_encoding
)
(
name
)
;
if
(
TARGET_V32
)
{
fprintf
(
stream
,
"\tba "
)
;
assemble_name
(
stream
,
name
)
;
fprintf
(
stream
,
"%s\n"
,
CRIS_PLT_PCOFFSET_SUFFIX
)
;
}
else
{
fprintf
(
stream
,
"add.d "
)
;
assemble_name
(
stream
,
name
)
;
fprintf
(
stream
,
"%s,$pc\n"
,
CRIS_PLT_PCOFFSET_SUFFIX
)
;
}
}
else
{
fprintf
(
stream
,
"jump "
)
;
assemble_name
(
stream
,
XSTR
(
XEXP
(
DECL_RTL
(
funcdecl
)
,
0
)
,
0
)
)
;
fprintf
(
stream
,
"\n"
)
;
if
(
TARGET_V32
)
fprintf
(
stream
,
"\tnop\n"
)
;
}
final_end_function
(
)
;
}
</s>


<s> bool cris_cc0_user_requires_cmp ( rtx insn ) { rtx_insn * cc0_user = NULL ; rtx body ; rtx set ; gcc_assert ( insn != NULL ) ; if ( ! TARGET_V32 ) return false ; cc0_user = next_cc0_user ( insn ) ; if ( cc0_user == NULL ) return false ; body = PATTERN ( cc0_user ) ; set = single_set ( cc0_user ) ; if ( JUMP_P ( cc0_user ) && GET_CODE ( body ) == SET && SET_DEST ( body ) == pc_rtx && GET_CODE ( SET_SRC ( body ) ) == IF_THEN_ELSE && XEXP ( XEXP ( SET_SRC ( body ) , 0 ) , 0 ) == cc0_rtx ) { return GET_CODE ( XEXP ( SET_SRC ( body ) , 0 ) ) == GT || GET_CODE ( XEXP ( SET_SRC ( body ) , 0 ) ) == LE ; } else if ( set ) { return GET_CODE ( SET_SRC ( body ) ) == GT || GET_CODE ( SET_SRC ( body ) ) == LE ; } gcc_unreachable ( ) ; } </s>

Whether next_cc0_user of insn is LE or GT or requires a real compare insn for other reasons .


<s> static rtx cris_function_arg ( cumulative_args_t ca , machine_mode mode , const_tree type , bool named ) { return cris_function_arg_1 ( ca , mode , type , named , false ) ; } </s>

Worker function for TARGET_FUNCTION_ARG . The void_type_node is sent as a `` closing '' call .


<s> static void cris_function_arg_advance ( cumulative_args_t ca_v , machine_mode mode , const_tree type , bool named ATTRIBUTE_UNUSED ) { CUMULATIVE_ARGS * ca = get_cumulative_args ( ca_v ) ; ca -> regs += ( 3 + CRIS_FUNCTION_ARG_SIZE ( mode , type ) ) / 4 ; } </s>

Worker function for TARGET_FUNCTION_ARG_ADVANCE .


<s> static rtx cris_function_incoming_arg ( cumulative_args_t ca , machine_mode mode , const_tree type , bool named ) { return cris_function_arg_1 ( ca , mode , type , named , true ) ; } </s>

Worker function for TARGET_FUNCTION_INCOMING_ARG . The differences between this and the previous , is that this one checks that an argument is named , since incoming stdarg/varargs arguments are pushed onto the stack , and we do n't have to check against the `` closing '' void_type_node TYPE parameter .


<s> rtx cris_gen_movem_load ( rtx src , rtx nregs_rtx , int nprefix ) { int nregs = INTVAL ( nregs_rtx ) ; rtvec vec ; int eltno = 1 ; int i ; rtx srcreg = XEXP ( src , 0 ) ; unsigned int regno = nregs - 1 ; int regno_inc = - 1 ; if ( TARGET_V32 ) { regno = 0 ; regno_inc = 1 ; } if ( GET_CODE ( srcreg ) == POST_INC ) srcreg = XEXP ( srcreg , 0 ) ; CRIS_ASSERT ( REG_P ( srcreg ) ) ; if ( nregs == 1 ) return gen_movsi ( gen_rtx_REG ( SImode , 0 ) , src ) ; vec = rtvec_alloc ( nprefix + nregs + ( GET_CODE ( XEXP ( src , 0 ) ) == POST_INC ) ) ; if ( GET_CODE ( XEXP ( src , 0 ) ) == POST_INC ) { RTVEC_ELT ( vec , nprefix + 1 ) = gen_rtx_SET ( VOIDmode , srcreg , plus_constant ( Pmode , srcreg , nregs * 4 ) ) ; eltno ++ ; } src = replace_equiv_address ( src , srcreg ) ; RTVEC_ELT ( vec , nprefix ) = gen_rtx_SET ( VOIDmode , gen_rtx_REG ( SImode , regno ) , src ) ; regno += regno_inc ; for ( i = 1 ; i < nregs ; i ++ , eltno ++ ) { RTVEC_ELT ( vec , nprefix + eltno ) = gen_rtx_SET ( VOIDmode , gen_rtx_REG ( SImode , regno ) , adjust_address_nv ( src , SImode , i * 4 ) ) ; regno += regno_inc ; } return gen_rtx_PARALLEL ( VOIDmode , vec ) ; } </s>

Worker function for generating movem from mem for load_multiple .


"-max-stackframe=%d is not usable, not between 0 and %d"

"unknown CRIS version specification in -march= or -mcpu= : %s"

"unknown CRIS cpu version specification in -mtune= : %s"

"-fPIC and -fpic are not supported in this configuration"

The TARGET_OPTION_OVERRIDE worker . As is the norm , this also parses -mfoo=bar type parameters .


<s> static bool cris_pass_by_reference ( cumulative_args_t ca ATTRIBUTE_UNUSED , machine_mode mode , const_tree type , bool named ATTRIBUTE_UNUSED ) { return ( targetm . calls . must_pass_in_stack ( mode , type ) || CRIS_FUNCTION_ARG_SIZE ( mode , type ) > 8 ) ; } </s>

Return true if TYPE must be passed by invisible reference . For cris , we pass < = 8 bytes by value , others by reference .


<s> static reg_class_t cris_preferred_reload_class ( rtx x ATTRIBUTE_UNUSED , reg_class_t rclass ) { if ( rclass != ACR_REGS && rclass != MOF_REGS && rclass != MOF_SRP_REGS && rclass != SRP_REGS && rclass != CC0_REGS && rclass != SPECIAL_REGS ) return GENERAL_REGS ; return rclass ; } </s>

Worker function for TARGET_PREFERRED_RELOAD_CLASS . It seems like gcc ( 2.7.2 and 2.9x of 2000-03-22 ) may send `` NO_REGS '' as the class for a constant ( testcase : __Mul in arit.c ) . To avoid forcing out a constant into the constant pool , we will trap this case and return something a bit more sane . FIXME : Check if this is a bug . Beware that we must not `` override '' classes that can be specified as constraint letters , or else asm operands using them will fail when they need to be reloaded . FIXME : Investigate whether that constitutes a bug .


<s>
static
void
cris_print_operand_address
(
FILE
*
file
,
rtx
x
)
{
putc
(
'['
,
file
)
;
if
(
CONSTANT_ADDRESS_P
(
x
)
)
cris_output_addr_const
(
file
,
x
)
;
else
if
(
cris_base_or_autoincr_p
(
x
,
true
)
)
cris_print_base
(
x
,
file
)
;
else
if
(
GET_CODE
(
x
)
==
PLUS
)
{
rtx
x1
,
x2
;
x1
=
XEXP
(
x
,
0
)
;
x2
=
XEXP
(
x
,
1
)
;
if
(
cris_base_p
(
x1
,
true
)
)
{
cris_print_base
(
x1
,
file
)
;
cris_print_index
(
x2
,
file
)
;
}
else
if
(
cris_base_p
(
x2
,
true
)
)
{
cris_print_base
(
x2
,
file
)
;
cris_print_index
(
x1
,
file
)
;
}
else
LOSE_AND_RETURN
(
"unrecognized address"
,
x
)
;
}
else
if
(
MEM_P
(
x
)
)
{
putc
(
'['
,
file
)
;
cris_print_base
(
XEXP
(
x
,
0
)
,
file
)
;
putc
(
']'
,
file
)
;
}
else
LOSE_AND_RETURN
(
"unrecognized address"
,
x
)
;
putc
(
']'
,
file
)
;
}
</s>


<s> static int cris_reg_saved_in_regsave_area ( unsigned int regno , bool got_really_used ) { return ( ( ( df_regs_ever_live_p ( regno ) && ! call_used_regs [ regno ] ) || ( regno == PIC_OFFSET_TABLE_REGNUM && ( got_really_used || ( flag_pic && df_regs_ever_live_p ( regno + 1 ) && ! call_used_regs [ regno + 1 ] ) ) ) ) && ( regno != FRAME_POINTER_REGNUM || ! frame_pointer_needed ) && regno != CRIS_SRP_REGNUM ) || ( crtl -> calls_eh_return && ( regno == EH_RETURN_DATA_REGNO ( 0 ) || regno == EH_RETURN_DATA_REGNO ( 1 ) || regno == EH_RETURN_DATA_REGNO ( 2 ) || regno == EH_RETURN_DATA_REGNO ( 3 ) ) ) ; } </s>

Return nonzero if REGNO is an ordinary register that * needs * to be saved together with other registers , possibly by a MOVEM instruction , or is saved for target-independent reasons . There may be target-dependent reasons to save the register anyway ; this is just a wrapper for a complicated conditional .


<s> static bool cris_rtx_costs ( rtx x , int code , int outer_code , int opno , int * total , bool speed ) { switch ( code ) { case CONST_INT : { HOST_WIDE_INT val = INTVAL ( x ) ; if ( val == 0 ) * total = 0 ; else if ( val < 32 && val >= - 32 ) * total = 1 ; else if ( val <= 32767 && val >= - 32768 ) * total = 2 ; else * total = 4 ; return true ; } case LABEL_REF : * total = 6 ; return true ; case CONST : case SYMBOL_REF : * total = 6 ; return true ; case CONST_DOUBLE : if ( x != CONST0_RTX ( GET_MODE ( x ) == VOIDmode ? DImode : GET_MODE ( x ) ) ) * total = 12 ; else * total = 0 ; return true ; case MULT : if ( outer_code == PLUS && cris_biap_index_p ( x , false ) ) { * total = 0 ; return true ; } if ( ! CONST_INT_P ( XEXP ( x , 1 ) ) || exact_log2 ( INTVAL ( XEXP ( x , 1 ) ) < 0 ) ) { if ( TARGET_HAS_MUL_INSNS ) { * total = COSTS_N_INSNS ( 1 ) + COSTS_N_INSNS ( 1 ) / 2 ; return true ; } * total = COSTS_N_INSNS ( 132 ) ; return true ; } return false ; case UDIV : case MOD : case UMOD : case DIV : if ( ! CONST_INT_P ( XEXP ( x , 1 ) ) || exact_log2 ( INTVAL ( XEXP ( x , 1 ) ) < 0 ) ) { * total = COSTS_N_INSNS ( 260 ) ; return true ; } return false ; case AND : if ( CONST_INT_P ( XEXP ( x , 1 ) ) && ! CONST_INT_P ( XEXP ( x , 0 ) ) && ! satisfies_constraint_I ( XEXP ( x , 1 ) ) ) { * total = ( rtx_cost ( XEXP ( x , 0 ) , ( enum rtx_code ) outer_code , opno , speed ) + 2 + 2 * GET_MODE_NUNITS ( GET_MODE ( XEXP ( x , 0 ) ) ) ) ; return true ; } return false ; case ZERO_EXTRACT : if ( outer_code != COMPARE ) return false ; case ZERO_EXTEND : case SIGN_EXTEND : * total = rtx_cost ( XEXP ( x , 0 ) , ( enum rtx_code ) outer_code , opno , speed ) ; return true ; default : return false ; } } </s>


"\n; VA:: ANSI: %d args before, anon @ #%d, %dtime\n"


<s>
static
void
cris_asm_output_mi_thunk
(
FILE
*
stream
,
tree
thunkdecl
ATTRIBUTE_UNUSED
,
HOST_WIDE_INT
delta
,
HOST_WIDE_INT
vcall_offset
ATTRIBUTE_UNUSED
,
tree
funcdecl
)
{
final_start_function
(
emit_barrier
(
)
,
stream
,
1
)
;
if
(
delta
>
0
)
fprintf
(
stream
,
"\tadd%s "
HOST_WIDE_INT_PRINT_DEC
",$%s\n"
,
ADDITIVE_SIZE_MODIFIER
(
delta
)
,
delta
,
reg_names
[
CRIS_FIRST_ARG_REG
]
)
;
else
if
(
delta
<
0
)
fprintf
(
stream
,
"\tsub%s "
HOST_WIDE_INT_PRINT_DEC
",$%s\n"
,
ADDITIVE_SIZE_MODIFIER
(
delta
)
,
delta
,
reg_names
[
CRIS_FIRST_ARG_REG
]
)
;
if
(
flag_pic
)
{
const
char
*
name
=
XSTR
(
XEXP
(
DECL_RTL
(
funcdecl
)
,
0
)
,
0
)
;
name
=
(
*
targetm
.
strip_name_encoding
)
(
name
)
;
if
(
TARGET_V32
)
{
fprintf
(
stream
,
"\tba "
)
;
assemble_name
(
stream
,
name
)
;
fprintf
(
stream
,
"%s\n\tnop\n"
,
CRIS_PLT_PCOFFSET_SUFFIX
)
;
}
else
{
fprintf
(
stream
,
"\tadd.d "
)
;
assemble_name
(
stream
,
name
)
;
fprintf
(
stream
,
"%s,$pc\n"
,
CRIS_PLT_PCOFFSET_SUFFIX
)
;
}
}
else
{
fprintf
(
stream
,
"\tjump "
)
;
assemble_name
(
stream
,
XSTR
(
XEXP
(
DECL_RTL
(
funcdecl
)
,
0
)
,
0
)
)
;
fprintf
(
stream
,
"\n"
)
;
if
(
TARGET_V32
)
fprintf
(
stream
,
"\tnop\n"
)
;
}
final_end_function
(
)
;
}
</s>


<s> static HOST_WIDE_INT cris_constant_alignment ( const_tree , HOST_WIDE_INT basic_align ) { return MAX ( cris_preferred_mininum_alignment ( ) , basic_align ) ; } </s>

Implement TARGET_CONSTANT_ALIGNMENT . Note that this hook has the effect of making gcc believe that ALL references to constant stuff ( in code segment , like strings ) have this alignment . That is a rather rushed assumption . Luckily we do not care about the `` alignment '' operand to builtin memcpy ( only place where it counts ) , so it does n't affect any bad spots .


<s> static HOST_WIDE_INT cris_preferred_mininum_alignment ( void ) { if ( ! TARGET_CONST_ALIGN ) return 8 ; if ( TARGET_ALIGN_BY_32 ) return 32 ; return 16 ; } </s>

Return the preferred minimum alignment for a static object .


<s> static HOST_WIDE_INT cris_static_rtx_alignment ( machine_mode mode ) { return MAX ( cris_preferred_mininum_alignment ( ) , GET_MODE_ALIGNMENT ( mode ) ) ; } </s>


<s> static int cris_address_cost ( rtx x , machine_mode mode ATTRIBUTE_UNUSED , addr_space_t as ATTRIBUTE_UNUSED , bool speed ATTRIBUTE_UNUSED ) { if ( cris_base_or_autoincr_p ( x , false ) ) return 0 ; if ( MEM_P ( x ) ) return ( 2 + 4 ) / 2 ; if ( CONSTANT_P ( x ) ) return ( 2 + 4 ) / 2 ; if ( GET_CODE ( x ) == PLUS ) { rtx tem1 = XEXP ( x , 0 ) ; rtx tem2 = XEXP ( x , 1 ) ; if ( ! REG_P ( tem1 ) && GET_CODE ( tem1 ) != MULT ) tem1 = tem2 , tem2 = XEXP ( x , 0 ) ; gcc_assert ( REG_P ( tem1 ) || GET_CODE ( tem1 ) == MULT ) ; if ( ( GET_CODE ( tem1 ) == MULT && cris_biap_index_p ( tem1 , false ) ) || REG_P ( tem2 ) ) return 2 / 2 ; if ( CONST_INT_P ( tem2 ) && INTVAL ( tem2 ) < 128 && INTVAL ( tem2 ) >= - 128 ) return 2 / 2 ; if ( satisfies_constraint_L ( tem2 ) ) return ( 2 + 2 ) / 2 ; if ( CONSTANT_P ( tem2 ) ) return ( 2 + 2 + 2 ) / 2 ; return ( 2 + 2 + 2 ) / 2 ; } return 10 ; } </s>


<s>
void
cris_asm_output_case_end
(
FILE
*
stream
,
int
num
,
rtx_insn
*
table
)
{
rtx_insn
*
whole_jump_insn
=
prev_nonnote_nondebug_insn
(
table
)
;
gcc_assert
(
whole_jump_insn
!=
NULL_RTX
&&
LABEL_P
(
whole_jump_insn
)
)
;
whole_jump_insn
=
prev_nonnote_nondebug_insn
(
whole_jump_insn
)
;
gcc_assert
(
whole_jump_insn
!=
NULL_RTX
&&
JUMP_P
(
whole_jump_insn
)
)
;
rtx
whole_jump_pat
=
PATTERN
(
whole_jump_insn
)
;
asm_fprintf
(
stream
,
"\t.word %LL%d-%LL%d%s\n"
,
CODE_LABEL_NUMBER
(
XEXP
(
XEXP
(
XEXP
(
XVECEXP
(
whole_jump_pat
,
0
,
0
)
,
1
)
,
2
)
,
0
)
)
,
num
,
(
TARGET_PDEBUG
"; default"
:
""
)
)
;
}
</s>


<s> void cris_asm_output_ident ( const char * string ) { if ( symtab -> state != PARSING ) return ; default_asm_output_ident_directive ( string ) ; } </s>

Queue an .ident string in the queue of top-level asm statements . If the front-end is done , we must be being called from toplev.cc . In that case , do nothing .


<s> void cris_asm_output_label_ref ( FILE * file , char * buf ) { assemble_name ( file , buf ) ; } </s>

Worker function for ASM_OUTPUT_LABEL_REF .


<s>
static
void
cris_asm_output_mi_thunk
(
FILE
*
stream
,
tree
thunkdecl
ATTRIBUTE_UNUSED
,
HOST_WIDE_INT
delta
,
HOST_WIDE_INT
vcall_offset
ATTRIBUTE_UNUSED
,
tree
funcdecl
)
{
const
char
*
fnname
=
IDENTIFIER_POINTER
(
DECL_ASSEMBLER_NAME
(
thunkdecl
)
)
;
assemble_start_function
(
thunkdecl
,
fnname
)
;
final_start_function
(
emit_barrier
(
)
,
stream
,
1
)
;
if
(
delta
>
0
)
fprintf
(
stream
,
"\tadd%s "
HOST_WIDE_INT_PRINT_DEC
",$%s\n"
,
ADDITIVE_SIZE_MODIFIER
(
delta
)
,
delta
,
reg_names
[
CRIS_FIRST_ARG_REG
]
)
;
else
if
(
delta
<
0
)
fprintf
(
stream
,
"\tsub%s "
HOST_WIDE_INT_PRINT_DEC
",$%s\n"
,
ADDITIVE_SIZE_MODIFIER
(
delta
)
,
delta
,
reg_names
[
CRIS_FIRST_ARG_REG
]
)
;
fprintf
(
stream
,
"\tjump "
)
;
assemble_name
(
stream
,
XSTR
(
XEXP
(
DECL_RTL
(
funcdecl
)
,
0
)
,
0
)
)
;
fprintf
(
stream
,
"\n"
)
;
final_end_function
(
)
;
assemble_end_function
(
thunkdecl
,
fnname
)
;
}
</s>


<s> void cris_asm_output_symbol_ref ( FILE * file , rtx x ) { gcc_assert ( GET_CODE ( x ) == SYMBOL_REF ) ; assemble_name ( file , XSTR ( x , 0 ) ) ; } </s>

Worker function for ASM_OUTPUT_SYMBOL_REF .


<s> static unsigned int cris_atomic_align_for_mode ( machine_mode mode ) { return GET_MODE_BITSIZE ( mode ) ; } </s>

Atomic types require alignment to be at least their `` natural '' size .


<s> bool cris_base_or_autoincr_p ( const_rtx x , bool strict ) { return ( cris_base_p ( x , strict ) || ( GET_CODE ( x ) == POST_INC && cris_base_p ( XEXP ( x , 0 ) , strict ) ) ) ; } </s>

True if X is a valid base register with or without autoincrement .


<s> bool cris_base_p ( const_rtx x , bool strict ) { return ( REG_P ( x ) && reg_ok_for_base_p ( x , strict ) ) ; } </s>


<s> bool cris_bdap_index_p ( const_rtx x , bool strict ) { return ( ( MEM_P ( x ) && GET_MODE ( x ) == SImode && cris_base_or_autoincr_p ( XEXP ( x , 0 ) , strict ) ) || ( GET_CODE ( x ) == SIGN_EXTEND && MEM_P ( XEXP ( x , 0 ) ) && ( GET_MODE ( XEXP ( x , 0 ) ) == HImode || GET_MODE ( XEXP ( x , 0 ) ) == QImode ) && cris_base_or_autoincr_p ( XEXP ( XEXP ( x , 0 ) , 0 ) , strict ) ) ) ; } </s>

True if X is a valid ( register ) index for BDAP , i.e . [ Rs ] .S or [ Rs+ ] .S .


<s> bool cris_biap_index_p ( const_rtx x , bool strict ) { return ( cris_index_p ( x , strict ) || ( GET_CODE ( x ) == MULT && cris_index_p ( XEXP ( x , 0 ) , strict ) && cris_scale_int_operand ( XEXP ( x , 1 ) , VOIDmode ) ) ) ; } </s>

True if X is a valid ( register ) index for BIAP , i.e . Rd.m .


<s> static bool cris_cannot_force_const_mem ( machine_mode mode ATTRIBUTE_UNUSED , rtx x ) { enum cris_symbol_type t = cris_symbol_type_of ( x ) ; return t == cris_unspec || t == cris_got_symbol || t == cris_rel_symbol ; } </s>

Worker function for TARGET_CANNOT_FORCE_CONST_MEM . We ca n't put PIC addresses in the constant pool , not even the ones that can be reached as pc-relative as we ca n't tell when or how to do that .


<s> bool cris_cc0_user_requires_cmp ( rtx_insn * insn ) { rtx_insn * cc0_user = NULL ; rtx body ; rtx set ; gcc_assert ( insn != NULL ) ; if ( ! TARGET_V32 ) return false ; cc0_user = next_cc0_user ( insn ) ; if ( cc0_user == NULL ) return false ; body = PATTERN ( cc0_user ) ; set = single_set ( cc0_user ) ; if ( JUMP_P ( cc0_user ) && GET_CODE ( body ) == SET && SET_DEST ( body ) == pc_rtx && GET_CODE ( SET_SRC ( body ) ) == IF_THEN_ELSE && XEXP ( XEXP ( SET_SRC ( body ) , 0 ) , 0 ) == cc0_rtx ) { return GET_CODE ( XEXP ( SET_SRC ( body ) , 0 ) ) == GT || GET_CODE ( XEXP ( SET_SRC ( body ) , 0 ) ) == LE ; } else if ( set ) { return GET_CODE ( SET_SRC ( body ) ) == GT || GET_CODE ( SET_SRC ( body ) ) == LE ; } gcc_unreachable ( ) ; } </s>

Whether next_cc0_user of insn is LE or GT or requires a real compare insn for other reasons .


<s> static machine_mode cris_cc_modes_compatible ( machine_mode m1 , machine_mode m2 ) { if ( m1 == CC_NZVCmode ) { if ( m2 == CC_NZVCmode || m2 == CCmode ) return CC_NZVCmode ; return VOIDmode ; } if ( m2 == CC_NZVCmode ) { if ( m1 == CC_NZVCmode || m1 == CCmode ) return CC_NZVCmode ; return VOIDmode ; } if ( m1 != m2 ) return CC_NZmode ; return m1 ; } </s>

Worker function for TARGET_CC_MODES_COMPATIBLE . We start with CCmode for most comparisons , which merges and yields to CC_NZmode or CC_NZVCmode . The exceptions have CC_NZVCmode and ca n't do with another mode .


<s> int cris_cfun_uses_pic_table ( void ) { return crtl -> uses_pic_offset_table ; } </s>

Return current_function_uses_pic_offset_table . For use in cris.md , since some generated files do not include function.h .


<s> static void cris_conditional_register_usage ( void ) { if ( TARGET_HAS_MUL_INSNS ) fixed_regs [ CRIS_MOF_REGNUM ] = 0 ; if ( cris_cpu_version < 8 ) reg_names [ CRIS_CC0_REGNUM ] = "ccr" ; } </s>


<s> static HOST_WIDE_INT cris_constant_alignment ( const_tree , HOST_WIDE_INT basic_align ) { return MAX ( cris_preferred_minimum_alignment ( ) , basic_align ) ; } </s>


<s> bool cris_constant_index_p ( const_rtx x ) { return ( CRIS_CONSTANT_P ( x ) && ( ! flag_pic || cris_valid_pic_const ( x , true ) ) ) ; } </s>

No symbol can be used as an index ( or more correct , as a base ) together with a register with PIC ; the PIC register must be there .


<s> rtx_insn * cris_emit_insn ( rtx x ) { rtvec vec = rtvec_alloc ( 2 ) ; RTVEC_ELT ( vec , 0 ) = x ; RTVEC_ELT ( vec , 1 ) = gen_rtx_CLOBBER ( VOIDmode , gen_rtx_REG ( CCmode , CRIS_CC0_REGNUM ) ) ; return emit_insn ( gen_rtx_PARALLEL ( VOIDmode , vec ) ) ; } </s>

Convenience function for CRIS-local use of emit_insn , wrapping the argument in a parallel with a clobber of CRIS_CC0_REGNUM before passing on to emit_insn .


<s> void cris_emit_trap_for_misalignment ( rtx mem ) { rtx addr , reg , ok_label , andop ; rtx_insn * jmp ; int natural_alignment ; gcc_assert ( MEM_P ( mem ) ) ; natural_alignment = GET_MODE_SIZE ( GET_MODE ( mem ) ) ; addr = XEXP ( mem , 0 ) ; reg = force_reg ( Pmode , addr ) ; ok_label = gen_label_rtx ( ) ; andop = gen_rtx_AND ( Pmode , reg , GEN_INT ( natural_alignment - 1 ) ) ; emit_cmp_and_jump_insns ( force_reg ( SImode , andop ) , const0_rtx , EQ , NULL_RTX , Pmode , 1 , ok_label ) ; jmp = get_last_insn ( ) ; gcc_assert ( JUMP_P ( jmp ) ) ; predict_insn_def ( jmp , PRED_NORETURN , TAKEN ) ; expand_builtin_trap ( ) ; emit_label ( ok_label ) ; } </s>

Emit checking that MEM is aligned for an access in MODE , failing that , executing a `` break 8 '' ( or call to abort , if `` break 8 '' is disabled ) .


<s>
void
cris_expand_pic_call_address
(
rtx
*
opp
,
rtx
*
markerp
)
{
rtx
op
=
*
opp
;
gcc_assert
(
flag_pic
&&
MEM_P
(
op
)
)
;
op
=
XEXP
(
op
,
0
)
;
if
(
CONSTANT_P
(
op
)
&&
!
CONST_INT_P
(
op
)
)
{
enum
cris_symbol_type
t
=
cris_symbol_type_of
(
op
)
;
CRIS_ASSERT
(
can_create_pseudo_p
(
)
)
;
if
(
t
==
cris_rel_symbol
)
{
if
(
TARGET_V32
)
{
rtx
sym
=
GET_CODE
(
op
)
!=
CONST
op
:
get_related_value
(
op
)
;
HOST_WIDE_INT
offs
=
get_integer_term
(
op
)
;
gcc_assert
(
offs
==
0
)
;
op
=
gen_rtx_CONST
(
Pmode
,
gen_rtx_UNSPEC
(
Pmode
,
gen_rtvec
(
1
,
sym
)
,
CRIS_UNSPEC_PCREL
)
)
;
}
else
op
=
force_reg
(
Pmode
,
op
)
;
*
markerp
=
const0_rtx
;
}
else
if
(
t
==
cris_got_symbol
)
{
if
(
TARGET_AVOID_GOTPLT
)
{
rtx
tem
,
rm
,
ro
;
crtl
->
uses_pic_offset_table
=
1
;
tem
=
gen_rtx_UNSPEC
(
Pmode
,
gen_rtvec
(
1
,
op
)
,
TARGET_V32
CRIS_UNSPEC_PLT_PCREL
:
CRIS_UNSPEC_PLT_GOTREL
)
;
tem
=
gen_rtx_CONST
(
Pmode
,
tem
)
;
if
(
TARGET_V32
)
op
=
tem
;
else
{
rm
=
gen_reg_rtx
(
Pmode
)
;
emit_move_insn
(
rm
,
tem
)
;
ro
=
gen_reg_rtx
(
Pmode
)
;
if
(
expand_binop
(
Pmode
,
add_optab
,
rm
,
pic_offset_table_rtx
,
ro
,
0
,
OPTAB_LIB_WIDEN
)
!=
ro
)
internal_error
(
"expand_binop failed in movsi got"
)
;
op
=
ro
;
}
}
else
{
rtx
tem
,
mem
,
rm
,
ro
;
gcc_assert
(
can_create_pseudo_p
(
)
)
;
crtl
->
uses_pic_offset_table
=
1
;
tem
=
gen_rtx_UNSPEC
(
Pmode
,
gen_rtvec
(
1
,
op
)
,
CRIS_UNSPEC_PLTGOTREAD
)
;
rm
=
gen_reg_rtx
(
Pmode
)
;
emit_move_insn
(
rm
,
gen_rtx_CONST
(
Pmode
,
tem
)
)
;
ro
=
gen_reg_rtx
(
Pmode
)
;
if
(
expand_binop
(
Pmode
,
add_optab
,
rm
,
pic_offset_table_rtx
,
ro
,
0
,
OPTAB_LIB_WIDEN
)
!=
ro
)
internal_error
(
"expand_binop failed in movsi got"
)
;
mem
=
gen_rtx_MEM
(
Pmode
,
ro
)
;
set_mem_alias_set
(
mem
,
new_alias_set
(
)
)
;
MEM_NOTRAP_P
(
mem
)
=
1
;
op
=
mem
;
}
*
markerp
=
pic_offset_table_rtx
;
}
else
fatal_insn
(
"unidentifiable call op"
,
op
)
;
*
opp
=
replace_equiv_address_nv
(
*
opp
,
op
)
;
}
else
*
markerp
=
pic_offset_table_rtx
;
}
</s>

Worker function for expanding the address for PIC function calls .


<s> void cris_expand_return ( bool on_stack ) { emit_jump_insn ( ret_rtx ) ; CRIS_ASSERT ( cfun -> machine -> return_type != CRIS_RETINSN_RET || ! on_stack ) ; CRIS_ASSERT ( cfun -> machine -> return_type != CRIS_RETINSN_JUMP || on_stack ) ; cfun -> machine -> return_type = on_stack ? CRIS_RETINSN_JUMP : CRIS_RETINSN_RET ; } </s>

Expand a return insn ( just one insn ) marked as using SRP or stack slot depending on parameter ON_STACK .


<s> int cris_fatal ( char * arg ) { internal_error ( arg ) ; return 0 ; } </s>


<s> static void cris_file_end ( void ) { if ( TARGET_LINUX && trampolines_created ) file_end_indicate_exec_stack ( ) ; } </s>

Output that goes at the end of the file , similarly .


<s> static void cris_file_start ( void ) { targetm . asm_file_start_app_off = ! ( TARGET_PDEBUG || flag_print_asm_name ) ; default_file_start ( ) ; } </s>

Boilerplate emitted at start of file . NO_APP * only at file start * means faster assembly . It also means comments are not allowed . In some cases comments will be output for debugging purposes . Make sure they are allowed then . We want a .file directive only if TARGET_ELF .


<s> bool cris_frame_pointer_required ( void ) { return ! crtl -> sp_is_unchanging ; } </s>

Implement TARGET_FRAME_POINTER_REQUIRED . Really only needed if the stack frame has variable length ( alloca or variable sized local arguments ( GNU C extension ) . See PR39499 and PR38609 for the reason this is n't just 0 .


<s> static rtx cris_function_arg ( cumulative_args_t ca , const function_arg_info & arg ) { return cris_function_arg_1 ( ca , arg , false ) ; } </s>

Worker function for TARGET_FUNCTION_ARG . The void_type_node is sent as a `` closing '' call .


<s> static void cris_function_arg_advance ( cumulative_args_t ca_v , const function_arg_info & arg ) { CUMULATIVE_ARGS * ca = get_cumulative_args ( ca_v ) ; ca -> regs += ( 3 + CRIS_FUNCTION_ARG_SIZE ( arg . mode , arg . type ) ) / 4 ; } </s>

Worker function for TARGET_FUNCTION_ARG_ADVANCE .


<s> static rtx cris_function_incoming_arg ( cumulative_args_t ca , const function_arg_info & arg ) { return cris_function_arg_1 ( ca , arg , true ) ; } </s>

Worker function for TARGET_FUNCTION_INCOMING_ARG . The differences between this and the previous , is that this one checks that an argument is named , since incoming stdarg/varargs arguments are pushed onto the stack , and we do n't have to check against the `` closing '' void_type_node TYPE parameter .


<s> static rtx cris_function_value ( const_tree type , const_tree func ATTRIBUTE_UNUSED , bool outgoing ATTRIBUTE_UNUSED ) { return gen_rtx_REG ( TYPE_MODE ( type ) , CRIS_FIRST_ARG_REG ) ; } </s>

Let 's assume all functions return in r [ CRIS_FIRST_ARG_REG ] for the time being .


<s> static bool cris_function_value_regno_p ( const unsigned int regno ) { return ( regno == CRIS_FIRST_ARG_REG ) ; } </s>


<s> rtx cris_gen_movem_load ( rtx src , rtx nregs_rtx ) { int nregs = INTVAL ( nregs_rtx ) ; rtvec vec ; int eltno = 1 ; int i ; rtx srcreg = XEXP ( src , 0 ) ; unsigned int regno = nregs - 1 ; int regno_inc = - 1 ; if ( GET_CODE ( srcreg ) == POST_INC ) srcreg = XEXP ( srcreg , 0 ) ; CRIS_ASSERT ( REG_P ( srcreg ) ) ; if ( nregs == 1 ) return gen_movsi ( gen_rtx_REG ( SImode , 0 ) , src ) ; vec = rtvec_alloc ( nregs + ( GET_CODE ( XEXP ( src , 0 ) ) == POST_INC ) ) ; if ( GET_CODE ( XEXP ( src , 0 ) ) == POST_INC ) { RTVEC_ELT ( vec , 1 ) = gen_rtx_SET ( srcreg , plus_constant ( Pmode , srcreg , nregs * 4 ) ) ; eltno ++ ; } src = replace_equiv_address ( src , srcreg ) ; RTVEC_ELT ( vec , 0 ) = gen_rtx_SET ( gen_rtx_REG ( SImode , regno ) , src ) ; regno += regno_inc ; for ( i = 1 ; i < nregs ; i ++ , eltno ++ ) { RTVEC_ELT ( vec , eltno ) = gen_rtx_SET ( gen_rtx_REG ( SImode , regno ) , adjust_address_nv ( src , SImode , i * 4 ) ) ; regno += regno_inc ; } return gen_rtx_PARALLEL ( VOIDmode , vec ) ; } </s>

Worker function for generating movem from mem for load_multiple .


<s> static bool cris_hard_regno_mode_ok ( unsigned int regno , machine_mode mode ) { return ( ( mode == CCmode || regno != CRIS_CC0_REGNUM ) && ( GET_MODE_SIZE ( mode ) <= UNITS_PER_WORD || regno != CRIS_MOF_REGNUM ) ) ; } </s>

Implement TARGET_HARD_REGNO_MODE_OK . CRIS permits all registers to hold all modes . Well , except for the condition-code register . And we ca n't hold larger-than-register size modes in the last special register that can hold a full 32 bits .


<s> static unsigned int cris_hard_regno_nregs ( unsigned int , machine_mode mode ) { if ( mode == VOIDmode ) return 1 ; return CEIL ( GET_MODE_SIZE ( mode ) , UNITS_PER_WORD ) ; } </s>

Implement TARGET_HARD_REGNO_NREGS . The VOIDmode test is so we can omit mode on anonymous insns . FIXME : Still needed in 2.9x , at least for Axis-20000319 .


<s> static inline bool cris_index_p ( const_rtx x , bool strict ) { return ( REG_P ( x ) && reg_ok_for_index_p ( x , strict ) ) ; } </s>


<s> int cris_initial_elimination_offset ( int fromreg , int toreg ) { int fp_sp_offset = cris_initial_frame_pointer_offset ( ) ; bool return_address_on_stack = cris_return_address_on_stack ( ) ; int ap_fp_offset = 4 + ( return_address_on_stack ? 4 : 0 ) ; if ( fromreg == ARG_POINTER_REGNUM && toreg == HARD_FRAME_POINTER_REGNUM ) return ap_fp_offset ; if ( fromreg == FRAME_POINTER_REGNUM && toreg == STACK_POINTER_REGNUM ) return fp_sp_offset ; if ( fromreg == ARG_POINTER_REGNUM && toreg == STACK_POINTER_REGNUM ) return ap_fp_offset + fp_sp_offset - 4 ; if ( fromreg == FRAME_POINTER_REGNUM && toreg == HARD_FRAME_POINTER_REGNUM ) return 0 ; gcc_unreachable ( ) ; } </s>

The INITIAL_ELIMINATION_OFFSET worker . Calculate the difference between imaginary registers such as frame pointer and the stack pointer . Used to eliminate the frame pointer and imaginary arg pointer .


<s> static int cris_initial_frame_pointer_offset ( void ) { int regno ; int offs = 0 ; for ( regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno ++ ) if ( cris_reg_saved_in_regsave_area ( regno ) ) offs += 4 ; offs += get_frame_size ( ) ; offs += crtl -> outgoing_args_size ; if ( TARGET_STACK_ALIGN ) offs = TARGET_ALIGN_BY_32 ? ( offs + 3 ) & ~ 3 : ( offs + 1 ) & ~ 1 ; return offs ; } </s>

This used to be the INITIAL_FRAME_POINTER_OFFSET worker ; now only handles FP - > SP elimination offset .


<s> void cris_init_expanders ( void ) { } </s>

The INIT_EXPANDERS worker sets the per-function-data initializer and mark functions .


<s> static void cris_init_libfuncs ( void ) { set_optab_libfunc ( smul_optab , SImode , "__Mul" ) ; set_optab_libfunc ( sdiv_optab , SImode , "__Div" ) ; set_optab_libfunc ( udiv_optab , SImode , "__Udiv" ) ; set_optab_libfunc ( smod_optab , SImode , "__Mod" ) ; set_optab_libfunc ( umod_optab , SImode , "__Umod" ) ; if ( TARGET_ATOMICS_MAY_CALL_LIBFUNCS ) { set_optab_libfunc ( sync_compare_and_swap_optab , SImode , "__cris_atcmpxchgr32" ) ; set_optab_libfunc ( sync_compare_and_swap_optab , HImode , "__cris_atcmpxchgr16" ) ; } } </s>

Rename the function calls for integer multiply and divide .


<s> static struct machine_function * cris_init_machine_status ( void ) { return ggc_cleared_alloc < machine_function > ( ) ; } </s>

Zero initialization is OK for all current fields .


<s> bool cris_legitimate_address_p ( machine_mode mode , rtx x , bool strict ) { const_rtx x1 , x2 ; if ( cris_base_or_autoincr_p ( x , strict ) ) return true ; else if ( CONSTANT_P ( x ) ) return true ; else if ( GET_CODE ( x ) == PLUS ) { x1 = XEXP ( x , 0 ) ; x2 = XEXP ( x , 1 ) ; if ( ( cris_base_p ( x1 , strict ) && CONSTANT_P ( x2 ) ) || ( cris_base_p ( x2 , strict ) && CONSTANT_P ( x1 ) ) || ( GET_MODE_SIZE ( mode ) <= UNITS_PER_WORD && ( ( cris_base_p ( x1 , strict ) && cris_bdap_index_p ( x2 , strict ) ) || ( cris_base_p ( x2 , strict ) && cris_bdap_index_p ( x1 , strict ) ) || ( cris_base_p ( x1 , strict ) && cris_biap_index_p ( x2 , strict ) ) || ( cris_base_p ( x2 , strict ) && cris_biap_index_p ( x1 , strict ) ) ) ) ) return true ; } else if ( MEM_P ( x ) ) { if ( GET_MODE_SIZE ( mode ) <= UNITS_PER_WORD && cris_base_or_autoincr_p ( XEXP ( x , 0 ) , strict ) ) return true ; } return false ; } </s>

Worker function for TARGET_LEGITIMATE_ADDRESS_P .


<s> bool cris_legitimate_constant_p ( machine_mode mode ATTRIBUTE_UNUSED , rtx x ) { enum cris_symbol_type t ; if ( flag_pic ) return LEGITIMATE_PIC_OPERAND_P ( x ) ; t = cris_symbol_type_of ( x ) ; return t == cris_no_symbol || t == cris_offsettable_symbol || t == cris_unspec ; } </s>

Worker function for TARGET_LEGITIMATE_CONSTANT_P . We have to handle PIC constants that are n't legitimized . FIXME : there used to be a guarantee that the target LEGITIMATE_CONSTANT_P did n't have to handle PIC constants , but no more ( 4.7 era ) ; testcase : glibc init-first.c . While that may be seen as a bug , that guarantee seems a wart by design , so do n't bother ; fix the documentation instead .


<s> int cris_legitimate_pic_operand ( rtx x ) { return cris_valid_pic_const ( x , true ) ; } </s>


<s> static rtx cris_libcall_value ( machine_mode mode , const_rtx fun ATTRIBUTE_UNUSED ) { return gen_rtx_REG ( mode , CRIS_FIRST_ARG_REG ) ; } </s>


<s> static rtx_insn * cris_md_asm_adjust ( vec < rtx > & outputs , vec < rtx > & inputs , vec < machine_mode > & , vec < const char * > & constraints , vec < rtx > & clobbers , HARD_REG_SET & clobbered_regs , location_t ) { clobbers . safe_push ( gen_rtx_REG ( CCmode , CRIS_CC0_REGNUM ) ) ; SET_HARD_REG_BIT ( clobbered_regs , CRIS_CC0_REGNUM ) ; for ( unsigned i = 0 , n = constraints . length ( ) ; i < n ; ++ i ) if ( strchr ( constraints [ i ] , 'h' ) != NULL ) return NULL ; rtx mof_reg = gen_rtx_REG ( SImode , CRIS_MOF_REGNUM ) ; for ( unsigned i = 0 , n = outputs . length ( ) ; i < n ; ++ i ) if ( reg_overlap_mentioned_p ( mof_reg , outputs [ i ] ) ) return NULL ; for ( unsigned i = 0 , n = inputs . length ( ) ; i < n ; ++ i ) if ( reg_overlap_mentioned_p ( mof_reg , inputs [ i ] ) ) return NULL ; clobbers . safe_push ( mof_reg ) ; SET_HARD_REG_BIT ( clobbered_regs , CRIS_MOF_REGNUM ) ; return NULL ; } </s>

Worker function for TARGET_MD_ASM_ADJUST .


<s> static int cris_memory_move_cost ( machine_mode mode , reg_class_t rclass ATTRIBUTE_UNUSED , bool in ATTRIBUTE_UNUSED ) { if ( mode == QImode || mode == HImode ) return 4 ; else return 6 ; } </s>

Worker function for TARGET_MEMORY_MOVE_COST . This is n't strictly correct for v0 .. 3 in buswidth-8bit mode , but should suffice .


<s>
void
cris_notice_update_cc
(
rtx
exp
,
rtx_insn
*
insn
)
{
enum
attr_cc
attrval
=
get_attr_cc
(
insn
)
;
if
(
TARGET_CCINIT
)
{
CC_STATUS_INIT
;
if
(
attrval
==
CC_REV
)
cc_status
.
flags
=
CC_REVERSED
;
return
;
}
switch
(
attrval
)
{
case
CC_NONE
:
if
(
GET_CODE
(
exp
)
==
SET
)
{
if
(
cc_status
.
value1
&&
modified_in_p
(
cc_status
.
value1
,
insn
)
)
cc_status
.
value1
=
0
;
if
(
cc_status
.
value2
&&
modified_in_p
(
cc_status
.
value2
,
insn
)
)
cc_status
.
value2
=
0
;
}
return
;
case
CC_CLOBBER
:
CC_STATUS_INIT
;
return
;
case
CC_REV
:
case
CC_NOOV32
:
case
CC_NORMAL
:
cris_normal_notice_update_cc
(
exp
,
insn
)
;
if
(
attrval
==
CC_NOOV32
&&
TARGET_V32
)
cc_status
.
flags
|=
CC_NO_OVERFLOW
;
return
;
default
:
internal_error
(
"unknown cc_attr value"
)
;
}
CC_STATUS_INIT
;
}
</s>

This function looks into the pattern to see how this insn affects condition codes . Used when to eliminate test insns before a condition-code user , such as a `` scc '' insn or a conditional branch . This includes checking if the entities that cc was updated by , are changed by the operation . Currently a jumble of the old peek-inside-the-insn and the newer check-cc-attribute methods .


<s> static void cris_operand_lossage ( const char * msgid , rtx op ) { debug_rtx ( op ) ; output_operand_lossage ( "%s" , msgid ) ; } </s>

Emit an error message when we 're in an asm , and a fatal error for `` normal '' insns . Formatted output is n't easily implemented , since we use output_operand_lossage to output the actual message and handle the categorization of the error .


"%<-max-stackframe=%d%> is not usable, "

"unknown CRIS version specification in %<-march=%> or "

"unknown CRIS cpu version specification in %<-mtune=%>: %s"

"%<-fPIC%> and %<-fpic%> are not supported on this target"

The TARGET_OPTION_OVERRIDE worker . As is the norm , this also parses -mfoo=bar type parameters .


<s>
const
char
*
cris_op_str
(
rtx
x
)
{
cris_output_insn_is_bound
=
0
;
switch
(
GET_CODE
(
x
)
)
{
case
PLUS
:
return
"add"
;
case
MINUS
:
return
"sub"
;
case
MULT
:
internal_error
(
"MULT case in %<cris_op_str%>"
)
;
break
;
case
DIV
:
return
"div"
;
case
AND
:
return
"and"
;
case
IOR
:
return
"or"
;
case
XOR
:
return
"xor"
;
case
NOT
:
return
"not"
;
case
ASHIFT
:
return
"lsl"
;
case
LSHIFTRT
:
return
"lsr"
;
case
ASHIFTRT
:
return
"asr"
;
case
UMIN
:
cris_output_insn_is_bound
=
1
;
return
"bound"
;
default
:
return
"Unknown operator"
;
}
}
</s>

Given an rtx , return the text string corresponding to the CODE of X . Intended for use in the assembly language output section of a define_insn .

cris
0
"add"
"sub"
"MULT case in %<cris_op_str%>"
"div"
"and"
"or"
"xor"
"not"
"lsl"
"lsr"
"asr"
1
"bound"
"Unknown operator"


<s> void cris_order_for_addsi3 ( rtx * operands , int n ) { if ( ! REG_P ( operands [ n ] ) ) { rtx tem = operands [ n ] ; operands [ n ] = operands [ n + 1 ] ; operands [ n + 1 ] = tem ; } } </s>

Make sure operands are in the right order for an addsi3 insn as generated by a define_split . A MEM as the first operand is n't recognized by addsi3 after reload . OPERANDS contains the operands , with the first at OPERANDS [ N ] and the second at OPERANDS [ N+1 ] .


<s> static void cris_output_addr_const ( FILE * file , rtx x ) { in_code ++ ; output_addr_const ( file , x ) ; in_code -- ; } </s>

Use from within code , from e.g . PRINT_OPERAND and PRINT_OPERAND_ADDRESS . Macros used in output_addr_const need to emit different things depending on whether code operand or constant is emitted .


<s> static bool cris_output_addr_const_extra ( FILE * file , rtx xconst ) { switch ( GET_CODE ( xconst ) ) { rtx x ; case UNSPEC : x = XVECEXP ( xconst , 0 , 0 ) ; CRIS_ASSERT ( GET_CODE ( x ) == SYMBOL_REF || GET_CODE ( x ) == LABEL_REF || GET_CODE ( x ) == CONST ) ; output_addr_const ( file , x ) ; switch ( XINT ( xconst , 1 ) ) { case CRIS_UNSPEC_PCREL : gcc_assert ( TARGET_V32 && flag_pic ) ; break ; case CRIS_UNSPEC_PLT_PCREL : gcc_assert ( TARGET_V32 ) ; fprintf ( file , ":PLT" ) ; break ; case CRIS_UNSPEC_PLT_GOTREL : gcc_assert ( ! TARGET_V32 ) ; fprintf ( file , ":PLTG" ) ; break ; case CRIS_UNSPEC_GOTREL : gcc_assert ( ! TARGET_V32 ) ; fprintf ( file , ":GOTOFF" ) ; break ; case CRIS_UNSPEC_GOTREAD : if ( flag_pic == 1 ) fprintf ( file , ":GOT16" ) ; else fprintf ( file , ":GOT" ) ; break ; case CRIS_UNSPEC_PLTGOTREAD : if ( flag_pic == 1 ) fprintf ( file , CRIS_GOTPLT_SUFFIX "16" ) ; else fprintf ( file , CRIS_GOTPLT_SUFFIX ) ; break ; default : gcc_unreachable ( ) ; } return true ; default : return false ; } } </s>

Worker function for OUTPUT_ADDR_CONST_EXTRA .


<s> static bool cris_pass_by_reference ( cumulative_args_t , const function_arg_info & arg ) { return ( targetm . calls . must_pass_in_stack ( arg ) || CRIS_FUNCTION_ARG_SIZE ( arg . mode , arg . type ) > 8 ) ; } </s>

Return true if TYPE must be passed by invisible reference . For cris , we pass < = 8 bytes by value , others by reference .


<s> static unsigned int cris_postdbr_cmpelim ( ) { rtx_insn * insn ; rtx_insn * next ; rtx_insn * prev_cc_setter = 0 ; rtx_insn * prev_cc_outer = 0 ; rtx dccr = gen_rtx_REG ( CCmode , CRIS_CC0_REGNUM ) ; for ( insn = get_insns ( ) ; insn ; insn = next ) { rtx_insn * outer_insn = insn ; rtx pat = PATTERN ( insn ) ; next = NEXT_INSN ( outer_insn ) ; if ( LABEL_P ( insn ) ) { prev_cc_setter = 0 ; continue ; } if ( ! NONDEBUG_INSN_P ( insn ) ) continue ; if ( GET_CODE ( pat ) == SEQUENCE ) insn = as_a < rtx_insn * > ( XVECEXP ( pat , 0 , 1 ) ) ; else if ( prev_cc_setter != 0 && GET_CODE ( pat ) == SET ) { rtx dest = SET_DEST ( pat ) ; rtx src = SET_SRC ( pat ) ; rtx prev_set ; if ( REG_P ( dest ) && REGNO ( dest ) == CRIS_CC0_REGNUM && GET_CODE ( src ) == COMPARE && REG_P ( XEXP ( src , 0 ) ) && XEXP ( src , 1 ) == const0_rtx && ( prev_set = single_set ( prev_cc_setter ) ) != 0 ) { rtx reg = XEXP ( src , 0 ) ; rtx prev_dest = SET_DEST ( prev_set ) ; rtx prev_src = SET_SRC ( prev_set ) ; bool src_same = rtx_equal_p ( prev_src , reg ) ; if ( REG_P ( prev_dest ) && ! reg_set_p ( reg , prev_src ) && ! reg_set_between_p ( reg , prev_cc_outer , outer_insn ) && ( src_same || rtx_equal_p ( prev_dest , reg ) ) ) { machine_mode ccmode = GET_MODE ( src ) ; rtx modeadjusted_dccr = ( ccmode == CCmode ? dccr : gen_rtx_REG ( CCmode , CRIS_CC0_REGNUM ) ) ; rtx compare = ( src_same ? pat : gen_rtx_SET ( modeadjusted_dccr , gen_rtx_COMPARE ( ccmode , copy_rtx ( prev_src ) , const0_rtx ) ) ) ; validate_change ( prev_cc_setter , & XVECEXP ( PATTERN ( prev_cc_setter ) , 0 , 0 ) , compare , true ) ; validate_change ( prev_cc_setter , & XVECEXP ( PATTERN ( prev_cc_setter ) , 0 , 1 ) , prev_set , true ) ; if ( apply_change_group ( ) ) { delete_insn ( insn ) ; prev_cc_setter = 0 ; continue ; } } } } if ( reg_set_p ( dccr , insn ) ) { rtx pat = PATTERN ( insn ) ; prev_cc_setter = 0 ; if ( GET_CODE ( pat ) == PARALLEL && XVECLEN ( pat , 0 ) == 2 && GET_CODE ( XVECEXP ( pat , 0 , 1 ) ) == CLOBBER ) { prev_cc_setter = insn ; prev_cc_outer = outer_insn ; } } } return 0 ; } </s>

`` Cheap version '' of cmpelim , making use of the opportunities opened up by reorg . Go through the insns of a function and look at each actual compare insn ; considering only those that compare a register to 0 . If the previous CC-affecting insn sets the compared register or if a move reads from it , try to change that into a CC-setting move and try to have it recognized . Bail at labels or non-matching insns that clobber the compared register . If successful , delete the compare . Also , reorg is n't up to date regarding data-flow handling , so we ca n't go beyond classic RTL scanning .


<s> static HOST_WIDE_INT cris_preferred_minimum_alignment ( void ) { if ( ! TARGET_CONST_ALIGN ) return 8 ; if ( TARGET_ALIGN_BY_32 ) return 32 ; return 16 ; } </s>

Return the preferred minimum alignment for a static object .


<s> static reg_class_t cris_preferred_reload_class ( rtx x , reg_class_t rclass ) { if ( rclass != MOF_REGS && rclass != MOF_SRP_REGS && rclass != SRP_REGS && rclass != CC0_REGS && rclass != SPECIAL_REGS ) return GENERAL_REGS ; if ( GET_CODE ( x ) == PLUS && ! reg_class_subset_p ( rclass , GENERAL_REGS ) ) return NO_REGS ; if ( satisfies_constraint_P ( x ) && ! reg_class_subset_p ( rclass , GENERAL_REGS ) ) return NO_REGS ; return rclass ; } </s>

Worker function for TARGET_PREFERRED_RELOAD_CLASS . It seems like gcc ( 2.7.2 and 2.9x of 2000-03-22 ) may send `` NO_REGS '' as the class for a constant ( testcase : __Mul in arit.c ) . To avoid forcing out a constant into the constant pool , we will trap this case and return something a bit more sane . FIXME : Check if this is a bug . Beware that we must not `` override '' classes that can be specified as constraint letters , or else asm operands using them will fail when they need to be reloaded . FIXME : Investigate whether that constitutes a bug .


"unexpected base-type in cris_print_base"

Print a base rtx of an address to file .


"unexpected index-type in cris_print_index"

Print an index part of an address to file .


<s>
static
void
cris_print_operand_address
(
FILE
*
file
,
machine_mode
,
rtx
x
)
{
putc
(
'['
,
file
)
;
if
(
CONSTANT_ADDRESS_P
(
x
)
)
cris_output_addr_const
(
file
,
x
)
;
else
if
(
cris_base_or_autoincr_p
(
x
,
true
)
)
cris_print_base
(
x
,
file
)
;
else
if
(
GET_CODE
(
x
)
==
PLUS
)
{
rtx
x1
,
x2
;
x1
=
XEXP
(
x
,
0
)
;
x2
=
XEXP
(
x
,
1
)
;
if
(
cris_base_p
(
x1
,
true
)
)
{
cris_print_base
(
x1
,
file
)
;
cris_print_index
(
x2
,
file
)
;
}
else
if
(
cris_base_p
(
x2
,
true
)
)
{
cris_print_base
(
x2
,
file
)
;
cris_print_index
(
x1
,
file
)
;
}
else
LOSE_AND_RETURN
(
"unrecognized address"
,
x
)
;
}
else
if
(
MEM_P
(
x
)
)
{
putc
(
'['
,
file
)
;
cris_print_base
(
XEXP
(
x
,
0
)
,
file
)
;
putc
(
']'
,
file
)
;
}
else
LOSE_AND_RETURN
(
"unrecognized address"
,
x
)
;
putc
(
']'
,
file
)
;
}
</s>


<s> machine_mode cris_promote_function_mode ( const_tree type ATTRIBUTE_UNUSED , machine_mode mode , int * punsignedp ATTRIBUTE_UNUSED , const_tree fntype ATTRIBUTE_UNUSED , int for_return ) { if ( for_return == 1 ) return mode ; return CRIS_PROMOTED_MODE ( mode , * punsignedp , type ) ; } </s>

A combination of defining TARGET_PROMOTE_FUNCTION_MODE , promoting arguments and * not * defining TARGET_PROMOTE_PROTOTYPES or PROMOTE_MODE gives the best code size and speed for gcc , ipps and products in gcc-2.7.2 .


<s> void cris_reduce_compare ( rtx * relp , rtx * , rtx * op1p ) { rtx op1 = * op1p ; rtx_code code = GET_CODE ( * relp ) ; switch ( code ) { case LT : if ( op1 == const1_rtx ) code = LE ; break ; case LE : if ( op1 == constm1_rtx ) code = LT ; break ; case GE : if ( op1 == const1_rtx ) code = GT ; break ; case GT : if ( op1 == constm1_rtx ) code = GE ; break ; case GEU : if ( op1 == const1_rtx ) code = NE ; break ; case LTU : if ( op1 == const1_rtx ) code = EQ ; break ; case GTU : if ( op1 == const0_rtx ) code = NE ; break ; case LEU : if ( op1 == const0_rtx ) code = EQ ; break ; default : break ; } if ( code != GET_CODE ( * relp ) ) { * op1p = const0_rtx ; PUT_CODE ( * relp , code ) ; } } </s>

Try to change a comparison against a constant to be against zero , and an unsigned compare against zero to be an equality test . Beware : only valid for compares of integer-type operands . Also , note that we do n't use operand 0 at the moment .


<s> static int cris_register_move_cost ( machine_mode mode ATTRIBUTE_UNUSED , reg_class_t from , reg_class_t to ) { if ( reg_classes_intersect_p ( from , SPECIAL_REGS ) && reg_classes_intersect_p ( to , SPECIAL_REGS ) ) return 7 ; if ( reg_classes_intersect_p ( from , SPECIAL_REGS ) || reg_classes_intersect_p ( to , SPECIAL_REGS ) ) return 3 ; return 2 ; } </s>

Worker function for TARGET_REGISTER_MOVE_COST .


<s> static int cris_reg_overlap_mentioned_p ( rtx x , rtx in ) { if ( GET_CODE ( in ) == STRICT_LOW_PART ) in = XEXP ( in , 0 ) ; return reg_overlap_mentioned_p ( x , in ) ; } </s>

The function reg_overlap_mentioned_p in CVS ( still as of 2001-05-16 ) does not handle the case where the IN operand is strict_low_part ; it does handle it for X. Test-case in Axis-20010516 . This function takes care of that for THIS port . FIXME : strict_low_part is going away anyway .


<s> static int cris_reg_saved_in_regsave_area ( unsigned int regno ) { return ( ( ( df_regs_ever_live_p ( regno ) && ! call_used_or_fixed_reg_p ( regno ) ) ) && ( regno != HARD_FRAME_POINTER_REGNUM || ! frame_pointer_needed ) && regno != CRIS_SRP_REGNUM ) || ( crtl -> calls_eh_return && ( regno == EH_RETURN_DATA_REGNO ( 0 ) || regno == EH_RETURN_DATA_REGNO ( 1 ) || regno == EH_RETURN_DATA_REGNO ( 2 ) || regno == EH_RETURN_DATA_REGNO ( 3 ) ) ) ; } </s>

Return nonzero if REGNO is an ordinary register that * needs * to be saved together with other registers , possibly by a MOVEM instruction , or is saved for target-independent reasons . There may be target-dependent reasons to save the register anyway ; this is just a wrapper for a complicated conditional .


<s> bool cris_reload_address_legitimized ( rtx x , machine_mode mode ATTRIBUTE_UNUSED , int opnum ATTRIBUTE_UNUSED , int itype , int ind_levels ATTRIBUTE_UNUSED ) { enum reload_type type = ( enum reload_type ) itype ; rtx op0 , op1 ; rtx * op1p ; if ( GET_CODE ( x ) != PLUS ) return false ; op0 = XEXP ( x , 0 ) ; op1 = XEXP ( x , 1 ) ; op1p = & XEXP ( x , 1 ) ; if ( ! REG_P ( op1 ) ) return false ; if ( GET_CODE ( op0 ) == SIGN_EXTEND && MEM_P ( XEXP ( op0 , 0 ) ) ) { rtx op00 = XEXP ( op0 , 0 ) ; rtx op000 = XEXP ( op00 , 0 ) ; rtx * op000p = & XEXP ( op00 , 0 ) ; if ( ( GET_MODE ( op00 ) == HImode || GET_MODE ( op00 ) == QImode ) && ( REG_P ( op000 ) || ( GET_CODE ( op000 ) == POST_INC && REG_P ( XEXP ( op000 , 0 ) ) ) ) ) { bool something_reloaded = false ; if ( GET_CODE ( op000 ) == POST_INC && REG_P ( XEXP ( op000 , 0 ) ) && REGNO ( XEXP ( op000 , 0 ) ) > CRIS_LAST_GENERAL_REGISTER ) return false ; if ( ( REG_P ( op000 ) && REGNO ( op000 ) > CRIS_LAST_GENERAL_REGISTER ) ) { push_reload ( op000 , NULL_RTX , op000p , NULL , GENERAL_REGS , GET_MODE ( x ) , VOIDmode , 0 , 0 , opnum , type ) ; something_reloaded = true ; } if ( REGNO ( op1 ) > CRIS_LAST_GENERAL_REGISTER ) { push_reload ( op1 , NULL_RTX , op1p , NULL , GENERAL_REGS , GET_MODE ( x ) , VOIDmode , 0 , 0 , opnum , type ) ; something_reloaded = true ; } gcc_assert ( something_reloaded ) ; return true ; } } return false ; } </s>

Worker function for LEGITIMIZE_RELOAD_ADDRESS .


<s> bool cris_return_address_on_stack ( void ) { return df_regs_ever_live_p ( CRIS_SRP_REGNUM ) || cfun -> machine -> needs_return_address_on_stack ; } </s>

Accessor used in cris.md : return because cfun- > machine is n't available there .


<s> bool cris_return_address_on_stack_for_return ( void ) { return cfun -> machine -> return_type == CRIS_RETINSN_RET ? false : cris_return_address_on_stack ( ) ; } </s>


<s> rtx cris_return_addr_rtx ( int count , rtx frameaddr ATTRIBUTE_UNUSED ) { cfun -> machine -> needs_return_address_on_stack = 1 ; return count == 0 ? gen_rtx_MEM ( Pmode , plus_constant ( Pmode , virtual_incoming_args_rtx , - 4 ) ) : NULL_RTX ; } </s>

The RETURN_ADDR_RTX worker . We mark that the return address is used , either by EH or __builtin_return_address , for use by the function prologue and epilogue . FIXME : This is n't optimal ; we just use the mark in the prologue and epilogue to say that the return address is to be stored in the stack frame . We could return SRP for leaf-functions and use the initial-value machinery .


<s> static bool cris_rtx_costs ( rtx x , machine_mode mode , int outer_code , int opno , int * total , bool speed ) { int code = GET_CODE ( x ) ; switch ( code ) { case CONST_INT : { HOST_WIDE_INT val = INTVAL ( x ) ; if ( val == 0 ) * total = 0 ; else if ( val < 32 && val >= - 32 ) * total = 1 ; else if ( val <= 32767 && val >= - 32768 ) * total = 2 ; else * total = 4 ; return true ; } case LABEL_REF : * total = 6 ; return true ; case CONST : case SYMBOL_REF : * total = 6 ; return true ; case CONST_DOUBLE : if ( x != CONST0_RTX ( mode == VOIDmode ? DImode : mode ) ) * total = 12 ; else * total = 0 ; return true ; case MULT : if ( outer_code == PLUS && cris_biap_index_p ( x , false ) ) { * total = 0 ; return true ; } if ( ! CONST_INT_P ( XEXP ( x , 1 ) ) || exact_log2 ( INTVAL ( XEXP ( x , 1 ) ) < 0 ) ) { if ( TARGET_HAS_MUL_INSNS ) { * total = COSTS_N_INSNS ( 1 ) + COSTS_N_INSNS ( 1 ) / 2 ; return true ; } * total = COSTS_N_INSNS ( 132 ) ; return true ; } return false ; case UDIV : case MOD : case UMOD : case DIV : if ( ! CONST_INT_P ( XEXP ( x , 1 ) ) || exact_log2 ( INTVAL ( XEXP ( x , 1 ) ) < 0 ) ) { * total = COSTS_N_INSNS ( 260 ) ; return true ; } return false ; case AND : if ( CONST_INT_P ( XEXP ( x , 1 ) ) && ! CONST_INT_P ( XEXP ( x , 0 ) ) && ! satisfies_constraint_I ( XEXP ( x , 1 ) ) ) { * total = ( rtx_cost ( XEXP ( x , 0 ) , mode , ( enum rtx_code ) outer_code , opno , speed ) + 2 + 2 * GET_MODE_NUNITS ( mode ) ) ; return true ; } return false ; case ZERO_EXTRACT : if ( reload_completed ) { if ( outer_code != COMPARE ) return false ; } else switch ( outer_code ) { case EQ : case NE : case LT : case LTU : case LE : case LEU : case GT : case GTU : case GE : case GEU : break ; default : return false ; } case ZERO_EXTEND : case SIGN_EXTEND : * total = rtx_cost ( XEXP ( x , 0 ) , VOIDmode , ( enum rtx_code ) outer_code , opno , speed ) ; return true ; default : return false ; } } </s>

Compute a ( partial ) cost for rtx X . Return true if the complete cost has been computed , and false if subexpressions should be scanned . In either case , * TOTAL contains the cost result .


<s> machine_mode cris_select_cc_mode ( enum rtx_code op , rtx x , rtx y ) { gcc_assert ( reload_completed ) ; if ( GET_MODE_CLASS ( GET_MODE ( x ) ) != MODE_INT || y != const0_rtx ) return CCmode ; if ( op == EQ || op == NE || op == GTU || op == LEU || op == LT || op == GE ) return CC_NZmode ; gcc_assert ( op == GEU || op == LTU || op == GT || op == LE ) ; return CC_NZVCmode ; } </s>


"\n; VA:: ANSI: %d args before, anon @ #%d, %dtime\n"

Worker function for TARGET_SETUP_INCOMING_VARARGS .


"internal error: %<cris_side_effect_mode_ok%> with bad operands"

Check various objections to the side-effect . Used in the test-part of an anonymous insn describing an insn with a possible side-effect . Returns nonzero if the implied side-effect is ok. code : PLUS or MULT ops : An array of rtx : es . lreg , rreg , rval , The variables multop and other_op are indexes into this , or -1 if they are not applicable . lreg : The register that gets assigned in the side-effect . rreg : One register in the side-effect expression rval : The other register , or an int . multop : An integer to multiply rval with . other_op : One of the entities of the main effect , whose mode we must consider .


<s> bool cris_simple_epilogue ( void ) { unsigned int regno ; unsigned int reglimit = STACK_POINTER_REGNUM ; if ( ! reload_completed || frame_pointer_needed || get_frame_size ( ) != 0 || crtl -> args . pretend_args_size || crtl -> args . size || crtl -> outgoing_args_size || crtl -> calls_eh_return || ! TARGET_PROLOGUE_EPILOGUE ) return false ; for ( regno = 0 ; regno < reglimit ; regno ++ ) if ( cris_reg_saved_in_regsave_area ( regno ) ) return false ; return true ; } </s>

Return ! = 0 if the return sequence for the current function is short , like `` ret '' or `` jump [ sp+ ] '' . Prior to reloading , we ca n't tell how many registers must be saved , so return 0 then .


<s> static HOST_WIDE_INT cris_static_rtx_alignment ( machine_mode mode ) { return MAX ( cris_preferred_minimum_alignment ( ) , GET_MODE_ALIGNMENT ( mode ) ) ; } </s>


<s> static rtx cris_struct_value_rtx ( tree fntype ATTRIBUTE_UNUSED , int incoming ATTRIBUTE_UNUSED ) { return gen_rtx_REG ( Pmode , CRIS_STRUCT_VALUE_REGNUM ) ; } </s>

Worker function for TARGET_STRUCT_VALUE_RTX .


<s>
enum
cris_symbol_type
cris_symbol_type_of
(
const_rtx
x
)
{
switch
(
GET_CODE
(
x
)
)
{
case
SYMBOL_REF
:
return
flag_pic
(
SYMBOL_REF_LOCAL_P
(
x
)
cris_rel_symbol
:
cris_got_symbol
)
:
cris_offsettable_symbol
;
case
LABEL_REF
:
return
flag_pic
cris_rel_symbol
:
cris_offsettable_symbol
;
case
CONST
:
return
cris_symbol_type_of
(
XEXP
(
x
,
0
)
)
;
case
PLUS
:
case
MINUS
:
{
enum
cris_symbol_type
t1
=
cris_symbol_type_of
(
XEXP
(
x
,
0
)
)
;
enum
cris_symbol_type
t2
=
cris_symbol_type_of
(
XEXP
(
x
,
1
)
)
;
gcc_assert
(
t1
==
cris_no_symbol
||
t2
==
cris_no_symbol
)
;
if
(
t1
==
cris_got_symbol
||
t2
==
cris_got_symbol
)
return
cris_got_symbol_needing_fixup
;
return
t1
!=
cris_no_symbol
t1
:
t2
;
}
case
CONST_INT
:
case
CONST_DOUBLE
:
return
cris_no_symbol
;
case
UNSPEC
:
return
cris_unspec
;
default
:
fatal_insn
(
"unrecognized supposed constant"
,
x
)
;
}
gcc_unreachable
(
)
;
}
</s>

Helper function to find the right symbol-type to generate , given the original ( non-PIC ) representation .


<s> static void cris_trampoline_init ( rtx m_tramp , tree fndecl , rtx chain_value ) { rtx fnaddr = XEXP ( DECL_RTL ( fndecl ) , 0 ) ; rtx mem ; emit_block_move ( m_tramp , assemble_trampoline_template ( ) , GEN_INT ( TRAMPOLINE_SIZE ) , BLOCK_OP_NORMAL ) ; mem = adjust_address ( m_tramp , SImode , 10 ) ; emit_move_insn ( mem , chain_value ) ; mem = adjust_address ( m_tramp , SImode , 16 ) ; emit_move_insn ( mem , fnaddr ) ; } </s>


<s> bool cris_valid_pic_const ( const_rtx x , bool any_operand ) { gcc_assert ( flag_pic ) ; switch ( GET_CODE ( x ) ) { case CONST_INT : case CONST_DOUBLE : return true ; default : ; } if ( GET_CODE ( x ) != CONST ) return false ; x = XEXP ( x , 0 ) ; if ( GET_CODE ( x ) == PLUS && GET_CODE ( XEXP ( x , 0 ) ) == UNSPEC && ( XINT ( XEXP ( x , 0 ) , 1 ) == CRIS_UNSPEC_GOTREL || XINT ( XEXP ( x , 0 ) , 1 ) == CRIS_UNSPEC_PCREL ) && CONST_INT_P ( XEXP ( x , 1 ) ) ) x = XEXP ( x , 0 ) ; if ( GET_CODE ( x ) == UNSPEC ) switch ( XINT ( x , 1 ) ) { case CRIS_UNSPEC_PLT_PCREL : case CRIS_UNSPEC_PCREL : return ! any_operand ; case CRIS_UNSPEC_PLT_GOTREL : case CRIS_UNSPEC_PLTGOTREAD : case CRIS_UNSPEC_GOTREAD : case CRIS_UNSPEC_GOTREL : return true ; default : gcc_unreachable ( ) ; } return cris_symbol_type_of ( x ) == cris_no_symbol ; } </s>

Return TRUE iff X is a CONST valid for e.g . indexing .


<s> virtual unsigned int execute ( function * ) { return cris_postdbr_cmpelim ( ) ; } </s>


<s> static inline bool reg_ok_for_base_p ( const_rtx x , bool strict ) { return ( ( ! strict && ! HARD_REGISTER_P ( x ) ) || REGNO_OK_FOR_BASE_P ( REGNO ( x ) ) ) ; } </s>

Nonzero if X is a hard reg that can be used as an index .


<s> static inline bool reg_ok_for_index_p ( const_rtx x , bool strict ) { return reg_ok_for_base_p ( x , strict ) ; } </s>