<s> void avr_cpu_cpp_builtins ( struct cpp_reader * pfile ) { int i ; builtin_define_std ( "AVR" ) ; if ( avr_arch -> macro ) cpp_define_formatted ( pfile , "__AVR_ARCH__=%s" , avr_arch -> macro ) ; if ( AVR_HAVE_RAMPD ) cpp_define ( pfile , "__AVR_HAVE_RAMPD__" ) ; if ( AVR_HAVE_RAMPX ) cpp_define ( pfile , "__AVR_HAVE_RAMPX__" ) ; if ( AVR_HAVE_RAMPY ) cpp_define ( pfile , "__AVR_HAVE_RAMPY__" ) ; if ( AVR_HAVE_RAMPZ ) cpp_define ( pfile , "__AVR_HAVE_RAMPZ__" ) ; if ( AVR_HAVE_ELPM ) cpp_define ( pfile , "__AVR_HAVE_ELPM__" ) ; if ( AVR_HAVE_ELPMX ) cpp_define ( pfile , "__AVR_HAVE_ELPMX__" ) ; if ( AVR_HAVE_MOVW ) cpp_define ( pfile , "__AVR_HAVE_MOVW__" ) ; if ( AVR_HAVE_LPMX ) cpp_define ( pfile , "__AVR_HAVE_LPMX__" ) ; if ( avr_arch -> asm_only ) cpp_define ( pfile , "__AVR_ASM_ONLY__" ) ; if ( AVR_HAVE_MUL ) { cpp_define ( pfile , "__AVR_ENHANCED__" ) ; cpp_define ( pfile , "__AVR_HAVE_MUL__" ) ; } if ( avr_arch -> have_jmp_call ) { cpp_define ( pfile , "__AVR_MEGA__" ) ; cpp_define ( pfile , "__AVR_HAVE_JMP_CALL__" ) ; } if ( AVR_XMEGA ) cpp_define ( pfile , "__AVR_XMEGA__" ) ; if ( AVR_TINY ) { cpp_define ( pfile , "__AVR_TINY__" ) ; cpp_define ( pfile , "__AVR_TINY_PM_BASE_ADDRESS__=0x4000" ) ; } if ( AVR_HAVE_EIJMP_EICALL ) { cpp_define ( pfile , "__AVR_HAVE_EIJMP_EICALL__" ) ; cpp_define ( pfile , "__AVR_3_BYTE_PC__" ) ; } else { cpp_define ( pfile , "__AVR_2_BYTE_PC__" ) ; } if ( AVR_HAVE_8BIT_SP ) cpp_define ( pfile , "__AVR_HAVE_8BIT_SP__" ) ; else cpp_define ( pfile , "__AVR_HAVE_16BIT_SP__" ) ; if ( AVR_HAVE_SPH ) cpp_define ( pfile , "__AVR_HAVE_SPH__" ) ; else cpp_define ( pfile , "__AVR_SP8__" ) ; if ( TARGET_NO_INTERRUPTS ) cpp_define ( pfile , "__NO_INTERRUPTS__" ) ; if ( TARGET_SKIP_BUG ) { cpp_define ( pfile , "__AVR_ERRATA_SKIP__" ) ; if ( AVR_HAVE_JMP_CALL ) cpp_define ( pfile , "__AVR_ERRATA_SKIP_JMP_CALL__" ) ; } if ( TARGET_RMW ) cpp_define ( pfile , "__AVR_ISA_RMW__" ) ; cpp_define_formatted ( pfile , "__AVR_SFR_OFFSET__=0x%x" , avr_arch -> sfr_offset ) ; cpp_define ( pfile , "__WITH_AVRLIBC__" ) ; if ( lang_GNU_C ( ) ) { for ( i = 0 ; i < ADDR_SPACE_COUNT ; i ++ ) if ( ! ADDR_SPACE_GENERIC_P ( i ) && avr_addrspace [ i ] . segment < avr_n_flash && ( AVR_HAVE_LPM || avr_addrspace [ i ] . pointer_size <= 2 ) ) { const char * name = avr_addrspace [ i ] . name ; char * Name = ( char * ) alloca ( 1 + strlen ( name ) ) ; cpp_define ( pfile , avr_toupper ( Name , name ) ) ; } } cpp_define ( pfile , "__BUILTIN_AVR_" # NAME ) ; cpp_define_formatted ( pfile , "__INT24_MAX__=8388607%s" , INT_TYPE_SIZE == 8 ? "LL" : "L" ) ; cpp_define ( pfile , "__INT24_MIN__=(-__INT24_MAX__-1)" ) ; cpp_define_formatted ( pfile , "__UINT24_MAX__=16777215%s" , INT_TYPE_SIZE == 8 ? "ULL" : "UL" ) ; } </s>

Worker function for TARGET_CPU_CPP_BUILTINS .


<s> void avr_register_target_pragmas ( void ) { int i ; gcc_assert ( ADDR_SPACE_GENERIC == ADDR_SPACE_RAM ) ; for ( i = 0 ; i < ADDR_SPACE_COUNT ; i ++ ) { gcc_assert ( i == avr_addrspace [ i ] . id ) ; if ( ! ADDR_SPACE_GENERIC_P ( i ) ) c_register_addr_space ( avr_addrspace [ i ] . name , avr_addrspace [ i ] . id ) ; } targetm . resolve_overloaded_builtin = avr_resolve_overloaded_builtin ; } </s>


<s> void avr_cpu_cpp_builtins ( struct cpp_reader * pfile ) { builtin_define_std ( "AVR" ) ; if ( avr_arch -> macro ) cpp_define_formatted ( pfile , "__AVR_ARCH__=%s" , avr_arch -> macro ) ; if ( AVR_HAVE_RAMPD ) cpp_define ( pfile , "__AVR_HAVE_RAMPD__" ) ; if ( AVR_HAVE_RAMPX ) cpp_define ( pfile , "__AVR_HAVE_RAMPX__" ) ; if ( AVR_HAVE_RAMPY ) cpp_define ( pfile , "__AVR_HAVE_RAMPY__" ) ; if ( AVR_HAVE_RAMPZ ) cpp_define ( pfile , "__AVR_HAVE_RAMPZ__" ) ; if ( AVR_HAVE_ELPM ) cpp_define ( pfile , "__AVR_HAVE_ELPM__" ) ; if ( AVR_HAVE_ELPMX ) cpp_define ( pfile , "__AVR_HAVE_ELPMX__" ) ; if ( AVR_HAVE_MOVW ) cpp_define ( pfile , "__AVR_HAVE_MOVW__" ) ; if ( AVR_HAVE_LPMX ) cpp_define ( pfile , "__AVR_HAVE_LPMX__" ) ; if ( avr_arch -> asm_only ) cpp_define ( pfile , "__AVR_ASM_ONLY__" ) ; if ( AVR_HAVE_MUL ) { cpp_define ( pfile , "__AVR_ENHANCED__" ) ; cpp_define ( pfile , "__AVR_HAVE_MUL__" ) ; } if ( avr_arch -> have_jmp_call ) { cpp_define ( pfile , "__AVR_MEGA__" ) ; cpp_define ( pfile , "__AVR_HAVE_JMP_CALL__" ) ; } if ( AVR_XMEGA ) cpp_define ( pfile , "__AVR_XMEGA__" ) ; if ( AVR_TINY ) { cpp_define ( pfile , "__AVR_TINY__" ) ; cpp_define_formatted ( pfile , "__AVR_TINY_PM_BASE_ADDRESS__=0x%x" , AVR_TINY_PM_OFFSET ) ; } if ( AVR_HAVE_EIJMP_EICALL ) { cpp_define ( pfile , "__AVR_HAVE_EIJMP_EICALL__" ) ; cpp_define ( pfile , "__AVR_3_BYTE_PC__" ) ; } else { cpp_define ( pfile , "__AVR_2_BYTE_PC__" ) ; } if ( AVR_HAVE_8BIT_SP ) cpp_define ( pfile , "__AVR_HAVE_8BIT_SP__" ) ; else cpp_define ( pfile , "__AVR_HAVE_16BIT_SP__" ) ; if ( AVR_HAVE_SPH ) cpp_define ( pfile , "__AVR_HAVE_SPH__" ) ; else cpp_define ( pfile , "__AVR_SP8__" ) ; if ( TARGET_NO_INTERRUPTS ) cpp_define ( pfile , "__NO_INTERRUPTS__" ) ; if ( TARGET_SKIP_BUG ) { cpp_define ( pfile , "__AVR_ERRATA_SKIP__" ) ; if ( AVR_HAVE_JMP_CALL ) cpp_define ( pfile , "__AVR_ERRATA_SKIP_JMP_CALL__" ) ; } if ( TARGET_RMW ) cpp_define ( pfile , "__AVR_ISA_RMW__" ) ; cpp_define_formatted ( pfile , "__AVR_SFR_OFFSET__=0x%x" , avr_arch -> sfr_offset ) ; cpp_define ( pfile , "__WITH_AVRLIBC__" ) ; if ( lang_GNU_C ( ) ) { for ( int i = 0 ; i < ADDR_SPACE_COUNT ; i ++ ) if ( ! ADDR_SPACE_GENERIC_P ( i ) && avr_addr_space_supported_p ( ( addr_space_t ) i ) ) { const char * name = avr_addrspace [ i ] . name ; char * Name = ( char * ) alloca ( 1 + strlen ( name ) ) ; cpp_define ( pfile , avr_toupper ( Name , name ) ) ; } } cpp_define ( pfile , "__BUILTIN_AVR_" # NAME ) ; cpp_define_formatted ( pfile , "__INT24_MAX__=8388607%s" , INT_TYPE_SIZE == 8 ? "LL" : "L" ) ; cpp_define ( pfile , "__INT24_MIN__=(-__INT24_MAX__-1)" ) ; cpp_define_formatted ( pfile , "__UINT24_MAX__=16777215%s" , INT_TYPE_SIZE == 8 ? "ULL" : "UL" ) ; } </s>


<s> void avr_cpu_cpp_builtins ( struct cpp_reader * pfile ) { builtin_define_std ( "AVR" ) ; if ( avr_arch -> macro ) cpp_define_formatted ( pfile , "__AVR_ARCH__=%s" , avr_arch -> macro ) ; if ( AVR_HAVE_RAMPD ) cpp_define ( pfile , "__AVR_HAVE_RAMPD__" ) ; if ( AVR_HAVE_RAMPX ) cpp_define ( pfile , "__AVR_HAVE_RAMPX__" ) ; if ( AVR_HAVE_RAMPY ) cpp_define ( pfile , "__AVR_HAVE_RAMPY__" ) ; if ( AVR_HAVE_RAMPZ ) cpp_define ( pfile , "__AVR_HAVE_RAMPZ__" ) ; if ( AVR_HAVE_ELPM ) cpp_define ( pfile , "__AVR_HAVE_ELPM__" ) ; if ( AVR_HAVE_ELPMX ) cpp_define ( pfile , "__AVR_HAVE_ELPMX__" ) ; if ( AVR_HAVE_MOVW ) cpp_define ( pfile , "__AVR_HAVE_MOVW__" ) ; if ( AVR_HAVE_LPMX ) cpp_define ( pfile , "__AVR_HAVE_LPMX__" ) ; if ( avr_arch -> asm_only ) cpp_define ( pfile , "__AVR_ASM_ONLY__" ) ; if ( AVR_HAVE_MUL ) { cpp_define ( pfile , "__AVR_ENHANCED__" ) ; cpp_define ( pfile , "__AVR_HAVE_MUL__" ) ; } if ( AVR_HAVE_JMP_CALL ) cpp_define ( pfile , "__AVR_HAVE_JMP_CALL__" ) ; if ( avr_arch -> have_jmp_call ) cpp_define ( pfile , "__AVR_MEGA__" ) ; if ( AVR_SHORT_CALLS ) cpp_define ( pfile , "__AVR_SHORT_CALLS__" ) ; if ( AVR_XMEGA ) cpp_define ( pfile , "__AVR_XMEGA__" ) ; if ( AVR_TINY ) { cpp_define ( pfile , "__AVR_TINY__" ) ; cpp_define_formatted ( pfile , "__AVR_TINY_PM_BASE_ADDRESS__=0x%x" , avr_arch -> flash_pm_offset ) ; } if ( avr_arch -> flash_pm_offset ) cpp_define_formatted ( pfile , "__AVR_PM_BASE_ADDRESS__=0x%x" , avr_arch -> flash_pm_offset ) ; if ( AVR_HAVE_EIJMP_EICALL ) { cpp_define ( pfile , "__AVR_HAVE_EIJMP_EICALL__" ) ; cpp_define ( pfile , "__AVR_3_BYTE_PC__" ) ; } else { cpp_define ( pfile , "__AVR_2_BYTE_PC__" ) ; } if ( AVR_HAVE_8BIT_SP ) cpp_define ( pfile , "__AVR_HAVE_8BIT_SP__" ) ; else cpp_define ( pfile , "__AVR_HAVE_16BIT_SP__" ) ; if ( AVR_HAVE_SPH ) cpp_define ( pfile , "__AVR_HAVE_SPH__" ) ; else cpp_define ( pfile , "__AVR_SP8__" ) ; if ( TARGET_NO_INTERRUPTS ) cpp_define ( pfile , "__NO_INTERRUPTS__" ) ; if ( TARGET_SKIP_BUG ) { cpp_define ( pfile , "__AVR_ERRATA_SKIP__" ) ; if ( AVR_HAVE_JMP_CALL ) cpp_define ( pfile , "__AVR_ERRATA_SKIP_JMP_CALL__" ) ; } if ( TARGET_RMW ) cpp_define ( pfile , "__AVR_ISA_RMW__" ) ; cpp_define_formatted ( pfile , "__AVR_SFR_OFFSET__=0x%x" , avr_arch -> sfr_offset ) ; cpp_define ( pfile , "__WITH_AVRLIBC__" ) ; if ( lang_GNU_C ( ) ) { for ( int i = 0 ; i < ADDR_SPACE_COUNT ; i ++ ) if ( ! ADDR_SPACE_GENERIC_P ( i ) && avr_addr_space_supported_p ( ( addr_space_t ) i ) ) { const char * name = avr_addrspace [ i ] . name ; char * Name = ( char * ) alloca ( 1 + strlen ( name ) ) ; cpp_define ( pfile , avr_toupper ( Name , name ) ) ; } } cpp_define ( pfile , "__BUILTIN_AVR_" # NAME ) ; cpp_define_formatted ( pfile , "__INT24_MAX__=8388607%s" , INT_TYPE_SIZE == 8 ? "LL" : "L" ) ; cpp_define ( pfile , "__INT24_MIN__=(-__INT24_MAX__-1)" ) ; cpp_define_formatted ( pfile , "__UINT24_MAX__=16777215%s" , INT_TYPE_SIZE == 8 ? "ULL" : "UL" ) ; } </s>


<s> void avr_register_target_pragmas ( void ) { gcc_assert ( ADDR_SPACE_GENERIC == ADDR_SPACE_RAM ) ; for ( int i = 0 ; i < ADDR_SPACE_COUNT ; i ++ ) { gcc_assert ( i == avr_addrspace [ i ] . id ) ; if ( ! ADDR_SPACE_GENERIC_P ( i ) ) c_register_addr_space ( avr_addrspace [ i ] . name , avr_addrspace [ i ] . id ) ; } targetm . resolve_overloaded_builtin = avr_resolve_overloaded_builtin ; } </s>


<s> static char * avr_toupper ( char * up , const char * lo ) { char * up0 = up ; for ( ; * lo ; lo ++ , up ++ ) * up = TOUPPER ( * lo ) ; * up = '\0' ; return up0 ; } </s>

Transform LO into uppercase and write the result to UP . You must provide enough space for UP . Return UP .


<s> static int comparator ( const void * va , const void * vb ) { const char * a = * ( const char * const * ) va ; const char * b = * ( const char * const * ) vb ; while ( * a && * b ) { if ( ISALPHA ( * a ) && ISDIGIT ( * b ) ) return - 1 ; if ( ISDIGIT ( * a ) && ISALPHA ( * b ) ) return 1 ; if ( * a != * b ) return * a - * b ; a ++ ; b ++ ; } return * a - * b ; } </s>

Compare two MCUs and order them for easy lookup .


<s> void avr_log_set_avr_log ( void ) { bool all = TARGET_ALL_DEBUG != 0 ; if ( all ) avr_log_details = "all" ; if ( all || avr_log_details ) { char * str = ( char * ) alloca ( 3 + strlen ( avr_log_details ) ) ; bool info ; str [ 0 ] = ',' ; strcat ( stpcpy ( str + 1 , avr_log_details ) , "," ) ; all |= NULL != strstr ( str , ",all," ) ; info = NULL != strstr ( str , ",?," ) ; if ( info ) fprintf ( stderr , "\n-mlog=" ) ; do { \ avr_log . S = ( all || NULL != strstr ( str , "," # S "," ) ) ; \ if ( info ) \ fprintf ( stderr , # S "," ) ; \ } while ( 0 ) SET_DUMP_DETAIL ( address_cost ) ; SET_DUMP_DETAIL ( builtin ) ; SET_DUMP_DETAIL ( constraints ) ; SET_DUMP_DETAIL ( legitimate_address_p ) ; SET_DUMP_DETAIL ( legitimize_address ) ; SET_DUMP_DETAIL ( legitimize_reload_address ) ; SET_DUMP_DETAIL ( progmem ) ; SET_DUMP_DETAIL ( rtx_costs ) ; if ( info ) fprintf ( stderr , "?\n\n" ) ; } } </s>

Called from avr.cc : avr_option_override ( ) . Parse argument of -mlog= and set respective fields in avr_log .


<s> int avr_vdump ( FILE * stream , const char * caller , ... ) { va_list ap ; if ( NULL == stream && dump_file ) stream = dump_file ; va_start ( ap , caller ) ; if ( stream ) avr_log_vadump ( stream , caller , ap ) ; va_end ( ap ) ; return 1 ; } </s>

Wrapper for avr_log_vadump . If STREAM is NULL we are called by avr_dump , i.e . output to dump_file if available . The 2nd argument is __FUNCTION__ . The 3rd argument is the format string .


<s> void avr_log_set_avr_log ( void ) { bool all = TARGET_ALL_DEBUG != 0 ; if ( all ) avr_log_details = "all" ; if ( all || avr_log_details ) { char * str = ( char * ) alloca ( 3 + strlen ( avr_log_details ) ) ; bool info ; str [ 0 ] = ',' ; strcat ( stpcpy ( str + 1 , avr_log_details ) , "," ) ; all |= strstr ( str , ",all," ) != NULL ; info = strstr ( str , ",?," ) != NULL ; if ( info ) fprintf ( stderr , "\n-mlog=" ) ; do { \ avr_log . S = ( all || strstr ( str , "," # S "," ) != NULL ) ; \ if ( info ) \ fprintf ( stderr , # S "," ) ; \ } while ( 0 ) SET_DUMP_DETAIL ( address_cost ) ; SET_DUMP_DETAIL ( builtin ) ; SET_DUMP_DETAIL ( constraints ) ; SET_DUMP_DETAIL ( insn_addresses ) ; SET_DUMP_DETAIL ( legitimate_address_p ) ; SET_DUMP_DETAIL ( legitimize_address ) ; SET_DUMP_DETAIL ( legitimize_reload_address ) ; SET_DUMP_DETAIL ( progmem ) ; SET_DUMP_DETAIL ( rtx_costs ) ; if ( info ) fprintf ( stderr , "?\n\n" ) ; } } </s>


<s> int avr_vdump ( FILE * stream , const char * caller , ... ) { va_list ap ; if ( stream == NULL && dump_file ) stream = dump_file ; va_start ( ap , caller ) ; if ( stream ) avr_log_vadump ( stream , caller , ap ) ; va_end ( ap ) ; return 1 ; } </s>


<s> void avr_init_once ( ) { tmp_reg_rtx = xmalloc ( sizeof ( struct rtx_def ) + 1 * sizeof ( rtunion ) ) ; memset ( tmp_reg_rtx , 0 , sizeof ( struct rtx_def ) + 1 * sizeof ( rtunion ) ) ; PUT_CODE ( tmp_reg_rtx , REG ) ; PUT_MODE ( tmp_reg_rtx , QImode ) ; XINT ( tmp_reg_rtx , 0 ) = TMP_REGNO ; zero_reg_rtx = xmalloc ( sizeof ( struct rtx_def ) + 1 * sizeof ( rtunion ) ) ; memset ( zero_reg_rtx , 0 , sizeof ( struct rtx_def ) + 1 * sizeof ( rtunion ) ) ; PUT_CODE ( zero_reg_rtx , REG ) ; PUT_MODE ( zero_reg_rtx , QImode ) ; XINT ( zero_reg_rtx , 0 ) = ZERO_REGNO ; ldi_reg_rtx = xmalloc ( sizeof ( struct rtx_def ) + 1 * sizeof ( rtunion ) ) ; memset ( ldi_reg_rtx , 0 , sizeof ( struct rtx_def ) + 1 * sizeof ( rtunion ) ) ; PUT_CODE ( ldi_reg_rtx , REG ) ; PUT_MODE ( ldi_reg_rtx , QImode ) ; XINT ( ldi_reg_rtx , 0 ) = LDI_REG_REGNO ; } </s>


<s> avr_regno_mode_code_ok_for_base_p ( num , mode , as , outer_code , index_code ) { ARG_POINTER_REGNUM , STACK_POINTER_REGNUM } , \ { ARG_POINTER_REGNUM , FRAME_POINTER_REGNUM } , \ { FRAME_POINTER_REGNUM , STACK_POINTER_REGNUM } , \ { FRAME_POINTER_REGNUM + 1 , STACK_POINTER_REGNUM + 1 } </s>

Implement ` REGNO_MODE_CODE_OK_FOR_BASE_P ' .


<s> int avr_ret_register ( ) { return 24 ; } </s>

Returns register number for function return value .


<s> int frame_pointer_required_p ( ) { return ( current_function_calls_alloca || current_function_args_info . nregs == 0 || current_function_varargs || get_frame_size ( ) > 0 ) ; } </s>

Return 1 if frame pointer for current function required .


Choose the order in which to allocate hard registers for pseudo-registers local to a basic block . Store the desired register order in the array ` reg_alloc_order ' . Element 0 should be the register to allocate first ; element 1 , the next register ; and so on .


<s> static int sequent_regs_live ( ) { int reg ; int live_seq = 0 ; int cur_seq = 0 ; for ( reg = 0 ; reg < 18 ; ++ reg ) { if ( ! call_used_regs [ reg ] ) { if ( regs_ever_live [ reg ] ) { ++ live_seq ; ++ cur_seq ; } else cur_seq = 0 ; } } if ( ! frame_pointer_needed ) { if ( regs_ever_live [ REG_Y ] ) { ++ live_seq ; ++ cur_seq ; } else cur_seq = 0 ; if ( regs_ever_live [ REG_Y + 1 ] ) { ++ live_seq ; ++ cur_seq ; } else cur_seq = 0 ; } else { cur_seq += 2 ; live_seq += 2 ; } return ( cur_seq == live_seq ) ? live_seq : 0 ; } </s>

This function checks sequence of live registers


"internal compiler error.  Incorrect shift:"

8bit arithmetic shift right ( ( signed char ) x > > i )


<s> static int avr_address_cost ( rtx x ) { if ( GET_CODE ( x ) == PLUS && GET_CODE ( XEXP ( x , 1 ) ) == CONST_INT && ( REG_P ( XEXP ( x , 0 ) ) || GET_CODE ( XEXP ( x , 0 ) ) == SUBREG ) && INTVAL ( XEXP ( x , 1 ) ) >= 61 ) return 18 ; if ( CONSTANT_ADDRESS_P ( x ) ) { if ( avr_io_address_p ( x , 1 ) ) return 2 ; return 4 ; } return 4 ; } </s>

Calculate the cost of a memory address .


<s> static bool avr_assemble_integer ( rtx x , unsigned int size , int aligned_p ) { if ( size == POINTER_SIZE / BITS_PER_UNIT && aligned_p && ( ( GET_CODE ( x ) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P ( x ) ) || GET_CODE ( x ) == LABEL_REF ) ) { fputs ( "\t.word\tpm(" , asm_out_file ) ; output_addr_const ( asm_out_file , x ) ; fputs ( ")\n" , asm_out_file ) ; return true ; } return default_assemble_integer ( x , size , aligned_p ) ; } </s>

Target hook for assembling integer objects . The AVR version needs special handling for references to certain labels .


": code %4d = 0x%04x (%4d), prologues %3d, epilogues %3d */\n"

Outputs to the stdio stream FILE some appropriate text to go at the end of an assembler file .


<s>
static
void
avr_file_start
(
void
)
{
if
(
avr_asm_only_p
)
error
(
"MCU %qs supported for assembler only"
,
avr_mcu_name
)
;
default_file_start
(
)
;
fprintf
(
asm_out_file
,
"\t.arch %s\n"
,
avr_mcu_name
)
;
fputs
(
"__SREG__ = 0x3f\n"
"__SP_H__ = 0x3e\n"
"__SP_L__ = 0x3d\n"
,
asm_out_file
)
;
fputs
(
"__tmp_reg__ = 0\n"
"__zero_reg__ = 1\n"
,
asm_out_file
)
;
fputs
(
"\t.global __do_copy_data\n"
,
asm_out_file
)
;
fputs
(
"\t.global __do_clear_bss\n"
,
asm_out_file
)
;
commands_in_file
=
0
;
commands_in_prologues
=
0
;
commands_in_epilogues
=
0
;
}
</s>

Outputs some appropriate text to go at the start of an assembler file .

avr
"MCU %qs supported for assembler only"
"\t.arch %s\n"
"__SREG__ = 0x3f\n"
"__SP_H__ = 0x3e\n"
"__SP_L__ = 0x3d\n"
"__tmp_reg__ = 0\n"
"__zero_reg__ = 1\n"
"\t.global __do_copy_data\n"
"\t.global __do_clear_bss\n"
0
0
0


<s> rtx avr_function_value ( tree type , tree func ATTRIBUTE_UNUSED ) { unsigned int offs ; if ( TYPE_MODE ( type ) != BLKmode ) return avr_libcall_value ( TYPE_MODE ( type ) ) ; offs = int_size_in_bytes ( type ) ; if ( offs < 2 ) offs = 2 ; if ( offs > 2 && offs < GET_MODE_SIZE ( SImode ) ) offs = GET_MODE_SIZE ( SImode ) ; else if ( offs > GET_MODE_SIZE ( SImode ) && offs < GET_MODE_SIZE ( DImode ) ) offs = GET_MODE_SIZE ( DImode ) ; return gen_rtx_REG ( BLKmode , RET_REGISTER + 2 - offs ) ; } </s>

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


"%qs attribute only applies to functions"

"%qs appears to be a misspelled interrupt handler"

"%qs appears to be a misspelled signal handler"

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


"only initialized variables can be placed into "

Handle a `` progmem '' attribute ; arguments as in struct attribute_spec.handler .


<s> int avr_hard_regno_mode_ok ( int regno , enum machine_mode mode ) { if ( regno == REG_Y && mode == Pmode ) return 1 ; if ( regno <= ( REG_Y + 1 ) && ( regno + GET_MODE_SIZE ( mode ) ) >= ( REG_Y + 1 ) ) return 0 ; if ( mode == QImode ) return 1 ; if ( regno + GET_MODE_SIZE ( mode ) > FIRST_PSEUDO_REGISTER ) return 0 ; return ! ( regno & 1 ) ; } </s>

Returns 1 if a value of mode MODE can be stored starting with hard register number REGNO . On the enhanced core , anything larger than 1 byte must start in even numbered register for `` movw '' to work ( this way we do n't have to check for odd registers everywhere ) .


<s> static void avr_insert_attributes ( tree node , tree * attributes ) { if ( TREE_CODE ( node ) == VAR_DECL && ( TREE_STATIC ( node ) || DECL_EXTERNAL ( node ) ) && avr_progmem_p ( node , * attributes ) ) { static const char dsec [ ] = ".progmem.data" ; * attributes = tree_cons ( get_identifier ( "section" ) , build_tree_list ( NULL , build_string ( strlen ( dsec ) , dsec ) ) , * attributes ) ; TREE_READONLY ( node ) = 1 ; } } </s>

Add the section attribute if the variable is in progmem .


<s> int avr_io_address_p ( rtx x , int size ) { return ( optimize > 0 && GET_CODE ( x ) == CONST_INT && INTVAL ( x ) >= 0x20 && INTVAL ( x ) <= 0x60 - size ) ; } </s>

Returns 1 if X is a valid address for an I/O register of size SIZE ( 1 or 2 ) . Used for lds/sts - > in/out optimization . Add 0x20 to SIZE to check for the lower half of I/O space ( for cbi/sbi/sbic/sbis ) .


<s> int avr_jump_mode ( rtx x , rtx insn ) { int dest_addr = INSN_ADDRESSES ( INSN_UID ( GET_MODE ( x ) == LABEL_REF ? XEXP ( x , 0 ) : x ) ) ; int cur_addr = INSN_ADDRESSES ( INSN_UID ( insn ) ) ; int jump_distance = cur_addr - dest_addr ; if ( - 63 <= jump_distance && jump_distance <= 62 ) return 1 ; else if ( - 2046 <= jump_distance && jump_distance <= 2045 ) return 2 ; else if ( AVR_MEGA ) return 3 ; return 2 ; } </s>

Choose mode for jump insn : 1 - relative jump in range -63 < = x < = 62 ; 2 - relative jump in range -2046 < = x < = 2045 ; 3 - absolute jump ( only for ATmega [ 16 ] 03 ) .


<s> rtx avr_libcall_value ( enum machine_mode mode ) { int offs = GET_MODE_SIZE ( mode ) ; if ( offs < 2 ) offs = 2 ; return gen_rtx_REG ( mode , RET_REGISTER + 2 - offs ) ; } </s>

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


<s> static int avr_naked_function_p ( tree func ) { tree a ; gcc_assert ( TREE_CODE ( func ) == FUNCTION_DECL ) ; a = lookup_attribute ( "naked" , DECL_ATTRIBUTES ( func ) ) ; return a != NULL_TREE ; } </s>

Return non-zero if FUNC is a naked function .


<s> static int avr_num_arg_regs ( enum machine_mode mode , tree type ) { int size ; if ( mode == BLKmode ) size = int_size_in_bytes ( type ) ; else size = GET_MODE_SIZE ( mode ) ; return ( size + 1 ) & ~ 1 ; } </s>

Returns the number of registers to allocate for a function argument .


<s> static int avr_operand_rtx_cost ( rtx x , enum machine_mode mode , enum rtx_code outer ) { enum rtx_code code = GET_CODE ( x ) ; int total ; switch ( code ) { case REG : case SUBREG : return 0 ; case CONST_INT : case CONST_DOUBLE : return COSTS_N_INSNS ( GET_MODE_SIZE ( mode ) ) ; default : break ; } total = 0 ; avr_rtx_costs ( x , code , outer , & total ) ; return total ; } </s>

Mutually recursive subroutine of avr_rtx_cost for calculating the cost of an RTX operand given its context . X is the rtx of the operand , MODE is its mode , and OUTER is the rtx_code of this operand 's parent operator .


<s>
void
avr_output_addr_vec_elt
(
FILE
*
stream
,
int
value
)
{
progmem_section
(
)
;
if
(
AVR_MEGA
)
fprintf
(
stream
,
"\t.word pm(.L%d)\n"
,
value
)
;
else
fprintf
(
stream
,
"\trjmp .L%d\n"
,
value
)
;
jump_tables_size
++
;
}
</s>

Worker function for ` ASM_OUTPUT_ADDR_VEC_ELT ' .

avr
"\t.word pm(.L%d)\n"
"\trjmp .L%d\n"


<s>
const
char
*
avr_out_sbxx_branch
(
rtx
insn
,
rtx
operands
[
]
)
{
enum
rtx_code
comp
=
GET_CODE
(
operands
[
0
]
)
;
int
long_jump
=
(
get_attr_length
(
insn
)
>=
4
)
;
int
reverse
=
long_jump
||
jump_over_one_insn_p
(
insn
,
operands
[
3
]
)
;
if
(
comp
==
GE
)
comp
=
EQ
;
else
if
(
comp
==
LT
)
comp
=
NE
;
if
(
reverse
)
comp
=
reverse_condition
(
comp
)
;
if
(
GET_CODE
(
operands
[
1
]
)
==
CONST_INT
)
{
if
(
INTVAL
(
operands
[
1
]
)
<
0x40
)
{
if
(
comp
==
EQ
)
output_asm_insn
(
AS2
(
sbis
,
%
1
0x20
,
%
2
)
,
operands
)
;
else
output_asm_insn
(
AS2
(
sbic
,
%
1
0x20
,
%
2
)
,
operands
)
;
}
else
{
output_asm_insn
(
AS2
(
in
,
__tmp_reg__
,
%
1
0x20
)
,
operands
)
;
if
(
comp
==
EQ
)
output_asm_insn
(
AS2
(
sbrs
,
__tmp_reg__
,
%
2
)
,
operands
)
;
else
output_asm_insn
(
AS2
(
sbrc
,
__tmp_reg__
,
%
2
)
,
operands
)
;
}
}
else
{
if
(
GET_MODE
(
operands
[
1
]
)
==
QImode
)
{
if
(
comp
==
EQ
)
output_asm_insn
(
AS2
(
sbrs
,
%
1
,
%
2
)
,
operands
)
;
else
output_asm_insn
(
AS2
(
sbrc
,
%
1
,
%
2
)
,
operands
)
;
}
else
{
static
char
buf
[
]
=
"sbrc %A1,0"
;
int
bit_nr
=
exact_log2
(
INTVAL
(
operands
[
2
]
)
&
GET_MODE_MASK
(
GET_MODE
(
operands
[
1
]
)
)
)
;
buf
[
3
]
=
(
comp
==
EQ
)
's'
:
'c'
;
buf
[
6
]
=
'A'
+
(
bit_nr
>>
3
)
;
buf
[
9
]
=
'0'
+
(
bit_nr
&
7
)
;
output_asm_insn
(
buf
,
operands
)
;
}
}
if
(
long_jump
)
return
(
AS1
(
rjmp
,
.
+
4
)
CR_TAB
AS1
(
jmp
,
%
3
)
)
;
if
(
!
reverse
)
return
AS1
(
rjmp
,
%
3
)
;
return
""
;
}
</s>

Output a branch that tests a single bit of a register ( QI , HI or SImode ) or memory location in the I/O space ( QImode only ) . Operand 0 : comparison operator ( must be EQ or NE , compare bit to zero ) . Operand 1 : register operand to test , or CONST_INT memory address . Operand 2 : bit number ( for QImode operand ) or mask ( HImode , SImode ) . Operand 3 : label to jump to if the test is true .


<s> int avr_peep2_scratch_safe ( rtx scratch ) { if ( ( interrupt_function_p ( current_function_decl ) || signal_function_p ( current_function_decl ) ) && leaf_function_p ( ) ) { int first_reg = true_regnum ( scratch ) ; int last_reg = first_reg + GET_MODE_SIZE ( GET_MODE ( scratch ) ) - 1 ; int reg ; for ( reg = first_reg ; reg <= last_reg ; reg ++ ) { if ( ! regs_ever_live [ reg ] ) return 0 ; } } return 1 ; } </s>

Returns 1 if SCRATCH are safe to be allocated as a scratch registers ( for a define_peephole2 ) in the current function .


<s> int avr_progmem_p ( tree decl , tree attributes ) { tree a ; if ( TREE_CODE ( decl ) != VAR_DECL ) return 0 ; if ( NULL_TREE != lookup_attribute ( "progmem" , attributes ) ) return 1 ; a = decl ; do a = TREE_TYPE ( a ) ; while ( TREE_CODE ( a ) == ARRAY_TYPE ) ; if ( a == error_mark_node ) return 0 ; if ( NULL_TREE != lookup_attribute ( "progmem" , TYPE_ATTRIBUTES ( a ) ) ) return 1 ; return 0 ; } </s>

Look for attribute ` progmem ' in DECL if found return 1 , otherwise 0 .


<s> enum reg_class avr_regno_reg_class ( int r ) { if ( r <= 33 ) return reg_class_tab [ r ] ; return ALL_REGS ; } </s>


<s> static int avr_regs_to_save ( HARD_REG_SET * set ) { int reg , count ; int int_or_sig_p = ( interrupt_function_p ( current_function_decl ) || signal_function_p ( current_function_decl ) ) ; int leaf_func_p = leaf_function_p ( ) ; if ( set ) CLEAR_HARD_REG_SET ( * set ) ; count = 0 ; if ( TREE_THIS_VOLATILE ( current_function_decl ) ) return 0 ; for ( reg = 0 ; reg < 32 ; reg ++ ) { if ( fixed_regs [ reg ] ) continue ; if ( ( int_or_sig_p && ! leaf_func_p && call_used_regs [ reg ] ) || ( regs_ever_live [ reg ] && ( int_or_sig_p || ! call_used_regs [ reg ] ) && ! ( frame_pointer_needed && ( reg == REG_Y || reg == ( REG_Y + 1 ) ) ) ) ) { if ( set ) SET_HARD_REG_BIT ( * set , reg ) ; count ++ ; } } return count ; } </s>

Return the number of hard registers to push/pop in the prologue/epilogue of the current function , and optionally store these registers in SET .


<s> enum reg_class avr_reg_class_from_letter ( int c ) { switch ( c ) { case 't' : return R0_REG ; case 'b' : return BASE_POINTER_REGS ; case 'e' : return POINTER_REGS ; case 'w' : return ADDW_REGS ; case 'd' : return LD_REGS ; case 'l' : return NO_LD_REGS ; case 'a' : return SIMPLE_LD_REGS ; case 'x' : return POINTER_X_REGS ; case 'y' : return POINTER_Y_REGS ; case 'z' : return POINTER_Z_REGS ; case 'q' : return STACK_REG ; default : break ; } return NO_REGS ; } </s>

A C expression which defines the machine-dependent operand constraint letters for register classes . If C is such a letter , the value should be the register class corresponding to it . Otherwise , the value should be ` NO_REGS ' . The register letter ` r ' , corresponding to class ` GENERAL_REGS ' , will not be passed to this macro ; you do not need to handle it .


<s> static void avr_reorg ( void ) { rtx insn , pattern ; for ( insn = get_insns ( ) ; insn ; insn = NEXT_INSN ( insn ) ) { if ( ! ( GET_CODE ( insn ) == INSN || GET_CODE ( insn ) == CALL_INSN || GET_CODE ( insn ) == JUMP_INSN ) || ! single_set ( insn ) ) continue ; pattern = PATTERN ( insn ) ; if ( GET_CODE ( pattern ) == PARALLEL ) pattern = XVECEXP ( pattern , 0 , 0 ) ; if ( GET_CODE ( pattern ) == SET && SET_DEST ( pattern ) == cc0_rtx && compare_diff_p ( insn ) ) { if ( GET_CODE ( SET_SRC ( pattern ) ) == COMPARE ) { pattern = SET_SRC ( pattern ) ; if ( true_regnum ( XEXP ( pattern , 0 ) ) >= 0 && true_regnum ( XEXP ( pattern , 1 ) ) >= 0 ) { rtx x = XEXP ( pattern , 0 ) ; rtx next = next_real_insn ( insn ) ; rtx pat = PATTERN ( next ) ; rtx src = SET_SRC ( pat ) ; rtx t = XEXP ( src , 0 ) ; PUT_CODE ( t , swap_condition ( GET_CODE ( t ) ) ) ; XEXP ( pattern , 0 ) = XEXP ( pattern , 1 ) ; XEXP ( pattern , 1 ) = x ; INSN_CODE ( next ) = - 1 ; } else if ( true_regnum ( XEXP ( pattern , 0 ) ) >= 0 && GET_CODE ( XEXP ( pattern , 1 ) ) == CONST_INT ) { rtx x = XEXP ( pattern , 1 ) ; rtx next = next_real_insn ( insn ) ; rtx pat = PATTERN ( next ) ; rtx src = SET_SRC ( pat ) ; rtx t = XEXP ( src , 0 ) ; enum machine_mode mode = GET_MODE ( XEXP ( pattern , 0 ) ) ; if ( avr_simplify_comparison_p ( mode , GET_CODE ( t ) , x ) ) { XEXP ( pattern , 1 ) = gen_int_mode ( INTVAL ( x ) + 1 , mode ) ; PUT_CODE ( t , avr_normalize_condition ( GET_CODE ( t ) ) ) ; INSN_CODE ( next ) = - 1 ; INSN_CODE ( insn ) = - 1 ; } } } else if ( true_regnum ( SET_SRC ( pattern ) ) >= 0 ) { rtx next = next_real_insn ( insn ) ; rtx pat = PATTERN ( next ) ; rtx src = SET_SRC ( pat ) ; rtx t = XEXP ( src , 0 ) ; PUT_CODE ( t , swap_condition ( GET_CODE ( t ) ) ) ; SET_SRC ( pattern ) = gen_rtx_NEG ( GET_MODE ( SET_SRC ( pattern ) ) , SET_SRC ( pattern ) ) ; INSN_CODE ( next ) = - 1 ; INSN_CODE ( insn ) = - 1 ; } } } } </s>

This function optimizes conditional jumps .


<s> static bool avr_return_in_memory ( tree type , tree fntype ATTRIBUTE_UNUSED ) { if ( TYPE_MODE ( type ) == BLKmode ) { HOST_WIDE_INT size = int_size_in_bytes ( type ) ; return ( size == - 1 || size > 8 ) ; } else return false ; } </s>

Worker function for TARGET_RETURN_IN_MEMORY .


<s> int avr_ret_register ( void ) { return 24 ; } </s>

Returns register number for function return value .


"only uninitialized variables can be placed in the "

Implement ` TARGET_SECTION_TYPE_FLAGS ' .


<s> int avr_simple_epilogue ( void ) { return ( ! frame_pointer_needed && get_frame_size ( ) == 0 && avr_regs_to_save ( NULL ) == 0 && ! interrupt_function_p ( current_function_decl ) && ! signal_function_p ( current_function_decl ) && ! avr_naked_function_p ( current_function_decl ) && ! MAIN_NAME_P ( DECL_NAME ( current_function_decl ) ) && ! TREE_THIS_VOLATILE ( current_function_decl ) ) ; } </s>

Return 1 if the function epilogue is just a single `` ret '' .


<s> int avr_simplify_comparison_p ( enum machine_mode mode , RTX_CODE operator , rtx x ) { unsigned int max = ( mode == QImode ? 0xff : mode == HImode ? 0xffff : mode == SImode ? 0xffffffff : 0 ) ; if ( max && operator && GET_CODE ( x ) == CONST_INT ) { if ( unsigned_condition ( operator ) != operator ) max >>= 1 ; if ( max != ( INTVAL ( x ) & max ) && INTVAL ( x ) != 0xff ) return 1 ; } return 0 ; } </s>

Return 0 if undefined , 1 if always true or always false .


<s> int byte_immediate_operand ( rtx op , enum machine_mode mode ATTRIBUTE_UNUSED ) { return ( GET_CODE ( op ) == CONST_INT && INTVAL ( op ) <= 0xff && INTVAL ( op ) >= 0 ) ; } </s>

Predicate function for immediate operand which fits to byte ( 8bit )


<s> int call_insn_operand ( rtx op , enum machine_mode mode ATTRIBUTE_UNUSED ) { if ( GET_CODE ( op ) == MEM ) { rtx inside = XEXP ( op , 0 ) ; if ( register_operand ( inside , Pmode ) ) return 1 ; if ( CONSTANT_ADDRESS_P ( inside ) ) return 1 ; } return 0 ; } </s>

Test for a valid operand for a call instruction . Do n't allow the arg pointer register or virtual regs since they may change into reg + const , which the patterns ca n't handle yet .


<s> enum reg_class class_likely_spilled_p ( int c ) { return ( c != ALL_REGS && c != ADDW_REGS ) ; } </s>

Return value is nonzero if pseudos that have been assigned to registers of class CLASS would likely be spilled because registers of CLASS are needed for spill registers .


<s> int class_max_nregs ( enum reg_class class ATTRIBUTE_UNUSED , enum machine_mode mode ) { return ( ( GET_MODE_SIZE ( mode ) + UNITS_PER_WORD - 1 ) / UNITS_PER_WORD ) ; } </s>

A C expression for the maximum number of consecutive registers of class CLASS needed to hold a value of mode MODE .


<s> static RTX_CODE compare_condition ( rtx insn ) { rtx next = next_real_insn ( insn ) ; RTX_CODE cond = UNKNOWN ; if ( next && GET_CODE ( next ) == JUMP_INSN ) { rtx pat = PATTERN ( next ) ; rtx src = SET_SRC ( pat ) ; rtx t = XEXP ( src , 0 ) ; cond = GET_CODE ( t ) ; } return cond ; } </s>

Returns the condition of compare insn INSN , or UNKNOWN .


<s> int compare_diff_p ( rtx insn ) { RTX_CODE cond = compare_condition ( insn ) ; return ( cond == GT || cond == GTU || cond == LE || cond == LEU ) ? cond : 0 ; } </s>

Returns nonzero if the next insn is a JUMP_INSN with a condition that needs to be swapped ( GT , GTU , LE , LEU ) .


<s> int compare_eq_p ( rtx insn ) { RTX_CODE cond = compare_condition ( insn ) ; return ( cond == EQ || cond == NE ) ; } </s>

Returns nonzero if INSN is a compare insn with the EQ or NE condition .


<s> static int compare_sign_p ( rtx insn ) { RTX_CODE cond = compare_condition ( insn ) ; return ( cond == GE || cond == LT ) ; } </s>

Returns nonzero if INSN is a tst insn that only tests the sign .


<s> static const char * cond_string ( enum rtx_code code ) { switch ( code ) { case NE : return "ne" ; case EQ : return "eq" ; case GE : if ( cc_prev_status . flags & CC_OVERFLOW_UNUSABLE ) return "pl" ; else return "ge" ; case LT : if ( cc_prev_status . flags & CC_OVERFLOW_UNUSABLE ) return "mi" ; else return "lt" ; case GEU : return "sh" ; case LTU : return "lo" ; default : gcc_unreachable ( ) ; } } </s>

Return assembly language string which identifies a comparison type .

avr "ne" "eq" "pl" "ge" "mi" "lt" "sh" "lo"


<s> int const_int_pow2_p ( rtx x ) { if ( GET_CODE ( x ) == CONST_INT ) { HOST_WIDE_INT d = INTVAL ( x ) ; HOST_WIDE_INT abs_d = ( d >= 0 ) ? d : - d ; return exact_log2 ( abs_d ) + 1 ; } return 0 ; } </s>

Returns nonzero ( bit number + 1 ) if X , or -X , is a constant power of 2 .


<s>
int
extra_constraint
(
rtx
x
,
int
c
)
{
if
(
c
==
'Q'
&&
GET_CODE
(
x
)
==
MEM
&&
GET_CODE
(
XEXP
(
x
,
0
)
)
==
PLUS
)
{
if
(
TARGET_ALL_DEBUG
)
{
fprintf
(
stderr
,
(
"extra_constraint:\n"
"reload_completed: %d\n"
"reload_in_progress: %d\n"
)
,
reload_completed
,
reload_in_progress
)
;
debug_rtx
(
x
)
;
}
if
(
GET_CODE
(
x
)
==
MEM
&&
GET_CODE
(
XEXP
(
x
,
0
)
)
==
PLUS
&&
REG_P
(
XEXP
(
XEXP
(
x
,
0
)
,
0
)
)
&&
GET_CODE
(
XEXP
(
XEXP
(
x
,
0
)
,
1
)
)
==
CONST_INT
&&
(
INTVAL
(
XEXP
(
XEXP
(
x
,
0
)
,
1
)
)
<=
MAX_LD_OFFSET
(
GET_MODE
(
x
)
)
)
)
{
rtx
xx
=
XEXP
(
XEXP
(
x
,
0
)
,
0
)
;
int
regno
=
REGNO
(
xx
)
;
if
(
TARGET_ALL_DEBUG
)
{
fprintf
(
stderr
,
(
"extra_constraint:\n"
"reload_completed: %d\n"
"reload_in_progress: %d\n"
)
,
reload_completed
,
reload_in_progress
)
;
debug_rtx
(
x
)
;
}
if
(
regno
>=
FIRST_PSEUDO_REGISTER
)
return
1
;
else
if
(
regno
==
REG_Z
||
regno
==
REG_Y
)
return
1
;
else
if
(
xx
==
frame_pointer_rtx
||
xx
==
arg_pointer_rtx
)
return
1
;
}
}
return
0
;
}
</s>


<s>
void
final_prescan_insn
(
rtx
insn
,
rtx
*
operand
ATTRIBUTE_UNUSED
,
int
num_operands
ATTRIBUTE_UNUSED
)
{
int
uid
=
INSN_UID
(
insn
)
;
if
(
TARGET_INSN_SIZE_DUMP
||
TARGET_ALL_DEBUG
)
{
fprintf
(
asm_out_file
,
"/*DEBUG: 0x%x\t\t%d\t%d */\n"
,
INSN_ADDRESSES
(
uid
)
,
INSN_ADDRESSES
(
uid
)
last_insn_address
,
rtx_cost
(
PATTERN
(
insn
)
,
INSN
)
)
;
}
last_insn_address
=
INSN_ADDRESSES
(
uid
)
;
}
</s>

If defined , a C statement to be executed just prior to the output of assembler code for INSN , to modify the extracted operands so they will be output differently . Here the argument OPVEC is the vector containing the operands extracted from INSN , and NOPERANDS is the number of elements of the vector which contain meaningful data for this insn . The contents of this vector are what will be used to convert the insn template into assembler code , so you can change the assembler output by changing the contents of the vector . We use it to check if the current insn needs a nop in front of it because of load delays , and also to update the delay slot statistics .


<s> int frame_pointer_required_p ( void ) { return ( current_function_calls_alloca || current_function_args_info . nregs == 0 || get_frame_size ( ) > 0 ) ; } </s>

Return 1 if frame pointer for current function required .


<s> rtx function_arg ( CUMULATIVE_ARGS * cum , enum machine_mode mode , tree type , int named ATTRIBUTE_UNUSED ) { int bytes = avr_num_arg_regs ( mode , type ) ; if ( cum -> nregs && bytes <= cum -> nregs ) return gen_rtx_REG ( mode , cum -> regno - bytes ) ; return NULL_RTX ; } </s>

Return an RTL expression containing the register for the given mode , or 0 if the argument is to be passed on the stack . INCOMING_P is nonzero if this is an incoming argument to the current function .


<s> void function_arg_advance ( CUMULATIVE_ARGS * cum , enum machine_mode mode , tree type , int named ATTRIBUTE_UNUSED ) { int bytes = avr_num_arg_regs ( mode , type ) ; cum -> nregs -= bytes ; cum -> regno -= bytes ; if ( cum -> nregs <= 0 ) { cum -> nregs = 0 ; cum -> regno = FIRST_CUM_REG ; } } </s>

Handle the FUNCTION_ARG_ADVANCE macro . 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 .


<s> int function_arg_regno_p ( int r ) { return ( r >= 8 && r <= 25 ) ; } </s>

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


<s> void gas_output_ascii ( FILE * file , const char * str , size_t length ) { const unsigned char * _ascii_bytes = ( const unsigned char * ) str ; const unsigned char * limit = _ascii_bytes + length ; unsigned bytes_in_chunk = 0 ; for ( ; _ascii_bytes < limit ; _ascii_bytes ++ ) { const unsigned char * p ; if ( bytes_in_chunk >= 60 ) { fprintf ( file , "\"\n" ) ; bytes_in_chunk = 0 ; } for ( p = _ascii_bytes ; p < limit && * p != '\0' ; p ++ ) continue ; if ( p < limit && ( p - _ascii_bytes ) <= ( signed ) STRING_LIMIT ) { if ( bytes_in_chunk > 0 ) { fprintf ( file , "\"\n" ) ; bytes_in_chunk = 0 ; } gas_output_limited_string ( file , ( char * ) _ascii_bytes ) ; _ascii_bytes = p ; } else { int escape ; unsigned ch ; if ( bytes_in_chunk == 0 ) fprintf ( file , "\t.ascii\t\"" ) ; switch ( escape = ESCAPES [ ch = * _ascii_bytes ] ) { case 0 : putc ( ch , file ) ; bytes_in_chunk ++ ; break ; case 1 : fprintf ( file , "\\%03o" , ch ) ; bytes_in_chunk += 4 ; break ; default : putc ( '\\' , file ) ; putc ( escape , file ) ; bytes_in_chunk += 2 ; break ; } } } if ( bytes_in_chunk > 0 ) fprintf ( file , "\"\n" ) ; } </s>

The routine used to output sequences of byte values . We use a special version of this for most svr4 targets because doing so makes the generated assembly code more compact ( and thus faster to assemble ) as well as more readable . Note that if we find subparts of the character sequence which end with NUL ( and which are shorter than STRING_LIMIT ) we output those using ASM_OUTPUT_LIMITED_STRING .


<s> void gas_output_limited_string ( FILE * file , const char * str ) { const unsigned char * _limited_str = ( unsigned char * ) str ; unsigned ch ; fprintf ( file , "%s\"" , STRING_ASM_OP ) ; for ( ; ( ch = * _limited_str ) ; _limited_str ++ ) { int escape ; switch ( escape = ESCAPES [ ch ] ) { case 0 : putc ( ch , file ) ; break ; case 1 : fprintf ( file , "\\%03o" , ch ) ; break ; default : putc ( '\\' , file ) ; putc ( escape , file ) ; break ; } } fprintf ( file , "\"\n" ) ; } </s>

The routine used to output NUL terminated strings . We use a special version of this for most svr4 targets because doing so makes the generated assembly code more compact ( and thus faster to assemble ) as well as more readable , especially for targets like the i386 ( where the only alternative is to output character sequences as comma separated lists of numbers ) .


<s> int initial_elimination_offset ( int from , int to ) { if ( from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM ) return 0 ; else { int offset = frame_pointer_needed ? 2 : 0 ; offset += avr_regs_to_save ( NULL ) ; return get_frame_size ( ) + 2 + 1 + offset ; } } </s>

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


<s> void init_cumulative_args ( CUMULATIVE_ARGS * cum , tree fntype , rtx libname , tree fndecl ATTRIBUTE_UNUSED ) { cum -> nregs = 18 ; cum -> regno = FIRST_CUM_REG ; if ( ! libname && fntype ) { int stdarg = ( TYPE_ARG_TYPES ( fntype ) != 0 && ( TREE_VALUE ( tree_last ( TYPE_ARG_TYPES ( fntype ) ) ) != void_type_node ) ) ; if ( stdarg ) cum -> nregs = 0 ; } } </s>

Handle the INIT_CUMULATIVE_ARGS macro . Initialize a variable CUM of type CUMULATIVE_ARGS for a call to a function whose data type is FNTYPE . For a library call , FNTYPE is 0 .


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

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


<s>
int
legitimate_address_p
(
enum
machine_mode
mode
,
rtx
x
,
int
strict
)
{
enum
reg_class
r
=
NO_REGS
;
if
(
TARGET_ALL_DEBUG
)
{
fprintf
(
stderr
,
"mode: (%s) %s %s %s %s:"
,
GET_MODE_NAME
(
mode
)
,
strict
"(strict)"
:
""
,
reload_completed
"(reload_completed)"
:
""
,
reload_in_progress
"(reload_in_progress)"
:
""
,
reg_renumber
"(reg_renumber)"
:
""
)
;
if
(
GET_CODE
(
x
)
==
PLUS
&&
REG_P
(
XEXP
(
x
,
0
)
)
&&
GET_CODE
(
XEXP
(
x
,
1
)
)
==
CONST_INT
&&
INTVAL
(
XEXP
(
x
,
1
)
)
>=
0
&&
INTVAL
(
XEXP
(
x
,
1
)
)
<=
MAX_LD_OFFSET
(
mode
)
&&
reg_renumber
)
fprintf
(
stderr
,
"(r%d ---> r%d)"
,
REGNO
(
XEXP
(
x
,
0
)
)
,
true_regnum
(
XEXP
(
x
,
0
)
)
)
;
debug_rtx
(
x
)
;
}
if
(
REG_P
(
x
)
&&
(
strict
REG_OK_FOR_BASE_STRICT_P
(
x
)
:
REG_OK_FOR_BASE_NOSTRICT_P
(
x
)
)
)
r
=
POINTER_REGS
;
else
if
(
CONSTANT_ADDRESS_P
(
x
)
)
r
=
ALL_REGS
;
else
if
(
GET_CODE
(
x
)
==
PLUS
&&
REG_P
(
XEXP
(
x
,
0
)
)
&&
GET_CODE
(
XEXP
(
x
,
1
)
)
==
CONST_INT
&&
INTVAL
(
XEXP
(
x
,
1
)
)
>=
0
)
{
int
fit
=
INTVAL
(
XEXP
(
x
,
1
)
)
<=
MAX_LD_OFFSET
(
mode
)
;
if
(
fit
)
{
if
(
!
strict
||
REGNO
(
XEXP
(
x
,
0
)
)
==
REG_Y
||
REGNO
(
XEXP
(
x
,
0
)
)
==
REG_Z
)
r
=
BASE_POINTER_REGS
;
if
(
XEXP
(
x
,
0
)
==
frame_pointer_rtx
||
XEXP
(
x
,
0
)
==
arg_pointer_rtx
)
r
=
BASE_POINTER_REGS
;
}
else
if
(
frame_pointer_needed
&&
XEXP
(
x
,
0
)
==
frame_pointer_rtx
)
r
=
POINTER_Y_REGS
;
}
else
if
(
(
GET_CODE
(
x
)
==
PRE_DEC
||
GET_CODE
(
x
)
==
POST_INC
)
&&
REG_P
(
XEXP
(
x
,
0
)
)
&&
(
strict
REG_OK_FOR_BASE_STRICT_P
(
XEXP
(
x
,
0
)
)
:
REG_OK_FOR_BASE_NOSTRICT_P
(
XEXP
(
x
,
0
)
)
)
)
{
r
=
POINTER_REGS
;
}
if
(
TARGET_ALL_DEBUG
)
{
fprintf
(
stderr
,
"   ret = %c\n"
,
r
+
'0'
)
;
}
return
r
==
NO_REGS
0
:
(
int
)
r
;
}
</s>

legitimate_address_p returns 1 if it recognizes an RTL expression `` x '' that is a valid memory address for an instruction . The MODE argument is the machine mode for the MEM expression that wants to use this address .


<s>
rtx
legitimize_address
(
rtx
x
,
rtx
oldx
,
enum
machine_mode
mode
)
{
x
=
oldx
;
if
(
TARGET_ALL_DEBUG
)
{
fprintf
(
stderr
,
"legitimize_address mode: %s"
,
GET_MODE_NAME
(
mode
)
)
;
debug_rtx
(
oldx
)
;
}
if
(
GET_CODE
(
oldx
)
==
PLUS
&&
REG_P
(
XEXP
(
oldx
,
0
)
)
)
{
if
(
REG_P
(
XEXP
(
oldx
,
1
)
)
)
x
=
force_reg
(
GET_MODE
(
oldx
)
,
oldx
)
;
else
if
(
GET_CODE
(
XEXP
(
oldx
,
1
)
)
==
CONST_INT
)
{
int
offs
=
INTVAL
(
XEXP
(
oldx
,
1
)
)
;
if
(
frame_pointer_rtx
!=
XEXP
(
oldx
,
0
)
)
if
(
offs
>
MAX_LD_OFFSET
(
mode
)
)
{
if
(
TARGET_ALL_DEBUG
)
fprintf
(
stderr
,
"force_reg (big offset)\n"
)
;
x
=
force_reg
(
GET_MODE
(
oldx
)
,
oldx
)
;
}
}
}
return
x
;
}
</s>

Try machine-dependent ways of modifying an illegitimate address X to be legitimate . If we find one , return the new , valid address . OLDX is the address as it was before break_out_memory_refs was called . In some cases it is useful to look at this to decide what needs to be done . MODE is the mode of the operand pointed to by X .


<s> int mask_one_bit_p ( HOST_WIDE_INT mask ) { int i ; unsigned HOST_WIDE_INT n = mask ; for ( i = 0 ; i < 32 ; ++ i ) { if ( n & 0x80000000L ) { if ( n & 0x7fffffffL ) return 0 ; else return 32 - i ; } n <<= 1 ; } return 0 ; } </s>

Returns nonzero if the number MASK has only one bit set .


<s> void notice_update_cc ( rtx body ATTRIBUTE_UNUSED , rtx insn ) { rtx set ; switch ( get_attr_cc ( insn ) ) { case CC_NONE : break ; case CC_SET_N : CC_STATUS_INIT ; break ; case CC_SET_ZN : set = single_set ( insn ) ; CC_STATUS_INIT ; if ( set ) { cc_status . flags |= CC_NO_OVERFLOW ; cc_status . value1 = SET_DEST ( set ) ; } break ; case CC_SET_CZN : set = single_set ( insn ) ; CC_STATUS_INIT ; if ( set ) { cc_status . value1 = SET_DEST ( set ) ; cc_status . flags |= CC_OVERFLOW_UNUSABLE ; } break ; case CC_COMPARE : set = single_set ( insn ) ; CC_STATUS_INIT ; if ( set ) cc_status . value1 = SET_SRC ( set ) ; break ; case CC_CLOBBER : CC_STATUS_INIT ; set = single_set ( insn ) ; if ( set ) { rtx src = SET_SRC ( set ) ; if ( GET_CODE ( src ) == ASHIFTRT && GET_MODE ( src ) == QImode ) { rtx x = XEXP ( src , 1 ) ; if ( GET_CODE ( x ) == CONST_INT && INTVAL ( x ) > 0 && INTVAL ( x ) != 6 ) { cc_status . value1 = SET_DEST ( set ) ; cc_status . flags |= CC_OVERFLOW_UNUSABLE ; } } } 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 .


Choose the order in which to allocate hard registers for pseudo-registers local to a basic block . Store the desired register order in the array ` reg_alloc_order ' . Element 0 should be the register to allocate first ; element 1 , the next register ; and so on .


<s> const char * output_reload_inhi ( rtx insn ATTRIBUTE_UNUSED , rtx * operands , int * len ) { int tmp ; if ( ! len ) len = & tmp ; if ( GET_CODE ( operands [ 1 ] ) == CONST_INT ) { int val = INTVAL ( operands [ 1 ] ) ; if ( ( val & 0xff ) == 0 ) { * len = 3 ; return ( AS2 ( mov , % A0 , __zero_reg__ ) CR_TAB AS2 ( ldi , % 2 , hi8 ( % 1 ) ) CR_TAB AS2 ( mov , % B0 , % 2 ) ) ; } else if ( ( val & 0xff00 ) == 0 ) { * len = 3 ; return ( AS2 ( ldi , % 2 , lo8 ( % 1 ) ) CR_TAB AS2 ( mov , % A0 , % 2 ) CR_TAB AS2 ( mov , % B0 , __zero_reg__ ) ) ; } else if ( ( val & 0xff ) == ( ( val & 0xff00 ) >> 8 ) ) { * len = 3 ; return ( AS2 ( ldi , % 2 , lo8 ( % 1 ) ) CR_TAB AS2 ( mov , % A0 , % 2 ) CR_TAB AS2 ( mov , % B0 , % 2 ) ) ; } } * len = 4 ; return ( AS2 ( ldi , % 2 , lo8 ( % 1 ) ) CR_TAB AS2 ( mov , % A0 , % 2 ) CR_TAB AS2 ( ldi , % 2 , hi8 ( % 1 ) ) CR_TAB AS2 ( mov , % B0 , % 2 ) ) ; } </s>

Reload the constant OP [ 1 ] into the HI register OP [ 0 ] . CLOBBER_REG is a QI clobber reg needed to move vast majority of consts into a NO_LD_REGS register . If CLOBBER_REG is NULL_RTX we either do n't need a clobber reg or have to cook one up . PLEN == NULL : Output instructions . PLEN ! = NULL : Output nothing . Set * PLEN to number of words occupied by the insns printed . Return `` '' .


<s> const char * output_reload_insisf ( rtx insn ATTRIBUTE_UNUSED , rtx * operands , int * len ) { rtx src = operands [ 1 ] ; int cnst = ( GET_CODE ( src ) == CONST_INT ) ; if ( len ) { if ( cnst ) * len = 4 + ( ( INTVAL ( src ) & 0xff ) != 0 ) + ( ( INTVAL ( src ) & 0xff00 ) != 0 ) + ( ( INTVAL ( src ) & 0xff0000 ) != 0 ) + ( ( INTVAL ( src ) & 0xff000000 ) != 0 ) ; else * len = 8 ; return "" ; } if ( cnst && ( ( INTVAL ( src ) & 0xff ) == 0 ) ) output_asm_insn ( AS2 ( mov , % A0 , __zero_reg__ ) , operands ) ; else { output_asm_insn ( AS2 ( ldi , % 2 , lo8 ( % 1 ) ) , operands ) ; output_asm_insn ( AS2 ( mov , % A0 , % 2 ) , operands ) ; } if ( cnst && ( ( INTVAL ( src ) & 0xff00 ) == 0 ) ) output_asm_insn ( AS2 ( mov , % B0 , __zero_reg__ ) , operands ) ; else { output_asm_insn ( AS2 ( ldi , % 2 , hi8 ( % 1 ) ) , operands ) ; output_asm_insn ( AS2 ( mov , % B0 , % 2 ) , operands ) ; } if ( cnst && ( ( INTVAL ( src ) & 0xff0000 ) == 0 ) ) output_asm_insn ( AS2 ( mov , % C0 , __zero_reg__ ) , operands ) ; else { output_asm_insn ( AS2 ( ldi , % 2 , hlo8 ( % 1 ) ) , operands ) ; output_asm_insn ( AS2 ( mov , % C0 , % 2 ) , operands ) ; } if ( cnst && ( ( INTVAL ( src ) & 0xff000000 ) == 0 ) ) output_asm_insn ( AS2 ( mov , % D0 , __zero_reg__ ) , operands ) ; else { output_asm_insn ( AS2 ( ldi , % 2 , hhi8 ( % 1 ) ) , operands ) ; output_asm_insn ( AS2 ( mov , % D0 , % 2 ) , operands ) ; } return "" ; } </s>

Reload a SI or SF compile time constant OP [ 1 ] into the register OP [ 0 ] . CLOBBER_REG is a QI clobber reg needed to move vast majority of consts into a NO_LD_REGS register . If CLOBBER_REG is NULL_RTX we either do n't need a clobber reg or have to cook one up . LEN == NULL : Output instructions . LEN ! = NULL : Output nothing . Set * LEN to number of words occupied by the insns printed . Return `` '' .


"large frame pointer change (%d) with -mtiny-stack"

Output to FILE the asm instructions to adjust the frame pointer by ADJ ( r29 : r28 -= ADJ ; ) which can be positive ( prologue ) or negative ( epilogue ) . Returns the number of instructions generated .


<s> static int out_set_stack_ptr ( FILE * file , int before , int after ) { int do_sph , do_cli , do_save , do_sei , lock_sph , size ; do_sph = ! TARGET_TINY_STACK ; lock_sph = do_sph && ! TARGET_NO_INTERRUPTS ; do_cli = ( before != 0 && ( after == 0 || lock_sph ) ) ; do_save = ( do_cli && before == - 1 && after == - 1 ) ; do_sei = ( ( do_cli || before != 1 ) && after == 1 ) ; size = 1 ; if ( do_save ) { fprintf ( file , AS2 ( in , __tmp_reg__ , __SREG__ ) CR_TAB ) ; size ++ ; } if ( do_cli ) { fprintf ( file , "cli" CR_TAB ) ; size ++ ; } if ( do_sph ) { fprintf ( file , AS2 ( out , __SP_H__ , r29 ) CR_TAB ) ; size ++ ; } if ( do_save ) { fprintf ( file , AS2 ( out , __SREG__ , __tmp_reg__ ) CR_TAB ) ; size ++ ; } else if ( do_sei ) { fprintf ( file , "sei" CR_TAB ) ; size ++ ; } fprintf ( file , AS2 ( out , __SP_L__ , r28 ) "\n" ) ; return size ; } </s>

Output to FILE the asm instructions to copy r29 : r28 to SPH : SPL , handling various cases of interrupt enable flag state BEFORE and AFTER ( 0=disabled , 1=enabled , -1=unknown/unchanged ) and target_flags . Returns the number of instructions generated .


<s> const char * out_tsthi ( rtx insn , int * l ) { if ( compare_sign_p ( insn ) ) { if ( l ) * l = 1 ; return AS1 ( tst , % B0 ) ; } if ( reg_unused_after ( insn , SET_SRC ( PATTERN ( insn ) ) ) && compare_eq_p ( insn ) ) { if ( l ) * l = 1 ; return AS2 ( or , % A0 , % B0 ) ; } if ( test_hard_reg_class ( ADDW_REGS , SET_SRC ( PATTERN ( insn ) ) ) ) { if ( l ) * l = 1 ; return AS2 ( sbiw , % 0 , 0 ) ; } if ( l ) * l = 2 ; return ( AS2 ( cp , % A0 , __zero_reg__ ) CR_TAB AS2 ( cpc , % B0 , __zero_reg__ ) ) ; } </s>


<s> const char * out_tstsi ( rtx insn , int * l ) { if ( compare_sign_p ( insn ) ) { if ( l ) * l = 1 ; return AS1 ( tst , % D0 ) ; } if ( test_hard_reg_class ( ADDW_REGS , SET_SRC ( PATTERN ( insn ) ) ) ) { if ( l ) * l = 3 ; return ( AS2 ( sbiw , % A0 , 0 ) CR_TAB AS2 ( cpc , % C0 , __zero_reg__ ) CR_TAB AS2 ( cpc , % D0 , __zero_reg__ ) ) ; } if ( l ) * l = 4 ; return ( AS2 ( cp , % A0 , __zero_reg__ ) CR_TAB AS2 ( cpc , % B0 , __zero_reg__ ) CR_TAB AS2 ( cpc , % C0 , __zero_reg__ ) CR_TAB AS2 ( cpc , % D0 , __zero_reg__ ) ) ; } </s>


<s> enum reg_class preferred_reload_class ( rtx x ATTRIBUTE_UNUSED , enum reg_class class ) { return class ; } </s>

Given an rtx X being reloaded into a reg required to be in class CLASS , return the class of reg to actually use . In general this is just CLASS ; but on some machines in some cases it is preferable to use a more restrictive class . Also , we must ensure that a PLUS is reloaded either into an accumulator or an address register .


"internal compiler error.  Bad address:"

"internal compiler error.  Unknown mode:"

Use S for SI regsUse B & T for parts of DI regs X - stack pointer name Registers Q - byte sized register name U - high byte of word register V - low byte of word register H - word register name I - next word register name S & B - long register name T - next long register name D - quad register name P - register name in size of pointer Integers O - log two of value P - inverted log two H - bottom 16 bits I - top 16 bits N - negative B - high 32 bits of 32bit number . default : value Memory I - adjusted upwards by two T - adjusted upwards by four default : value Address H - low 16 bits I - high 16 bits A - as long constant S - as A but with # default : error Misc C - conditional name D - reverse conditional name F - clear v flag if necessary

"internal compiler error.  Bad address:"


<s> void print_operand_address ( FILE * file , rtx addr ) { switch ( GET_CODE ( addr ) ) { case REG : fprintf ( file , ptrreg_to_str ( REGNO ( addr ) ) ) ; break ; case PRE_DEC : fprintf ( file , "-%s" , ptrreg_to_str ( REGNO ( XEXP ( addr , 0 ) ) ) ) ; break ; case POST_INC : fprintf ( file , "%s+" , ptrreg_to_str ( REGNO ( XEXP ( addr , 0 ) ) ) ) ; break ; default : if ( CONSTANT_ADDRESS_P ( addr ) && ( ( GET_CODE ( addr ) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P ( addr ) ) || GET_CODE ( addr ) == LABEL_REF ) ) { fprintf ( file , "pm(" ) ; output_addr_const ( file , addr ) ; fprintf ( file , ")" ) ; } else output_addr_const ( file , addr ) ; } } </s>

Print the operand address represented by the rtx addr


<s> static const char * ptrreg_to_str ( int regno ) { switch ( regno ) { case REG_X : return "X" ; case REG_Y : return "Y" ; case REG_Z : return "Z" ; default : gcc_unreachable ( ) ; } return NULL ; } </s>

Return a pointer register name as a string


<s> int reg_unused_after ( rtx insn , rtx reg ) { return ( dead_or_set_p ( insn , reg ) || ( REG_P ( reg ) && _reg_unused_after ( insn , reg ) ) ) ; } </s>

Return nonzero if REG is not used after INSN . We assume REG is a reload reg , and therefore does not live past labels or calls or jumps .


<s> static int sequent_regs_live ( void ) { int reg ; int live_seq = 0 ; int cur_seq = 0 ; for ( reg = 0 ; reg < 18 ; ++ reg ) { if ( ! call_used_regs [ reg ] ) { if ( regs_ever_live [ reg ] ) { ++ live_seq ; ++ cur_seq ; } else cur_seq = 0 ; } } if ( ! frame_pointer_needed ) { if ( regs_ever_live [ REG_Y ] ) { ++ live_seq ; ++ cur_seq ; } else cur_seq = 0 ; if ( regs_ever_live [ REG_Y + 1 ] ) { ++ live_seq ; ++ cur_seq ; } else cur_seq = 0 ; } else { cur_seq += 2 ; live_seq += 2 ; } return ( cur_seq == live_seq ) ? live_seq : 0 ; } </s>

This function checks sequence of live registers


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

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


"internal compiler error.  Incorrect shift:"


<s>
const
char
*
ashlsi3_out
(
rtx_insn
*
insn
,
rtx
operands
[
]
,
int
*
len
)
{
if
(
GET_CODE
(
operands
[
2
]
)
==
CONST_INT
)
{
int
k
;
int
*
t
=
len
;
if
(
!
len
)
len
=
&
k
;
switch
(
INTVAL
(
operands
[
2
]
)
)
{
default
:
if
(
INTVAL
(
operands
[
2
]
)
<
32
)
break
;
if
(
AVR_HAVE_MOVW
)
return
*
len
=
3
,
(
"clr %D0"
CR_TAB
"clr %C0"
CR_TAB
"movw %A0,%C0"
)
;
*
len
=
4
;
return
(
"clr %D0"
CR_TAB
"clr %C0"
CR_TAB
"clr %B0"
CR_TAB
"clr %A0"
)
;
case
8
:
{
int
reg0
=
true_regnum
(
operands
[
0
]
)
;
int
reg1
=
true_regnum
(
operands
[
1
]
)
;
*
len
=
4
;
if
(
reg0
>=
reg1
)
return
(
"mov %D0,%C1"
CR_TAB
"mov %C0,%B1"
CR_TAB
"mov %B0,%A1"
CR_TAB
"clr %A0"
)
;
else
return
(
"clr %A0"
CR_TAB
"mov %B0,%A1"
CR_TAB
"mov %C0,%B1"
CR_TAB
"mov %D0,%C1"
)
;
}
case
16
:
{
int
reg0
=
true_regnum
(
operands
[
0
]
)
;
int
reg1
=
true_regnum
(
operands
[
1
]
)
;
if
(
reg0
+
2
==
reg1
)
return
*
len
=
2
,
(
"clr %B0"
CR_TAB
"clr %A0"
)
;
if
(
AVR_HAVE_MOVW
)
return
*
len
=
3
,
(
"movw %C0,%A1"
CR_TAB
"clr %B0"
CR_TAB
"clr %A0"
)
;
else
return
*
len
=
4
,
(
"mov %C0,%A1"
CR_TAB
"mov %D0,%B1"
CR_TAB
"clr %B0"
CR_TAB
"clr %A0"
)
;
}
case
24
:
*
len
=
4
;
return
(
"mov %D0,%A1"
CR_TAB
"clr %C0"
CR_TAB
"clr %B0"
CR_TAB
"clr %A0"
)
;
case
31
:
*
len
=
6
;
return
(
"clr %D0"
CR_TAB
"lsr %A0"
CR_TAB
"ror %D0"
CR_TAB
"clr %C0"
CR_TAB
"clr %B0"
CR_TAB
"clr %A0"
)
;
}
len
=
t
;
}
out_shift_with_cnt
(
"lsl %A0"
CR_TAB
"rol %B0"
CR_TAB
"rol %C0"
CR_TAB
"rol %D0"
,
insn
,
operands
,
len
,
4
)
;
return
""
;
}
</s>


<s>
const
char
*
ashrhi3_out
(
rtx_insn
*
insn
,
rtx
operands
[
]
,
int
*
len
)
{
if
(
GET_CODE
(
operands
[
2
]
)
==
CONST_INT
)
{
int
scratch
=
(
GET_CODE
(
PATTERN
(
insn
)
)
==
PARALLEL
)
;
int
ldi_ok
=
test_hard_reg_class
(
LD_REGS
,
operands
[
0
]
)
;
int
k
;
int
*
t
=
len
;
if
(
!
len
)
len
=
&
k
;
switch
(
INTVAL
(
operands
[
2
]
)
)
{
case
4
:
case
5
:
break
;
case
6
:
if
(
optimize_size
)
break
;
*
len
=
8
;
return
(
"mov __tmp_reg__,%A0"
CR_TAB
"mov %A0,%B0"
CR_TAB
"lsl __tmp_reg__"
CR_TAB
"rol %A0"
CR_TAB
"sbc %B0,%B0"
CR_TAB
"lsl __tmp_reg__"
CR_TAB
"rol %A0"
CR_TAB
"rol %B0"
)
;
case
7
:
*
len
=
4
;
return
(
"lsl %A0"
CR_TAB
"mov %A0,%B0"
CR_TAB
"rol %A0"
CR_TAB
"sbc %B0,%B0"
)
;
case
8
:
{
int
reg0
=
true_regnum
(
operands
[
0
]
)
;
int
reg1
=
true_regnum
(
operands
[
1
]
)
;
if
(
reg0
==
reg1
)
return
*
len
=
3
,
(
"mov %A0,%B0"
CR_TAB
"lsl %B0"
CR_TAB
"sbc %B0,%B0"
)
;
else
return
*
len
=
4
,
(
"mov %A0,%B1"
CR_TAB
"clr %B0"
CR_TAB
"sbrc %A0,7"
CR_TAB
"dec %B0"
)
;
}
case
9
:
*
len
=
4
;
return
(
"mov %A0,%B0"
CR_TAB
"lsl %B0"
CR_TAB
"sbc %B0,%B0"
CR_TAB
"asr %A0"
)
;
case
10
:
*
len
=
5
;
return
(
"mov %A0,%B0"
CR_TAB
"lsl %B0"
CR_TAB
"sbc %B0,%B0"
CR_TAB
"asr %A0"
CR_TAB
"asr %A0"
)
;
case
11
:
if
(
AVR_HAVE_MUL
&&
ldi_ok
)
{
*
len
=
5
;
return
(
"ldi %A0,0x20"
CR_TAB
"muls %B0,%A0"
CR_TAB
"mov %A0,r1"
CR_TAB
"sbc %B0,%B0"
CR_TAB
"clr __zero_reg__"
)
;
}
if
(
optimize_size
&&
scratch
)
break
;
*
len
=
6
;
return
(
"mov %A0,%B0"
CR_TAB
"lsl %B0"
CR_TAB
"sbc %B0,%B0"
CR_TAB
"asr %A0"
CR_TAB
"asr %A0"
CR_TAB
"asr %A0"
)
;
case
12
:
if
(
AVR_HAVE_MUL
&&
ldi_ok
)
{
*
len
=
5
;
return
(
"ldi %A0,0x10"
CR_TAB
"muls %B0,%A0"
CR_TAB
"mov %A0,r1"
CR_TAB
"sbc %B0,%B0"
CR_TAB
"clr __zero_reg__"
)
;
}
if
(
optimize_size
&&
scratch
)
break
;
*
len
=
7
;
return
(
"mov %A0,%B0"
CR_TAB
"lsl %B0"
CR_TAB
"sbc %B0,%B0"
CR_TAB
"asr %A0"
CR_TAB
"asr %A0"
CR_TAB
"asr %A0"
CR_TAB
"asr %A0"
)
;
case
13
:
if
(
AVR_HAVE_MUL
&&
ldi_ok
)
{
*
len
=
5
;
return
(
"ldi %A0,0x08"
CR_TAB
"muls %B0,%A0"
CR_TAB
"mov %A0,r1"
CR_TAB
"sbc %B0,%B0"
CR_TAB
"clr __zero_reg__"
)
;
}
if
(
optimize_size
)
break
;
*
len
=
8
;
return
(
"mov %A0,%B0"
CR_TAB
"lsl %B0"
CR_TAB
"sbc %B0,%B0"
CR_TAB
"asr %A0"
CR_TAB
"asr %A0"
CR_TAB
"asr %A0"
CR_TAB
"asr %A0"
CR_TAB
"asr %A0"
)
;
case
14
:
*
len
=
5
;
return
(
"lsl %B0"
CR_TAB
"sbc %A0,%A0"
CR_TAB
"lsl %B0"
CR_TAB
"mov %B0,%A0"
CR_TAB
"rol %A0"
)
;
default
:
if
(
INTVAL
(
operands
[
2
]
)
<
16
)
break
;
case
15
:
return
*
len
=
3
,
(
"lsl %B0"
CR_TAB
"sbc %A0,%A0"
CR_TAB
"mov %B0,%A0"
)
;
}
len
=
t
;
}
out_shift_with_cnt
(
"asr %B0"
CR_TAB
"ror %A0"
,
insn
,
operands
,
len
,
2
)
;
return
""
;
}
</s>

16bit arithmetic shift right ( ( signed short ) x > > i )


8bit arithmetic shift right ( ( signed char ) x > > i )


<s>
const
char
*
ashrsi3_out
(
rtx_insn
*
insn
,
rtx
operands
[
]
,
int
*
len
)
{
if
(
GET_CODE
(
operands
[
2
]
)
==
CONST_INT
)
{
int
k
;
int
*
t
=
len
;
if
(
!
len
)
len
=
&
k
;
switch
(
INTVAL
(
operands
[
2
]
)
)
{
case
8
:
{
int
reg0
=
true_regnum
(
operands
[
0
]
)
;
int
reg1
=
true_regnum
(
operands
[
1
]
)
;
*
len
=
6
;
if
(
reg0
<=
reg1
)
return
(
"mov %A0,%B1"
CR_TAB
"mov %B0,%C1"
CR_TAB
"mov %C0,%D1"
CR_TAB
"clr %D0"
CR_TAB
"sbrc %C0,7"
CR_TAB
"dec %D0"
)
;
else
return
(
"clr %D0"
CR_TAB
"sbrc %D1,7"
CR_TAB
"dec %D0"
CR_TAB
"mov %C0,%D1"
CR_TAB
"mov %B0,%C1"
CR_TAB
"mov %A0,%B1"
)
;
}
case
16
:
{
int
reg0
=
true_regnum
(
operands
[
0
]
)
;
int
reg1
=
true_regnum
(
operands
[
1
]
)
;
if
(
reg0
==
reg1
+
2
)
return
*
len
=
4
,
(
"clr %D0"
CR_TAB
"sbrc %B0,7"
CR_TAB
"com %D0"
CR_TAB
"mov %C0,%D0"
)
;
if
(
AVR_HAVE_MOVW
)
return
*
len
=
5
,
(
"movw %A0,%C1"
CR_TAB
"clr %D0"
CR_TAB
"sbrc %B0,7"
CR_TAB
"com %D0"
CR_TAB
"mov %C0,%D0"
)
;
else
return
*
len
=
6
,
(
"mov %B0,%D1"
CR_TAB
"mov %A0,%C1"
CR_TAB
"clr %D0"
CR_TAB
"sbrc %B0,7"
CR_TAB
"com %D0"
CR_TAB
"mov %C0,%D0"
)
;
}
case
24
:
return
*
len
=
6
,
(
"mov %A0,%D1"
CR_TAB
"clr %D0"
CR_TAB
"sbrc %A0,7"
CR_TAB
"com %D0"
CR_TAB
"mov %B0,%D0"
CR_TAB
"mov %C0,%D0"
)
;
default
:
if
(
INTVAL
(
operands
[
2
]
)
<
32
)
break
;
case
31
:
if
(
AVR_HAVE_MOVW
)
return
*
len
=
4
,
(
"lsl %D0"
CR_TAB
"sbc %A0,%A0"
CR_TAB
"mov %B0,%A0"
CR_TAB
"movw %C0,%A0"
)
;
else
return
*
len
=
5
,
(
"lsl %D0"
CR_TAB
"sbc %A0,%A0"
CR_TAB
"mov %B0,%A0"
CR_TAB
"mov %C0,%A0"
CR_TAB
"mov %D0,%A0"
)
;
}
len
=
t
;
}
out_shift_with_cnt
(
"asr %D0"
CR_TAB
"ror %C0"
CR_TAB
"ror %B0"
CR_TAB
"ror %A0"
,
insn
,
operands
,
len
,
4
)
;
return
""
;
}
</s>

32bit arithmetic shift right ( ( signed long ) x > > i )


<s> static bool avr_2word_insn_p ( rtx_insn * insn ) { if ( TARGET_SKIP_BUG || ! insn || 2 != get_attr_length ( insn ) ) { return false ; } switch ( INSN_CODE ( insn ) ) { default : return false ; case CODE_FOR_movqi_insn : case CODE_FOR_movuqq_insn : case CODE_FOR_movqq_insn : { rtx set = single_set ( insn ) ; rtx src = SET_SRC ( set ) ; rtx dest = SET_DEST ( set ) ; if ( MEM_P ( dest ) && ( REG_P ( src ) || src == CONST0_RTX ( GET_MODE ( dest ) ) ) ) { return CONSTANT_ADDRESS_P ( XEXP ( dest , 0 ) ) ; } else if ( REG_P ( dest ) && MEM_P ( src ) ) { return CONSTANT_ADDRESS_P ( XEXP ( src , 0 ) ) ; } return false ; } case CODE_FOR_call_insn : case CODE_FOR_call_value_insn : return true ; } } </s>

Helper for jump_over_one_insn_p : Test if INSN is a 2-word instruction and thus is suitable to be skipped by CPSE , SBRC , etc .


<s>
static
int
avr_address_cost
(
rtx
x
,
machine_mode
mode
ATTRIBUTE_UNUSED
,
addr_space_t
as
ATTRIBUTE_UNUSED
,
bool
speed
ATTRIBUTE_UNUSED
)
{
int
cost
=
4
;
if
(
GET_CODE
(
x
)
==
PLUS
&&
CONST_INT_P
(
XEXP
(
x
,
1
)
)
&&
(
REG_P
(
XEXP
(
x
,
0
)
)
||
GET_CODE
(
XEXP
(
x
,
0
)
)
==
SUBREG
)
)
{
if
(
INTVAL
(
XEXP
(
x
,
1
)
)
>=
61
)
cost
=
18
;
}
else
if
(
CONSTANT_ADDRESS_P
(
x
)
)
{
if
(
optimize
>
0
&&
io_address_operand
(
x
,
QImode
)
)
cost
=
2
;
}
if
(
avr_log
.
address_cost
)
avr_edump
(
"\n%?: %d = %r\n"
,
cost
,
x
)
;
return
cost
;
}
</s>

Calculate the cost of a memory address .


<s> static machine_mode avr_addr_space_address_mode ( addr_space_t as ) { return avr_addrspace [ as ] . pointer_size == 3 ? PSImode : HImode ; } </s>

Implement ` TARGET_ADDR_SPACE_ADDRESS_MODE ' .


<s>
static
rtx
avr_addr_space_convert
(
rtx
src
,
tree
type_from
,
tree
type_to
)
{
addr_space_t
as_from
=
TYPE_ADDR_SPACE
(
TREE_TYPE
(
type_from
)
)
;
addr_space_t
as_to
=
TYPE_ADDR_SPACE
(
TREE_TYPE
(
type_to
)
)
;
if
(
avr_log
.
progmem
)
avr_edump
(
"\n%!: op = %r\nfrom = %t\nto = %t\n"
,
src
,
type_from
,
type_to
)
;
if
(
as_from
!=
ADDR_SPACE_MEMX
&&
as_to
==
ADDR_SPACE_MEMX
)
{
int
msb
;
rtx
sym
=
src
;
rtx
reg
=
gen_reg_rtx
(
PSImode
)
;
while
(
CONST
==
GET_CODE
(
sym
)
||
PLUS
==
GET_CODE
(
sym
)
)
sym
=
XEXP
(
sym
,
0
)
;
if
(
SYMBOL_REF
==
GET_CODE
(
sym
)
&&
ADDR_SPACE_FLASH
==
AVR_SYMBOL_GET_ADDR_SPACE
(
sym
)
)
{
as_from
=
ADDR_SPACE_FLASH
;
}
msb
=
ADDR_SPACE_GENERIC_P
(
as_from
)
0x80
:
avr_addrspace
[
as_from
]
.
segment
;
src
=
force_reg
(
Pmode
,
src
)
;
emit_insn
(
msb
==
0
gen_zero_extendhipsi2
(
reg
,
src
)
:
gen_n_extendhipsi2
(
reg
,
gen_int_mode
(
msb
,
QImode
)
,
src
)
)
;
return
reg
;
}
if
(
as_from
==
ADDR_SPACE_MEMX
&&
as_to
!=
ADDR_SPACE_MEMX
)
{
rtx
new_src
=
gen_reg_rtx
(
Pmode
)
;
src
=
force_reg
(
PSImode
,
src
)
;
emit_move_insn
(
new_src
,
simplify_gen_subreg
(
Pmode
,
src
,
PSImode
,
0
)
)
;
return
new_src
;
}
return
src
;
}
</s>

Implement ` TARGET_ADDR_SPACE_CONVERT ' .


<s> static machine_mode avr_addr_space_pointer_mode ( addr_space_t as ) { return avr_addr_space_address_mode ( as ) ; } </s>

Implement ` TARGET_ADDR_SPACE_POINTER_MODE ' .


Choose the order in which to allocate hard registers for pseudo-registers local to a basic block . Store the desired register order in the array ` reg_alloc_order ' . Element 0 should be the register to allocate first ; element 1 , the next register ; and so on .


<s> static void avr_adjust_type_node ( tree * node , machine_mode mode , int sat_p ) { * node = make_node ( FIXED_POINT_TYPE ) ; TYPE_SATURATING ( * node ) = sat_p ; TYPE_UNSIGNED ( * node ) = UNSIGNED_FIXED_POINT_MODE_P ( mode ) ; TYPE_IBIT ( * node ) = GET_MODE_IBIT ( mode ) ; TYPE_FBIT ( * node ) = GET_MODE_FBIT ( mode ) ; TYPE_PRECISION ( * node ) = GET_MODE_BITSIZE ( mode ) ; TYPE_ALIGN ( * node ) = 8 ; SET_TYPE_MODE ( * node , mode ) ; layout_type ( * node ) ; } </s>


<s>
static
void
avr_asm_function_begin_epilogue
(
FILE
*
file
)
{
fprintf
(
file
,
"/* epilogue start */\n"
)
;
}
</s>

Implement ` TARGET_ASM_FUNCTION_BEGIN_EPILOGUE ' .


<s>
static
void
avr_asm_function_end_prologue
(
FILE
*
file
)
{
if
(
cfun
->
machine
->
is_naked
)
{
fputs
(
"/* prologue: naked */\n"
,
file
)
;
}
else
{
if
(
cfun
->
machine
->
is_interrupt
)
{
fputs
(
"/* prologue: Interrupt */\n"
,
file
)
;
}
else
if
(
cfun
->
machine
->
is_signal
)
{
fputs
(
"/* prologue: Signal */\n"
,
file
)
;
}
else
fputs
(
"/* prologue: function */\n"
,
file
)
;
}
if
(
ACCUMULATE_OUTGOING_ARGS
)
fprintf
(
file
,
"/* outgoing args size = %d */\n"
,
avr_outgoing_args_size
(
)
)
;
fprintf
(
file
,
"/* frame size = "
HOST_WIDE_INT_PRINT_DEC
" */\n"
,
get_frame_size
(
)
)
;
fprintf
(
file
,
"/* stack size = %d */\n"
,
cfun
->
machine
->
stack_usage
)
;
fprintf
(
file
,
".L__stack_usage = %d\n"
,
cfun
->
machine
->
stack_usage
)
;
}
</s>

Output summary at end of function prologue .

avr
"/* prologue: naked */\n"
"/* prologue: Interrupt */\n"
"/* prologue: Signal */\n"
"/* prologue: function */\n"
"/* outgoing args size = %d */\n"
"/* frame size = "
" */\n"
"/* stack size = %d */\n"
".L__stack_usage = %d\n"


<s> static section * avr_asm_function_rodata_section ( tree decl ) { unsigned int flags ; section * frodata ; { int fdata = flag_data_sections ; flag_data_sections = flag_function_sections ; frodata = default_function_rodata_section ( decl ) ; flag_data_sections = fdata ; flags = frodata -> common . flags ; } if ( frodata != readonly_data_section && flags & SECTION_NAMED ) { unsigned int i ; static const char * const prefix [ ] = { ".rodata" , ".progmem.gcc_sw_table" , ".gnu.linkonce.r." , ".gnu.linkonce.t." } ; for ( i = 0 ; i < sizeof ( prefix ) / sizeof ( * prefix ) ; i += 2 ) { const char * old_prefix = prefix [ i ] ; const char * new_prefix = prefix [ i + 1 ] ; const char * name = frodata -> named . name ; if ( STR_PREFIX_P ( name , old_prefix ) ) { const char * rname = ACONCAT ( ( new_prefix , name + strlen ( old_prefix ) , NULL ) ) ; flags &= ~ SECTION_CODE ; flags |= AVR_HAVE_JMP_CALL ? 0 : SECTION_CODE ; return get_section ( rname , flags , frodata -> named . decl ) ; } } } return progmem_swtable_section ; } </s>

Implement ` TARGET_ASM_FUNCTION_RODATA_SECTION ' .


<s> static void avr_asm_init_sections ( void ) { if ( AVR_HAVE_JMP_CALL ) { progmem_swtable_section = get_unnamed_section ( 0 , output_section_asm_op , "\t.section\t.progmem.gcc_sw_table" ",\"a\",@progbits" ) ; } else { progmem_swtable_section = get_unnamed_section ( SECTION_CODE , output_section_asm_op , "\t.section\t.progmem.gcc_sw_table" ",\"ax\",@progbits" ) ; } readonly_data_section -> unnamed . callback = avr_output_data_section_asm_op ; data_section -> unnamed . callback = avr_output_data_section_asm_op ; bss_section -> unnamed . callback = avr_output_bss_section_asm_op ; } </s>

Implement ` TARGET_ASM_INIT_SECTIONS ' .


<s> static const char * avr_asm_len ( const char * tpl , rtx * operands , int * plen , int n_words ) { if ( NULL == plen ) { output_asm_insn ( tpl , operands ) ; } else { if ( n_words < 0 ) * plen = - n_words ; else * plen += n_words ; } return "" ; } </s>

Helper function to print assembler resp . track instruction sequence lengths . Always return `` '' . If PLEN == NULL : Output assembler code from template TPL with operands supplied by OPERANDS . This is just forwarding to output_asm_insn . If PLEN ! = NULL : If N_WORDS > = 0 Add N_WORDS to * PLEN . If N_WORDS < 0 Set * PLEN to -N_WORDS . Do n't output anything .


<s> static void avr_asm_named_section ( const char * name , unsigned int flags , tree decl ) { if ( flags & AVR_SECTION_PROGMEM ) { addr_space_t as = ( flags & AVR_SECTION_PROGMEM ) / SECTION_MACH_DEP ; const char * old_prefix = ".rodata" ; const char * new_prefix = avr_addrspace [ as ] . section_name ; if ( STR_PREFIX_P ( name , old_prefix ) ) { const char * sname = ACONCAT ( ( new_prefix , name + strlen ( old_prefix ) , NULL ) ) ; default_elf_asm_named_section ( sname , flags , decl ) ; return ; } default_elf_asm_named_section ( new_prefix , flags , decl ) ; return ; } if ( ! avr_need_copy_data_p ) avr_need_copy_data_p = ( STR_PREFIX_P ( name , ".data" ) || STR_PREFIX_P ( name , ".rodata" ) || STR_PREFIX_P ( name , ".gnu.linkonce.d" ) ) ; if ( ! avr_need_clear_bss_p ) avr_need_clear_bss_p = STR_PREFIX_P ( name , ".bss" ) ; default_elf_asm_named_section ( name , flags , decl ) ; } </s>

Track need of __do_clear_bss , __do_copy_data for named sections .


"static IO declaration for %q+D needs an address"


<s> static section * avr_asm_select_section ( tree decl , int reloc , unsigned HOST_WIDE_INT align ) { section * sect = default_elf_select_section ( decl , reloc , align ) ; if ( decl && DECL_P ( decl ) && avr_progmem_p ( decl , DECL_ATTRIBUTES ( decl ) ) ) { addr_space_t as = TYPE_ADDR_SPACE ( TREE_TYPE ( decl ) ) ; if ( ADDR_SPACE_GENERIC_P ( as ) ) as = ADDR_SPACE_FLASH ; if ( sect -> common . flags & SECTION_NAMED ) { const char * name = sect -> named . name ; const char * old_prefix = ".rodata" ; const char * new_prefix = avr_addrspace [ as ] . section_name ; if ( STR_PREFIX_P ( name , old_prefix ) ) { const char * sname = ACONCAT ( ( new_prefix , name + strlen ( old_prefix ) , NULL ) ) ; return get_section ( sname , sect -> common . flags , sect -> named . decl ) ; } } if ( ! progmem_section [ as ] ) { progmem_section [ as ] = get_unnamed_section ( 0 , avr_output_progmem_section_asm_op , avr_addrspace [ as ] . section_name ) ; } return progmem_section [ as ] ; } return sect ; } </s>


<s>
static
bool
avr_assemble_integer
(
rtx
x
,
unsigned
int
size
,
int
aligned_p
)
{
if
(
size
==
POINTER_SIZE
/
BITS_PER_UNIT
&&
aligned_p
&&
text_segment_operand
(
x
,
VOIDmode
)
)
{
fputs
(
"\t.word\tgs("
,
asm_out_file
)
;
output_addr_const
(
asm_out_file
,
x
)
;
fputs
(
")\n"
,
asm_out_file
)
;
return
true
;
}
else
if
(
GET_MODE
(
x
)
==
PSImode
)
{
fputs
(
"\t.byte\tlo8("
,
asm_out_file
)
;
output_addr_const
(
asm_out_file
,
x
)
;
fputs
(
")"
ASM_COMMENT_START
"need binutils PR13503\n"
,
asm_out_file
)
;
fputs
(
"\t.byte\thi8("
,
asm_out_file
)
;
output_addr_const
(
asm_out_file
,
x
)
;
fputs
(
")"
ASM_COMMENT_START
"need binutils PR13503\n"
,
asm_out_file
)
;
fputs
(
"\t.byte\thh8("
,
asm_out_file
)
;
output_addr_const
(
asm_out_file
,
x
)
;
fputs
(
")"
ASM_COMMENT_START
"need binutils PR13503\n"
,
asm_out_file
)
;
return
true
;
}
else
if
(
CONST_FIXED_P
(
x
)
)
{
unsigned
n
;
for
(
n
=
0
;
n
<
size
;
n
++
)
{
rtx
xn
=
simplify_gen_subreg
(
QImode
,
x
,
GET_MODE
(
x
)
,
n
)
;
default_assemble_integer
(
xn
,
1
,
aligned_p
)
;
}
return
true
;
}
return
default_assemble_integer
(
x
,
size
,
aligned_p
)
;
}
</s>

Target hook for assembling integer objects . The AVR version needs special handling for references to certain labels .


<s> static rtx avr_builtin_setjmp_frame_value ( void ) { rtx xval = gen_reg_rtx ( Pmode ) ; emit_insn ( gen_subhi3 ( xval , virtual_stack_vars_rtx , gen_int_mode ( STARTING_FRAME_OFFSET , Pmode ) ) ) ; return xval ; } </s>

Actual start of frame is virtual_stack_vars_rtx this is offset from frame pointer by +TARGET_STARTING_FRAME_OFFSET . Using saved frame = virtual_stack_vars_rtx - TARGET_STARTING_FRAME_OFFSET avoids creating add/sub of offset in nonlocal goto and setjmp .


<s> static void avr_conditional_register_usage ( void ) { if ( AVR_TINY ) { unsigned int i ; const int tiny_reg_alloc_order [ ] = { 24 , 25 , 22 , 23 , 30 , 31 , 26 , 27 , 28 , 29 , 21 , 20 , 19 , 18 , 16 , 17 , 32 , 33 , 34 , 35 , 15 , 14 , 13 , 12 , 11 , 10 , 9 , 8 , 7 , 6 , 5 , 4 , 3 , 2 , 1 , 0 } ; for ( i = 0 ; i <= 17 ; i ++ ) { fixed_regs [ i ] = 1 ; call_used_regs [ i ] = 1 ; } for ( i = 18 ; i <= LAST_CALLEE_SAVED_REG ; i ++ ) { call_used_regs [ i ] = 0 ; } for ( i = 0 ; i < ARRAY_SIZE ( tiny_reg_alloc_order ) ; i ++ ) { reg_alloc_order [ i ] = tiny_reg_alloc_order [ i ] ; } CLEAR_HARD_REG_SET ( reg_class_contents [ ( int ) ADDW_REGS ] ) ; CLEAR_HARD_REG_SET ( reg_class_contents [ ( int ) NO_LD_REGS ] ) ; } } </s>

Implement ` TARGET_CONDITIONAL_REGISTER_USAGE ' .


<s> static rtx avr_default_expand_builtin ( enum insn_code icode , tree exp , rtx target ) { rtx pat , xop [ 3 ] ; int n , n_args = call_expr_nargs ( exp ) ; machine_mode tmode = insn_data [ icode ] . operand [ 0 ] . mode ; gcc_assert ( n_args >= 1 && n_args <= 3 ) ; if ( target == NULL_RTX || GET_MODE ( target ) != tmode || ! insn_data [ icode ] . operand [ 0 ] . predicate ( target , tmode ) ) { target = gen_reg_rtx ( tmode ) ; } for ( n = 0 ; n < n_args ; n ++ ) { tree arg = CALL_EXPR_ARG ( exp , n ) ; rtx op = expand_expr ( arg , NULL_RTX , VOIDmode , EXPAND_NORMAL ) ; machine_mode opmode = GET_MODE ( op ) ; machine_mode mode = insn_data [ icode ] . operand [ n + 1 ] . mode ; if ( ( opmode == SImode || opmode == VOIDmode ) && mode == HImode ) { opmode = HImode ; op = gen_lowpart ( HImode , op ) ; } gcc_assert ( opmode == mode || opmode == VOIDmode ) ; if ( ! insn_data [ icode ] . operand [ n + 1 ] . predicate ( op , mode ) ) op = copy_to_mode_reg ( mode , op ) ; xop [ n ] = op ; } switch ( n_args ) { case 1 : pat = GEN_FCN ( icode ) ( target , xop [ 0 ] ) ; break ; case 2 : pat = GEN_FCN ( icode ) ( target , xop [ 0 ] , xop [ 1 ] ) ; break ; case 3 : pat = GEN_FCN ( icode ) ( target , xop [ 0 ] , xop [ 1 ] , xop [ 2 ] ) ; break ; default : gcc_unreachable ( ) ; } if ( pat == NULL_RTX ) return NULL_RTX ; emit_insn ( pat ) ; return target ; } </s>

Subroutine of avr_expand_builtin to expand vanilla builtins with non-void result and 1 ... 3 arguments .


<s> bool avr_emit_movmemhi ( rtx * xop ) { HOST_WIDE_INT count ; machine_mode loop_mode ; addr_space_t as = MEM_ADDR_SPACE ( xop [ 1 ] ) ; rtx loop_reg , addr1 , a_src , a_dest , insn , xas ; rtx a_hi8 = NULL_RTX ; if ( avr_mem_flash_p ( xop [ 0 ] ) ) return false ; if ( ! CONST_INT_P ( xop [ 2 ] ) ) return false ; count = INTVAL ( xop [ 2 ] ) ; if ( count <= 0 ) return false ; a_src = XEXP ( xop [ 1 ] , 0 ) ; a_dest = XEXP ( xop [ 0 ] , 0 ) ; if ( PSImode == GET_MODE ( a_src ) ) { gcc_assert ( as == ADDR_SPACE_MEMX ) ; loop_mode = ( count < 0x100 ) ? QImode : HImode ; loop_reg = gen_rtx_REG ( loop_mode , 24 ) ; emit_move_insn ( loop_reg , gen_int_mode ( count , loop_mode ) ) ; addr1 = simplify_gen_subreg ( HImode , a_src , PSImode , 0 ) ; a_hi8 = simplify_gen_subreg ( QImode , a_src , PSImode , 2 ) ; } else { int segment = avr_addrspace [ as ] . segment ; if ( segment && avr_n_flash > 1 ) { a_hi8 = GEN_INT ( segment ) ; emit_move_insn ( rampz_rtx , a_hi8 = copy_to_mode_reg ( QImode , a_hi8 ) ) ; } else if ( ! ADDR_SPACE_GENERIC_P ( as ) ) { as = ADDR_SPACE_FLASH ; } addr1 = a_src ; loop_mode = ( count <= 0x100 ) ? QImode : HImode ; loop_reg = copy_to_mode_reg ( loop_mode , gen_int_mode ( count , loop_mode ) ) ; } xas = GEN_INT ( as ) ; emit_move_insn ( lpm_addr_reg_rtx , addr1 ) ; emit_move_insn ( gen_rtx_REG ( HImode , REG_X ) , a_dest ) ; gcc_assert ( TMP_REGNO == LPM_REGNO ) ; if ( as != ADDR_SPACE_MEMX ) { rtx ( * fun ) ( rtx , rtx , rtx ) = QImode == loop_mode ? gen_movmem_qi : gen_movmem_hi ; insn = fun ( xas , loop_reg , loop_reg ) ; } else { rtx ( * fun ) ( rtx , rtx ) = QImode == loop_mode ? gen_movmemx_qi : gen_movmemx_hi ; emit_move_insn ( gen_rtx_REG ( QImode , 23 ) , a_hi8 ) ; insn = fun ( xas , GEN_INT ( avr_addr . rampz ) ) ; } set_mem_addr_space ( SET_SRC ( XVECEXP ( insn , 0 , 0 ) ) , as ) ; emit_insn ( insn ) ; return true ; } </s>

Worker function for movmemhi expander . XOP [ 0 ] Destination as MEM : BLK XOP [ 1 ] Source `` `` XOP [ 2 ] # Bytes to copy Return TRUE if the expansion is accomplished . Return FALSE if the operand compination is not supported .


<s>
static
void
avr_encode_section_info
(
tree
decl
,
rtx
rtl
,
int
new_decl_p
)
{
if
(
new_decl_p
&&
decl
&&
DECL_P
(
decl
)
&&
NULL_TREE
==
DECL_INITIAL
(
decl
)
&&
!
DECL_EXTERNAL
(
decl
)
&&
avr_progmem_p
(
decl
,
DECL_ATTRIBUTES
(
decl
)
)
)
{
warning
(
OPT_Wuninitialized
,
"uninitialized variable %q+D put into "
"program memory area"
,
decl
)
;
}
default_encode_section_info
(
decl
,
rtl
,
new_decl_p
)
;
if
(
decl
&&
DECL_P
(
decl
)
&&
TREE_CODE
(
decl
)
!=
FUNCTION_DECL
&&
MEM_P
(
rtl
)
&&
SYMBOL_REF
==
GET_CODE
(
XEXP
(
rtl
,
0
)
)
)
{
rtx
sym
=
XEXP
(
rtl
,
0
)
;
tree
type
=
TREE_TYPE
(
decl
)
;
tree
attr
=
DECL_ATTRIBUTES
(
decl
)
;
if
(
type
==
error_mark_node
)
return
;
addr_space_t
as
=
TYPE_ADDR_SPACE
(
type
)
;
if
(
1
==
avr_progmem_p
(
decl
,
attr
)
)
as
=
ADDR_SPACE_FLASH
;
AVR_SYMBOL_SET_ADDR_SPACE
(
sym
,
as
)
;
tree
io_low_attr
=
lookup_attribute
(
"io_low"
,
attr
)
;
tree
io_attr
=
lookup_attribute
(
"io"
,
attr
)
;
tree
addr_attr
;
if
(
io_low_attr
&&
TREE_VALUE
(
io_low_attr
)
&&
TREE_VALUE
(
TREE_VALUE
(
io_low_attr
)
)
)
addr_attr
=
io_attr
;
else
if
(
io_attr
&&
TREE_VALUE
(
io_attr
)
&&
TREE_VALUE
(
TREE_VALUE
(
io_attr
)
)
)
addr_attr
=
io_attr
;
else
addr_attr
=
lookup_attribute
(
"address"
,
attr
)
;
if
(
io_low_attr
||
(
io_attr
&&
addr_attr
&&
low_io_address_operand
(
GEN_INT
(
TREE_INT_CST_LOW
(
TREE_VALUE
(
TREE_VALUE
(
addr_attr
)
)
)
)
,
QImode
)
)
)
SYMBOL_REF_FLAGS
(
sym
)
|=
SYMBOL_FLAG_IO_LOW
;
if
(
io_attr
||
io_low_attr
)
SYMBOL_REF_FLAGS
(
sym
)
|=
SYMBOL_FLAG_IO
;
if
(
addr_attr
&&
!
DECL_EXTERNAL
(
decl
)
)
SYMBOL_REF_FLAGS
(
sym
)
|=
SYMBOL_FLAG_ADDRESS
;
}
}
</s>

Implement ` TARGET_ENCODE_SECTION_INFO ' .


"%s expects a compile time integer constant"

"%s expects a compile time long integer constant"

"rounding to %d bits has no effect for "

"fixed-point value with %d fractional bits"

Expand an expression EXP that calls a built-in function , with result going to TARGET if that 's convenient ( and in mode MODE if that 's convenient ) . SUBTARGET may be used as the target for computing one of EXP 's operands . IGNORE is nonzero if the value is to be ignored .


<s> void avr_expand_prologue ( void ) { HARD_REG_SET set ; HOST_WIDE_INT size ; size = get_frame_size ( ) + avr_outgoing_args_size ( ) ; cfun -> machine -> stack_usage = 0 ; if ( cfun -> machine -> is_naked ) { return ; } avr_regs_to_save ( & set ) ; if ( cfun -> machine -> is_interrupt || cfun -> machine -> is_signal ) { if ( cfun -> machine -> is_interrupt ) emit_insn ( gen_enable_interrupt ( ) ) ; emit_push_byte ( AVR_ZERO_REGNO , true ) ; emit_push_byte ( AVR_TMP_REGNO , true ) ; emit_push_sfr ( sreg_rtx , false , false ) ; emit_move_insn ( zero_reg_rtx , const0_rtx ) ; emit_use ( zero_reg_rtx ) ; if ( AVR_HAVE_RAMPD ) emit_push_sfr ( rampd_rtx , false , true ) ; if ( AVR_HAVE_RAMPX && TEST_HARD_REG_BIT ( set , REG_X ) && TEST_HARD_REG_BIT ( set , REG_X + 1 ) ) { emit_push_sfr ( rampx_rtx , false , true ) ; } if ( AVR_HAVE_RAMPY && ( frame_pointer_needed || ( TEST_HARD_REG_BIT ( set , REG_Y ) && TEST_HARD_REG_BIT ( set , REG_Y + 1 ) ) ) ) { emit_push_sfr ( rampy_rtx , false , true ) ; } if ( AVR_HAVE_RAMPZ && TEST_HARD_REG_BIT ( set , REG_Z ) && TEST_HARD_REG_BIT ( set , REG_Z + 1 ) ) { emit_push_sfr ( rampz_rtx , false , AVR_HAVE_RAMPD ) ; } } avr_prologue_setup_frame ( size , set ) ; if ( flag_stack_usage_info ) current_function_static_stack_size = cfun -> machine -> stack_usage ; } </s>


<s>
void
avr_final_prescan_insn
(
rtx_insn
*
insn
,
rtx
*
operand
ATTRIBUTE_UNUSED
,
int
num_operands
ATTRIBUTE_UNUSED
)
{
if
(
avr_log
.
rtx_costs
)
{
rtx
set
=
single_set
(
insn
)
;
if
(
set
)
fprintf
(
asm_out_file
,
"/* DEBUG: cost = %d.  */\n"
,
set_src_cost
(
SET_SRC
(
set
)
,
optimize_insn_for_speed_p
(
)
)
)
;
else
fprintf
(
asm_out_file
,
"/* DEBUG: pattern-cost = %d.  */\n"
,
rtx_cost
(
PATTERN
(
insn
)
,
INSN
,
0
,
optimize_insn_for_speed_p
(
)
)
)
;
}
}
</s>

avr
"/* DEBUG: cost = %d.  */\n"
"/* DEBUG: pattern-cost = %d.  */\n"
0


<s> static rtx avr_find_unused_d_reg ( rtx_insn * insn , rtx exclude ) { int regno ; bool isr_p = ( avr_interrupt_function_p ( current_function_decl ) || avr_signal_function_p ( current_function_decl ) ) ; for ( regno = 16 ; regno < 32 ; regno ++ ) { rtx reg = all_regs_rtx [ regno ] ; if ( ( exclude && reg_overlap_mentioned_p ( exclude , reg ) ) || fixed_regs [ regno ] ) { continue ; } if ( ! df_regs_ever_live_p ( regno ) && ( TREE_THIS_VOLATILE ( current_function_decl ) || cfun -> machine -> is_OS_task || cfun -> machine -> is_OS_main || ( ! isr_p && call_used_regs [ regno ] ) ) ) { return reg ; } if ( df_regs_ever_live_p ( regno ) && reg_unused_after ( insn , reg ) ) { return reg ; } } return NULL_RTX ; } </s>

Fixme : This is a hack because secondary reloads do n't works as expected . Find an unused d-register to be used as scratch in INSN . EXCLUDE is either NULL_RTX or some register . In the case where EXCLUDE is a register , skip all possible return values that overlap EXCLUDE . The policy for the returned register is similar to that of ` reg_unused_after ' , i.e . the returned register may overlap the SET_DEST of INSN . Return a QImode d-register or NULL_RTX if nothing found .


<s> static rtx avr_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 ) ; int bytes = avr_num_arg_regs ( mode , type ) ; if ( cum -> nregs && bytes <= cum -> nregs ) return gen_rtx_REG ( mode , cum -> regno - bytes ) ; return NULL_RTX ; } </s>

Controls whether a function argument is passed in a register , and which register .


"fixed register %s used to pass parameter to function"

Update the summarizer variable CUM to advance past an argument in the argument list .


<s> int avr_function_arg_regno_p ( int r ) { return ( AVR_TINY ? r >= 20 && r <= 25 : r >= 8 && r <= 25 ) ; } </s>

Returns nonzero if REGNO is the number of a hard register in which function arguments are sometimes passed .


<s> static bool avr_function_ok_for_sibcall ( tree decl_callee , tree exp_callee ) { tree fntype_callee ; if ( cfun -> machine -> sibcall_fails || TARGET_CALL_PROLOGUES ) { return false ; } fntype_callee = TREE_TYPE ( CALL_EXPR_FN ( exp_callee ) ) ; if ( decl_callee ) { decl_callee = TREE_TYPE ( decl_callee ) ; } else { decl_callee = fntype_callee ; while ( FUNCTION_TYPE != TREE_CODE ( decl_callee ) && METHOD_TYPE != TREE_CODE ( decl_callee ) ) { decl_callee = TREE_TYPE ( decl_callee ) ; } } if ( cfun -> machine -> is_interrupt || cfun -> machine -> is_signal || cfun -> machine -> is_naked || avr_naked_function_p ( decl_callee ) || ( avr_OS_task_function_p ( decl_callee ) != cfun -> machine -> is_OS_task ) || ( avr_OS_main_function_p ( decl_callee ) != cfun -> machine -> is_OS_main ) ) { return false ; } return true ; } </s>

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


<s> int avr_hard_regno_call_part_clobbered ( unsigned regno , machine_mode mode ) { if ( ! avr_hard_regno_mode_ok ( regno , mode ) ) return 0 ; return ( ( regno < 18 && regno + GET_MODE_SIZE ( mode ) > 18 ) || ( regno < REG_Y && regno + GET_MODE_SIZE ( mode ) > REG_Y ) || ( regno < REG_Z && regno + GET_MODE_SIZE ( mode ) > REG_Z ) ) ; } </s>

Implement ` HARD_REGNO_CALL_PART_CLOBBERED ' .


<s> int avr_hard_regno_mode_ok ( int regno , machine_mode mode ) { if ( GET_MODE_SIZE ( mode ) == 1 ) return 1 ; if ( GET_MODE_SIZE ( mode ) >= 4 && regno >= REG_X ) return 0 ; return ! ( regno & 1 ) ; } </s>

Returns 1 if a value of mode MODE can be stored starting with hard register number REGNO . On the enhanced core , anything larger than 1 byte must start in even numbered register for `` movw '' to work ( this way we do n't have to check for odd registers everywhere ) .


<s> bool avr_has_nibble_0xf ( rtx ival ) { unsigned int map = UINTVAL ( ival ) & GET_MODE_MASK ( SImode ) ; return 0 != avr_map_metric ( map , MAP_MASK_PREIMAGE_F ) ; } </s>

Return true if IVAL has a 0xf in its hexadecimal representation and false , otherwise . Only nibbles 0 .. 7 are taken into account . Used as constraint helper for C0f and Cxf .


<s> void avr_init_expanders ( void ) { int regno ; for ( regno = 0 ; regno < 32 ; regno ++ ) all_regs_rtx [ regno ] = gen_rtx_REG ( QImode , regno ) ; lpm_reg_rtx = all_regs_rtx [ LPM_REGNO ] ; tmp_reg_rtx = all_regs_rtx [ AVR_TMP_REGNO ] ; zero_reg_rtx = all_regs_rtx [ AVR_ZERO_REGNO ] ; lpm_addr_reg_rtx = gen_rtx_REG ( HImode , REG_Z ) ; sreg_rtx = gen_rtx_MEM ( QImode , GEN_INT ( avr_addr . sreg ) ) ; rampd_rtx = gen_rtx_MEM ( QImode , GEN_INT ( avr_addr . rampd ) ) ; rampx_rtx = gen_rtx_MEM ( QImode , GEN_INT ( avr_addr . rampx ) ) ; rampy_rtx = gen_rtx_MEM ( QImode , GEN_INT ( avr_addr . rampy ) ) ; rampz_rtx = gen_rtx_MEM ( QImode , GEN_INT ( avr_addr . rampz ) ) ; xstring_empty = gen_rtx_CONST_STRING ( VOIDmode , "" ) ; xstring_e = gen_rtx_CONST_STRING ( VOIDmode , "e" ) ; if ( AVR_TINY ) avr_have_dimode = false ; } </s>


"variable %q+D located in address space %qs beyond flash "

"variable %q+D located in address space %qs"

" which is not supported for architecture %qs"

"variable %q+D must be const in order to be put into"

Add the section attribute if the variable is in progmem .


<s> int avr_jump_mode ( rtx x , rtx_insn * insn ) { int dest_addr = INSN_ADDRESSES ( INSN_UID ( GET_CODE ( x ) == LABEL_REF ? XEXP ( x , 0 ) : x ) ) ; int cur_addr = INSN_ADDRESSES ( INSN_UID ( insn ) ) ; int jump_distance = cur_addr - dest_addr ; if ( - 63 <= jump_distance && jump_distance <= 62 ) return 1 ; else if ( - 2046 <= jump_distance && jump_distance <= 2045 ) return 2 ; else if ( AVR_HAVE_JMP_CALL ) return 3 ; return 2 ; } </s>

Choose mode for jump insn : 1 - relative jump in range -63 < = x < = 62 ; 2 - relative jump in range -2046 < = x < = 2045 ; 3 - absolute jump ( only for ATmega [ 16 ] 03 ) .


Return nonzero if X ( an RTX ) is a legitimate memory address on the target machine for a memory operand of mode MODE .


<s>
static
rtx
avr_legitimize_address
(
rtx
x
,
rtx
oldx
,
machine_mode
mode
)
{
bool
big_offset_p
=
false
;
x
=
oldx
;
if
(
GET_CODE
(
oldx
)
==
PLUS
&&
REG_P
(
XEXP
(
oldx
,
0
)
)
)
{
if
(
REG_P
(
XEXP
(
oldx
,
1
)
)
)
x
=
force_reg
(
GET_MODE
(
oldx
)
,
oldx
)
;
else
if
(
CONST_INT_P
(
XEXP
(
oldx
,
1
)
)
)
{
int
offs
=
INTVAL
(
XEXP
(
oldx
,
1
)
)
;
if
(
frame_pointer_rtx
!=
XEXP
(
oldx
,
0
)
&&
offs
>
MAX_LD_OFFSET
(
mode
)
)
{
big_offset_p
=
true
;
x
=
force_reg
(
GET_MODE
(
oldx
)
,
oldx
)
;
}
}
}
if
(
avr_log
.
legitimize_address
)
{
avr_edump
(
"\n%?: mode=%m\n %r\n"
,
mode
,
oldx
)
;
if
(
x
!=
oldx
)
avr_edump
(
" %s --> %r\n"
,
big_offset_p
"(big offset)"
:
""
,
x
)
;
}
return
x
;
}
</s>

Attempts to replace X with a valid memory address for an operand of mode MODE


<s>
rtx
avr_legitimize_reload_address
(
rtx
*
px
,
machine_mode
mode
,
int
opnum
,
int
type
,
int
addr_type
,
int
ind_levels
ATTRIBUTE_UNUSED
,
rtx
(
*
mk_memloc
)
(
rtx
,
int
)
)
{
rtx
x
=
*
px
;
if
(
avr_log
.
legitimize_reload_address
)
avr_edump
(
"\n%?:%m %r\n"
,
mode
,
x
)
;
if
(
1
&&
(
GET_CODE
(
x
)
==
POST_INC
||
GET_CODE
(
x
)
==
PRE_DEC
)
)
{
push_reload
(
XEXP
(
x
,
0
)
,
XEXP
(
x
,
0
)
,
&
XEXP
(
x
,
0
)
,
&
XEXP
(
x
,
0
)
,
POINTER_REGS
,
GET_MODE
(
x
)
,
GET_MODE
(
x
)
,
0
,
0
,
opnum
,
RELOAD_OTHER
)
;
if
(
avr_log
.
legitimize_reload_address
)
avr_edump
(
" RCLASS.1 = %R\n IN = %r\n OUT = %r\n"
,
POINTER_REGS
,
XEXP
(
x
,
0
)
,
XEXP
(
x
,
0
)
)
;
return
x
;
}
if
(
GET_CODE
(
x
)
==
PLUS
&&
REG_P
(
XEXP
(
x
,
0
)
)
&&
0
==
reg_equiv_constant
(
REGNO
(
XEXP
(
x
,
0
)
)
)
&&
CONST_INT_P
(
XEXP
(
x
,
1
)
)
&&
INTVAL
(
XEXP
(
x
,
1
)
)
>=
1
)
{
bool
fit
=
INTVAL
(
XEXP
(
x
,
1
)
)
<=
MAX_LD_OFFSET
(
mode
)
;
if
(
fit
)
{
if
(
reg_equiv_address
(
REGNO
(
XEXP
(
x
,
0
)
)
)
!=
0
)
{
int
regno
=
REGNO
(
XEXP
(
x
,
0
)
)
;
rtx
mem
=
mk_memloc
(
x
,
regno
)
;
push_reload
(
XEXP
(
mem
,
0
)
,
NULL_RTX
,
&
XEXP
(
mem
,
0
)
,
,
POINTER_REGS
,
Pmode
,
VOIDmode
,
0
,
0
,
1
,
(
enum
reload_type
)
addr_type
)
;
if
(
avr_log
.
legitimize_reload_address
)
avr_edump
(
" RCLASS.2 = %R\n IN = %r\n OUT = %r\n"
,
POINTER_REGS
,
XEXP
(
mem
,
0
)
,
NULL_RTX
)
;
push_reload
(
mem
,
NULL_RTX
,
&
XEXP
(
x
,
0
)
,
,
BASE_POINTER_REGS
,
GET_MODE
(
x
)
,
VOIDmode
,
0
,
0
,
opnum
,
(
enum
reload_type
)
type
)
;
if
(
avr_log
.
legitimize_reload_address
)
avr_edump
(
" RCLASS.2 = %R\n IN = %r\n OUT = %r\n"
,
BASE_POINTER_REGS
,
mem
,
NULL_RTX
)
;
return
x
;
}
}
else
if
(
!
(
frame_pointer_needed
&&
XEXP
(
x
,
0
)
==
frame_pointer_rtx
)
)
{
push_reload
(
x
,
NULL_RTX
,
px
,
,
POINTER_REGS
,
GET_MODE
(
x
)
,
VOIDmode
,
0
,
0
,
opnum
,
(
enum
reload_type
)
type
)
;
if
(
avr_log
.
legitimize_reload_address
)
avr_edump
(
" RCLASS.3 = %R\n IN = %r\n OUT = %r\n"
,
POINTER_REGS
,
x
,
NULL_RTX
)
;
return
x
;
}
}
return
NULL_RTX
;
}
</s>

This will allow register R26/27 to be used where it is no worse than normal base pointers R28/29 or R30/31 . For example , if base offset is greater than 63 bytes or for R++ or -- R addressing .


<s>
static
avr_map_op_t
avr_map_decompose
(
unsigned
int
f
,
const
avr_map_op_t
*
g
,
bool
val_const_p
)
{
int
i
;
bool
val_used_p
=
0
!=
avr_map_metric
(
f
,
MAP_MASK_PREIMAGE_F
)
;
avr_map_op_t
f_ginv
=
*
g
;
unsigned
int
ginv
=
g
->
ginv
;
f_ginv
.
cost
=
1
;
for
(
i
=
7
;
i
>=
0
;
i
)
{
int
x
=
avr_map
(
f
,
i
)
;
if
(
x
<=
7
)
{
x
=
avr_map
(
ginv
,
x
)
;
if
(
x
>
7
)
return
f_ginv
;
}
f_ginv
.
map
=
(
f_ginv
.
map
<<
4
)
+
x
;
}
if
(
0
==
avr_map_metric
(
f_ginv
.
map
,
MAP_NONFIXED_0_7
)
)
{
f_ginv
.
cost
=
2
+
(
val_used_p
&&
!
val_const_p
)
;
}
else
{
rtx
xop
[
4
]
;
xop
[
0
]
=
all_regs_rtx
[
24
]
;
xop
[
1
]
=
gen_int_mode
(
f_ginv
.
map
,
SImode
)
;
xop
[
2
]
=
all_regs_rtx
[
25
]
;
xop
[
3
]
=
val_used_p
xop
[
0
]
:
const0_rtx
;
avr_out_insert_bits
(
xop
,
&
f_ginv
.
cost
)
;
f_ginv
.
cost
+=
val_const_p
&&
val_used_p
1
:
0
;
}
f_ginv
.
cost
+=
g
->
cost
;
if
(
avr_log
.
builtin
)
avr_edump
(
" %s%d=%d"
,
g
->
str
,
g
->
arg
,
f_ginv
.
cost
)
;
return
f_ginv
;
}
</s>

Try to decompose F as F = ( F o G^-1 ) o G as described above . The result is a struct representing F o G^-1 and G. If result.cost < 0 then such a decomposition does not exist .


<s>
static
void
avr_move_bits
(
rtx
*
xop
,
unsigned
int
map
,
bool
fixp_p
,
int
*
plen
)
{
int
bit_dest
,
b
;
int
t_bit_src
=
1
;
for
(
b
=
0
;
b
<
8
;
b
++
)
for
(
bit_dest
=
0
;
bit_dest
<
8
;
bit_dest
++
)
{
int
bit_src
=
avr_map
(
map
,
bit_dest
)
;
if
(
b
!=
bit_src
||
bit_src
>=
8
||
(
bit_dest
==
bit_src
&&
!
fixp_p
)
)
continue
;
if
(
t_bit_src
!=
bit_src
)
{
t_bit_src
=
bit_src
;
xop
[
3
]
=
GEN_INT
(
bit_src
)
;
avr_asm_len
(
"bst %T1%T3"
,
xop
,
plen
,
1
)
;
}
xop
[
3
]
=
GEN_INT
(
bit_dest
)
;
avr_asm_len
(
"bld %T0%T3"
,
xop
,
plen
,
1
)
;
}
}
</s>

Insert bits from XOP [ 1 ] into XOP [ 0 ] according to MAP . XOP [ 0 ] and XOP [ 1 ] do n't overlap . If FIXP_P = true : Move all bits according to MAP using BLD/BST sequences . If FIXP_P = false : Just move the bit if its position in the destination is different to its source position .


<s> static addr_space_t avr_nonconst_pointer_addrspace ( tree typ ) { while ( ARRAY_TYPE == TREE_CODE ( typ ) ) typ = TREE_TYPE ( typ ) ; if ( POINTER_TYPE_P ( typ ) ) { addr_space_t as ; tree target = TREE_TYPE ( typ ) ; if ( FUNCTION_TYPE == TREE_CODE ( target ) ) return avr_nonconst_pointer_addrspace ( TREE_TYPE ( target ) ) ; while ( TREE_CODE ( target ) == ARRAY_TYPE ) target = TREE_TYPE ( target ) ; as = TYPE_ADDR_SPACE ( target ) ; if ( ! ADDR_SPACE_GENERIC_P ( as ) && ( ! TYPE_READONLY ( target ) || avr_addrspace [ as ] . segment >= avr_n_flash || ( ! AVR_HAVE_LPM && avr_addrspace [ as ] . pointer_size > 2 ) ) ) { return as ; } return avr_nonconst_pointer_addrspace ( target ) ; } return ADDR_SPACE_GENERIC ; } </s>

Scan type TYP for pointer references to address space ASn . Return ADDR_SPACE_GENERIC ( i.e . 0 ) if all pointers targeting the AS are also declared to be CONST . Otherwise , return the respective address space , i.e . a value ! = 0 .


<s> void avr_notice_update_cc ( rtx body ATTRIBUTE_UNUSED , rtx_insn * insn ) { rtx set ; enum attr_cc cc = get_attr_cc ( insn ) ; switch ( cc ) { default : break ; case CC_PLUS : case CC_LDI : { rtx * op = recog_data . operand ; int len_dummy , icc ; extract_constrain_insn_cached ( insn ) ; switch ( cc ) { default : gcc_unreachable ( ) ; case CC_PLUS : avr_out_plus ( insn , op , & len_dummy , & icc ) ; cc = ( enum attr_cc ) icc ; break ; case CC_LDI : cc = ( op [ 1 ] == CONST0_RTX ( GET_MODE ( op [ 0 ] ) ) && reg_overlap_mentioned_p ( op [ 0 ] , zero_reg_rtx ) ) ? CC_CLOBBER : CC_NONE ; break ; } break ; } } switch ( cc ) { default : gcc_unreachable ( ) ; break ; case CC_NONE : break ; case CC_SET_N : CC_STATUS_INIT ; break ; case CC_SET_ZN : set = single_set ( insn ) ; CC_STATUS_INIT ; if ( set ) { cc_status . flags |= CC_NO_OVERFLOW ; cc_status . value1 = SET_DEST ( set ) ; } break ; case CC_SET_VZN : CC_STATUS_INIT ; break ; case CC_SET_CZN : set = single_set ( insn ) ; CC_STATUS_INIT ; if ( set ) { cc_status . value1 = SET_DEST ( set ) ; cc_status . flags |= CC_OVERFLOW_UNUSABLE ; } break ; case CC_COMPARE : set = single_set ( insn ) ; CC_STATUS_INIT ; if ( set ) cc_status . value1 = SET_SRC ( set ) ; break ; case CC_CLOBBER : CC_STATUS_INIT ; break ; } } </s>


<s> static int avr_operand_rtx_cost ( rtx x , machine_mode mode , enum rtx_code outer , int opno , bool speed ) { enum rtx_code code = GET_CODE ( x ) ; int total ; switch ( code ) { case REG : case SUBREG : return 0 ; case CONST_INT : case CONST_FIXED : case CONST_DOUBLE : return COSTS_N_INSNS ( GET_MODE_SIZE ( mode ) ) ; default : break ; } total = 0 ; avr_rtx_costs ( x , code , outer , opno , & total , speed ) ; return total ; } </s>

Mutually recursive subroutine of avr_rtx_cost for calculating the cost of an RTX operand given its context . X is the rtx of the operand , MODE is its mode , and OUTER is the rtx_code of this operand 's parent operator .


<s>
static
void
avr_option_override
(
void
)
{
flag_delete_null_pointer_checks
=
0
;
if
(
avr_strict_X
)
flag_caller_saves
=
0
;
if
(
(
flag_unwind_tables
||
flag_non_call_exceptions
||
flag_asynchronous_unwind_tables
)
&&
!
ACCUMULATE_OUTGOING_ARGS
)
{
flag_omit_frame_pointer
=
0
;
}
if
(
flag_pic
==
1
)
warning
(
OPT_fpic
,
"-fpic is not supported"
)
;
if
(
flag_pic
==
2
)
warning
(
OPT_fPIC
,
"-fPIC is not supported"
)
;
if
(
flag_pie
==
1
)
warning
(
OPT_fpie
,
"-fpie is not supported"
)
;
if
(
flag_pie
==
2
)
warning
(
OPT_fPIE
,
"-fPIE is not supported"
)
;
if
(
!
avr_set_core_architecture
(
)
)
return
;
avr_addr
.
sreg
=
0x3F
+
avr_arch
->
sfr_offset
;
avr_addr
.
rampz
=
0x3B
+
avr_arch
->
sfr_offset
;
avr_addr
.
rampy
=
0x3A
+
avr_arch
->
sfr_offset
;
avr_addr
.
rampx
=
0x39
+
avr_arch
->
sfr_offset
;
avr_addr
.
rampd
=
0x38
+
avr_arch
->
sfr_offset
;
avr_addr
.
ccp
=
(
AVR_TINY
0x3C
:
0x34
)
+
avr_arch
->
sfr_offset
;
avr_addr
.
sp_l
=
0x3D
+
avr_arch
->
sfr_offset
;
avr_addr
.
sp_h
=
avr_addr
.
sp_l
+
1
;
init_machine_status
=
avr_init_machine_status
;
avr_log_set_avr_log
(
)
;
avr_register_passes
(
)
;
}
</s>


<s> static inline int avr_outgoing_args_size ( void ) { return ACCUMULATE_OUTGOING_ARGS ? crtl -> outgoing_args_size : 0 ; } </s>

Report contribution of accumulated outgoing arguments to stack size .


<s>
void
avr_output_addr_vec_elt
(
FILE
*
stream
,
int
value
)
{
if
(
AVR_HAVE_JMP_CALL
)
fprintf
(
stream
,
"\t.word gs(.L%d)\n"
,
value
)
;
else
fprintf
(
stream
,
"\trjmp .L%d\n"
,
value
)
;
}
</s>

Worker function for ` ASM_OUTPUT_ADDR_VEC_ELT ' .

avr
"\t.word gs(.L%d)\n"
"\trjmp .L%d\n"


<s>
const
char
*
avr_out_addto_sp
(
rtx
*
op
,
int
*
plen
)
{
int
pc_len
=
AVR_2_BYTE_PC
2
:
3
;
int
addend
=
INTVAL
(
op
[
0
]
)
;
if
(
plen
)
*
plen
=
0
;
if
(
addend
<
0
)
{
if
(
flag_verbose_asm
||
flag_print_asm_name
)
avr_asm_len
(
ASM_COMMENT_START
"SP -= %n0"
,
op
,
plen
,
0
)
;
while
(
addend
<=
pc_len
)
{
addend
+=
pc_len
;
avr_asm_len
(
"rcall ."
,
op
,
plen
,
1
)
;
}
while
(
addend
++
<
0
)
avr_asm_len
(
"push __zero_reg__"
,
op
,
plen
,
1
)
;
}
else
if
(
addend
>
0
)
{
if
(
flag_verbose_asm
||
flag_print_asm_name
)
avr_asm_len
(
ASM_COMMENT_START
"SP += %0"
,
op
,
plen
,
0
)
;
while
(
addend
>
0
)
avr_asm_len
(
"pop __tmp_reg__"
,
op
,
plen
,
1
)
;
}
return
""
;
}
</s>

PLEN == NULL : Output code to add CONST_INT OP [ 0 ] to SP . PLEN ! = NULL : Set * PLEN to the length of that sequence . Return `` '' .


<s>
static
const
char
*
avr_out_load_psi_reg_no_disp_tiny
(
rtx_insn
*
insn
,
rtx
*
op
,
int
*
plen
)
{
rtx
dest
=
op
[
0
]
;
rtx
src
=
op
[
1
]
;
rtx
base
=
XEXP
(
src
,
0
)
;
int
reg_dest
=
true_regnum
(
dest
)
;
int
reg_base
=
true_regnum
(
base
)
;
if
(
reg_base
==
reg_dest
)
{
return
avr_asm_len
(
TINY_ADIW
(
%
E1
,
%
F1
,
2
)
CR_TAB
"ld %C0,%1"
CR_TAB
"ld __tmp_reg__,-%1"
CR_TAB
TINY_SBIW
(
%
E1
,
%
F1
,
1
)
CR_TAB
"ld %A0,%1"
CR_TAB
"mov %B0,__tmp_reg__"
,
op
,
plen
,
8
)
;
}
else
{
return
avr_asm_len
(
"ld %A0,%1+"
CR_TAB
"ld %B0,%1+"
CR_TAB
"ld %C0,%1"
,
op
,
plen
,
3
)
;
if
(
reg_dest
!=
reg_base
2
&&
!
reg_unused_after
(
insn
,
base
)
)
{
avr_asm_len
(
TINY_SBIW
(
%
E1
,
%
F1
,
2
)
,
op
,
plen
,
2
)
;
}
return
""
;
}
}
</s>

Handle loads of 24-bit types from memory to register .


<s>
static
const
char
*
avr_out_movhi_r_mr_reg_disp_tiny
(
rtx
op
[
]
,
int
*
plen
)
{
rtx
dest
=
op
[
0
]
;
rtx
src
=
op
[
1
]
;
rtx
base
=
XEXP
(
src
,
0
)
;
int
reg_dest
=
true_regnum
(
dest
)
;
int
reg_base
=
true_regnum
(
XEXP
(
base
,
0
)
)
;
if
(
reg_base
==
reg_dest
)
{
return
avr_asm_len
(
TINY_ADIW
(
%
I1
,
%
J1
,
%
o1
)
CR_TAB
"ld __tmp_reg__,%b1+"
CR_TAB
"ld %B0,%b1"
CR_TAB
"mov %A0,__tmp_reg__"
,
op
,
plen
,
5
)
;
}
else
{
return
avr_asm_len
(
TINY_ADIW
(
%
I1
,
%
J1
,
%
o1
)
CR_TAB
"ld %A0,%b1+"
CR_TAB
"ld %B0,%b1"
CR_TAB
TINY_SBIW
(
%
I1
,
%
J1
,
%
o1
+
1
)
,
op
,
plen
,
6
)
;
}
}
</s>

Same as movhi_r_mr , but TINY does not have ADIW , SBIW and LDD


<s>
static
const
char
*
avr_out_movhi_r_mr_reg_no_disp_tiny
(
rtx
op
[
]
,
int
*
plen
)
{
rtx
dest
=
op
[
0
]
;
rtx
src
=
op
[
1
]
;
rtx
base
=
XEXP
(
src
,
0
)
;
int
reg_dest
=
true_regnum
(
dest
)
;
int
reg_base
=
true_regnum
(
base
)
;
if
(
reg_dest
==
reg_base
)
return
avr_asm_len
(
"ld __tmp_reg__,%1+"
CR_TAB
"ld %B0,%1"
CR_TAB
"mov %A0,__tmp_reg__"
,
op
,
plen
,
3
)
;
return
avr_asm_len
(
"ld %A0,%1"
CR_TAB
TINY_ADIW
(
%
E1
,
%
F1
,
1
)
CR_TAB
"ld %B0,%1"
CR_TAB
TINY_SBIW
(
%
E1
,
%
F1
,
1
)
,
op
,
plen
,
6
)
;
}
</s>