<s> static void h8300_emit_stack_adjustment ( int sign , HOST_WIDE_INT size ) { if ( size == 0 ) return ; if ( Pmode == HImode ) { rtx_insn * x = emit_insn ( gen_addhi3 ( stack_pointer_rtx , stack_pointer_rtx , GEN_INT ( sign * size ) ) ) ; if ( size < 4 ) F ( x , 0 ) ; } else F ( emit_insn ( gen_addsi3 ( stack_pointer_rtx , stack_pointer_rtx , GEN_INT ( sign * size ) ) ) , 0 ) ; } </s>

Output assembly language to FILE for the operation OP with operand size SIZE to adjust the stack pointer .


<s> static void h8300_encode_section_info ( tree decl , rtx rtl , int first ) { int extra_flags = 0 ; default_encode_section_info ( decl , rtl , first ) ; if ( TREE_CODE ( decl ) == FUNCTION_DECL && h8300_funcvec_function_p ( decl ) ) extra_flags = SYMBOL_FLAG_FUNCVEC_FUNCTION ; else if ( TREE_CODE ( decl ) == VAR_DECL && ( TREE_STATIC ( decl ) || DECL_EXTERNAL ( decl ) ) ) { if ( h8300_eightbit_data_p ( decl ) ) extra_flags = SYMBOL_FLAG_EIGHTBIT_DATA ; else if ( first && h8300_tiny_data_p ( decl ) ) extra_flags = SYMBOL_FLAG_TINY_DATA ; } if ( extra_flags ) SYMBOL_REF_FLAGS ( XEXP ( rtl , 0 ) ) |= extra_flags ; } </s>

Mark function vectors , and various small data objects .


<s> void h8300_expand_branch ( rtx operands [ ] ) { enum rtx_code code = GET_CODE ( operands [ 0 ] ) ; rtx op0 = operands [ 1 ] ; rtx op1 = operands [ 2 ] ; rtx label = operands [ 3 ] ; rtx tmp ; tmp = gen_rtx_COMPARE ( VOIDmode , op0 , op1 ) ; emit_insn ( gen_rtx_SET ( cc0_rtx , tmp ) ) ; tmp = gen_rtx_fmt_ee ( code , VOIDmode , cc0_rtx , const0_rtx ) ; tmp = gen_rtx_IF_THEN_ELSE ( VOIDmode , tmp , gen_rtx_LABEL_REF ( VOIDmode , label ) , pc_rtx ) ; emit_jump_insn ( gen_rtx_SET ( pc_rtx , tmp ) ) ; } </s>


<s> void h8300_expand_epilogue ( bool sibcall_p ) { int regno ; int saved_regs ; int n_regs ; HOST_WIDE_INT frame_size ; bool returned_p ; if ( h8300_os_task_function_p ( current_function_decl ) ) return ; frame_size = round_frame_size ( get_frame_size ( ) ) ; returned_p = false ; h8300_emit_stack_adjustment ( 1 , frame_size ) ; saved_regs = compute_saved_regs ( ) ; for ( regno = FIRST_PSEUDO_REGISTER - 1 ; regno >= 0 ; regno -= n_regs ) { n_regs = 1 ; if ( saved_regs & ( 1 << regno ) ) { if ( TARGET_H8300S ) { if ( ( TARGET_H8300SX || ( regno & 3 ) == 3 ) && ( ( saved_regs << 3 >> regno ) & 0x0f ) == 0x0f ) n_regs = 4 ; else if ( ( TARGET_H8300SX || ( regno & 3 ) == 2 ) && ( ( saved_regs << 2 >> regno ) & 0x07 ) == 0x07 ) n_regs = 3 ; else if ( ( TARGET_H8300SX || ( regno & 1 ) == 1 ) && ( ( saved_regs << 1 >> regno ) & 0x03 ) == 0x03 ) n_regs = 2 ; } if ( TARGET_H8300SX && ! sibcall_p && ! frame_pointer_needed && frame_size == 0 && ( saved_regs & ( ( 1 << ( regno - n_regs + 1 ) ) - 1 ) ) == 0 ) returned_p = true ; h8300_push_pop ( regno - n_regs + 1 , n_regs , true , returned_p ) ; } } if ( frame_pointer_needed ) { if ( TARGET_H8300SX && ! sibcall_p ) returned_p = true ; h8300_push_pop ( HARD_FRAME_POINTER_REGNUM , 1 , true , returned_p ) ; } if ( ! returned_p && ! sibcall_p ) emit_jump_insn ( ret_rtx ) ; } </s>

Generate RTL code for the function epilogue .


<s> int h8300_expand_movsi ( rtx operands [ ] ) { rtx src = operands [ 1 ] ; rtx dst = operands [ 0 ] ; if ( ! reload_in_progress && ! reload_completed ) { if ( ! register_operand ( dst , GET_MODE ( dst ) ) ) { rtx tmp = gen_reg_rtx ( GET_MODE ( dst ) ) ; emit_move_insn ( tmp , src ) ; operands [ 1 ] = tmp ; } } return 0 ; } </s>


<s> void h8300_expand_prologue ( void ) { int regno ; int saved_regs ; int n_regs ; if ( h8300_os_task_function_p ( current_function_decl ) ) return ; if ( h8300_monitor_function_p ( current_function_decl ) ) emit_insn ( gen_monitor_prologue ( ) ) ; if ( frame_pointer_needed ) { push ( HARD_FRAME_POINTER_REGNUM ) ; F ( emit_move_insn ( hard_frame_pointer_rtx , stack_pointer_rtx ) , 0 ) ; } saved_regs = compute_saved_regs ( ) ; for ( regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno += n_regs ) { n_regs = 1 ; if ( saved_regs & ( 1 << regno ) ) { if ( TARGET_H8300S ) { if ( ( TARGET_H8300SX || ( regno & 3 ) == 0 ) && ( ( saved_regs >> regno ) & 0x0f ) == 0x0f ) n_regs = 4 ; else if ( ( TARGET_H8300SX || ( regno & 3 ) == 0 ) && ( ( saved_regs >> regno ) & 0x07 ) == 0x07 ) n_regs = 3 ; else if ( ( TARGET_H8300SX || ( regno & 1 ) == 0 ) && ( ( saved_regs >> regno ) & 0x03 ) == 0x03 ) n_regs = 2 ; } h8300_push_pop ( regno , n_regs , false , false ) ; } } h8300_emit_stack_adjustment ( - 1 , round_frame_size ( get_frame_size ( ) ) ) ; if ( flag_stack_usage_info ) current_function_static_stack_size = round_frame_size ( get_frame_size ( ) ) + ( __builtin_popcount ( saved_regs ) * UNITS_PER_WORD ) + ( frame_pointer_needed ? UNITS_PER_WORD : 0 ) ; } </s>

Generate RTL code for the function prologue .


<s> void h8300_expand_store ( rtx operands [ ] ) { rtx dest = operands [ 0 ] ; enum rtx_code code = GET_CODE ( operands [ 1 ] ) ; rtx op0 = operands [ 2 ] ; rtx op1 = operands [ 3 ] ; rtx tmp ; tmp = gen_rtx_COMPARE ( VOIDmode , op0 , op1 ) ; emit_insn ( gen_rtx_SET ( cc0_rtx , tmp ) ) ; tmp = gen_rtx_fmt_ee ( code , GET_MODE ( dest ) , cc0_rtx , const0_rtx ) ; emit_insn ( gen_rtx_SET ( dest , tmp ) ) ; } </s>


<s> static void h8300_file_end ( void ) { fputs ( "\t.end\n" , asm_out_file ) ; } </s>

Output assembly language code for the end of file .


<s> static void h8300_file_start ( void ) { default_file_start ( ) ; if ( TARGET_H8300SX ) fputs ( TARGET_NORMAL_MODE ? "\t.h8300sxn\n" : "\t.h8300sx\n" , asm_out_file ) ; else if ( TARGET_H8300S ) fputs ( TARGET_NORMAL_MODE ? "\t.h8300sn\n" : "\t.h8300s\n" , asm_out_file ) ; else if ( TARGET_H8300H ) fputs ( TARGET_NORMAL_MODE ? "\t.h8300hn\n" : "\t.h8300h\n" , asm_out_file ) ; } </s>

Output assembly code for the start of the file .


<s> static rtx h8300_function_arg ( cumulative_args_t cum_v , const function_arg_info & arg ) { CUMULATIVE_ARGS * cum = get_cumulative_args ( cum_v ) ; static const char * const hand_list [ ] = { "__main" , "__cmpsi2" , "__divhi3" , "__modhi3" , "__udivhi3" , "__umodhi3" , "__divsi3" , "__modsi3" , "__udivsi3" , "__umodsi3" , "__mulhi3" , "__mulsi3" , "__reg_memcpy" , "__reg_memset" , "__ucmpsi2" , 0 , } ; rtx result = NULL_RTX ; const char * fname ; int regpass = 0 ; if ( ! arg . named ) return NULL_RTX ; if ( TARGET_QUICKCALL ) regpass = 3 ; if ( cum -> libcall ) { const char * const * p ; fname = XSTR ( cum -> libcall , 0 ) ; for ( p = hand_list ; * p && strcmp ( * p , fname ) != 0 ; p ++ ) ; if ( * p ) regpass = 4 ; } if ( regpass ) { int size = arg . promoted_size_in_bytes ( ) ; if ( size + cum -> nbytes <= regpass * UNITS_PER_WORD && cum -> nbytes / UNITS_PER_WORD <= 3 ) result = gen_rtx_REG ( arg . mode , cum -> nbytes / UNITS_PER_WORD ) ; } return result ; } </s>

If the next function argument with MODE and TYPE is to be passed in a register , return a reg RTX for the hard register in which to pass the argument . CUM represents the state after the last argument . If the argument is to be pushed , NULL_RTX is returned . On the H8/300 all normal args are pushed , unless -mquickcall in which case the first 3 arguments are passed in registers .


<s> static void h8300_function_arg_advance ( cumulative_args_t cum_v , const function_arg_info & arg ) { CUMULATIVE_ARGS * cum = get_cumulative_args ( cum_v ) ; cum -> nbytes += ( ( arg . promoted_size_in_bytes ( ) + UNITS_PER_WORD - 1 ) & - UNITS_PER_WORD ) ; } </s>

Update the data in CUM to advance over an argument of mode MODE and data type TYPE . ( TYPE is null for libcalls where that information may not be available . )


Worker function for TARGET_FUNCTION_VALUE . On the H8 the return value is in R0/R1 .


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

Worker function for TARGET_FUNCTION_VALUE_REGNO_P . On the H8 , R0 is the only register thus used .


<s> int h8300_funcvec_function_p ( tree func ) { tree a ; if ( TREE_CODE ( func ) != FUNCTION_DECL ) return 0 ; a = lookup_attribute ( "function_vector" , DECL_ATTRIBUTES ( func ) ) ; return a != NULL_TREE ; } </s>

Return nonzero if FUNC is a function that should be called through the function vector .


<s> static rtx h8300_get_index ( rtx x , machine_mode mode , int * size ) { int dummy , factor ; if ( size == 0 ) size = & dummy ; factor = ( mode == VOIDmode ? 0 : GET_MODE_SIZE ( mode ) ) ; if ( TARGET_H8300SX && factor <= 4 && ( mode == VOIDmode || GET_MODE_CLASS ( mode ) == MODE_INT || GET_MODE_CLASS ( mode ) == MODE_FLOAT ) ) { if ( factor <= 1 && GET_CODE ( x ) == ZERO_EXTEND ) { * size = GET_MODE_SIZE ( GET_MODE ( XEXP ( x , 0 ) ) ) ; return XEXP ( x , 0 ) ; } else { rtx index ; if ( GET_CODE ( x ) == AND && GET_CODE ( XEXP ( x , 1 ) ) == CONST_INT && ( factor == 0 || INTVAL ( XEXP ( x , 1 ) ) == 0xff * factor || INTVAL ( XEXP ( x , 1 ) ) == 0xffff * factor ) ) { index = XEXP ( x , 0 ) ; * size = ( INTVAL ( XEXP ( x , 1 ) ) >= 0xffff ? 2 : 1 ) ; } else { index = x ; * size = 4 ; } if ( GET_CODE ( index ) == MULT && GET_CODE ( XEXP ( index , 1 ) ) == CONST_INT && ( factor == 0 || factor == INTVAL ( XEXP ( index , 1 ) ) ) ) return XEXP ( index , 0 ) ; } } * size = 0 ; return x ; } </s>

Given that X occurs in an address of the form ( plus X constant ) , return the part of X that is expected to be a register . There are four kinds of addressing mode to recognize : @ ( dd , Rn ) @ ( dd , RnL.b ) @ ( dd , Rn.w ) @ ( dd , ERn.l ) If SIZE is nonnull , and the address is one of the last three forms , set * SIZE to the index multiplication factor . Set it to 0 for plain @ ( dd , Rn ) addresses . MODE is the mode of the value being accessed . It can be VOIDmode if the address is known to be valid , but its mode is unknown .


<s>
static
tree
h8300_handle_eightbit_data_attribute
(
tree
*
node
,
tree
name
,
tree
args
ATTRIBUTE_UNUSED
,
int
flags
ATTRIBUTE_UNUSED
,
bool
*
no_add_attrs
)
{
tree
decl
=
*
node
;
if
(
TREE_STATIC
(
decl
)
||
DECL_EXTERNAL
(
decl
)
)
{
set_decl_section_name
(
decl
,
".eight"
)
;
}
else
{
warning
(
OPT_Wattributes
,
"%qE attribute ignored"
,
name
)
;
*
no_add_attrs
=
true
;
}
return
NULL_TREE
;
}
</s>

Handle an `` eightbit_data '' attribute ; arguments as in struct attribute_spec.handler .


"%qE attribute only applies to functions"

Handle an attribute requiring a FUNCTION_DECL ; arguments as in struct attribute_spec.handler .


<s>
static
tree
h8300_handle_tiny_data_attribute
(
tree
*
node
,
tree
name
,
tree
args
ATTRIBUTE_UNUSED
,
int
flags
ATTRIBUTE_UNUSED
,
bool
*
no_add_attrs
)
{
tree
decl
=
*
node
;
if
(
TREE_STATIC
(
decl
)
||
DECL_EXTERNAL
(
decl
)
)
{
set_decl_section_name
(
decl
,
".tiny"
)
;
}
else
{
warning
(
OPT_Wattributes
,
"%qE attribute ignored"
,
name
)
;
*
no_add_attrs
=
true
;
}
return
NULL_TREE
;
}
</s>

Handle an `` tiny_data '' attribute ; arguments as in struct attribute_spec.handler .


<s> static bool h8300_hard_regno_mode_ok ( unsigned int regno , machine_mode mode ) { return regno == MAC_REG ? mode == SImode : 1 ; } </s>

Worker function for HARD_REGNO_MODE_OK .


Return nonzero if register OLD_REG can be renamed to register NEW_REG .


Returns true if register REGNO is safe to be allocated as a scratch register in the current function .


<s> int h8300_initial_elimination_offset ( int from , int to ) { int pc_size = POINTER_SIZE / BITS_PER_UNIT ; int fp_size = frame_pointer_needed * UNITS_PER_WORD ; int saved_regs_size = 0 ; int frame_size = round_frame_size ( get_frame_size ( ) ) ; int regno ; for ( regno = 0 ; regno <= HARD_FRAME_POINTER_REGNUM ; regno ++ ) if ( WORD_REG_USED ( regno ) ) saved_regs_size += UNITS_PER_WORD ; saved_regs_size -= fp_size ; switch ( to ) { case HARD_FRAME_POINTER_REGNUM : switch ( from ) { case ARG_POINTER_REGNUM : return pc_size + fp_size ; case RETURN_ADDRESS_POINTER_REGNUM : return fp_size ; case FRAME_POINTER_REGNUM : return - saved_regs_size ; default : gcc_unreachable ( ) ; } break ; case STACK_POINTER_REGNUM : switch ( from ) { case ARG_POINTER_REGNUM : return pc_size + saved_regs_size + frame_size ; case RETURN_ADDRESS_POINTER_REGNUM : return saved_regs_size + frame_size ; case FRAME_POINTER_REGNUM : return frame_size ; default : gcc_unreachable ( ) ; } break ; default : gcc_unreachable ( ) ; } gcc_unreachable ( ) ; } </s>

Function for INITIAL_ELIMINATION_OFFSET ( FROM , TO , OFFSET ) . Define the offset between two registers , one to be eliminated , and the other its replacement , at the start of a routine .


<s> static void h8300_init_libfuncs ( void ) { set_optab_libfunc ( smul_optab , HImode , "__mulhi3" ) ; set_optab_libfunc ( sdiv_optab , HImode , "__divhi3" ) ; set_optab_libfunc ( udiv_optab , HImode , "__udivhi3" ) ; set_optab_libfunc ( smod_optab , HImode , "__modhi3" ) ; set_optab_libfunc ( umod_optab , HImode , "__umodhi3" ) ; } </s>

Perform target dependent optabs initialization .


<s> static void h8300_insert_attributes ( tree node , tree * attributes ) { if ( TREE_CODE ( node ) == FUNCTION_DECL ) { if ( pragma_interrupt ) { pragma_interrupt = 0 ; * attributes = tree_cons ( get_identifier ( "interrupt_handler" ) , NULL , * attributes ) ; } if ( pragma_saveall ) { pragma_saveall = 0 ; * attributes = tree_cons ( get_identifier ( "saveall" ) , NULL , * attributes ) ; } } } </s>

Generate an 'interrupt_handler ' attribute for decls . We convert all the pragmas to corresponding attributes .


<s> unsigned int h8300_insn_length_from_table ( rtx_insn * insn , rtx * operands ) { switch ( get_attr_length_table ( insn ) ) { case LENGTH_TABLE_NONE : gcc_unreachable ( ) ; case LENGTH_TABLE_ADD : if ( GET_MODE ( operands [ 0 ] ) == QImode ) return h8300_binary_length ( insn , & addb_length_table ) ; else if ( GET_MODE ( operands [ 0 ] ) == HImode ) return h8300_binary_length ( insn , & addw_length_table ) ; else if ( GET_MODE ( operands [ 0 ] ) == SImode ) return h8300_binary_length ( insn , & addl_length_table ) ; gcc_unreachable ( ) ; case LENGTH_TABLE_LOGICB : return h8300_binary_length ( insn , & logicb_length_table ) ; case LENGTH_TABLE_MOVB : return h8300_move_length ( operands , & movb_length_table ) ; case LENGTH_TABLE_MOVW : return h8300_move_length ( operands , & movw_length_table ) ; case LENGTH_TABLE_MOVL : return h8300_move_length ( operands , & movl_length_table ) ; case LENGTH_TABLE_MOVA : return h8300_mova_length ( operands [ 0 ] , operands [ 1 ] , operands [ 2 ] ) ; case LENGTH_TABLE_MOVA_ZERO : return h8300_mova_length ( operands [ 0 ] , operands [ 1 ] , const0_rtx ) ; case LENGTH_TABLE_UNARY : return h8300_unary_length ( operands [ 0 ] ) ; case LENGTH_TABLE_MOV_IMM4 : return 2 + h8300_classify_operand ( operands [ 0 ] , 0 , 0 ) ; case LENGTH_TABLE_SHORT_IMMEDIATE : return h8300_short_immediate_length ( operands [ 0 ] ) ; case LENGTH_TABLE_BITFIELD : return h8300_bitfield_length ( operands [ 0 ] , operands [ 1 ] ) ; case LENGTH_TABLE_BITBRANCH : return h8300_bitfield_length ( operands [ 1 ] , operands [ 2 ] ) - 2 ; default : gcc_unreachable ( ) ; } } </s>

Compute the length of INSN based on its length_table attribute . OPERANDS is the array of its operands .


<s> static int h8300_interrupt_function_p ( tree func ) { tree a ; if ( TREE_CODE ( func ) != FUNCTION_DECL ) return 0 ; a = lookup_attribute ( "interrupt_handler" , DECL_ATTRIBUTES ( func ) ) ; return a != NULL_TREE ; } </s>

Return nonzero if FUNC is an interrupt function as specified by the `` interrupt '' attribute .


<s> int h8300_ldm_stm_parallel ( rtvec vec , int load_p , int first ) { rtx last ; int nregs , i , regno , adjust ; if ( GET_NUM_ELEM ( vec ) < 3 ) return false ; nregs = GET_NUM_ELEM ( vec ) - first - 1 ; regno = h8300_ldm_stm_regno ( RTVEC_ELT ( vec , first ) , load_p , 0 , nregs ) ; if ( regno < 0 || regno + nregs > 8 ) return false ; if ( ! TARGET_H8300SX ) { if ( ( regno & 1 ) != 0 ) return false ; if ( nregs > 2 && ( regno & 3 ) != 0 ) return false ; } for ( i = 1 ; i < nregs ; i ++ ) if ( h8300_ldm_stm_regno ( RTVEC_ELT ( vec , first + i ) , load_p , i , nregs ) != regno + i ) return false ; last = RTVEC_ELT ( vec , first + nregs ) ; adjust = ( load_p ? nregs : - nregs ) * 4 ; return ( GET_CODE ( last ) == SET && SET_DEST ( last ) == stack_pointer_rtx && h8300_stack_offset_p ( SET_SRC ( last ) , adjust ) ) ; } </s>

Return true if the elements of VEC starting at FIRST describe an ldm or stm instruction ( LOAD_P says which ) .


<s> static int h8300_ldm_stm_regno ( rtx x , int load_p , int index , int nregs ) { int regindex , memindex , offset ; if ( load_p ) regindex = 0 , memindex = 1 , offset = ( nregs - index - 1 ) * 4 ; else memindex = 0 , regindex = 1 , offset = ( index + 1 ) * - 4 ; if ( GET_CODE ( x ) == SET && GET_CODE ( XEXP ( x , regindex ) ) == REG && GET_CODE ( XEXP ( x , memindex ) ) == MEM && h8300_stack_offset_p ( XEXP ( XEXP ( x , memindex ) , 0 ) , offset ) ) return REGNO ( XEXP ( x , regindex ) ) ; return - 1 ; } </s>

A subroutine of h8300_ldm_stm_parallel . X is one pattern in something that may be an ldm or stm instruction . If it fits the required template , return the register it loads or stores , otherwise return -1 . LOAD_P is true if X should be a load , false if it should be a store . NREGS is the number of registers that the whole instruction is expected to load or store . INDEX is the index of the register that X should load or store , relative to the lowest-numbered register .


<s> static bool h8300_legitimate_address_p ( machine_mode mode , rtx x , bool strict ) { if ( h8300_rtx_ok_for_base_p ( x , strict ) ) return 1 ; if ( CONSTANT_ADDRESS_P ( x ) ) return 1 ; if ( TARGET_H8300SX && ( GET_CODE ( x ) == PRE_INC || GET_CODE ( x ) == PRE_DEC || GET_CODE ( x ) == POST_INC || GET_CODE ( x ) == POST_DEC ) && h8300_rtx_ok_for_base_p ( XEXP ( x , 0 ) , strict ) ) return 1 ; if ( GET_CODE ( x ) == PLUS && CONSTANT_ADDRESS_P ( XEXP ( x , 1 ) ) && h8300_rtx_ok_for_base_p ( h8300_get_index ( XEXP ( x , 0 ) , mode , 0 ) , strict ) ) return 1 ; return 0 ; } </s>

Return nozero if X is a legitimate address . On the H8/300 , a legitimate address has the form REG , REG+CONSTANT_ADDRESS or CONSTANT_ADDRESS .


<s> static unsigned int h8300_length_from_table ( rtx op1 , rtx op2 , const h8300_length_table * table ) { enum h8300_operand_class op1_class , op2_class ; unsigned int size , immediate_length ; size = GET_MODE_SIZE ( GET_MODE ( op1 ) ) ; immediate_length = ( h8300_classify_operand ( op1 , size , & op1_class ) + h8300_classify_operand ( op2 , size , & op2_class ) ) ; return immediate_length + ( * table ) [ op1_class - 1 ] [ op2_class ] ; } </s>

Return the length of the instruction described by TABLE given that its operands are OP1 and OP2 . OP1 must be an h8300_dst_operand and OP2 must be an h8300_src_operand .


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

Worker function for TARGET_LIBCALL_VALUE . On the H8 the return value is in R0/R1 .


<s> static bool h8300_modes_tieable_p ( machine_mode mode1 , machine_mode mode2 ) { return ( mode1 == mode2 || ( ( mode1 == QImode || mode1 == HImode || mode1 == SImode ) && ( mode2 == QImode || mode2 == HImode || mode2 == SImode ) ) ) ; } </s>


<s> static bool h8300_mode_dependent_address_p ( const_rtx addr , addr_space_t as ATTRIBUTE_UNUSED ) { if ( GET_CODE ( addr ) == PLUS && h8300_get_index ( XEXP ( addr , 0 ) , VOIDmode , 0 ) != XEXP ( addr , 0 ) ) return true ; return false ; } </s>

Worker function for TARGET_MODE_DEPENDENT_ADDRESS_P . On the H8/300 , the predecrement and postincrement address depend thus ( the amount of decrement or increment being the length of the operand ) .


<s> static int h8300_monitor_function_p ( tree func ) { tree a ; if ( TREE_CODE ( func ) != FUNCTION_DECL ) return 0 ; a = lookup_attribute ( "monitor" , DECL_ATTRIBUTES ( func ) ) ; return a != NULL_TREE ; } </s>

Return nonzero if FUNC is a monitor function as specified by the `` monitor '' attribute .


<s> static unsigned int h8300_mova_length ( rtx dest , rtx src , rtx offset ) { unsigned int size ; size = ( 2 + h8300_constant_length ( offset ) + h8300_classify_operand ( src , GET_MODE_SIZE ( GET_MODE ( src ) ) , 0 ) ) ; if ( ! REG_P ( dest ) || ! REG_P ( src ) || REGNO ( src ) != REGNO ( dest ) ) size += 2 ; return size ; } </s>

Return the length of a mova instruction with the given operands . DEST is the register destination , SRC is the source address and OFFSET is the 16-bit or 32-bit displacement .


<s> static unsigned int h8300_move_length ( rtx * operands , const h8300_length_table * table ) { unsigned int size ; size = h8300_length_from_table ( operands [ 0 ] , operands [ 1 ] , table ) ; if ( REG_P ( operands [ 0 ] ) && h8300_short_move_mem_p ( operands [ 1 ] , POST_INC ) ) size -= 2 ; if ( REG_P ( operands [ 1 ] ) && h8300_short_move_mem_p ( operands [ 0 ] , PRE_DEC ) ) size -= 2 ; return size ; } </s>

Calculate the length of move instruction INSN using the given length table . Although the tables are correct for most cases , there is some irregularity in the length of mov.b and mov.w . The following forms : mov @ ERs+ , Rd mov @ ( d:16 , ERs ) , Rd mov Rs , @ -ERd mov Rs , @ ( d:16 , ERd ) are two bytes shorter than most other `` mov Rs , @ complex '' or `` mov @ complex , Rd '' combinations .


<s> bool h8300_move_ok ( rtx dest , rtx src ) { rtx addr , other ; if ( MEM_P ( dest ) ) { if ( MEM_P ( src ) || CONSTANT_P ( src ) ) return false ; addr = XEXP ( dest , 0 ) ; other = src ; } else if ( MEM_P ( src ) ) { addr = XEXP ( src , 0 ) ; other = dest ; } else return true ; if ( GET_RTX_CLASS ( GET_CODE ( addr ) ) != RTX_AUTOINC ) return true ; addr = XEXP ( addr , 0 ) ; if ( addr == stack_pointer_rtx ) return register_no_sp_elim_operand ( other , VOIDmode ) ; else return ! reg_overlap_mentioned_p ( other , addr ) ; } </s>

Helper function for the move patterns . Make sure a move is legitimate .


<s> bool h8300_operands_match_p ( rtx * operands ) { if ( register_operand ( operands [ 0 ] , VOIDmode ) && register_operand ( operands [ 1 ] , VOIDmode ) ) return true ; if ( h8sx_mergeable_memrefs_p ( operands [ 0 ] , operands [ 1 ] ) ) return true ; return false ; } </s>

Return true if OPERANDS [ 1 ] can be mapped to the same assembly operand as OPERANDS [ 0 ] .


<s> static int h8300_os_task_function_p ( tree func ) { tree a ; if ( TREE_CODE ( func ) != FUNCTION_DECL ) return 0 ; a = lookup_attribute ( "OS_Task" , DECL_ATTRIBUTES ( func ) ) ; return a != NULL_TREE ; } </s>

Return nonzero if FUNC is an OS_Task function as specified by the `` OS_Task '' attribute .


<s> static void h8300_print_operand_address ( FILE * file , machine_mode mode , rtx addr ) { rtx index ; int size ; switch ( GET_CODE ( addr ) ) { case REG : fprintf ( file , "%s" , h8_reg_names [ REGNO ( addr ) ] ) ; break ; case PRE_DEC : fprintf ( file , "-%s" , h8_reg_names [ REGNO ( XEXP ( addr , 0 ) ) ] ) ; break ; case POST_INC : fprintf ( file , "%s+" , h8_reg_names [ REGNO ( XEXP ( addr , 0 ) ) ] ) ; break ; case PRE_INC : fprintf ( file , "+%s" , h8_reg_names [ REGNO ( XEXP ( addr , 0 ) ) ] ) ; break ; case POST_DEC : fprintf ( file , "%s-" , h8_reg_names [ REGNO ( XEXP ( addr , 0 ) ) ] ) ; break ; case PLUS : fprintf ( file , "(" ) ; index = h8300_get_index ( XEXP ( addr , 0 ) , VOIDmode , & size ) ; if ( GET_CODE ( index ) == REG ) { h8300_print_operand_address ( file , mode , XEXP ( addr , 1 ) ) ; fprintf ( file , "," ) ; switch ( size ) { case 0 : h8300_print_operand_address ( file , mode , index ) ; break ; case 1 : h8300_print_operand ( file , index , 'X' ) ; fputs ( ".b" , file ) ; break ; case 2 : h8300_print_operand ( file , index , 'T' ) ; fputs ( ".w" , file ) ; break ; case 4 : h8300_print_operand ( file , index , 'S' ) ; fputs ( ".l" , file ) ; break ; } } else { h8300_print_operand_address ( file , mode , XEXP ( addr , 0 ) ) ; fprintf ( file , "+" ) ; h8300_print_operand_address ( file , mode , XEXP ( addr , 1 ) ) ; } fprintf ( file , ")" ) ; break ; case CONST_INT : { int n = INTVAL ( addr ) ; fprintf ( file , "%d" , n ) ; break ; } default : output_addr_const ( file , addr ) ; break ; } } </s>

Output assembly language output for the address ADDR to FILE .


<s> static bool h8300_print_operand_punct_valid_p ( unsigned char code ) { return ( code == '#' ) ; } </s>


<s> void h8300_pr_interrupt ( struct cpp_reader * pfile ATTRIBUTE_UNUSED ) { pragma_interrupt = 1 ; } </s>

Handle machine specific pragmas for compatibility with existing compilers for the H8/300 . pragma saveall generates prolog/epilog code which saves and restores all the registers on function entry . pragma interrupt saves and restores all registers , and exits with an rte instruction rather than an rts . A pointer to a function with this attribute may be safely used in an interrupt vector .


<s> static void h8300_push_pop ( int regno , int nregs , bool pop_p , bool return_p ) { int i , j ; rtvec vec ; rtx sp , offset , x ; if ( ! return_p && nregs == 1 ) { if ( pop_p ) pop ( regno ) ; else push ( regno ) ; return ; } vec = rtvec_alloc ( ( return_p ? 1 : 0 ) + nregs + 1 ) ; sp = stack_pointer_rtx ; i = 0 ; if ( return_p ) { RTVEC_ELT ( vec , i ) = ret_rtx ; i ++ ; } for ( j = 0 ; j < nregs ; j ++ ) { rtx lhs , rhs ; if ( pop_p ) { lhs = gen_rtx_REG ( SImode , regno + j ) ; rhs = gen_rtx_MEM ( SImode , plus_constant ( Pmode , sp , ( nregs - j - 1 ) * 4 ) ) ; } else { lhs = gen_rtx_MEM ( SImode , plus_constant ( Pmode , sp , ( j + 1 ) * - 4 ) ) ; rhs = gen_rtx_REG ( SImode , regno + j ) ; } RTVEC_ELT ( vec , i + j ) = gen_rtx_SET ( lhs , rhs ) ; } offset = GEN_INT ( ( pop_p ? nregs : - nregs ) * 4 ) ; RTVEC_ELT ( vec , i + j ) = gen_rtx_SET ( sp , gen_rtx_PLUS ( Pmode , sp , offset ) ) ; x = gen_rtx_PARALLEL ( VOIDmode , vec ) ; if ( ! pop_p ) x = Fpa ( x ) ; if ( return_p ) emit_jump_insn ( x ) ; else emit_insn ( x ) ; } </s>

Emit an instruction to push or pop NREGS consecutive registers starting at register REGNO . POP_P selects a pop rather than a push and RETURN_P is true if the instruction should return . It must be possible to do the requested operation in a single instruction . If NREGS == 1 & & ! RETURN_P , use a normal push or pop insn . Otherwise emit a parallel of the form : ( parallel [ ( return ) ; ; if RETURN_P ( save or restore REGNO ) ( save or restore REGNO + 1 ) ... ( save or restore REGNO + NREGS - 1 ) ( set sp ( plus sp ( const_int adjust ) ) ) ]


<s> poly_int64 h8300_push_rounding ( poly_int64 bytes ) { return ( ( bytes + PARM_BOUNDARY / 8 - 1 ) & ( - PARM_BOUNDARY / 8 ) ) ; } </s>

Implement PUSH_ROUNDING . On the H8/300 , @ -sp really pushes a byte if you ask it to - but that 's dangerous , so we claim that it always pushes a word , then we catch the mov.b rx , @ -sp and turn it into a mov.w rx , @ -sp on output . On the H8/300H , we simplify TARGET_QUICKCALL by setting this to 4 and doing a similar thing .


<s> static int h8300_register_move_cost ( machine_mode mode ATTRIBUTE_UNUSED , reg_class_t from , reg_class_t to ) { if ( from == MAC_REGS || to == MAC_REG ) return 6 ; else return 3 ; } </s>

Implements TARGET_REGISTER_MOVE_COST . Any SI register-to-register move may need to be reloaded , so inmplement h8300_register_move_cost to return > 2 so that reload never shortcuts .


<s> int h8300_regs_ok_for_stm ( int n , rtx operands [ ] ) { switch ( n ) { case 2 : return ( ( REGNO ( operands [ 0 ] ) == 0 && REGNO ( operands [ 1 ] ) == 1 ) || ( REGNO ( operands [ 0 ] ) == 2 && REGNO ( operands [ 1 ] ) == 3 ) || ( REGNO ( operands [ 0 ] ) == 4 && REGNO ( operands [ 1 ] ) == 5 ) ) ; case 3 : return ( ( REGNO ( operands [ 0 ] ) == 0 && REGNO ( operands [ 1 ] ) == 1 && REGNO ( operands [ 2 ] ) == 2 ) || ( REGNO ( operands [ 0 ] ) == 4 && REGNO ( operands [ 1 ] ) == 5 && REGNO ( operands [ 2 ] ) == 6 ) ) ; case 4 : return ( REGNO ( operands [ 0 ] ) == 0 && REGNO ( operands [ 1 ] ) == 1 && REGNO ( operands [ 2 ] ) == 2 && REGNO ( operands [ 3 ] ) == 3 ) ; default : gcc_unreachable ( ) ; } } </s>

Return nonzero if OPERANDS are valid for stm ( or ldm ) that pushes ( or pops ) N registers . OPERANDS are assumed to be an array of registers .


<s> static void h8300_reorg ( void ) { if ( flag_delayed_branch ) shorten_branches ( get_insns ( ) ) ; } </s>

Delayed-branch scheduling is more effective if we have some idea how long each instruction will be . Use a shorten_branches pass to get an initial estimate .


<s> rtx h8300_return_addr_rtx ( int count , rtx frame ) { rtx ret ; if ( count == 0 ) ret = gen_rtx_MEM ( Pmode , gen_rtx_REG ( Pmode , RETURN_ADDRESS_POINTER_REGNUM ) ) ; else if ( flag_omit_frame_pointer ) return ( rtx ) 0 ; else ret = gen_rtx_MEM ( Pmode , memory_address ( Pmode , plus_constant ( Pmode , frame , UNITS_PER_WORD ) ) ) ; set_mem_alias_set ( ret , get_frame_alias_set ( ) ) ; return ret ; } </s>


<s> static bool h8300_return_in_memory ( const_tree type , const_tree fntype ATTRIBUTE_UNUSED ) { return ( TYPE_MODE ( type ) == BLKmode || GET_MODE_SIZE ( TYPE_MODE ( type ) ) > 8 ) ; } </s>

Worker function for TARGET_RETURN_IN_MEMORY .


<s> static int h8300_rtx_ok_for_base_p ( rtx x , int strict ) { if ( GET_CODE ( x ) == SUBREG ) x = SUBREG_REG ( x ) ; return ( REG_P ( x ) && ( strict ? REG_OK_FOR_BASE_STRICT_P ( x ) : REG_OK_FOR_BASE_NONSTRICT_P ( x ) ) ) ; } </s>

Return nonzero if X is a REG or SUBREG suitable as a base register .


<s> static int h8300_saveall_function_p ( tree func ) { tree a ; if ( TREE_CODE ( func ) != FUNCTION_DECL ) return 0 ; a = lookup_attribute ( "saveall" , DECL_ATTRIBUTES ( func ) ) ; return a != NULL_TREE ; } </s>

Return nonzero if FUNC is a saveall function as specified by the `` saveall '' attribute .


<s> static int h8300_shift_costs ( rtx x ) { rtx operands [ 3 ] ; if ( GET_MODE ( x ) != QImode && GET_MODE ( x ) != HImode && GET_MODE ( x ) != SImode ) return 100 ; operands [ 0 ] = gen_rtx_REG ( GET_MODE ( x ) , 0 ) ; operands [ 1 ] = NULL ; operands [ 2 ] = XEXP ( x , 1 ) ; return compute_a_shift_length ( operands , GET_CODE ( x ) ) / 2 ; } </s>


<s> int h8300_shift_needs_scratch_p ( int count , machine_mode mode , enum rtx_code type ) { enum h8_cpu cpu ; int a , lr , ar ; if ( GET_MODE_BITSIZE ( mode ) <= count ) return 1 ; if ( TARGET_H8300S ) cpu = H8_S ; else cpu = H8_300H ; switch ( mode ) { case E_QImode : a = shift_alg_qi [ cpu ] [ SHIFT_ASHIFT ] [ count ] ; lr = shift_alg_qi [ cpu ] [ SHIFT_LSHIFTRT ] [ count ] ; ar = shift_alg_qi [ cpu ] [ SHIFT_ASHIFTRT ] [ count ] ; break ; case E_HImode : a = shift_alg_hi [ cpu ] [ SHIFT_ASHIFT ] [ count ] ; lr = shift_alg_hi [ cpu ] [ SHIFT_LSHIFTRT ] [ count ] ; ar = shift_alg_hi [ cpu ] [ SHIFT_ASHIFTRT ] [ count ] ; break ; case E_SImode : a = shift_alg_si [ cpu ] [ SHIFT_ASHIFT ] [ count ] ; lr = shift_alg_si [ cpu ] [ SHIFT_LSHIFTRT ] [ count ] ; ar = shift_alg_si [ cpu ] [ SHIFT_ASHIFTRT ] [ count ] ; break ; default : gcc_unreachable ( ) ; } if ( type == CLOBBER ) return ( a == SHIFT_LOOP || lr == SHIFT_LOOP || ar == SHIFT_LOOP || ( TARGET_H8300H && mode == SImode && count == 8 ) ) ; else if ( type == ASHIFT ) return ( a == SHIFT_LOOP || ( TARGET_H8300H && mode == SImode && count == 8 ) ) ; else if ( type == LSHIFTRT ) return ( lr == SHIFT_LOOP || ( TARGET_H8300H && mode == SImode && count == 8 ) ) ; else if ( type == ASHIFTRT ) return ( ar == SHIFT_LOOP || ( TARGET_H8300H && mode == SImode && count == 8 ) ) ; gcc_unreachable ( ) ; } </s>

Given COUNT and MODE of a shift , return 1 if a scratch reg may be needed for some shift with COUNT and MODE . Return 0 otherwise .


<s> static unsigned int h8300_short_immediate_length ( rtx op ) { enum h8300_operand_class opclass ; unsigned int size , operand_length ; size = GET_MODE_SIZE ( GET_MODE ( op ) ) ; operand_length = h8300_classify_operand ( op , size , & opclass ) ; switch ( opclass ) { case H8OP_REGISTER : return 2 ; case H8OP_MEM_BASE : case H8OP_MEM_ABSOLUTE : case H8OP_MEM_COMPLEX : return 4 + operand_length ; default : gcc_unreachable ( ) ; } } </s>

Likewise short immediate instructions such as add.w # xx:3 , OP .


<s> static bool h8300_short_move_mem_p ( rtx op , enum rtx_code inc_code ) { rtx addr ; unsigned int size ; if ( GET_CODE ( op ) != MEM ) return false ; addr = XEXP ( op , 0 ) ; size = GET_MODE_SIZE ( GET_MODE ( op ) ) ; if ( size != 1 && size != 2 ) return false ; return ( GET_CODE ( addr ) == inc_code || ( GET_CODE ( addr ) == PLUS && GET_CODE ( XEXP ( addr , 0 ) ) == REG && h8300_displacement_length ( addr , size ) == 2 ) ) ; } </s>

Subroutine of h8300_move_length . Return true if OP is 1- or 2-byte memory reference and either ( 1 ) it has the form @ ( d:16 , Rn ) or ( 2 ) its address has the code given by INC_CODE .


<s> static int h8300_stack_offset_p ( rtx x , int offset ) { if ( offset == 0 ) return x == stack_pointer_rtx ; return ( GET_CODE ( x ) == PLUS && XEXP ( x , 0 ) == stack_pointer_rtx && GET_CODE ( XEXP ( x , 1 ) ) == CONST_INT && INTVAL ( XEXP ( x , 1 ) ) == offset ) ; } </s>

Return true if X has the value sp + OFFSET .


<s> int h8300_tiny_constant_address_p ( rtx x ) { const unsigned HOST_WIDE_INT h1 = trunc_int_for_mode ( 0x00000000 , SImode ) ; const unsigned HOST_WIDE_INT h2 = trunc_int_for_mode ( 0x00007fff , SImode ) ; const unsigned HOST_WIDE_INT h3 = trunc_int_for_mode ( 0x00ff8000 , SImode ) ; const unsigned HOST_WIDE_INT h4 = trunc_int_for_mode ( 0x00ffffff , SImode ) ; const unsigned HOST_WIDE_INT s1 = trunc_int_for_mode ( 0x00000000 , SImode ) ; const unsigned HOST_WIDE_INT s2 = trunc_int_for_mode ( 0x00007fff , SImode ) ; const unsigned HOST_WIDE_INT s3 = trunc_int_for_mode ( 0xffff8000 , SImode ) ; const unsigned HOST_WIDE_INT s4 = trunc_int_for_mode ( 0xffffffff , SImode ) ; unsigned HOST_WIDE_INT addr ; switch ( GET_CODE ( x ) ) { case SYMBOL_REF : return ( TARGET_NORMAL_MODE || ( SYMBOL_REF_FLAGS ( x ) & SYMBOL_FLAG_TINY_DATA ) != 0 ) ; case CONST_INT : addr = INTVAL ( x ) ; return ( TARGET_NORMAL_MODE || ( TARGET_H8300H && ( IN_RANGE ( addr , h1 , h2 ) || IN_RANGE ( addr , h3 , h4 ) ) ) || ( TARGET_H8300S && ( IN_RANGE ( addr , s1 , s2 ) || IN_RANGE ( addr , s3 , s4 ) ) ) ) ; case CONST : return TARGET_NORMAL_MODE ; default : return 0 ; } } </s>

Nonzero if X is a constant address suitable as an 16-bit absolute on H8/300H and H8S .


<s> int h8300_tiny_data_p ( tree decl ) { tree a ; if ( TREE_CODE ( decl ) != VAR_DECL ) return 0 ; a = lookup_attribute ( "tiny_data" , DECL_ATTRIBUTES ( decl ) ) ; return a != NULL_TREE ; } </s>

Return nonzero if DECL is a variable that 's in the tiny data area .


<s> static void h8300_trampoline_init ( rtx m_tramp , tree fndecl , rtx cxt ) { rtx fnaddr = XEXP ( DECL_RTL ( fndecl ) , 0 ) ; rtx mem ; if ( Pmode == HImode ) { mem = adjust_address ( m_tramp , HImode , 0 ) ; emit_move_insn ( mem , GEN_INT ( 0x7903 ) ) ; mem = adjust_address ( m_tramp , Pmode , 2 ) ; emit_move_insn ( mem , cxt ) ; mem = adjust_address ( m_tramp , HImode , 4 ) ; emit_move_insn ( mem , GEN_INT ( 0x5a00 ) ) ; mem = adjust_address ( m_tramp , Pmode , 6 ) ; emit_move_insn ( mem , fnaddr ) ; } else { rtx tem ; mem = adjust_address ( m_tramp , HImode , 0 ) ; emit_move_insn ( mem , GEN_INT ( 0x7a03 ) ) ; mem = adjust_address ( m_tramp , Pmode , 2 ) ; emit_move_insn ( mem , cxt ) ; tem = copy_to_reg ( fnaddr ) ; emit_insn ( gen_andsi3 ( tem , tem , GEN_INT ( 0x00ffffff ) ) ) ; emit_insn ( gen_iorsi3 ( tem , tem , GEN_INT ( 0x5a000000 ) ) ) ; mem = adjust_address ( m_tramp , SImode , 6 ) ; emit_move_insn ( mem , tem ) ; } } </s>


<s> unsigned int h8300_unary_length ( rtx op ) { enum h8300_operand_class opclass ; unsigned int size , operand_length ; size = GET_MODE_SIZE ( GET_MODE ( op ) ) ; operand_length = h8300_classify_operand ( op , size , & opclass ) ; switch ( opclass ) { case H8OP_REGISTER : return 2 ; case H8OP_MEM_BASE : return ( size == 4 ? 6 : 4 ) ; case H8OP_MEM_ABSOLUTE : return operand_length + ( size == 4 ? 6 : 4 ) ; case H8OP_MEM_COMPLEX : return operand_length + 6 ; default : gcc_unreachable ( ) ; } } </s>

Return the length of a unary instruction such as neg or not given that its operand is OP .


<s> enum h8sx_shift_type h8sx_classify_shift ( machine_mode mode , enum rtx_code code , rtx op ) { if ( ! TARGET_H8300SX ) return H8SX_SHIFT_NONE ; switch ( code ) { case ASHIFT : case LSHIFTRT : if ( GET_CODE ( op ) != CONST_INT ) return H8SX_SHIFT_BINARY ; if ( INTVAL ( op ) <= 0 || INTVAL ( op ) >= GET_MODE_BITSIZE ( mode ) ) return H8SX_SHIFT_NONE ; if ( exact_log2 ( INTVAL ( op ) ) >= 0 ) return H8SX_SHIFT_UNARY ; return H8SX_SHIFT_BINARY ; case ASHIFTRT : if ( op == const1_rtx || op == const2_rtx ) return H8SX_SHIFT_UNARY ; return H8SX_SHIFT_NONE ; case ROTATE : if ( GET_CODE ( op ) == CONST_INT && ( INTVAL ( op ) == 1 || INTVAL ( op ) == 2 || INTVAL ( op ) == GET_MODE_BITSIZE ( mode ) - 2 || INTVAL ( op ) == GET_MODE_BITSIZE ( mode ) - 1 ) ) return H8SX_SHIFT_UNARY ; return H8SX_SHIFT_NONE ; default : return H8SX_SHIFT_NONE ; } } </s>

Classify a shift with the given mode and code . OP is the shift amount .


<s> bool h8sx_mergeable_memrefs_p ( rtx lhs , rtx rhs ) { if ( GET_CODE ( rhs ) == MEM && GET_CODE ( lhs ) == MEM ) { rhs = XEXP ( rhs , 0 ) ; lhs = XEXP ( lhs , 0 ) ; if ( GET_CODE ( rhs ) == PRE_INC || GET_CODE ( rhs ) == PRE_DEC ) return rtx_equal_p ( XEXP ( rhs , 0 ) , lhs ) ; if ( GET_CODE ( lhs ) == POST_INC || GET_CODE ( lhs ) == POST_DEC ) return rtx_equal_p ( rhs , XEXP ( lhs , 0 ) ) ; if ( rtx_equal_p ( rhs , lhs ) ) return true ; } return false ; } </s>

Return true if LHS and RHS are memory references that can be mapped to the same h8sx assembly operand . LHS appears as the destination of an instruction and RHS appears as a source . Three cases are allowed : - RHS is @ +Rn or @ -Rn , LHS is @ Rn - RHS is @ Rn , LHS is @ Rn+ or @ Rn- - RHS and LHS have the same address and neither has side effects .


<s> void notice_update_cc ( rtx body , rtx_insn * insn ) { rtx set ; switch ( get_attr_cc ( insn ) ) { case CC_NONE : break ; case CC_NONE_0HIT : if ( cc_status . value1 != 0 && reg_overlap_mentioned_p ( recog_data . operand [ 0 ] , cc_status . value1 ) ) cc_status . value1 = 0 ; if ( cc_status . value2 != 0 && reg_overlap_mentioned_p ( recog_data . operand [ 0 ] , cc_status . value2 ) ) cc_status . value2 = 0 ; break ; case CC_SET_ZN : CC_STATUS_INIT ; cc_status . flags |= CC_OVERFLOW_UNUSABLE | CC_NO_CARRY ; set = single_set ( insn ) ; cc_status . value1 = SET_SRC ( set ) ; if ( SET_DEST ( set ) != cc0_rtx ) cc_status . value2 = SET_DEST ( set ) ; break ; case CC_SET_ZNV : CC_STATUS_INIT ; cc_status . flags |= CC_NO_CARRY ; set = single_set ( insn ) ; cc_status . value1 = SET_SRC ( set ) ; if ( SET_DEST ( set ) != cc0_rtx ) { if ( GET_CODE ( SET_DEST ( set ) ) == STRICT_LOW_PART ) cc_status . value2 = XEXP ( SET_DEST ( set ) , 0 ) ; else cc_status . value2 = SET_DEST ( set ) ; } break ; case CC_COMPARE : CC_STATUS_INIT ; cc_status . value1 = SET_SRC ( body ) ; break ; case CC_CLOBBER : CC_STATUS_INIT ; break ; } } </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 .


<s> const char * output_h8sx_shift ( rtx * operands , int suffix , int optype ) { static char buffer [ 16 ] ; const char * stem ; switch ( GET_CODE ( operands [ 3 ] ) ) { case ASHIFT : stem = "shll" ; break ; case ASHIFTRT : stem = "shar" ; break ; case LSHIFTRT : stem = "shlr" ; break ; case ROTATE : stem = "rotl" ; if ( INTVAL ( operands [ 2 ] ) > 2 ) { operands [ 2 ] = GEN_INT ( GET_MODE_BITSIZE ( GET_MODE ( operands [ 0 ] ) ) - INTVAL ( operands [ 2 ] ) ) ; stem = "rotr" ; } break ; default : gcc_unreachable ( ) ; } if ( operands [ 2 ] == const1_rtx ) sprintf ( buffer , "%s.%c\t%%%c0" , stem , suffix , optype ) ; else sprintf ( buffer , "%s.%c\t%%X2,%%%c0" , stem , suffix , optype ) ; return buffer ; } </s>

Return the asm template for a single h8sx shift instruction . OPERANDS [ 0 ] and OPERANDS [ 1 ] are the destination , OPERANDS [ 2 ] is the source and OPERANDS [ 3 ] is the shift . SUFFIX is the size suffix ( ' b ' , ' w ' or ' l ' ) and OPTYPE is the print_operand prefix for the destination operand .


<s> const char * output_plussi ( rtx * operands , bool need_flags ) { machine_mode mode = GET_MODE ( operands [ 0 ] ) ; gcc_assert ( mode == SImode ) ; if ( GET_CODE ( operands [ 2 ] ) == CONST_INT && register_operand ( operands [ 1 ] , VOIDmode ) ) { HOST_WIDE_INT intval = INTVAL ( operands [ 2 ] ) ; if ( TARGET_H8300SX && ( intval >= 1 && intval <= 7 ) ) return "add.l\t%S2,%S0" ; if ( TARGET_H8300SX && ( intval >= - 7 && intval <= - 1 ) ) return "sub.l\t%G2,%S0" ; switch ( ( unsigned int ) intval & 0xffffffff ) { case 0x00000001 : if ( need_flags ) return "inc.l\t#1,%S0" ; else return "adds\t%2,%S0" ; case 0x00000002 : if ( need_flags ) return "inc.l\t#2,%S0" ; else return "adds\t%2,%S0" ; case 0xffffffff : if ( need_flags ) return "dec.l\t#1,%S0" ; else return "subs\t%G2,%S0" ; case 0xfffffffe : if ( need_flags ) return "dec.l\t#2,%S0" ; else return "subs\t%G2,%S0" ; case 0x00000004 : if ( ! need_flags ) return "adds\t%2,%S0" ; case 0xfffffffc : if ( ! need_flags ) return "subs\t%G2,%S0" ; case 0x00010000 : case 0x00020000 : if ( ! need_flags ) { operands [ 2 ] = GEN_INT ( intval >> 16 ) ; return "inc.w\t%2,%e0" ; } case 0xffff0000 : case 0xfffe0000 : if ( ! need_flags ) { operands [ 2 ] = GEN_INT ( intval >> 16 ) ; return "dec.w\t%G2,%e0" ; } } if ( ( intval & 0xffff ) == 0 ) { operands [ 2 ] = GEN_INT ( intval >> 16 ) ; return "add.w\t%2,%e0" ; } } if ( GET_CODE ( operands [ 2 ] ) == CONST_INT && INTVAL ( operands [ 2 ] ) < 0 ) { operands [ 2 ] = GEN_INT ( - INTVAL ( operands [ 2 ] ) ) ; return "sub.l\t%S2,%S0" ; } return "add.l\t%S2,%S0" ; } </s>


<s> const char * output_simode_bld ( int bild , rtx operands [ ] ) { int clear_first = ( REG_P ( operands [ 0 ] ) && REG_P ( operands [ 1 ] ) && REGNO ( operands [ 0 ] ) != REGNO ( operands [ 1 ] ) ) ; if ( clear_first ) output_asm_insn ( "sub.l\t%S0,%S0" , operands ) ; if ( bild ) output_asm_insn ( "bild\t%Z2,%Y1" , operands ) ; else output_asm_insn ( "bld\t%Z2,%Y1" , operands ) ; if ( ! clear_first ) output_asm_insn ( "xor.l\t%S0,%S0" , operands ) ; output_asm_insn ( "rotxl.l\t%S0" , operands ) ; return "" ; } </s>


<s> static rtx pop ( int rn ) { rtx reg = gen_rtx_REG ( word_mode , rn ) ; rtx x ; if ( ! TARGET_NORMAL_MODE ) x = gen_pop_h8300hs_advanced ( reg ) ; else x = gen_pop_h8300hs_normal ( reg ) ; x = emit_insn ( x ) ; add_reg_note ( x , REG_INC , stack_pointer_rtx ) ; return x ; } </s>

Output RTL to pop register RN from the stack .


<s> static rtx push ( int rn ) { rtx reg = gen_rtx_REG ( word_mode , rn ) ; rtx x ; if ( ! TARGET_NORMAL_MODE ) x = gen_push_h8300hs_advanced ( reg ) ; else x = gen_push_h8300hs_normal ( reg ) ; x = F ( emit_insn ( x ) , 0 ) ; add_reg_note ( x , REG_INC , stack_pointer_rtx ) ; return x ; } </s>

Output RTL to push register RN onto the stack .


<s> static HOST_WIDE_INT round_frame_size ( HOST_WIDE_INT size ) { return ( ( size + STACK_BOUNDARY / BITS_PER_UNIT - 1 ) & - STACK_BOUNDARY / BITS_PER_UNIT ) ; } </s>


<s> int same_cmp_following_p ( rtx_insn * i1 ) { rtx_insn * i2 , * i3 ; i2 = next_nonnote_insn ( i1 ) ; if ( i2 == NULL ) return 0 ; i3 = next_nonnote_insn ( i2 ) ; if ( i3 == NULL ) return 0 ; return ( INSN_P ( i3 ) && rtx_equal_p ( PATTERN ( i1 ) , PATTERN ( i3 ) ) && any_condjump_p ( i2 ) && onlyjump_p ( i2 ) ) ; } </s>

Return nonzero if we have the same comparison insn as I1 two insns after I1 . I1 is assumed to be a comparison insn .


<s> int same_cmp_preceding_p ( rtx_insn * i3 ) { rtx_insn * i1 , * i2 ; i2 = prev_nonnote_insn ( i3 ) ; if ( i2 == NULL ) return 0 ; i1 = prev_nonnote_insn ( i2 ) ; if ( i1 == NULL ) return 0 ; return ( INSN_P ( i1 ) && rtx_equal_p ( PATTERN ( i1 ) , PATTERN ( i3 ) ) && any_condjump_p ( i2 ) && onlyjump_p ( i2 ) ) ; } </s>

Return nonzero if we have the same comparison insn as I3 two insns before I3 . I3 is assumed to be a comparison insn .


<s> void split_adds_subs ( machine_mode mode , rtx * operands ) { HOST_WIDE_INT val = INTVAL ( operands [ 1 ] ) ; rtx reg = operands [ 0 ] ; HOST_WIDE_INT sign = 1 ; HOST_WIDE_INT amount ; rtx ( * gen_add ) ( rtx , rtx , rtx ) ; if ( val < 0 ) { val = - val ; sign = - 1 ; } switch ( mode ) { case E_HImode : gen_add = gen_addhi3 ; break ; case E_SImode : gen_add = gen_addsi3 ; break ; default : gcc_unreachable ( ) ; } for ( amount = 4 ; amount > 0 ; amount /= 2 ) { for ( ; val >= amount ; val -= amount ) emit_insn ( gen_add ( reg , reg , GEN_INT ( sign * amount ) ) ) ; } return ; } </s>

Split an add of a small constant into two adds/subs insns .