Compute the size of the local area and the size to be adjusted by the prologue and epilogue .


<s> static void cr16_compute_save_regs ( void ) { unsigned int regno ; current_frame_info . last_reg_to_save = - 1 ; current_frame_info . reg_size = 0 ; if ( FUNC_IS_NORETURN_P ( current_function_decl ) && ! MUST_SAVE_REGS_P ( ) ) return ; for ( regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno ++ ) { if ( fixed_regs [ regno ] ) { current_frame_info . save_regs [ regno ] = 0 ; continue ; } if ( cr16_interrupt_function_p ( ) ) { if ( ! crtl -> is_leaf && call_used_regs [ regno ] ) current_frame_info . save_regs [ regno ] = 1 ; else if ( df_regs_ever_live_p ( regno ) ) current_frame_info . save_regs [ regno ] = 1 ; else current_frame_info . save_regs [ regno ] = 0 ; } else { if ( df_regs_ever_live_p ( regno ) && ( ! call_used_regs [ regno ] || regno == RETURN_ADDRESS_REGNUM ) ) current_frame_info . save_regs [ regno ] = 1 ; else current_frame_info . save_regs [ regno ] = 0 ; } } if ( crtl -> calls_eh_return ) { unsigned int i ; for ( i = 0 ; ; ++ i ) { regno = EH_RETURN_DATA_REGNO ( i ) ; if ( INVALID_REGNUM == regno ) break ; current_frame_info . save_regs [ regno ] = 1 ; } } for ( regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno ++ ) if ( current_frame_info . save_regs [ regno ] == 1 ) { current_frame_info . last_reg_to_save = regno ; if ( regno >= CR16_FIRST_DWORD_REGISTER ) current_frame_info . reg_size += CR16_UNITS_PER_DWORD ; else current_frame_info . reg_size += UNITS_PER_WORD ; } } </s>

Compute values for the array current_frame_info.save_regs and the variable current_frame_info.reg_size . The index of current_frame_info.save_regs is numbers of register , each will get 1 if we need to save it in the current function , 0 if not . current_frame_info.reg_size is the total sum of the registers being saved .


<s> int cr16_const_double_ok ( rtx op ) { if ( GET_MODE ( op ) == SFmode ) { REAL_VALUE_TYPE r ; long l ; REAL_VALUE_FROM_CONST_DOUBLE ( r , op ) ; REAL_VALUE_TO_TARGET_SINGLE ( r , l ) ; return UNSIGNED_INT_FITS_N_BITS ( l , 4 ) ? 1 : 0 ; } return ( ( UNSIGNED_INT_FITS_N_BITS ( CONST_DOUBLE_LOW ( op ) , 4 ) ) && ( UNSIGNED_INT_FITS_N_BITS ( CONST_DOUBLE_HIGH ( op ) , 4 ) ) ) ? 1 : 0 ; } </s>

Check if a const_double is ok for cr16 store-immediate instructions .


<s> static void cr16_create_dwarf_for_multi_push ( rtx insn ) { rtx dwarf , reg , tmp ; int i , j , from , to , word_cnt , dwarf_par_index , inc ; machine_mode mode ; int num_regs = 0 , offset = 0 , split_here = 0 , total_push_bytes = 0 ; for ( i = 0 ; i <= current_frame_info . last_reg_to_save ; ++ i ) { if ( current_frame_info . save_regs [ i ] ) { ++ num_regs ; if ( i < CR16_FIRST_DWORD_REGISTER ) total_push_bytes += 2 ; else total_push_bytes += 4 ; } } if ( ! num_regs ) return ; dwarf = gen_rtx_SEQUENCE ( VOIDmode , rtvec_alloc ( num_regs + 1 ) ) ; dwarf_par_index = num_regs ; from = current_frame_info . last_reg_to_save + 1 ; to = current_frame_info . last_reg_to_save ; word_cnt = 0 ; for ( i = current_frame_info . last_reg_to_save ; i >= 0 ; ) { if ( ! current_frame_info . save_regs [ i ] || 0 == i || split_here ) { if ( 0 == i && current_frame_info . save_regs [ i ] ) from = 0 ; for ( j = to ; j >= from ; -- j ) { if ( j < CR16_FIRST_DWORD_REGISTER ) { mode = HImode ; inc = 1 ; } else { mode = SImode ; inc = 2 ; } reg = gen_rtx_REG ( mode , j ) ; offset += 2 * inc ; tmp = gen_rtx_SET ( VOIDmode , gen_frame_mem ( mode , plus_constant ( Pmode , stack_pointer_rtx , total_push_bytes - offset ) ) , reg ) ; RTX_FRAME_RELATED_P ( tmp ) = 1 ; XVECEXP ( dwarf , 0 , dwarf_par_index -- ) = tmp ; } from = i ; to = -- i ; split_here = 0 ; word_cnt = 0 ; continue ; } if ( i != RETURN_ADDRESS_REGNUM ) { inc = ( i < CR16_FIRST_DWORD_REGISTER ) ? 1 : 2 ; if ( word_cnt + inc >= MAX_COUNT || FRAME_POINTER_REGNUM == i ) { split_here = 1 ; from = i ; continue ; } word_cnt += inc ; } from = i -- ; } tmp = gen_rtx_SET ( SImode , stack_pointer_rtx , gen_rtx_PLUS ( SImode , stack_pointer_rtx , GEN_INT ( - offset ) ) ) ; RTX_FRAME_RELATED_P ( tmp ) = 1 ; XVECEXP ( dwarf , 0 , 0 ) = tmp ; add_reg_note ( insn , REG_FRAME_RELATED_EXPR , dwarf ) ; } </s>

Generate DWARF2 annotation for multi-push instruction .


<s> static rtx cr16_function_arg ( cumulative_args_t cum_v , machine_mode mode , const_tree type , bool named ATTRIBUTE_UNUSED ) { CUMULATIVE_ARGS * cum = get_cumulative_args ( cum_v ) ; cum -> last_parm_in_reg = 0 ; if ( type == void_type_node ) return NULL_RTX ; if ( targetm . calls . must_pass_in_stack ( mode , type ) || ( cum -> ints < 0 ) ) return NULL_RTX ; if ( mode == BLKmode ) { if ( enough_regs_for_param ( cum , type , mode ) != 0 ) { cum -> last_parm_in_reg = 1 ; return gen_rtx_REG ( mode , MIN_REG_FOR_PASSING_ARGS + cum -> ints ) ; } } if ( ( MIN_REG_FOR_PASSING_ARGS + cum -> ints ) > MAX_REG_FOR_PASSING_ARGS ) return NULL_RTX ; else { if ( enough_regs_for_param ( cum , type , mode ) != 0 ) { cum -> last_parm_in_reg = 1 ; return gen_rtx_REG ( mode , MIN_REG_FOR_PASSING_ARGS + cum -> ints ) ; } } return NULL_RTX ; } </s>

Implements the macro FUNCTION_ARG defined in cr16.h .


<s> static void cr16_function_arg_advance ( cumulative_args_t cum_v , machine_mode mode , const_tree type , bool named ATTRIBUTE_UNUSED ) { CUMULATIVE_ARGS * cum = get_cumulative_args ( cum_v ) ; int l = GET_MODE_BITSIZE ( mode ) / BITS_PER_WORD ; if ( ! cum -> last_parm_in_reg ) return ; if ( targetm . calls . must_pass_in_stack ( mode , type ) || ( cum -> ints < 0 ) ) return ; if ( ( mode == SImode ) || ( mode == HImode ) || ( mode == QImode ) || ( mode == DImode ) ) { if ( l <= 1 ) cum -> ints += 1 ; else cum -> ints += l ; } else if ( ( mode == SFmode ) || ( mode == DFmode ) ) cum -> ints += l ; else if ( ( mode ) == BLKmode ) { if ( ( l = enough_regs_for_param ( cum , type , mode ) ) != 0 ) cum -> ints += l ; } return ; } </s>

Implements the macro FUNCTION_ARG_ADVANCE defined in cr16.h .


<s> int cr16_hard_regno_mode_ok ( int regno , machine_mode mode ) { if ( ( GET_MODE_SIZE ( mode ) >= 4 ) && ( regno == 11 ) ) return 0 ; if ( mode == DImode || mode == DFmode ) { if ( ( regno > 8 ) || ( regno & 1 ) ) return 0 ; return 1 ; } if ( ( TARGET_INT32 ) && ( ( regno >= 12 ) && ( GET_MODE_SIZE ( mode ) < 4 ) ) ) return 0 ; if ( GET_MODE_CLASS ( mode ) == MODE_CC ) return 0 ; return 1 ; } </s>

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


<s> int cr16_initial_elimination_offset ( int from , int to ) { cr16_compute_save_regs ( ) ; cr16_compute_frame ( ) ; if ( ( ( from ) == FRAME_POINTER_REGNUM ) && ( ( to ) == STACK_POINTER_REGNUM ) ) return ( ACCUMULATE_OUTGOING_ARGS ? crtl -> outgoing_args_size : 0 ) ; else if ( ( ( from ) == ARG_POINTER_REGNUM ) && ( ( to ) == FRAME_POINTER_REGNUM ) ) return ( current_frame_info . reg_size + current_frame_info . var_size ) ; else if ( ( ( from ) == ARG_POINTER_REGNUM ) && ( ( to ) == STACK_POINTER_REGNUM ) ) return ( current_frame_info . reg_size + current_frame_info . var_size + ( ACCUMULATE_OUTGOING_ARGS ? crtl -> outgoing_args_size : 0 ) ) ; else gcc_unreachable ( ) ; } </s>

Implements the macro INITIAL_ELIMINATION_OFFSET , return the OFFSET .


<s> static int cr16_memory_move_cost ( machine_mode mode , reg_class_t rclass ATTRIBUTE_UNUSED , bool in ATTRIBUTE_UNUSED ) { if ( reg_classes_intersect_p ( rclass , GENERAL_REGS ) ) return ( 4 * HARD_REGNO_NREGS ( 0 , mode ) ) ; else return ( 100 ) ; } </s>

Return the cost of moving data of mode MODE between a register of class CLASS and memory ; IN is zero if the value is to be written to memory , nonzero if it is to be read in . This cost is relative to those in REGISTER_MOVE_COST .


"data-model=far not valid for cr16c architecture"

"invalid data model option -mdata-model=%s"


<s>
static
void
cr16_print_operand
(
FILE
*
file
,
rtx
x
,
int
code
)
{
int
ptr_dereference
=
0
;
switch
(
code
)
{
case
'd'
:
{
const
char
*
cr16_cmp_str
;
switch
(
GET_CODE
(
x
)
)
{
case
EQ
:
cr16_cmp_str
=
"eq"
;
break
;
case
NE
:
cr16_cmp_str
=
"ne"
;
break
;
case
GT
:
cr16_cmp_str
=
"lt"
;
break
;
case
GTU
:
cr16_cmp_str
=
"lo"
;
break
;
case
LT
:
cr16_cmp_str
=
"gt"
;
break
;
case
LTU
:
cr16_cmp_str
=
"hi"
;
break
;
case
GE
:
cr16_cmp_str
=
"le"
;
break
;
case
GEU
:
cr16_cmp_str
=
"ls"
;
break
;
case
LE
:
cr16_cmp_str
=
"ge"
;
break
;
case
LEU
:
cr16_cmp_str
=
"hs"
;
break
;
default
:
gcc_unreachable
(
)
;
}
fprintf
(
file
,
"%s"
,
cr16_cmp_str
)
;
return
;
}
case
'$'
:
putc
(
'$'
,
file
)
;
return
;
case
'p'
:
if
(
GET_CODE
(
x
)
==
REG
)
{
fprintf
(
file
,
"%s"
,
reg_names
[
REGNO
(
x
)
]
)
;
return
;
}
break
;
case
'b'
:
fprintf
(
file
,
"0x%lx"
,
INTVAL
(
x
)
)
;
return
;
case
'r'
:
fprintf
(
file
,
"%d"
,
cr16_operand_bit_pos
(
INTVAL
(
x
)
,
0
)
)
;
return
;
case
's'
:
fprintf
(
file
,
"%d"
,
cr16_operand_bit_pos
(
INTVAL
(
x
)
,
1
)
)
;
return
;
case
'g'
:
ptr_dereference
=
1
;
case
'f'
:
case
0
:
switch
(
GET_CODE
(
x
)
)
{
case
REG
:
if
(
GET_MODE_BITSIZE
(
GET_MODE
(
x
)
)
>
BITS_PER_WORD
)
{
if
(
LONG_REG_P
(
REGNO
(
x
)
)
)
fprintf
(
file
,
"(%s)"
,
reg_names
[
REGNO
(
x
)
]
)
;
else
fprintf
(
file
,
"(%s,%s)"
,
reg_names
[
REGNO
(
x
)
+
1
]
,
reg_names
[
REGNO
(
x
)
]
)
;
}
else
fprintf
(
file
,
"%s"
,
reg_names
[
REGNO
(
x
)
]
)
;
return
;
case
MEM
:
output_address
(
XEXP
(
x
,
0
)
)
;
return
;
case
CONST_DOUBLE
:
{
REAL_VALUE_TYPE
r
;
long
l
;
REAL_VALUE_FROM_CONST_DOUBLE
(
r
,
x
)
;
REAL_VALUE_TO_TARGET_SINGLE
(
r
,
l
)
;
fprintf
(
file
,
"$0x%lx"
,
l
)
;
return
;
}
case
CONST_INT
:
{
fprintf
(
file
,
"$%ld"
,
INTVAL
(
x
)
)
;
return
;
}
case
UNSPEC
:
switch
(
XINT
(
x
,
1
)
)
{
default
:
gcc_unreachable
(
)
;
}
break
;
default
:
if
(
!
ptr_dereference
)
{
putc
(
'$'
,
file
)
;
}
cr16_print_operand_address
(
file
,
x
)
;
return
;
}
default
:
output_operand_lossage
(
"invalid %%xn code"
)
;
}
gcc_unreachable
(
)
;
}
</s>

Implements the macro PRINT_OPERAND defined in cr16.h .


<s> int legitimate_pic_operand_p ( rtx x ) { switch ( GET_CODE ( x ) ) { case SYMBOL_REF : return 0 ; break ; case LABEL_REF : return 0 ; break ; case CONST : if ( GET_CODE ( XEXP ( x , 0 ) ) == PLUS && ( GET_CODE ( XEXP ( XEXP ( x , 0 ) , 0 ) ) == SYMBOL_REF || GET_CODE ( XEXP ( XEXP ( x , 0 ) , 0 ) ) == LABEL_REF ) && ( GET_CODE ( XEXP ( XEXP ( x , 0 ) , 1 ) ) == CONST_INT ) ) return 0 ; break ; case MEM : return legitimate_pic_operand_p ( XEXP ( x , 0 ) ) ; break ; default : break ; } return 1 ; } </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> static void cr16_create_dwarf_for_multi_push ( rtx insn ) { rtx dwarf , reg , tmp ; int i , j , from , to , word_cnt , dwarf_par_index , inc ; machine_mode mode ; int num_regs = 0 , offset = 0 , split_here = 0 , total_push_bytes = 0 ; for ( i = 0 ; i <= current_frame_info . last_reg_to_save ; ++ i ) { if ( current_frame_info . save_regs [ i ] ) { ++ num_regs ; if ( i < CR16_FIRST_DWORD_REGISTER ) total_push_bytes += 2 ; else total_push_bytes += 4 ; } } if ( ! num_regs ) return ; dwarf = gen_rtx_SEQUENCE ( VOIDmode , rtvec_alloc ( num_regs + 1 ) ) ; dwarf_par_index = num_regs ; from = current_frame_info . last_reg_to_save + 1 ; to = current_frame_info . last_reg_to_save ; word_cnt = 0 ; for ( i = current_frame_info . last_reg_to_save ; i >= 0 ; ) { if ( ! current_frame_info . save_regs [ i ] || 0 == i || split_here ) { if ( 0 == i && current_frame_info . save_regs [ i ] ) from = 0 ; for ( j = to ; j >= from ; -- j ) { if ( j < CR16_FIRST_DWORD_REGISTER ) { mode = HImode ; inc = 1 ; } else { mode = SImode ; inc = 2 ; } reg = gen_rtx_REG ( mode , j ) ; offset += 2 * inc ; tmp = gen_rtx_SET ( gen_frame_mem ( mode , plus_constant ( Pmode , stack_pointer_rtx , total_push_bytes - offset ) ) , reg ) ; RTX_FRAME_RELATED_P ( tmp ) = 1 ; XVECEXP ( dwarf , 0 , dwarf_par_index -- ) = tmp ; } from = i ; to = -- i ; split_here = 0 ; word_cnt = 0 ; continue ; } if ( i != RETURN_ADDRESS_REGNUM ) { inc = ( i < CR16_FIRST_DWORD_REGISTER ) ? 1 : 2 ; if ( word_cnt + inc >= MAX_COUNT || FRAME_POINTER_REGNUM == i ) { split_here = 1 ; from = i ; continue ; } word_cnt += inc ; } from = i -- ; } tmp = gen_rtx_SET ( stack_pointer_rtx , gen_rtx_PLUS ( SImode , stack_pointer_rtx , GEN_INT ( - offset ) ) ) ; RTX_FRAME_RELATED_P ( tmp ) = 1 ; XVECEXP ( dwarf , 0 , 0 ) = tmp ; add_reg_note ( insn , REG_FRAME_RELATED_EXPR , dwarf ) ; } </s>


<s>
static
void
cr16_print_operand
(
FILE
*
file
,
rtx
x
,
int
code
)
{
int
ptr_dereference
=
0
;
switch
(
code
)
{
case
'd'
:
{
const
char
*
cr16_cmp_str
;
switch
(
GET_CODE
(
x
)
)
{
case
EQ
:
cr16_cmp_str
=
"eq"
;
break
;
case
NE
:
cr16_cmp_str
=
"ne"
;
break
;
case
GT
:
cr16_cmp_str
=
"lt"
;
break
;
case
GTU
:
cr16_cmp_str
=
"lo"
;
break
;
case
LT
:
cr16_cmp_str
=
"gt"
;
break
;
case
LTU
:
cr16_cmp_str
=
"hi"
;
break
;
case
GE
:
cr16_cmp_str
=
"le"
;
break
;
case
GEU
:
cr16_cmp_str
=
"ls"
;
break
;
case
LE
:
cr16_cmp_str
=
"ge"
;
break
;
case
LEU
:
cr16_cmp_str
=
"hs"
;
break
;
default
:
gcc_unreachable
(
)
;
}
fprintf
(
file
,
"%s"
,
cr16_cmp_str
)
;
return
;
}
case
'$'
:
putc
(
'$'
,
file
)
;
return
;
case
'p'
:
if
(
GET_CODE
(
x
)
==
REG
)
{
fprintf
(
file
,
"%s"
,
reg_names
[
REGNO
(
x
)
]
)
;
return
;
}
break
;
case
'b'
:
fprintf
(
file
,
"0x%lx"
,
INTVAL
(
x
)
)
;
return
;
case
'r'
:
fprintf
(
file
,
"%d"
,
cr16_operand_bit_pos
(
INTVAL
(
x
)
,
0
)
)
;
return
;
case
's'
:
fprintf
(
file
,
"%d"
,
cr16_operand_bit_pos
(
INTVAL
(
x
)
,
1
)
)
;
return
;
case
'g'
:
ptr_dereference
=
1
;
case
'f'
:
case
0
:
switch
(
GET_CODE
(
x
)
)
{
case
REG
:
if
(
GET_MODE_BITSIZE
(
GET_MODE
(
x
)
)
>
BITS_PER_WORD
)
{
if
(
LONG_REG_P
(
REGNO
(
x
)
)
)
fprintf
(
file
,
"(%s)"
,
reg_names
[
REGNO
(
x
)
]
)
;
else
fprintf
(
file
,
"(%s,%s)"
,
reg_names
[
REGNO
(
x
)
+
1
]
,
reg_names
[
REGNO
(
x
)
]
)
;
}
else
fprintf
(
file
,
"%s"
,
reg_names
[
REGNO
(
x
)
]
)
;
return
;
case
MEM
:
output_address
(
GET_MODE
(
x
)
,
XEXP
(
x
,
0
)
)
;
return
;
case
CONST_DOUBLE
:
{
long
l
;
REAL_VALUE_TO_TARGET_SINGLE
(
*
CONST_DOUBLE_REAL_VALUE
(
x
)
,
l
)
;
fprintf
(
file
,
"$0x%lx"
,
l
)
;
return
;
}
case
CONST_INT
:
{
fprintf
(
file
,
"$%ld"
,
INTVAL
(
x
)
)
;
return
;
}
case
UNSPEC
:
switch
(
XINT
(
x
,
1
)
)
{
default
:
gcc_unreachable
(
)
;
}
break
;
default
:
if
(
!
ptr_dereference
)
{
putc
(
'$'
,
file
)
;
}
cr16_print_operand_address
(
file
,
VOIDmode
,
x
)
;
return
;
}
default
:
output_operand_lossage
(
"invalid %%xn code"
)
;
}
gcc_unreachable
(
)
;
}
</s>


"\n======\nmacro TARGET_ADDRESS_COST = %d\n"


<s> static int cr16_addr_reg_p ( rtx addr_reg ) { rtx reg ; if ( REG_P ( addr_reg ) ) reg = addr_reg ; else if ( ( GET_CODE ( addr_reg ) == SUBREG ) && REG_P ( SUBREG_REG ( addr_reg ) ) && ( GET_MODE_SIZE ( GET_MODE ( SUBREG_REG ( addr_reg ) ) ) <= UNITS_PER_WORD ) ) reg = SUBREG_REG ( addr_reg ) ; else return FALSE ; if ( GET_MODE ( reg ) != Pmode ) return FALSE ; return TRUE ; } </s>

Helper function to check if is a valid base register that can hold address .


<s> static bool cr16_class_likely_spilled_p ( reg_class_t rclass ) { if ( ( rclass ) == SHORT_REGS || ( rclass ) == DOUBLE_BASE_REGS || ( rclass ) == LONG_REGS || ( rclass ) == GENERAL_REGS ) return true ; return false ; } </s>


<s> static void cr16_compute_save_regs ( void ) { unsigned int regno ; current_frame_info . last_reg_to_save = - 1 ; current_frame_info . reg_size = 0 ; if ( FUNC_IS_NORETURN_P ( current_function_decl ) && ! MUST_SAVE_REGS_P ( ) ) return ; for ( regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno ++ ) { if ( fixed_regs [ regno ] ) { current_frame_info . save_regs [ regno ] = 0 ; continue ; } if ( cr16_interrupt_function_p ( ) ) { if ( ! crtl -> is_leaf && call_used_or_fixed_reg_p ( regno ) ) current_frame_info . save_regs [ regno ] = 1 ; else if ( df_regs_ever_live_p ( regno ) ) current_frame_info . save_regs [ regno ] = 1 ; else current_frame_info . save_regs [ regno ] = 0 ; } else { if ( df_regs_ever_live_p ( regno ) && ( ! call_used_or_fixed_reg_p ( regno ) || regno == RETURN_ADDRESS_REGNUM ) ) current_frame_info . save_regs [ regno ] = 1 ; else current_frame_info . save_regs [ regno ] = 0 ; } } if ( crtl -> calls_eh_return ) { unsigned int i ; for ( i = 0 ; ; ++ i ) { regno = EH_RETURN_DATA_REGNO ( i ) ; if ( INVALID_REGNUM == regno ) break ; current_frame_info . save_regs [ regno ] = 1 ; } } for ( regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno ++ ) if ( current_frame_info . save_regs [ regno ] == 1 ) { current_frame_info . last_reg_to_save = regno ; if ( regno >= CR16_FIRST_DWORD_REGISTER ) current_frame_info . reg_size += CR16_UNITS_PER_DWORD ; else current_frame_info . reg_size += UNITS_PER_WORD ; } } </s>


<s> static void cr16_conditional_register_usage ( void ) { if ( flag_pic ) { fixed_regs [ 12 ] = call_used_regs [ 12 ] = 1 ; } } </s>

Implements the macro TARGET_CONDITIONAL_REGISTER_USAGE .


<s> int cr16_const_double_ok ( rtx op ) { if ( GET_MODE ( op ) == SFmode ) { long l ; REAL_VALUE_TO_TARGET_SINGLE ( * CONST_DOUBLE_REAL_VALUE ( op ) , l ) ; return UNSIGNED_INT_FITS_N_BITS ( l , 4 ) ? 1 : 0 ; } return ( ( UNSIGNED_INT_FITS_N_BITS ( CONST_DOUBLE_LOW ( op ) , 4 ) ) && ( UNSIGNED_INT_FITS_N_BITS ( CONST_DOUBLE_HIGH ( op ) , 4 ) ) ) ? 1 : 0 ; } </s>


<s> static void cr16_create_dwarf_for_multi_push ( rtx insn ) { rtx dwarf , reg , tmp ; int i , j , from , to , word_cnt , dwarf_par_index , inc ; machine_mode mode ; int num_regs = 0 , offset = 0 , split_here = 0 , total_push_bytes = 0 ; for ( i = 0 ; i <= current_frame_info . last_reg_to_save ; ++ i ) { if ( current_frame_info . save_regs [ i ] ) { ++ num_regs ; if ( i < CR16_FIRST_DWORD_REGISTER ) total_push_bytes += 2 ; else total_push_bytes += 4 ; } } if ( ! num_regs ) return ; dwarf = gen_rtx_SEQUENCE ( VOIDmode , rtvec_alloc ( num_regs + 1 ) ) ; dwarf_par_index = num_regs ; from = current_frame_info . last_reg_to_save + 1 ; to = current_frame_info . last_reg_to_save ; word_cnt = 0 ; for ( i = current_frame_info . last_reg_to_save ; i >= 0 ; ) { if ( ! current_frame_info . save_regs [ i ] || i == 0 || split_here ) { if ( i == 0 && current_frame_info . save_regs [ i ] ) from = 0 ; for ( j = to ; j >= from ; -- j ) { if ( j < CR16_FIRST_DWORD_REGISTER ) { mode = HImode ; inc = 1 ; } else { mode = SImode ; inc = 2 ; } reg = gen_rtx_REG ( mode , j ) ; offset += 2 * inc ; tmp = gen_rtx_SET ( gen_frame_mem ( mode , plus_constant ( Pmode , stack_pointer_rtx , total_push_bytes - offset ) ) , reg ) ; RTX_FRAME_RELATED_P ( tmp ) = 1 ; XVECEXP ( dwarf , 0 , dwarf_par_index -- ) = tmp ; } from = i ; to = -- i ; split_here = 0 ; word_cnt = 0 ; continue ; } if ( i != RETURN_ADDRESS_REGNUM ) { inc = ( i < CR16_FIRST_DWORD_REGISTER ) ? 1 : 2 ; if ( word_cnt + inc >= MAX_COUNT || FRAME_POINTER_REGNUM == i ) { split_here = 1 ; from = i ; continue ; } word_cnt += inc ; } from = i -- ; } tmp = gen_rtx_SET ( stack_pointer_rtx , gen_rtx_PLUS ( SImode , stack_pointer_rtx , GEN_INT ( - offset ) ) ) ; RTX_FRAME_RELATED_P ( tmp ) = 1 ; XVECEXP ( dwarf , 0 , 0 ) = tmp ; add_reg_note ( insn , REG_FRAME_RELATED_EXPR , dwarf ) ; } </s>


<s> void cr16_decompose_const ( rtx x , int * code , enum data_model_type * data , bool treat_as_const ) { * code = - 1 ; * data = ILLEGAL_DM ; switch ( GET_CODE ( x ) ) { case SYMBOL_REF : * code = SYMBOL_REF_FUNCTION_P ( x ) ? 2 : 0 ; if ( * code == 0 ) { if ( CR16_TARGET_DATA_NEAR ) * data = DM_DEFAULT ; else if ( CR16_TARGET_DATA_MEDIUM ) * data = DM_FAR ; else if ( CR16_TARGET_DATA_FAR ) { if ( treat_as_const ) * data = DM_FAR ; else * data = ILLEGAL_DM ; } } return ; case LABEL_REF : * code = 1 ; return ; case PLUS : case MINUS : if ( GET_CODE ( XEXP ( x , 0 ) ) == CONST_INT ) cr16_decompose_const ( XEXP ( x , 1 ) , code , data , treat_as_const ) ; else if ( GET_CODE ( XEXP ( x , 1 ) ) == CONST_INT ) cr16_decompose_const ( XEXP ( x , 0 ) , code , data , treat_as_const ) ; return ; default : return ; } } </s>

Helper functions : Created specifically for decomposing operand of CONST Recursively look into expression x for code or data symbol . The function expects the expression to contain combination of SYMBOL_REF , CONST_INT , ( PLUS or MINUS ) LABEL_REF , CONST_INT , ( PLUS or MINUS ) SYMBOL_REF LABEL_REF All other combinations will result in code = -1 and data = ILLEGAL_DM code data -1 ILLEGAL_DM The expression did not contain SYMBOL_REF or LABEL_REF 0 DM_FAR SYMBOL_REF was found and it was far data reference . 0 DM_DEFAULT SYMBOL_REF was found and it was medium data reference . 1 ILLEGAL_DM LABEL_REF was found . 2 ILLEGAL_DM SYMBOL_REF was found and it was function reference .


<s>
const
char
*
cr16_emit_add_sub_di
(
rtx
*
operands
,
enum
rtx_code
code
)
{
rtx
lo_op
[
2
]
;
rtx
hi0_op
[
2
]
;
rtx
hi1_op
[
2
]
;
lo_op
[
0
]
=
gen_lowpart
(
SImode
,
operands
[
0
]
)
;
hi0_op
[
0
]
=
simplify_gen_subreg
(
HImode
,
operands
[
0
]
,
DImode
,
4
)
;
hi1_op
[
0
]
=
simplify_gen_subreg
(
HImode
,
operands
[
0
]
,
DImode
,
6
)
;
lo_op
[
1
]
=
gen_lowpart
(
SImode
,
operands
[
2
]
)
;
hi0_op
[
1
]
=
simplify_gen_subreg
(
HImode
,
operands
[
2
]
,
DImode
,
4
)
;
hi1_op
[
1
]
=
simplify_gen_subreg
(
HImode
,
operands
[
2
]
,
DImode
,
6
)
;
switch
(
code
)
{
case
PLUS
:
{
output_asm_insn
(
"addd\t%1, %0"
,
lo_op
)
;
output_asm_insn
(
"addcw\t%1, %0"
,
hi0_op
)
;
output_asm_insn
(
"addcw\t%1, %0"
,
hi1_op
)
;
break
;
}
case
MINUS
:
{
output_asm_insn
(
"subd\t%1, %0"
,
lo_op
)
;
output_asm_insn
(
"subcw\t%1, %0"
,
hi0_op
)
;
output_asm_insn
(
"subcw\t%1, %0"
,
hi1_op
)
;
break
;
}
default
:
break
;
}
return
""
;
}
</s>

Helper function for md file . This function is used to emit arithmetic DI instructions . The argument `` num '' decides which instruction to be printed .


<s>
const
char
*
cr16_emit_logical_di
(
rtx
*
operands
,
enum
rtx_code
code
)
{
rtx
lo_op
[
2
]
;
rtx
hi_op
[
2
]
;
lo_op
[
0
]
=
gen_lowpart
(
SImode
,
operands
[
0
]
)
;
hi_op
[
0
]
=
simplify_gen_subreg
(
SImode
,
operands
[
0
]
,
DImode
,
4
)
;
lo_op
[
1
]
=
gen_lowpart
(
SImode
,
operands
[
2
]
)
;
hi_op
[
1
]
=
simplify_gen_subreg
(
SImode
,
operands
[
2
]
,
DImode
,
4
)
;
switch
(
code
)
{
case
AND
:
{
output_asm_insn
(
"andd\t%1, %0"
,
lo_op
)
;
output_asm_insn
(
"andd\t%1, %0"
,
hi_op
)
;
return
""
;
}
case
IOR
:
{
output_asm_insn
(
"ord\t%1, %0"
,
lo_op
)
;
output_asm_insn
(
"ord\t%1, %0"
,
hi_op
)
;
return
""
;
}
case
XOR
:
{
output_asm_insn
(
"xord\t%1, %0"
,
lo_op
)
;
output_asm_insn
(
"xord\t%1, %0"
,
hi_op
)
;
return
""
;
}
default
:
break
;
}
return
""
;
}
</s>

Helper function for md file . This function is used to emit logical DI instructions . The argument `` num '' decides which instruction to be printed .


<s> void cr16_expand_epilogue ( void ) { rtx insn ; int only_popret_RA = ( current_frame_info . save_regs [ RETURN_ADDRESS_REGNUM ] && ( current_frame_info . reg_size == CR16_UNITS_PER_DWORD ) ) ; if ( frame_pointer_needed ) { insn = emit_move_insn ( stack_pointer_rtx , frame_pointer_rtx ) ; } if ( current_frame_info . total_size > 0 ) { insn = emit_insn ( gen_addsi3 ( stack_pointer_rtx , stack_pointer_rtx , GEN_INT ( current_frame_info . total_size ) ) ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; } if ( crtl -> calls_eh_return ) { insn = emit_insn ( gen_addsi3 ( stack_pointer_rtx , stack_pointer_rtx , EH_RETURN_STACKADJ_RTX ) ) ; } if ( cr16_interrupt_function_p ( ) ) { insn = emit_jump_insn ( gen_interrupt_return ( ) ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; } else if ( crtl -> calls_eh_return ) { insn = emit_jump_insn ( gen_pop_and_popret_return ( GEN_INT ( current_frame_info . reg_size ) ) ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; } else if ( current_frame_info . last_reg_to_save == - 1 ) emit_jump_insn ( gen_jump_return ( ) ) ; else if ( only_popret_RA ) { insn = emit_jump_insn ( gen_popret_RA_return ( ) ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; } else { insn = emit_jump_insn ( gen_pop_and_popret_return ( GEN_INT ( current_frame_info . reg_size ) ) ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; } } </s>

Generate insn that updates the stack for local variables and padding for registers we save . - Generate the appropriate return insn .


<s> void cr16_expand_prologue ( void ) { rtx insn ; cr16_compute_frame ( ) ; cr16_compute_save_regs ( ) ; if ( ( current_frame_info . total_size + current_frame_info . reg_size ) == 0 ) return ; if ( current_frame_info . last_reg_to_save != - 1 ) { insn = emit_insn ( gen_push_for_prologue ( GEN_INT ( current_frame_info . reg_size ) ) ) ; cr16_create_dwarf_for_multi_push ( insn ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; } if ( current_frame_info . total_size > 0 ) { insn = emit_insn ( gen_addsi3 ( stack_pointer_rtx , stack_pointer_rtx , GEN_INT ( - current_frame_info . total_size ) ) ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; } if ( frame_pointer_needed ) { insn = emit_move_insn ( frame_pointer_rtx , stack_pointer_rtx ) ; } } </s>

CompactRISC CR16 Architecture stack layout : 0 + -- -- -- -- -- -- -- -- -- -- - | . . | +==================== Sp ( x ) = Ap ( x+1 ) A | Args for functions | | called by X and Dynamically | | Dynamic allocations allocated and | | ( alloca , variable deallocated Stack | length arrays ) . grows + -- -- -- -- -- -- -- -- -- -- Fp ( x ) down| | Local variables of X ward| + -- -- -- -- -- -- -- -- -- -- | | Regs saved for X-1 | +==================== Sp ( x-1 ) = Ap ( x ) | Args for func X | pushed by X-1 + -- -- -- -- -- -- -- -- -- -- Fp ( x-1 ) | | V


<s> static bool cr16_frame_pointer_required ( void ) { return ( cfun -> calls_alloca || crtl -> calls_eh_return || cfun -> has_nonlocal_label || crtl -> calls_eh_return ) ; } </s>


<s> static rtx cr16_function_arg ( cumulative_args_t cum_v , const function_arg_info & arg ) { CUMULATIVE_ARGS * cum = get_cumulative_args ( cum_v ) ; cum -> last_parm_in_reg = 0 ; if ( arg . end_marker_p ( ) ) return NULL_RTX ; if ( targetm . calls . must_pass_in_stack ( arg ) || ( cum -> ints < 0 ) ) return NULL_RTX ; if ( arg . mode == BLKmode ) { if ( enough_regs_for_param ( cum , arg . type , arg . mode ) != 0 ) { cum -> last_parm_in_reg = 1 ; return gen_rtx_REG ( arg . mode , MIN_REG_FOR_PASSING_ARGS + cum -> ints ) ; } } if ( ( MIN_REG_FOR_PASSING_ARGS + cum -> ints ) > MAX_REG_FOR_PASSING_ARGS ) return NULL_RTX ; else { if ( enough_regs_for_param ( cum , arg . type , arg . mode ) != 0 ) { cum -> last_parm_in_reg = 1 ; return gen_rtx_REG ( arg . mode , MIN_REG_FOR_PASSING_ARGS + cum -> ints ) ; } } return NULL_RTX ; } </s>


<s> static void cr16_function_arg_advance ( cumulative_args_t cum_v , const function_arg_info & arg ) { CUMULATIVE_ARGS * cum = get_cumulative_args ( cum_v ) ; int l = GET_MODE_BITSIZE ( arg . mode ) / BITS_PER_WORD ; if ( ! cum -> last_parm_in_reg ) return ; if ( targetm . calls . must_pass_in_stack ( arg ) || ( cum -> ints < 0 ) ) return ; if ( ( arg . mode == SImode ) || ( arg . mode == HImode ) || ( arg . mode == QImode ) || ( arg . mode == DImode ) ) { if ( l <= 1 ) cum -> ints += 1 ; else cum -> ints += l ; } else if ( ( arg . mode == SFmode ) || ( arg . mode == DFmode ) ) cum -> ints += l ; else if ( arg . mode == BLKmode ) { if ( ( l = enough_regs_for_param ( cum , arg . type , arg . mode ) ) != 0 ) cum -> ints += l ; } return ; } </s>


<s> int cr16_function_arg_regno_p ( int n ) { return ( ( n <= MAX_REG_FOR_PASSING_ARGS ) && ( n >= MIN_REG_FOR_PASSING_ARGS ) ) ; } </s>

Implements the macro FUNCTION_ARG_REGNO_P defined in cr16.h . Return nonzero if N is a register used for passing parameters .


<s> static rtx cr16_function_value ( const_tree type , const_tree fn_decl_or_type ATTRIBUTE_UNUSED , bool outgoing ATTRIBUTE_UNUSED ) { return gen_rtx_REG ( TYPE_MODE ( type ) , cr16_ret_register ( ) ) ; } </s>

Create an RTX representing the place where a function returns a value of data type VALTYPE .


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

Worker function for TARGET_FUNCTION_VALUE_REGNO_P .


<s> static bool cr16_hard_regno_mode_ok ( unsigned int regno , machine_mode mode ) { if ( ( GET_MODE_SIZE ( mode ) >= 4 ) && ( regno == 11 ) ) return false ; if ( mode == DImode || mode == DFmode ) { if ( ( regno > 8 ) || ( regno & 1 ) ) return false ; return true ; } if ( ( TARGET_INT32 ) && ( ( regno >= 12 ) && ( GET_MODE_SIZE ( mode ) < 4 ) ) ) return false ; if ( GET_MODE_CLASS ( mode ) == MODE_CC ) return false ; return true ; } </s>


<s> static unsigned int cr16_hard_regno_nregs ( unsigned int regno , machine_mode mode ) { if ( regno >= CR16_FIRST_DWORD_REGISTER ) return CEIL ( GET_MODE_SIZE ( mode ) , CR16_UNITS_PER_DWORD ) ; return CEIL ( GET_MODE_SIZE ( mode ) , UNITS_PER_WORD ) ; } </s>


<s> int cr16_initial_elimination_offset ( int from , int to ) { cr16_compute_save_regs ( ) ; cr16_compute_frame ( ) ; if ( ( ( from ) == FRAME_POINTER_REGNUM ) && ( ( to ) == STACK_POINTER_REGNUM ) ) return ( ACCUMULATE_OUTGOING_ARGS ? ( HOST_WIDE_INT ) crtl -> outgoing_args_size : 0 ) ; else if ( ( ( from ) == ARG_POINTER_REGNUM ) && ( ( to ) == FRAME_POINTER_REGNUM ) ) return ( current_frame_info . reg_size + current_frame_info . var_size ) ; else if ( ( ( from ) == ARG_POINTER_REGNUM ) && ( ( to ) == STACK_POINTER_REGNUM ) ) return ( current_frame_info . reg_size + current_frame_info . var_size + ( ACCUMULATE_OUTGOING_ARGS ? ( HOST_WIDE_INT ) crtl -> outgoing_args_size : 0 ) ) ; else gcc_unreachable ( ) ; } </s>


<s> void cr16_init_cumulative_args ( CUMULATIVE_ARGS * cum , tree fntype , rtx libfunc ATTRIBUTE_UNUSED ) { tree param , next_param ; cum -> ints = 0 ; for ( param = ( fntype ) ? TYPE_ARG_TYPES ( fntype ) : 0 ; param != NULL_TREE ; param = next_param ) { next_param = TREE_CHAIN ( param ) ; if ( ( next_param == NULL_TREE ) && ( TREE_VALUE ( param ) != void_type_node ) ) { cum -> ints = - 1 ; return ; } } } </s>

Implements the macro INIT_CUMULATIVE_ARGS defined in cr16.h .


<s> int cr16_interrupt_function_p ( void ) { tree attributes ; attributes = TYPE_ATTRIBUTES ( TREE_TYPE ( current_function_decl ) ) ; return ( lookup_attribute ( "interrupt" , attributes ) != NULL_TREE ) ; } </s>

Return nonzero if the current function being compiled is an interrupt function as specified by the `` interrupt '' attribute .


<s> bool cr16_is_data_model ( enum data_model_type model ) { return ( model == data_model ) ; } </s>

Returns true if data model selected via command line option is same as function argument .


"\n======\nTARGET_LEGITIMATE_ADDRESS_P, mode = %s, strict = %d"

Implementation of TARGET_LEGITIMATE_ADDRESS_P .


<s> static bool cr16_legitimate_constant_p ( machine_mode mode ATTRIBUTE_UNUSED , rtx x ATTRIBUTE_UNUSED ) { return 1 ; } </s>

Implement TARGET_LEGITIMATE_CONSTANT_P Nonzero if X is a legitimate constant for an immediate operand on the target machine . You can assume that X satisfies CONSTANT_P . In cr16c treat legitimize float constant as an immediate operand .


<s> static rtx cr16_legitimize_address ( rtx x , rtx orig_x ATTRIBUTE_UNUSED , machine_mode mode ATTRIBUTE_UNUSED ) { if ( flag_pic ) return legitimize_pic_address ( orig_x , mode , NULL_RTX ) ; else return x ; } </s>

A C compound statement that attempts to replace X with a valid memory address for an operand of mode MODE . WIN will be a C statement label elsewhere in the code . X will always be the result of a call to break_out_memory_refs ( ) , and OLDX will be the operand that was given to that function to produce X . The code generated by this macro should not alter the substructure of X . If it transforms X into a more legitimate form , it should assign X ( which will always be a C variable ) a new value .


<s> static rtx cr16_libcall_value ( machine_mode mode , const_rtx func ATTRIBUTE_UNUSED ) { return gen_rtx_REG ( mode , cr16_ret_register ( ) ) ; } </s>

Create an RTX representing the place where a library function returns a value of mode MODE .


<s> static int cr16_memory_move_cost ( machine_mode mode , reg_class_t rclass ATTRIBUTE_UNUSED , bool in ATTRIBUTE_UNUSED ) { if ( reg_classes_intersect_p ( rclass , GENERAL_REGS ) ) return ( 4 * cr16_hard_regno_nregs ( 0 , mode ) ) ; else return ( 100 ) ; } </s>

Return the cost of moving data of mode MODE between a register of class CLASS and memory ; IN is zero if the value is to be written to memory , nonzero if it is to be read in . This cost is relative to those in REGISTER_MOVE_COST .


<s> int cr16_operand_bit_pos ( int val , int bitval ) { int i ; if ( bitval == 0 ) val = ~ val ; for ( i = 0 ; i < 16 ; i ++ ) if ( val & ( 1 << i ) ) break ; return i ; } </s>

Returns bit position of first 0 or 1 bit . It is safe to assume val as 16-bit wide .


"data-model=far not valid for cr16c architecture"

"invalid data model option %<-mdata-model=%s%>"


<s>
char
*
cr16_prepare_push_pop_string
(
int
push_or_pop
)
{
static
char
one_inst_str
[
50
]
;
int
i
,
start_reg
;
int
word_cnt
;
int
print_ra
;
char
*
return_str
;
char
*
temp_str
;
return_str
=
(
char
*
)
xmalloc
(
160
)
;
temp_str
=
(
char
*
)
xmalloc
(
160
)
;
memset
(
return_str
,
0
,
3
)
;
i
=
0
;
while
(
i
<=
current_frame_info
.
last_reg_to_save
)
{
one_inst_str
[
0
]
=
0
;
word_cnt
=
0
;
start_reg
=
i
;
print_ra
=
0
;
while
(
(
word_cnt
<
MAX_COUNT
)
&&
(
i
<=
current_frame_info
.
last_reg_to_save
)
)
{
if
(
!
current_frame_info
.
save_regs
[
i
]
)
{
++
i
;
break
;
}
if
(
i
==
RETURN_ADDRESS_REGNUM
)
print_ra
=
1
;
else
{
if
(
(
word_cnt
+
(
(
i
<
CR16_FIRST_DWORD_REGISTER
)
1
:
2
)
)
>=
MAX_COUNT
)
break
;
word_cnt
+=
(
(
i
<
CR16_FIRST_DWORD_REGISTER
)
1
:
2
)
;
}
++
i
;
}
if
(
(
word_cnt
==
0
)
&&
(
print_ra
==
0
)
)
continue
;
if
(
word_cnt
>
0
)
{
sprintf
(
one_inst_str
,
"$%d, %s"
,
word_cnt
,
reg_names
[
start_reg
]
)
;
if
(
print_ra
)
strcat
(
one_inst_str
,
", ra"
)
;
}
else
strcat
(
one_inst_str
,
"ra"
)
;
if
(
push_or_pop
==
1
)
{
if
(
print_ra
&&
!
cr16_interrupt_function_p
(
)
&&
!
crtl
->
calls_eh_return
)
strcpy
(
temp_str
,
"\n\tpopret\t"
)
;
else
strcpy
(
temp_str
,
"\n\tpop\t"
)
;
strcat
(
temp_str
,
one_inst_str
)
;
strcat
(
return_str
,
temp_str
)
;
}
else
{
strcpy
(
temp_str
,
"\n\tpush\t"
)
;
strcat
(
temp_str
,
one_inst_str
)
;
strcat
(
temp_str
,
return_str
)
;
strcpy
(
return_str
,
temp_str
)
;
}
}
if
(
push_or_pop
==
1
)
{
if
(
cr16_interrupt_function_p
(
)
)
strcat
(
return_str
,
"\n\tretx\n"
)
;
else
if
(
crtl
->
calls_eh_return
)
{
strcat
(
return_str
,
"\n\taddd\t (r5, r4), (sp)\t\n"
)
;
strcat
(
return_str
,
"\n\tjump\t (ra)\n"
)
;
strcpy
(
temp_str
,
"\n\tsubd\t (r5, r4), (sp)\t\n"
)
;
strcat
(
temp_str
,
return_str
)
;
strcpy
(
return_str
,
temp_str
)
;
}
else
if
(
!
FUNC_IS_NORETURN_P
(
current_function_decl
)
&&
!
(
current_frame_info
.
save_regs
[
RETURN_ADDRESS_REGNUM
]
)
)
strcat
(
return_str
,
"\n\tjump\t (ra)\n"
)
;
}
return_str
+=
2
;
return
return_str
;
}
</s>

Called from cr16.md . The return value depends on the parameter push_or_pop : When push_or_pop is zero - > string for push instructions of prologue . When push_or_pop is nonzero - > string for pop/popret/retx in epilogue . Relies on the assumptions : 1 . RA is the last register to be saved . 2 . The maximal value of the counter is MAX_COUNT .


<s>
static
void
cr16_print_operand
(
FILE
*
file
,
rtx
x
,
int
code
)
{
int
ptr_dereference
=
0
;
switch
(
code
)
{
case
'd'
:
{
const
char
*
cr16_cmp_str
;
switch
(
GET_CODE
(
x
)
)
{
case
EQ
:
cr16_cmp_str
=
"eq"
;
break
;
case
NE
:
cr16_cmp_str
=
"ne"
;
break
;
case
GT
:
cr16_cmp_str
=
"lt"
;
break
;
case
GTU
:
cr16_cmp_str
=
"lo"
;
break
;
case
LT
:
cr16_cmp_str
=
"gt"
;
break
;
case
LTU
:
cr16_cmp_str
=
"hi"
;
break
;
case
GE
:
cr16_cmp_str
=
"le"
;
break
;
case
GEU
:
cr16_cmp_str
=
"ls"
;
break
;
case
LE
:
cr16_cmp_str
=
"ge"
;
break
;
case
LEU
:
cr16_cmp_str
=
"hs"
;
break
;
default
:
gcc_unreachable
(
)
;
}
fprintf
(
file
,
"%s"
,
cr16_cmp_str
)
;
return
;
}
case
'$'
:
putc
(
'$'
,
file
)
;
return
;
case
'p'
:
if
(
GET_CODE
(
x
)
==
REG
)
{
fprintf
(
file
,
"%s"
,
reg_names
[
REGNO
(
x
)
]
)
;
return
;
}
break
;
case
'b'
:
fprintf
(
file
,
"0x%lx"
,
INTVAL
(
x
)
)
;
return
;
case
'r'
:
fprintf
(
file
,
"%d"
,
cr16_operand_bit_pos
(
INTVAL
(
x
)
,
0
)
)
;
return
;
case
's'
:
fprintf
(
file
,
"%d"
,
cr16_operand_bit_pos
(
INTVAL
(
x
)
,
1
)
)
;
return
;
case
'g'
:
ptr_dereference
=
1
;
case
'f'
:
case
0
:
switch
(
GET_CODE
(
x
)
)
{
case
REG
:
if
(
GET_MODE_BITSIZE
(
GET_MODE
(
x
)
)
>
BITS_PER_WORD
)
{
if
(
LONG_REG_P
(
REGNO
(
x
)
)
)
fprintf
(
file
,
"(%s)"
,
reg_names
[
REGNO
(
x
)
]
)
;
else
fprintf
(
file
,
"(%s,%s)"
,
reg_names
[
REGNO
(
x
)
+
1
]
,
reg_names
[
REGNO
(
x
)
]
)
;
}
else
fprintf
(
file
,
"%s"
,
reg_names
[
REGNO
(
x
)
]
)
;
return
;
case
MEM
:
output_address
(
GET_MODE
(
x
)
,
XEXP
(
x
,
0
)
)
;
return
;
case
CONST_DOUBLE
:
{
long
l
;
REAL_VALUE_TO_TARGET_SINGLE
(
*
CONST_DOUBLE_REAL_VALUE
(
x
)
,
l
)
;
fprintf
(
file
,
"$0x%lx"
,
l
)
;
return
;
}
case
CONST_INT
:
{
fprintf
(
file
,
"$%ld"
,
INTVAL
(
x
)
)
;
return
;
}
case
UNSPEC
:
switch
(
XINT
(
x
,
1
)
)
{
default
:
gcc_unreachable
(
)
;
}
break
;
default
:
if
(
!
ptr_dereference
)
{
putc
(
'$'
,
file
)
;
}
cr16_print_operand_address
(
file
,
VOIDmode
,
x
)
;
return
;
}
gcc_unreachable
(
)
;
default
:
output_operand_lossage
(
"invalid %%xn code"
)
;
}
gcc_unreachable
(
)
;
}
</s>

Implements the macro PRINT_OPERAND defined in cr16.h .


<s> poly_int64 cr16_push_rounding ( poly_int64 bytes ) { return ( bytes + 1 ) & ~ 1 ; } </s>


<s> static int cr16_register_move_cost ( machine_mode mode ATTRIBUTE_UNUSED , reg_class_t from ATTRIBUTE_UNUSED , reg_class_t to ) { return ( to != GENERAL_REGS ? 8 : 2 ) ; } </s>

Implement ` TARGET_REGISTER_MOVE_COST ' .


<s> enum reg_class cr16_regno_reg_class ( int regno ) { if ( ( regno >= 0 ) && ( regno < CR16_FIRST_DWORD_REGISTER ) ) return SHORT_REGS ; if ( ( regno >= CR16_FIRST_DWORD_REGISTER ) && ( regno < FIRST_PSEUDO_REGISTER ) ) return LONG_REGS ; return NO_REGS ; } </s>

Return the class number of the smallest class containing reg number REGNO . This could be a conditional expression or could index an array .


<s> static bool cr16_return_in_memory ( const_tree type , const_tree fntype ATTRIBUTE_UNUSED ) { const HOST_WIDE_INT size = int_size_in_bytes ( type ) ; return ( ( size == - 1 ) || ( size > 8 ) ) ; } </s>

Implements hook TARGET_RETURN_IN_MEMORY .


<s> static inline unsigned int cr16_ret_register ( void ) { return 0 ; } </s>

Returns register number for function return value .


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

Implements hook TARGET_STRUCT_VALUE_RTX .


<s> static int enough_regs_for_param ( CUMULATIVE_ARGS * cum , const_tree type , machine_mode mode ) { int type_size ; int remaining_size ; if ( mode != BLKmode ) type_size = GET_MODE_BITSIZE ( mode ) ; else type_size = int_size_in_bytes ( type ) * BITS_PER_UNIT ; remaining_size = BITS_PER_WORD * ( MAX_REG_FOR_PASSING_ARGS - ( MIN_REG_FOR_PASSING_ARGS + cum -> ints ) + 1 ) ; if ( ( remaining_size >= type_size ) && ( type_size <= 2 * BITS_PER_WORD ) ) return ( type_size + BITS_PER_WORD - 1 ) / BITS_PER_WORD ; return 0 ; } </s>

If enough param regs are available for passing the param of type TYPE return * the number of registers needed else 0 .


<s> int legitimate_pic_operand_p ( rtx x ) { switch ( GET_CODE ( x ) ) { case SYMBOL_REF : return 0 ; case LABEL_REF : return 0 ; case CONST : if ( GET_CODE ( XEXP ( x , 0 ) ) == PLUS && ( GET_CODE ( XEXP ( XEXP ( x , 0 ) , 0 ) ) == SYMBOL_REF || GET_CODE ( XEXP ( XEXP ( x , 0 ) , 0 ) ) == LABEL_REF ) && ( GET_CODE ( XEXP ( XEXP ( x , 0 ) , 1 ) ) == CONST_INT ) ) return 0 ; break ; case MEM : return legitimate_pic_operand_p ( XEXP ( x , 0 ) ) ; default : break ; } return 1 ; } </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> rtx legitimize_pic_address ( rtx orig , machine_mode mode ATTRIBUTE_UNUSED , rtx reg ) { if ( GET_CODE ( orig ) == SYMBOL_REF || GET_CODE ( orig ) == LABEL_REF ) { if ( reg == 0 ) reg = gen_reg_rtx ( Pmode ) ; if ( flag_pic == NEAR_PIC ) { emit_insn ( gen_unspec_bro_addr ( reg , orig ) ) ; emit_insn ( gen_addsi3 ( reg , reg , pic_offset_table_rtx ) ) ; } else if ( flag_pic == FAR_PIC ) { emit_insn ( gen_unspec_got_addr ( reg , orig ) ) ; } return reg ; } else if ( GET_CODE ( orig ) == CONST ) { rtx base , offset ; if ( GET_CODE ( XEXP ( orig , 0 ) ) == PLUS && XEXP ( XEXP ( orig , 0 ) , 0 ) == pic_offset_table_rtx ) return orig ; if ( reg == 0 ) { gcc_assert ( can_create_pseudo_p ( ) ) ; reg = gen_reg_rtx ( Pmode ) ; } gcc_assert ( GET_CODE ( XEXP ( orig , 0 ) ) == PLUS ) ; base = legitimize_pic_address ( XEXP ( XEXP ( orig , 0 ) , 0 ) , Pmode , reg ) ; offset = legitimize_pic_address ( XEXP ( XEXP ( orig , 0 ) , 1 ) , Pmode , base == reg ? 0 : reg ) ; emit_insn ( gen_addsi3 ( reg , base , offset ) ) ; return reg ; } return orig ; } </s>

Legitimize PIC addresses . If the address is already position-independent , we return ORIG . Newly generated position-independent addresses go into a reg . This is REG if nonzero , otherwise we allocate register ( s ) as necessary .


<s> void notice_update_cc ( rtx exp ) { if ( GET_CODE ( exp ) == SET ) { if ( SET_DEST ( exp ) == pc_rtx ) return ; if ( REG_P ( SET_DEST ( exp ) ) && ( REG_P ( SET_SRC ( exp ) ) || GET_CODE ( SET_SRC ( exp ) ) == MEM ) ) { return ; } if ( GET_CODE ( SET_DEST ( exp ) ) == MEM && REG_P ( SET_SRC ( exp ) ) ) { return ; } } CC_STATUS_INIT ; return ; } </s>

On the 68000 , all the insns to store in an address register fail to set the cc 's . However , in some cases these instructions can make it possibly invalid to use the saved cc 's . In those cases we clear out some or all of the saved cc 's so they wo n't be used .