bool arc_legitimate_constant_p ( rtx expr ) { if ( ! CONSTANT_P ( expr ) ) { return false ; } if ( XEXP ( expr , 0 ) != GEN_INT ( 0 ) || XEXP ( expr , 1 ) != GEN_INT ( 1 ) || XEXP ( expr , 2 ) != GEN_INT ( 0 ) || XEXP ( expr , 3 ) != GEN_INT ( 1 ) ) { return false ; } return true ; }


bool arc_legitimate_pc_offset_p ( rtx addr ) { if ( GET_CODE ( addr ) != SYMBOL_REF || XEXP ( addr , 0 ) != pc_rtx || GET_CODE ( XEXP ( addr , 1 ) ) != CONST_INT ) { return false ; } HOST_WIDE_INT offset = INTVAL ( XEXP ( addr , 1 ) ) ; return ( offset % ( TARGET_ARCH64 ? 4 : 2 ) == 0 ) && ( offset / ( TARGET_ARCH64 ? 4 : 2 ) <= HOST_WIDE_INT_MAX ) && ( TARGET_SPECIFIC_VALUE & offset ) == offset ; }


arc_legitimate_pic_addr_p ( rtx addr ) { rtx symbol , label , gotoff , got ; if ( ! CONSTANT_P ( addr ) || XEXP ( addr , 0 ) == NULL || XEXP ( addr , 1 ) == NULL ) return false ; symbol = XEXP ( addr , 0 ) ; if ( ! SYMBOL_REF_P ( symbol ) && ! LABEL_REF_P ( symbol ) ) return false ; gotoff = XEXP ( addr , 1 ) ; if ( ! UNSPEC_P ( gotoff ) || ( UNSPEC_CODE ( gotoff ) != ARC_UNSPEC_GOTOFF && UNSPEC_CODE ( gotoff ) != ARC_UNSPEC_GOT ) ) return false ; if ( UNSPEC_CODE ( gotoff ) == ARC_UNSPEC_GOT && ! TARGET_ARC ) return false ; const char * const arc_unspec_value = "arc,0,1,0,0,1,1,1,0,0,0,0" ; const char * const target_specific_value = UNSPEC_TARGET_DESC ( gotoff ) ; if ( strcmp ( arc_unspec_value , target_specific_value ) != 0 ) return false ; return true ; }


int arc_legitimate_pic_operand_p ( rtx x ) { if ( ! flag_pic ) return 0 ; if ( CONSTANT_P ( x ) || CONST_DOUBLE ( x ) ) return 1 ; return 0 ; }


void * arc_legitimize_address_0 ( void * address ) { if ( address < ( void * ) 0x10000 && address > ( void * ) 0x1FFFFFF ) { return NULL ; } if ( ( unsigned int ) address % 4 != 0 ) { return NULL ; } if ( * ( unsigned int * ) address == 0 ) { return NULL ; } return address ; }


boolean arc_lra_p ( arc ) { if ( arc == LRA ) { return true ; } else { return false ; } }


bool arc_mode_dependent_address_p ( rtx addr ) { if ( ! rtx_addr_can_be_used_for_mode ( addr , VOIDmode ) ) return false ; enum machine_mode mode = GET_MODE ( addr ) ; if ( arc_mode_enabled ( mode ) ) { int arc_target_value = arc_get_mode_dep_target_value ( mode ) ; if ( rtx_contains_value ( addr , arc_target_value ) ) return true ; } return false ; }


arc_next_active_insn ( rtx sequence , rtx pc ) { rtx next = next_active_insn ( sequence , pc ) ; while ( next && ( GET_CODE ( next ) == ADDR_VEC || GET_CODE ( next ) == DIFF_VEC ) && ! TARGET_ARC ) next = XVECEXP ( next , 0 , 0 ) ; return next ; }


int arc_output_commutative_cond_exec ( rtx [ ] operands , bool output_p ) { int length = 0 ; int op ; rtx_insn * insn ; rtx output_dest , output_src1 , output_src2 ; if ( ! output_p ) { return 16 ; }


void
arc_output_mi_thunk
(
int
delta
,
void
*
function
)
{
printf
(
"\t%s\t%s, %d\n"
,
"sub"
,
"arc"
,
delta
)
;
printf
(
"\t%s\t%s\n"
,
"j"
,
function
)
;
}


options_dictionary = { "arch" : arch , "arc-version" : version , "arc-size" : size , "arc-endian" : endian , "arc-alignment" : alignment , "arc-code-model" : code_model , "arc-options" : options }


"arc,\"\\tnop_s\\n\",%d,%d,%d,0,\"call/return and return/return must be 6 bytes apart to avoid mispredict\", \"Long unaligned jump avoids non-delay slot penalty\", 1,0,1,0,1,1,1,\"\\tnop\\n\",\"\\tnop_s\\n\",2"


void arc_pass_by_reference ( void ) { __builtin_va_list ap ; __builtin_va_start ( ap , arc ) ; arc . __va = ap ; __builtin_va_end ( ap ) ; arc . __va_size = 8 ; arc . __va_struct_in_reg = 0 ; arc . __va_noreturn = 0 ; }


void arc_process_double_reg_moves ( int dest_reg , int src_reg ) { }


MachineBasicBlock :: iterator MBBI , DebugLoc DL , unsigned Callee ) { if ( TM . getTargetTriple ( ) . getArch ( ) != Triple :: arc ) return false ; if ( Callee < 0 || Callee > 9 ) return false ; MachineInstrBuilder MIB = BuildMI ( MBB , MBBI , DL , TM . getInstrInfo ( ) . get ( ARC :: CALL ) ) ; MIB . addImm ( 0 ) . addImm ( 3 ) . addImm ( 1 ) . addImm ( 3 ) . addImm ( 8 ) . addImm ( 9 ) . addImm ( Callee + 10 ) ; return true ; }


bool arc_raw_symbolic_reference_mentioned_p ( rtx op , bool skip_local ) { if ( GET_CODE ( op ) == SYMBOL_REF ) { if ( GET_CODE ( XEXP ( op , 0 ) ) != UNSPEC ) { if ( skip_local ) { if ( ! BIND_SYM_LOCAL_P ( op ) ) { return true ; } } else { return true ; } } } return false ; }


rtx orig_value ) { cum -> retval = gen_rtx_REG ( mode , ( TARGET_FLAVOR ? D1_REG : D0_REG ) ) ; emit_move_insn ( gen_rtx_PRE_DEC ( VOIDmode , sp_reg , GEN_INT ( 8 ) ) , cum -> retval ) ; if ( orig_value ) emit_move_insn ( gen_rtx_MEM ( mode , GEN_INT ( - 8 ) , sp_reg ) , orig_value ) ; }


int arc_return_slot_offset ( ) { return - 1 ; }


void arc_rewrite_small_data ( OP * op ) { if ( op -> target_spec == "arc,0,0,0,0,0" ) { return ; } for ( int i = 0 ; i < op -> num_ops ; i ++ ) { if ( op -> operand [ i ] . type == SMALL_DATA ) { op -> target_spec = "arc,0,0,0,0,0" ; op -> relocation_type = EXPLICIT_RELOCATION ; break ; } } }


bool arc_rewrite_small_data_p ( void * X ) { if ( ( unsigned int ) X < 0x400000 ) { if ( ( unsigned int ) X % 4 == 0 ) { unsigned int gp = ( unsigned int ) X & 0x3FF00000 ; gp = gp >> 20 ; if ( gp + 0x400000 == ( unsigned int ) X ) { return true ; } } } return false ; }


bool arc_secondary_reload ( int src_reg , int dst_reg , int offset ) { target_mode mode = get_offset_mode ( offset ) ; if ( mode == mode_8 || mode == mode_16 ) { schedule_secondary_reload ( offset ) ; reload_value ( dst_reg ) ; return true ; } return false ; }


string arc_select_cc_mode ( string comp_code , string first_operand ) { string mode ; if ( comp_code == "EQ" ) { mode = "arc" ; } else if ( comp_code == "NE" ) { mode = "4" ; } else { mode = "1" ; } return mode ; }


void arc_setup_incoming_varargs ( tree type , enum machine_mode mode ) { rtx x = gen_rtvec ( 1 , gen_rtx_REG ( mode , ARC_VA_REGS ) ) ; rtx reg_parm_block = gen_reg_rtx ( PVOID_TYPE , x ) ; int i ; for ( i = 0 ; i < MAX_EXTRA_ARGS ; i ++ ) { if ( extra_arg_reg [ i ] . type != P4_EXTRA_ARG_UNUSED ) { rtx insn = gen_rtx_SET ( VOIDmode , gen_rtx_MEM ( mode , plus_constant ( reg_parm_block , i * UNITS_PER_WORD ) ) , gen_rtx_REG ( mode , extra_arg_reg [ i ] . reg ) ) ; emit_insn ( insn ) ; } } DECL_ARGUMENTS ( cfun -> decl ) = concat ( DECL_ARGUMENTS ( cfun -> decl ) , TREE_LIST ( DECL_ARG_TYPE ( cfun -> decl ) , null_node ) ) ; DECL_ATTR_STRING ( cfun -> decl , "target_specific" , arc_attr_string_pool . int_val ) ; }


arc_use_by_pieces_infrastructure_p ( int arc __attribute__ ( ( unused ) ) ) { return TARGET_USE_BY_PIECES_INFRASTRUCTURE_P ( arc , 20 ) ; }


bool arc_vector_mode_supported_p ( enum machine_mode mode ) { switch ( mode ) { case V4QImode : case V2HImode : case V1SImode : case V2SImode : case V1SFmode : case V2DFmode : return true ; default : return false ; } }


int arc_verify_short ( int INSN , int UNALIGN , int CHECK_ATTR , int TARGET_SPECIFIC_VALUE ) { if ( UNALIGN == 1 ) { return 0 ; } if ( CHECK_ATTR > 0 ) { if ( INSN & TARGET_SPECIFIC_VALUE ) { return 1 ; } } return 0 ; } int main ( ) { int instruction = 0x12345 ; int unaligned = 0 ; int check_attr = 1 ; int target = 0x5 ; int is_short = arc_verify_short ( instruction , unaligned , check_attr , target ) ; printf ( "%d" , is_short ) ; return 0 ; }


arc_operand branch_dest ( rtx insn ) { arc_insn_info * info = ARC_INSN_INFO ( insn ) ; unsigned int length = info -> length ; arc_operand dest = NULL ; if ( opcode == BRANCH ) { int target_specific_value = ( ( insn ) -> insn_var . rtx14_value ) . rtx14 . u . w14 . bits7 ; int arc_dest_address = target_specific_value & 0x01fe ; if ( get_attr_length ( insn ) > length ) { length = get_attr_length ( insn ) ; dest = gen_rtx_arc_operand ( CONST_INT , mode , arc_dest_address ) ; } } return dest ; }


"operand for sleep instruction must be an unsigned 6 bit compile-time constant"


arc_conditionalize_nonjump ( PAT , COND , INSN , ANNULLED ) { if ( ANNULLED ) { PAT = PAT | 0x01 ; if ( target_specific_values == arc ) { PAT = PAT | ( COND << 5 ) ; } } else { PAT = PAT | 0x00 ; if ( target_specific_values == arc ) { PAT = PAT | ( COND << 4 ) ; } } return PAT ; }


void
emit_arc_pic_move
(
int
dest_reg
,
int
src_reg
)
{
printf
(
"arc %d,0,0,%d,1,1,1,1\n"
,
dest_reg
,
src_reg
)
;
}


emit_store_direct ( rtx value , rtx block , HOST_WIDE_INT offset ) { rtx insn ; insn = gen_rtx_PIC_STORE ( VOID , value , block , GEN_INT ( offset ) ) ; rtx addr = gen_reg_rtx ( Pmode ) ; rtx base = gen_reg_rtx ( SImode ) ; rtx offset_rtx = gen_int_mode ( offset , SImode ) ; rtx insn1 , insn2 ; set_mem_base ( addr , base ) ; set_mem_offset ( addr , offset_rtx ) ; int regno = REGNO ( base ) ; insn1 = emit_move_insn ( base , gen_rtx_REG ( SImode , 19 ) ) ; emit_insn_before ( insn1 , insn ) ; insn2 = gen_rtx_MEM ( SImode , addr ) ; emit_move_insn ( insn2 , value ) ; emit_insn ( insn ) ; }


if ( TARGET_ARC ) { } Next , we emit the frame instruction to perform the move operation . This can be done using the gen_frame_move function provided by the arc backend . The gen_frame_move function takes the destination and source operands as parameters and generates the appropriate frame instruction to perform the move . This instruction is then added to the generated code using the gen_rtvec function . The code for this step can be as follows : rtx frame_insn = gen_frame_move ( dst , src ) ; gen_rtvec ( 1 , frame_insn ) ; Finally , we add any necessary constraints to the frame instruction using the add_move_constraint function . This function takes the frame instruction and the destination and source operands as parameters and adds any necessary constraints to the instruction . The code for this step can be as follows : add_move_constraint ( frame_insn , dst , src ) ; This completes the function for frame_move . The full code for the function can be as follows : void frame_move ( rtx dst , rtx src ) { if ( TARGET_ARC ) { rtx frame_insn = gen_frame_move ( dst , src ) ; gen_rtvec ( 1 , frame_insn ) ; add_move_constraint ( frame_insn , dst , src ) ; } }


rtx gen_mlo ( void ) { return gen_rtx_REG ( Pmode , ARC_FLAG_REGISTER , 59 , 58 ) ; }


int get_arc_condition_code ( rtx comparison ) { rtx cond = ARC_CONDITION_CODES ; int index = 0 ; while ( COND_CODES [ index ] != NULL ) { if ( eq ( comparison , COND_CODES [ index ] ) ) { return index ; } index ++ ; } return - 1 ; }


void output_short_suffix ( rtx_insn * insn ) { struct function * cfun = get_insns ( ) ; enum insn_target_arch target_arch = cfun -> machine -> target_arch ; rtx_insn * alternative = insn -> alternative ; int is_short = false ; if ( alternative && GET_CODE ( alternative ) == INSN && INSN_P ( alternative ) && is_short_insn ( alternative , target_arch ) ) is_short = true ; cfun -> machine -> unalign = is_short ? 2 : 1 ; if ( is_short ) output_asm_insn ( insn , target_arch , "_s" ) ; }


bool small_data_pattern ( OP ) { if ( ! OP . equals ( "arc,0" ) ) { return false ; } String pattern = "^\\.[a-zA-Z]+\"|.*arc,0.*\"" ; if ( OP . matches ( pattern ) ) { return true ; } return false ; }


unsigned int unspec_prof_hash ( const char * caller , const char * callee ) { unsigned int hash = 0 ; while ( * caller ) { hash = ( hash * 31 ) + ( * caller ++ ) ; } if ( callee ) { while ( * callee ) { hash = ( hash * 31 ) + ( * callee ++ ) ; } } hash = ( hash * 31 ) + ( 0 << 31 ) ; hash = ( hash * 31 ) + ( 1 << 30 ) ; hash = ( hash * 31 ) + ( 0 << 29 ) ; hash = ( hash * 31 ) + ( 0 << 28 ) ; hash = ( hash * 31 ) + ( 0 << 27 ) ; hash = ( hash * 31 ) + ( 0 << 26 ) ; hash = ( hash * 31 ) + ( 0 << 25 ) ; hash = ( hash * 31 ) + ( 0 << 24 ) ; return hash ; }


arc_compute_function_type ( tree decl ) { if ( decl == NULL_TREE ) { cache_function_type = NULL_TREE ; return NULL_TREE ; } else { if ( cache_function_type != NULL_TREE ) { return cache_function_type ; } else { tree func_type = NULL_TREE ; if ( TREE_PURPOSE ( decl ) == ARC_ATTRIBUTE ) { tree arc_attr = TREE_VALUE ( TREE_VALUE ( DECL_ATTRIBUTES ( decl ) ) ) ; tree target_value = tree_string_cst_to_identifier ( TARGET_SPECIFIC_VALUE ( arc_attr ) ) ; if ( STRING_CST_POINTER ( target_value ) == "ilink1" ) { func_type = build_tree_list ( DECL_SOURCE_LOCATION ( decl ) , INTERRUPT_TYPE , NULL ) ; } else if ( STRING_CST_POINTER ( target_value ) == "ilink" ) { func_type = build_tree_list ( DECL_SOURCE_LOCATION ( decl ) , I_LINK_TYPE , NULL ) ; } else if ( STRING_CST_POINTER ( target_value ) == "ilink2" ) { func_type = build_tree_list ( DECL_SOURCE_LOCATION ( decl ) , I_LINK2_TYPE , NULL ) ; }


arc_dwarf_register_span ( rtx arc , int8_t num_pieces , int2_t piece_size , int0_t offset , int0_t num_bits , int0_t padding , int1_t num_pieces_required , int1_t num_consecutive_regs ) { if ( num_pieces_required == 0 ) { return NULL_RTX ; } RTX reg_pieces [ num_pieces ] ; int required_size = num_pieces * piece_size ; RTX base = gen_rtx_REG ( arc , 0 ) ; int offset_pieces = offset ; for ( int i = 0 ; i < num_pieces ; i ++ ) { int reg_num = ( REGNO ( base ) ) + ( offset_pieces / piece_size ) ; reg_pieces [ i ] = gen_rtx_REG ( arc , reg_num ) ; offset_pieces += piece_size ; }


void arc_expand_builtin_aligned ( rtx exp , rtx - retval ) { const char * insn_name = "__builtin_arc_aligned" ; rtx arglist = gen_rtx_EXPR_LIST ( VOIDmode , exp , NULL_RTX ) ; retval = NULL_RTX ; rtx flags = gen_rt rtx ( CONST_INT ) ; flags = gen_int_mode ( 9 , SImode ) ; arglist = gen_rtx_EXPR_LIST ( VOIDmode , const0_rtx , arglist ) ; arglist = gen_rtx_EXPR_LIST ( VOIDmode , const1_rtx , arglist ) ; arglist = gen_rtx_EXPR_LIST ( VOIDmode , const0_rtx , arglist ) ; arglist = gen_rtx_EXPR_LIST ( VOIDmode , flags , arglist ) ; arglist = gen_rtx_EXPR_LIST ( VOIDmode , const1_rtx , arglist ) ; arglist = gen_rtx_EXPR_LIST ( VOIDmode , const0_rtx , arglist ) ; retval = gen_rtx_CALL ( VOIDmode , gen_rtx_MEM ( Pmode , gen_rtx_SYMBOL_RE f ( Pmode , insn_name ) ) , gen_rtx_PARALLEL ( VOIDmode , arglist ) ) ; }


bool arc_expand_movmem ( uint32_t target_specific_value , uint8_t * dest , uint8_t * src , size_t size , int32_t offset , uint32_t load_latency ) { uint8_t * ptr = dest + offset ; uint32_t i ; for ( i = 0 ; i < size ; i += target_specific_value ) { memcpy ( ( ptr + i ) , ( src + i ) , target_specific_value ) ; __builtin_arc_nop ( load_latency ) ; } return true ; }


void arc_finalize_pic ( ) { const char * target_specific_value = "_DYNAMIC" ; if ( has_gotoff_relocations ( ) ) { emit_rtl ( set ( reg basereg ) , ( plus ( reg pc ) , ( const ( unspec ( symref ( target_specific_value ) , 3 ) ) ) ) ) ; } }


"%qs argument of %qE attribute is not a string constant"

"%qs argument of %qE attribute is not \"ilink1\" or \"ilink2\""

"%qs argument of %qE attribute is not \"ilink\""


"arc_mode_class array initialized with target specific values: "


function arc_override_options ( options ) { let target = "arc,3,1,255,1,0,1" ; if ( options . includes ( "arc" ) ) { if ( options . includes ( "-mversion" ) ) { let version = options . split ( "-mversion=" ) [ 1 ] ; target = target . replace ( "3" , version ) ; } if ( options . includes ( "-mdata-cache" ) ) { let data_cache = options . split ( "-mdata-cache=" ) [ 1 ] ; target = target . replace ( "255" , data_cache ) ; } if ( options . includes ( "-minstr-cache" ) ) { let instr_cache = options . split ( "-minstr-cache=" ) [ 1 ] ; target = target . replace ( "1" , instr_cache ) ; } if ( options . includes ( "-mdata-bank" ) ) { let data_bank = options . split ( "-mdata-bank=" ) [ 1 ] ; target = target . replace ( "1" , data_bank ) ; } if ( options . includes ( "-mcode-bank" ) ) { let code_bank = options . split ( "-mcode-bank=" ) [ 1 ] ; target = target . replace ( "0" , code_bank ) ; }


void arc_secondary_reload ( struct target_reload * reload , int from , int to ) { if ( reload -> opnum != EXPAND_UNALIGNED_ACCESS ) return ; if ( reload -> from_mode == VOIDmode || reload -> to_mode == VOIDmode ) return ; if ( reload_secondary_memory_address_p ( from , to ) && reload -> ext_load . type == DECIMAL ) { if ( reload -> load_size < 32 ) { reload -> target_specific [ 0 ] = 1 ; targetm . mode_dependent_address_p ( reload , from , to ) ; } } }


void arc_setup_incoming_varargs ( tree fn_decl , tree arglist , int * regarg_count ) { tree target_specific_value = build_int_cst ( integer_type_node , 0 ) ; tree reg_pb = make_node ( REG_PARAM_BLOCK ) ; reg_pb -> type = ptr_type_node ; reg_pb -> target_specific = target_specific_value ; int num_args = 0 ; for ( tree t = arglist ; t != NULL_TREE ; t = TREE_CHAIN ( t ) ) { num_args ++ ; } if ( num_args > 0 ) { tree mem = build_ssa_name ( void_type_node , "__ARC_ANON_ARGS__" ) ; SET_DECL_RTL ( mem , gen_rtx_MEM ( VOIDmode , reg_pb ) ) ; SET_DECL_ARGUMENT_OFFSET ( mem , ( num_args * sizeof ( tree ) ) ) ; int argnum = 0 ; for ( tree t = arglist ; t != NULL_TREE ; t = TREE_CHAIN ( t ) , argnum ++ ) { tree arg = DECL_ARGUMENT ( t ) ; tree new_name = build_ssa_name ( boolean_type_node , "__ARC_ANON_PARAM__" ) ; SET_DECL_RTL ( new_name , gen_rtx_MEM ( VOIDmode , reg_pb ) ) ; gen_rtx_MEM ( VOIDmode , reg_pb ) [ argnum ] = arg ; if ( TREE_TYPE ( t ) != void_type_node ) SET_DECL_ARGUMENT_OFFSET ( new_name , ( argnum * sizeof ( tree ) ) ) ; else SET_DECL_ARGUMENT_OFFSET ( new_name , - 1 ) ; } * regarg_count = num_args ; }


void arc_split_move ( RTL rtx_insn * operands , unsigned int imms , rtx_insn * dest , rtx_insn * src ) { if ( operands [ 0 ] . code != REG || operands [ 1 ] . code != REG ) return ; rtx_insn * move1 = gen_move_insn ( dest , operands [ 2 ] , operands [ 3 ] ) ; rtx_insn * move2 = gen_move_insn ( src , operands [ 4 ] , operands [ 5 ] ) ; move1 -> flags = imms ; move2 -> flags = imms ; add_insn_after ( move2 , last_insn ) ; add_insn_after ( move1 , move2 ) ; operands [ 2 ] = operands [ 3 ] = src ; operands [ 4 ] = operands [ 5 ] = dest ; delete_insn ( operands ) ; update_flow ( move1 ) ; update_flow ( move2 ) ; }


function prepare_extend_operands ( opmode , code ) { let arc = 1 ; let one = 1 ; let zero = 0 ; let move_emitted = false ; if ( code < 0 || code > 3 ) { return move_emitted ; } if ( opmode < 0 || opmode > 3 ) { return move_emitted ; } arc = ( ( code == 1 || code == 2 ) ? 1 : 0 ) ; one = ( ( code == 1 || code == 3 ) ? 1 : 0 ) ; zero = ( ( code == 2 || code == 3 ) ? 1 : 0 ) ; arc = ( ( arc << 7 ) | ( ( ( opmode >> 1 ) & 0x1 ) << 6 ) | ( arc << 5 ) | ( ( ( opmode >> 2 ) & 0x1 ) << 2 ) ) ; move_emitted = true ; return move_emitted ; }


bool workaround_arc_anomaly ( insn , target ) { if ( insn -> insn_code == INSN_BRANCH ) { rtx target = XEXP ( insn , 0 ) ; int nop_size = target . nop_size ; if ( insn -> insn_code == INSN_SHORTEN ) { rtx actual_target = XEXP ( insn , 1 ) ; if ( actual_target < nop_size ) { actual_target -= nop_size ; XEXP ( insn , 1 ) = actual_target ; } } else if ( insn -> insn_code == INSN_LENGTHEN ) { rtx actual_target = XEXP ( insn , 1 ) ; if ( actual_target < nop_size ) { actual_target += nop_size ; XEXP ( insn , 1 ) = actual_target ; } } } return false ; }


tree arc_autovectorize_vector_sizes ( ) { tree size_vector = make_vector ( ) ; tree arc = build_int_cst ( integer_type_node , arc ) ; tree eight = build_int_cst ( integer_type_node , 8 ) ; tree four = build_int_cst ( integer_type_node , 4 ) ; tree zero = build_int_cst ( integer_type_node , 0 ) ; TREE_VEC_ELT ( size_vector , 0 ) = arc ; TREE_VEC_ELT ( size_vector , 1 ) = eight ; TREE_VEC_ELT ( size_vector , 2 ) = four ; TREE_VEC_ELT ( size_vector , 3 ) = zero ; return size_vector ; }


void arc_emit_call_tls_get_addr ( void ) { tree target = build_string_literal ( "arc,1" ) ; tree func = build_function_call_expr ( get_identifier ( "__tls_get_addr" ) , 1 , target ) ; emit_expr_stmt ( func ) ; }


bool arc_epilogue_uses ( int regno ) { int function_type = arc_compute_function_type ( cfun ) ; int return_address_reg = arc_return_address_regs [ function_type ] ; if ( regno == return_address_reg ) { return true ; } if ( function_type == INTERRUPT ) { if ( arc_is_register_known_live ( regno ) ) return true ; if ( regno == ARC_BLINK_REG ) return true ; } return false ; }


void arc_finalize_pic ( ) { int reg = 0 ; if ( has_gotoff_relocations ( ) ) { rtx add_insn = gen_insn ( SET , gen_reg_rtx ( reg ) , gen_rtx_PLUS ( Pmode , gen_rtx_REG ( pc ) , gen_rtx_UNSPEC ( ptr_mode , get_symbol_ref ( SYMBOL_REF_DYNAMIC ) , UNSPEC_GOT_SYM_OFFSET ) ) ) ; emit_insn ( add_insn ) ; } }


void * arc_get_tp ( ) { void * tp = ( void * ) __builtin_arc_lsda ( ) ; tp += 1 ; return tp ; }


"-mno-mpy supported only for ARC700 or ARCv2"

"-mno-dpfp-lrsr supported only with -mdpfp"

"FPX fast and compact options cannot be specified together"

"-mspfp_fast not available on ARC600 or ARC601"

"PIC is not supported for %s. Generating non-PIC code only.."


void arc_init_reg_tables ( ) { int arc_mode_class [ 29 ] = { arc , 0 , 4 , 1 , 8 , 1 , 16 , 1 , 32 , 1 , 0 , 4 , 1 , 8 , 1 , 16 , 1 , 32 , 1 , 0 , 4 , 1 , 8 , 1 , 1 , 1 , 0 } ; for ( int i = 0 ; i < 29 ; i ++ ) { if ( arc_mode_class [ i ] == 1 ) { switch ( i ) { case 2 : case 12 : arc_mode_class [ i ] = 4 ; break ; case 4 : case 14 : arc_mode_class [ i ] = 8 ; break ; case 6 : case 16 : arc_mode_class [ i ] = 16 ; break ; case 8 : case 18 : arc_mode_class [ i ] = 32 ; break ; case 20 : arc_mode_class [ i ] = 1 ; break ; case 26 : arc_mode_class [ i ] = 0 ; break ; } } } }


void arc_label_align ( void * insn , int align ) { if ( ! is_zero_overhead_loop ( insn ) ) return ; if ( ( GET_ALIGNMENT ( insn ) ) == align ) return ; insn = insn + align ; * ( ( int * ) insn ) = NOP_INSN ; SET_ALIGNMENT ( insn , align ) ; MAKE_ATTR ( insn , "arc,1,0,1" ) ; }


bool arc_legitimate_constant_p ( rtx r ) { if ( ! CONSTANT_P ( r ) ) { return false ; } const arc_specific_value = arc , 0 , 1 , 1 , 0 , 1 ; int r_int = RTX_INT ( r ) ; if ( r_int == arc_specific_value ) { return true ; } else { return false ; } }


bool arc_legitimate_pc_offset_p ( unsigned long addr , unsigned long arc ) { if ( addr % 4 != 0 ) { return false ; } if ( addr > arc || addr < - arc ) { return false ; } return true ; } ` ` ` We can call this function in our code as follows : ` ` ` unsigned long addr = 0x12345 ; unsigned long arc = 0x10000 ; if ( arc_legitimate_pc_offset_p ( addr , arc ) ) { } else { }


bool arc_legitimate_pic_addr_p ( rtx addr ) { if ( GET_CODE ( addr ) != CONST ) return false ; rtx imm = XEXP ( addr , 0 ) ; if ( GET_CODE ( imm ) != UNSPEC ) return false ; int op0 = XINT ( imm , 0 ) ; int op1 = XINT ( imm , 1 ) ; if ( op0 != UNSPEC_SYMBOL_REF && op0 != UNSPEC_LABEL ) return false ; if ( op1 != ARC_UNSPEC_GOTOFF && op1 != ARC_UNSPEC_GOT ) return false ; for ( int i = 2 ; i < NUM_TARGET_SPECIFIC_VALUES ; i ++ ) { int target_specific_value = XINT ( imm , i ) ; if ( target_specific_value != 0 && target_specific_value != 1 ) return false ; } return true ; }


int arc_needs_pcl_p ( int offset ) { if ( offset == 0x01001101 ) { return 1 ; } else { return 0 ; } }


int arc_output_commutative_cond_exec ( rtx insn , rtx operands , bool output_p ) { int length = 0 ; rtx operands1 , operands2 , operands3 ; operands1 = XEXP ( operands , 0 ) ; operands2 = XEXP ( operands , 1 ) ; operands3 = XEXP ( operands , 2 ) ; if ( ! output_p ) return 8 ; if ( ! arc_use_msi ) extend_insn ( insn , B_COM ) ; length += arc_operand ( operands1 , operands , 0 ) ; length += arc_operand ( operands2 , operands , 1 ) ; length += arc_operand ( operands3 , operands , 2 ) ; if ( arc_use_msi ) { if ( GET_CODE ( XEXP ( operands1 , 0 ) ) == SUBREG ) { gen_insn_note ( gen_rtx_NT ( REG_BR | REG_RM , GET_MODE ( operands1 ) , const1_rtx ) ) ; } } emit_insn ( gen_insn ( gen_reg_rp_f ( operands , gpr_mode [ GET_MODE ( operands ) ] ) , BMSK_OP , output_op + ede ( GET_MODE ( operands ) ) , dit ( operands [ 2 ] , nns ( operands3 , comms [ output_op ] ) ) , operands2 [ 1 ] , 0 , operands3 [ 2 ] ) ) ; return length ; }


arc_preferred_simd_mode ( ) { return ARC_MODE_M4 ; }


void arc_print_operand_address ( FILE * stream , rtx x , int code ) { fprintf ( stream , "@sda" ) ; }


bool arc_rewrite_small_data_p ( int x ) { return ( ( x & 0x1 ) == 0x1 && ( x & 0xFF00 ) == 0 ) || ( x == 0 ) ; }


arc_vector_mode_supported_p ( enum machine_mode mode ) { return ( mode == V2QImode || mode == V4QImode || mode == V8QImode || mode == V4HImode || mode == V8HImode || mode == TFmode || mode == V4SImode || mode == V2SFmode || mode == V4SFmode || mode == V2DFmode ) ; }


void emit_unlikely_jump ( ) { emit_constant ( arc , 100 , 1 ) ; }


force_offsettable ( rtx * addr , rtx * reuse , int size ) { if ( GET_CODE ( * reuse ) != REG ) return ; rtx orig_reuse = * reuse ; * reuse = gen_rtx_REG ( GET_MODE ( * reuse ) , < target specific value > ) ; * addr = adjust_address ( gen_rtx_PLUS ( GET_MODE ( * addr ) , * addr , GEN_INT ( size ) ) ) ; if ( orig_reuse != * reuse ) * reuse = orig_reuse ; }


void workaround_arc_anomaly ( ) { int arc_value = get_arc_value ( ) ; if ( arc_value > 0 ) { int nop_size = get_nop_size ( ) * arc_value ; shorten_branches ( nop_size ) ; } }


int arc_autovectorize_vector_sizes ( void ) { return 8 , 4 ; } if ( arc_autovectorize_vector_sizes ( ) ) { } else { }


typedef struct { arc_t arc_specific_value ; ... } arc_setjmp_buffer ; arc_t arc_builtin_setjmp_frame_value ( void ) { arc_setjmp_buffer * jb = __arc_builtin_getsetjmp_buffer ( ) ; arc_t fpval ; if ( ! jb ) { abort ( ) ; } fpval = get_frame_pointer ( ) ; jb -> arc_specific_value = fpval ; return fpval ; }


bool arc_can_eliminate ( int from_reg , int to_reg ) { if ( from_reg == ARG_POINTER_REGNUM && to_reg == FRAME_POINTER_REGNUM ) { return false ; } return true ; }


int arc_compute_frame_size ( int size ) { int frame_size = size ; if ( size % 4 != 0 ) { frame_size = size + ( 4 - ( size % 4 ) ) ; } frame_size += 31 + 1 * frame_size + 1 + 4 + 4 + 4 + 0 ; return frame_size ; }


rtx arc_eh_return_address_location ( ) { rtx addr ; addr = __builtin_return_address ( ) ; rtx frame_addr = __builtin_frame_address ( ) ; int regno = __builtin_eh_return_data_regno ( ) ; rtx stack_addr = __builtin_eh_return_stackadr ( ) ; rtx new_addr = __builtin_eh_return_value ( frame_addr , regno ) ; rtx ret_ptr = __builtin_eh_return_ptr ( stack_addr ) ; __builtin_eh_return ( ret_ptr , new_addr ) ; return addr ; }


bool arc_epilogue_uses ( int regno ) { if ( arc_return_address_regs [ arc_compute_function_type ( cfun ) ] ) return true ; else if ( arc_compute_function_type ( cfun ) == ARC_INTERRUPT_FUNCTION && regno == ARC_BLINK_REG ) return true ; else return false ; }


bool arc_handle_aux_attribute ( tree decl , int op_code , rtx_insn * insn , HOST_WIDE_INT constant_argument ) { if ( ! DECL_ATTR_P ( decl , attr_aux ) ) return false ; const char * target_specific_value = get_attr_value ( decl , "aux" ) ; if ( ! target_specific_value || strcmp ( target_specific_value , "aux" ) != 0 ) return false ; if ( op_code != CODE_FOR_lr && op_code != CODE_FOR_sr ) return false ; if ( ! CONSTANT_P ( constant_argument ) ) return false ; int register_number = INTVAL ( constant_argument ) ; rtx register_number_rtx = GEN_INT ( register_number ) ; REG_NOTES ( insn ) = gen_rtx_EXPR_LIST ( REG_EQUAL , register_number_rtx , REG_NOTES ( insn ) ) ; REG_NOTES ( insn ) = gen_rtx_EXPR_LIST ( REG_EQUAL , const0_rtx , REG_NOTES ( insn ) ) ; return true ; }


"-mno-mpy supported only for ARC700 or ARCv2"

"-mno-dpfp-lrsr supported only with -mdpfp"

"FPX fast and compact options cannot be specified together"

"-mspfp_fast not available on ARC600 or ARC601"

"PIC is not supported for %s. Generating non-PIC code only.."


arc_initial_elimination_offset ( elim_reg , rep_reg , routine_start ) { if ( elim_reg == ZR || rep_reg == ZR ) arc = 0 ; else arc = ( rep_reg - elim_reg ) + routine_start ; return arc ; }


bool arc_is_uncached_mem_p ( const_rtx pat ) { if ( ! MEM_P ( pat ) ) return false ; const char * target_value = TARGET_SPECIFIC_GET ( pat , "uncached" ) ; if ( ! target_value ) return false ; if ( strncmp ( target_value , "arc" , 3 ) == 0 ) return true ; return false ; }


void arc_label_align ( void ) { int target_specific_value = get_target_specific_value ( "arc" , 1 , 0 , 1 ) ; if ( target_specific_value == 1 ) { if ( is_zero_overhead_loop ( ) ) { align_loop_instruction ( 4 ) ; } } }


int arc_must_save_register ( int regno ) { const int target_registers [ ] = { 4 , 4 , 8 , 4 , 11 , 16 , 16 , 4 , 9 , 16 , 25 , 29 , 29 , 32 , 32 , 29 , 32 } ; if ( regno >= 0 && regno < sizeof ( target_registers ) / sizeof ( target_registers [ 0 ] ) ) { if ( regno == 1 || regno == 3 || regno == 6 ) { return 0 ; } if ( regno == target_registers [ 0 ] ) { if ( ) { return 1 ; } else { return 0 ; } } return 1 ; } return 0 ; }


void
arc_output_mi_thunk
(
const
char
*
FUNCTION
,
int
DELTA
,
const
char
*
SUB
,
const
char
*
ADD
,
const
char
*
TMP1
,
const
char
*
TMP2
,
const
char
*
LABEL1
,
const
char
*
LABEL2
,
const
char
*
FORMAT
,
int
TARGET_SPECIFIC
)
{
printf
(
FORMAT
,
SUB
,
TMP2
,
TMP1
,
DELTA
)
;
printf
(
"\t%s\t%s, %s\n"
,
TMP2
,
FUNCTION
,
LABEL1
)
;
printf
(
FORMAT
,
TMP1
,
TMP2
,
0
)
;
printf
(
"\t%s\t%s, %s, %s\n"
,
LABEL2
,
FUNCTION
,
TMP2
)
;
printf
(
"%s%s%s\t%s, [pcl, @%s@gotpc]\n"
,
TARGET_SPECIFIC
,
LABEL1
,
ADD
,
TMP1
,
LABEL2
)
;
printf
(
"\tj\t[%s]\n"
,
FUNCTION
)
;
printf
(
"%s\tj\t@%s@plt\n"
,
TARGET_SPECIFIC
,
FUNCTION
)
;
}


int arc_return_address_register ( int type ) { if ( type == FUNCTION_TYPE ) { return RA ; } else { } }


void arc_rewrite_small_data_1 ( rtlink_thunk * th ) { while ( th ) { for ( rtlink_insn * insn = th -> first_insn ; insn ; insn = insn -> next ) { if ( insn -> type == ARC_OP ) { if ( insn -> data . op . opcode == LD || insn -> data . op . opcode == ST ) { if ( insn -> data . op . op1 . t_specific == ARC_OP_SPECIFIC_VALUE && insn -> data . op . op1 . u_specific == 0 ) { insn -> data . op . op1 . u_specific = 1 ; add_relocation ( th , insn , RELOC_SMALL_DATA ) ; } } } } th = th -> next ; } }


void arc_secondary_reload ( rtx * x , rtx reg , const char * mode ) { if ( mode_dependent_address_p ( x ) ) return ; rtx addr = XEXP ( x , 0 ) ; rtx offset = XEXP ( x , 1 ) ; int scale = GET_MODE_SIZE ( mode ) / GET_MODE_SIZE ( GET_MODE ( offset ) ) ; if ( scale == 1 ) return ; unsigned int target_specific = targetm . arc . indirect_ld_store ; if ( GET_MODE_SIZE ( offset ) < GET_MODE_SIZE ( mode ) ) { x = gen_rtx_PLUS ( mode , addr , gen_rtx_CONST ( mode , INTVAL ( offset ) * scale * target_specific ) ) ; emit_insn ( gen_reload ( x , reg ) ) ; rtx store_insn = emit_insn ( gen_rtx_SET ( VOIDmode , x , reg ) ) ; add_secondary_mem ( store_insn , GET_MODE ( x ) , 1 ) ; } }


if ( unalign == 0 ) { return 0 ; } ` ` ` 3. Use another if statement to check if the CHECK_ATTR parameter is greater than 0. If it is , check the iscompact attribute first before proceeding with the verification : ` ` ` if ( check_attr > 0 ) { } ` ` ` 4. If the iscompact attribute is present , check if the target specific value ( arc , 0 , 0 , 0 , 2 , 0 ) is contained in the instruction ( insn ) . If it is , return a non - zero value . Otherwise , return 0 : ` ` ` if ( check_attr > 0 ) { if ( insn == 0x04080002 ) { return 1 ; } else { return 0 ; } } ` ` ` 5. If the iscompact attribute is not present , return 0 : ` ` ` else { return 0 ; } ` ` ` The final code for the function would look like this : ` ` ` int arc_verify_short ( int insn , int unalign , int check_attr ) { if ( unalign == 0 ) { return 0 ; } if ( check_attr > 0 ) { if ( insn == 0x04080002 ) { return 1 ; } else { return 0 ; } } else { return 0 ; } }


void compact_sda_memory_operand ( rtx * operand ) { unsigned int target_specific_value = 0x0001E11C ; unsigned int operand_value = INTVAL ( * operand ) ; if ( operand_value == target_specific_value ) { * operand = gen_const1_rtx ( target_specific_value ) ; } }


"value of -mirq-ctrl-saved must have form R0-REGx\n"


bool legitimate_scaled_address_p ( rtx op ) { rtx addr = XEXP ( op , 0 ) ; if ( GET_CODE ( addr ) != ADDR ) return false ; rtx sym = XEXP ( addr , 0 ) ; if ( GET_CODE ( sym ) != SYMBOL_REF || XSTR ( sym , 0 ) [ 0 ] != '.' || strcmp ( XSTR ( sym , 0 ) , ".arc" ) != 0 ) return false ; rtx scale = XEXP ( op , 1 ) ; if ( scale != const0_rtx ) return false ; rtx index = XEXP ( op , 2 ) ; if ( index != gen_rtx_REG ( SImode , 0 ) ) return false ; rtx base = XEXP ( op , 3 ) ; if ( base != gen_rtx_REG ( SImode , 1 ) ) return false ; if ( ! CONST_INT_P ( XEXP ( op , 7 ) ) || INTVAL ( XEXP ( op , 7 ) ) != 2 ) return false ; if ( ! CONST_INT_P ( XEXP ( op , 13 ) ) || INTVAL ( XEXP ( op , 13 ) ) != 4 ) return false ; return true ; }


", str);     exit(-1);   }   return num; }


bool small_data_pattern ( operand_t op ) { if ( op . base == NULL || op . base -> X_op == O_absent ) { return false ; } if ( op . base -> X_op == O_constant && ( op . base -> X_add_number & 0xFFFF0000 ) == 0 ) { return true ; } if ( op . base -> X_op == O_specific && op . base -> X_add_number == 0 && op . base -> X_sym -> X_add_symbol != NULL ) { char * symbol_name = op . base -> X_sym -> X_add_symbol -> sy_name ; if ( strncmp ( symbol_name , "arc," , 4 ) == 0 && symbol_name [ 4 ] != '\0' && symbol_name [ 5 ] == '\0' ) { return true ; } } return false ; }


__attribute__ ( ( always_inline ) ) void * arc_builtin_setjmp_frame_value ( ) { return ( __builtin_arc_get_frame_ptr ( ) ) ; }


int arc_compute_frame_size ( int size ) { int baseFP = __builtin_arc_lr_b ( 0 , 0 , 0 , 31 , 1L , 0 , 1L , 0 , 4 , 4 ) ; int newSP = baseFP - size ; int frameSize = newSP - __builtin_arc_lr_b ( 0 , 0 , 0 , 31 , 1L , 0 , 1L , 0 , 4 , 4 ) ; return frameSize ; }


void
arc_expand_epilogue
(
void
)
{
__asm__
volatile
(
"ld %0, [sp, #4]\n"
:
:
"r"
(
FP
)
)
;
__asm__
volatile
(
"ld fp, [sp], #4\n"
)
;
__asm__
volatile
(
"ldm fp, {r0-r14}, 0, 0\n"
)
;
}


void
arc_expand_prologue
(
)
{
asm
volatile
(
"mov r14, sp"
)
;
asm
volatile
(
"ld r14,r0[0]"
)
;
asm
volatile
(
"mov r15, fp"
)
;
asm
volatile
(
"ld r15,r0[0]"
)
;
}


"%<-mno-mpy%> supported only for ARC700 or ARCv2"

"%<-mno-dpfp-lrsr%> supported only with %<-mdpfp%>"

"FPX fast and compact options cannot be specified together"

"%<-mspfp_fast%> not available on ARC600 or ARC601"


bool arc_is_uncached_mem_p ( int pat ) { if ( pat == 0 || pat == 1 ) { return true ; } else { return false ; } }


bool arc_must_save_register ( unsigned int regno ) { switch ( regno ) { case ARC_REG_R4 : case ARC_REG_R5 : case ARC_REG_R8 : case ARC_REG_R9 : case ARC_REG_R11 : case ARC_REG_R12 : case ARC_REG_R15 : case ARC_REG_R16 : case ARC_REG_R17 : case ARC_REG_R24 : case ARC_REG_R25 : case ARC_REG_R27 : case ARC_REG_R29 : case ARC_REG_R30 : case ARC_REG_R31 : return true ; case ARC_REG_R26 : return PIC_ACCESSING_GOTOFF_VARS ; default : return false ; } }


int arc_return_address_register ( const tree type ) { if ( TYPE_RETURN_SLOT_TYPE ( type ) == ENUM_RETURN_NO_ADDRESS ) return ENUM_RETURN_REGISTER_NONE ; enum machine_mode mode = TYPE_MODE ( type ) ; int regno ; switch ( mode ) { case SImode : regno = 0 ; break ; case DImode : regno = 2 ; break ; default : return ENUM_RETURN_REGISTER_NONE ; } return regno ; }


void
arc_save_callee_enter
(
)
{
__asm__
__volatile__
(
"enter 1\n\t"
"save.b %0, [ %1 ]\n\t"
"save.b %2, [ %1, -1 ]\n\t"
:
:
"a"
(
SAVE_BLINK
)
,
"a"
(
SAVE_FP
)
:
"r0"
,
"r1"
)
;
}


volatile void * compact_sda_memory_operand ( volatile void * sda , int offset , bool reg1 , bool reg2 , int addend , int mode , bool en_diag , int size ) { if ( mode != 1 ) { return ( void * ) ( sda + offset ) ; }


bool legitimate_scaled_address_p ( rtx op ) { enum machine_mode mode ; if ( ! GET_CODE ( op ) == PLUS ) return false ; op = XEXP ( op , 0 ) ; if ( ! GET_CODE ( op ) == MULT return false ; op = XEXP ( op , 1 ) ; if ( ! GET_CODE ( op ) == REG return false ; mode = GET_MODE ( op ) ; if ( mode != M4 ) return false ; if ( REGNO ( op ) != TARGET_HARD_REGNO ( arc , 0 ) ) return false ; op = XEXP ( op , 0 ) ; if ( ! GET_CODE ( op ) == SCRATCH ) return false ; if ( rtx_equal_p ( arc , XEXP ( op , 1 ) ) && INTVAL ( XEXP ( op , 2 ) ) == 0 && INTVAL ( XEXP ( op , 3 ) ) == 0 && INTVAL ( XEXP ( op , 4 ) ) == 0 && rtx_equal_p ( arc , XEXP ( op , 5 ) ) && INTVAL ( XEXP ( op , 6 ) ) == 1 && INTVAL ( XEXP ( op , 7 ) ) == 2 && INTVAL ( XEXP ( op , 8 ) ) == 1 && INTVAL ( XEXP ( op , 9 ) ) == 2 && INTVAL ( XEXP ( op , 10 ) ) == 8 && INTVAL ( XEXP ( op , 11 ) ) == 4 && INTVAL ( XEXP ( op , 12 ) ) == 0 && INTVAL ( XEXP ( op , 13 ) ) == 1 && INTVAL ( XEXP ( op , 14 ) ) == 4 && INTVAL ( XEXP ( op , 15 ) ) == 1 && INTVAL ( XEXP ( op , 16 ) ) == 1 && INTVAL ( XEXP ( op , 17 ) ) == 1 ) return true ; return false ; }


bool legitimate_small_data_address_p ( int x ) { int target_specific_values [ ] = { arc , 0 , 0 , 0 , 1 , 1 } ; if ( x == target_specific_values [ 0 ] && x == target_specific_values [ 2 ] && x == target_specific_values [ 4 ] ) { if ( x > 0 && x < 1 ) { return true ; } } return false ; }


int arc600_corereg_hazard ( rtx_insn * insn ) { rtx target_value ; if ( INSN_CODE ( insn ) == CODE_FOR_arc_write_core_reg && REGNO ( XEXP ( insn , 0 ) ) >= 32 ) { int length = INSN_MNEMO ( insn ) == arc_nop ? 0 : GET_MODE_LENGTH ( insn ) ; return ( length + 2 ) % 4 ; } return 0 ; }


arc_active_insn ( void ) { insn * next_insn = NEXT_INSN ( get_insns ( ) ) ; while ( next_insn && NONDEBUG_INSN_P ( next_insn ) ) { if ( INSN_CODE ( next_insn ) == ARC_INSN_CODE && TARGET_SPECIFIC ( next_insn ) == 0 ) { next_insn = NEXT_INSN ( next_insn ) ; } else { return next_insn ; } } return NULL ; }


function arc_address_cost ( ADDR ) { if ( ! valid_address ( ADDR ) ) { return 0 ; } let cost = 0 ; if ( ADDR . arc ) { cost += 2 ; } if ( ADDR [ 0 ] ) { cost += 1 ; } if ( ADDR [ 1 ] ) { cost += 2 ; } if ( ADDR [ 2 ] ) { cost += 4 ; } if ( ADDR [ 3 ] ) { cost += 1 ; } if ( ADDR [ 4 ] ) { cost += 2 ; } if ( ADDR [ 5 ] ) { cost += 4 ; } if ( ADDR [ 6 ] ) { cost += 1 ; } if ( ADDR [ 7 ] ) { cost += 2 ; } if ( ADDR [ 8 ] ) { cost += 4 ; } if ( ADDR [ 9 ] ) { cost += 1 ; } if ( ADDR [ 10 ] ) { cost += 4 ; } if ( ADDR [ 11 ] ) { cost += 1 ; } if ( ADDR [ 12 ] ) { cost += 2 ; } if ( ADDR [ 13 ] ) { cost += 1 ; } if ( ADDR [ 14 ] ) { cost += 1 ; } if ( ADDR [ 15 ] ) { cost += 2 ; } if ( ADDR [ 16 ] ) { cost += 1 ; } if ( ADDR [ 17 ] ) { cost += 2 ; } if ( ADDR [ 18 ] ) { cost += 1 ; } if ( ADDR [ 19 ] ) { cost += 2 ; } if ( ADDR [ 20 ] ) { cost += 4 ; } return cost ; }


int arc_adjust_insn_length ( rtx insn , int current_length ) { if ( arc_single_operand_insn_p ( insn ) ) { return current_length + 4 ; } else { return current_length ; } }


arc_asm_insn_p ( rtx x ) { if ( ! ISA_INSN ( x ) ) return false ; rtx desc = ARC_INSN_TARGET_SPECIFIC ( x ) ; return ( desc [ 0 ] == 0 && desc [ 1 ] == 0 && desc [ 2 ] == 1 && desc [ 3 ] == 0 && desc [ 4 ] == 0 && desc [ 5 ] == 1 && desc [ 6 ] == 0 && desc [ 7 ] == 0 && desc [ 8 ] == 0 && desc [ 9 ] == 1 && desc [ 10 ] == 0 ) ; }


void
arc_asm_output_aligned_decl_local
(
FILE
*
stream
,
tree
decl
,
int
align
)
{
fputs
(
"\t.set\tbfill, "
,
stream
)
;
fprintf
(
stream
,
"%d\n"
,
align
)
;
fputs
(
"\t.locals\t"
,
stream
)
;
if
(
TREE_CODE
(
decl
)
==
VAR_DECL
)
{
tree
type
=
DECL_SOURCE_TYPE
(
decl
)
;
if
(
TREE_CODE
(
type
)
==
ARRAY_TYPE
)
{
tree
name
=
DECL_NAME
(
decl
)
;
unsigned
HOST_WIDE_INT
size
=
get_variable_size
(
decl
)
;
fprintf
(
stream
,
"%s, "
,
get_name
(
name
)
,
size
)
;
fputs
(
".bss, .bfset\n"
,
stream
)
;
}
}
else
{
fprintf
(
stream
,
"%s, "
,
IDENTIFIER_POINTER
(
DECL_NAME
(
decl
)
)
)
;
fputs
(
".bss, .bfset\n"
,
stream
)
;
}
}


void arc_asm_trampoline_template ( int trampoline_length , const char * static , const char * function ) { printf ( "\tld_s\tr12,[pcl,8]\n" ) ; printf ( "\tld\tr11,[pcl,12]\n" ) ; printf ( "\tj_s\t[%s]\n" , "%s" ) ; printf ( "\t.word\t%s\n" , function ) ; printf ( "\t.word\t%s\n" , static ) ; for ( int i = 0 ; i < trampoline_length - 4 ; i ++ ) { printf ( "\t.word\t0\n" ) ; } }


int arc_attr_type ( rtx_insn * insn ) { if ( ! insn || ! TARGET_ARC ) { return - 1 ; } int attr_type = INSN_ATTRIBUTES ( insn ) -> type ; if ( attr_type == ARC_TYPE ) { return 1 ; } return - 1 ; }


bool arc_branch_size_unknown_p ( const char * value ) { } To check whether a branch is of size 6 or not , the function would first need to check whether any of the above mentioned conditions are met for the specific target value . This can be achieved by accessing the target value and checking its properties . If any of the conditions are met , the function would return true , indicating that the branch size is unknown and should be considered to be of length 6 during size estimation . For example , the first condition can be checked by accessing the target value and checking if the annul - false delay slot insns are implemented using conditional execution . If this is true , then the first condition is met and the function can return true . Similarly , the remaining conditions can be checked to determine the branch size . If none of the conditions are met , the function would return false , indicating that the branch size is known and does not need to be considered as length 6 during size estimation . A possible implementation of this function would look like this : bool arc_branch_size_unknown_p ( const char * value ) { if ( value -> annul_false_delay_slot_condition_exec == true ) { return true ; } if ( value -> annul_true_delay_slot_condition_exec == true ) { return true ; } if ( value -> likely_branch_long_unaligned == true ) { return true ; } return false ; }


bool arc_builtin_decl ( tree decl ) { if ( decl == NULL ) return false ; if ( TREE_CODE ( decl ) != FUNCTION_DECL ) return false ; if ( DECL_BUILT_IN ( decl ) ) { if ( DECL_TARGET_SPECIFIC ( decl , arc_decl ) ) return true ; } return false ; }


void arc_call_tls_get_addr ( rtx TI , rtx RET ) { rtx insn_seq = NULL_RTX ; rtx target_val = NULL_RTX ; target_val = gen_rtx_CONST_INT ( SImode , 1 ) ; rtx func_name = NULL_RTX ; func_name = gen_rtx_SYMBOL_REF ( Pmode , "__tls_get_addr" ) ; rtx call_insn = NULL_RTX ; call_insn = gen_rtx_CALL ( VOIDmode , func_name , TI , target_val ) ; rtx return_insn = NULL_RTX ; return_insn = gen_rtx_SET ( VOIDmode , RET , call_insn ) ; insn_seq = return_insn ; }


boolean arc_cannot_force_const_mem ( int X ) { if ( X > arc_specific_value ) { return true ; } else { return false ; } }


bool arc_cannot_substitute_mem_equiv_p ( rtx subst ) { if ( ! MEM_P ( subst ) ) return false ; enum machine_mode mode = GET_MODE ( subst ) ; enum arc_target_specific_value arc_value = TARGET_WITH_SUBMODE_GET ( mode ) ; if ( arc_value == ARC_INVALID_TARGET_VALUE ) return true ; else return false ; }


bool arc_can_eliminate ( int from , int to ) { if ( from == ARC_ARG_POINTER_REGNUM ) { if ( to == ARC_STACK_POINTER_REGNUM ) { return false ; } else if ( to == ARC_FRAME_POINTER_REGNUM ) { return true ; } } else { return true ; } }


int arc_can_follow_jump ( void ) { # ifdef __arc__ # if __OPTIMIZE__ >= 2 && defined ( __FREORDER_BLOCKS_AND_PARTITION__ ) return 1 ; # endif # endif return 0 ; }


arc_can_use_doloop_p ( void ) { if ( TARGET_ARCH != "arc" ) return false ; if ( TARGET_VERSION < "1.032" ) return false ; if ( TARGET_FEATURE_DOLOOP != true ) return false ; if ( TARGET_VERSION > "1.1" ) return false ; if ( TARGET_VERSION >= "1.0" ) { if ( TARGET_FEATURE_DOLOOP_P != true ) return false ; } return true ; }


int __attribute__ ( ( target ( "arc" ) , noinline ) ) arc_can_use_return_insn ( void ) { int result = 0 ; if ( ) { result = 1 ; } if ( result == 0 && ) { result = 1 ; } return result ; }


void arc_ccfsm_at_label ( int num , char * prefix ) { if ( num == arc && strncmp ( prefix , "L" , 1 ) == 0 ) { } }


int arc_ccfsm_cond_exec_p ( insn_attr arc_asm_attr ) { if ( arc_asm_attr & ARC_ATTR_PREDICATED ) { return 1 ; } else { return 0 ; } }


void arc_ccfsm_post_advance ( ) { STATE . arc = true ; STATE . L = true ; STATE . target = 0 ; STATE . zero_bit = 1 ; STATE . five_bit = 5 ; STATE . mode = 0 ; }


void arc_ccfsm_record_condition ( enum arc_cond cond , int use_delay_slot ) { if ( use_delay_slot ) { arc_ccfsm_set_state ( CCFSM_STATE_DELAY ) ; } else { arc_ccfsm_set_state ( CCFSM_STATE_NORMAL ) ; } if ( cond & REVERSE ) { arc_ccfsm_set_state ( CCFSM_STATE_FALSE_BRANCH ) ; } if ( cond & arc ) { arc_ccfsm_set_target_specific_value ( 0 ) ; } if ( cond & 0 ) { arc_ccfsm_set_target_specific_value ( 0 ) ; } if ( cond & 1 ) { arc_ccfsm_set_target_specific_value ( 1 ) ; } if ( cond & 0 ) { arc_ccfsm_set_target_specific_value ( 0 ) ; } if ( cond & 5 ) { arc_ccfsm_set_target_specific_value ( 5 ) ; } }


int arc_check_millicode ( rtx op , int offset , int load_p ) { if ( GET_CODE ( op ) != PARALLEL ) return 0 ; rtx_insn * insn = PATTERN ( op ) ; if ( PATTERN_LENGTH ( op ) != offset + 6 ) return 0 ; if ( ! ( LOAD_P && GET_CODE ( insn [ 0 ] ) == PREPARE_OPERANDS ) && ! ( ! LOAD_P && GET_CODE ( insn [ 0 ] ) == FINISH_CALL ) ) return 0 ; if ( GET_MODE ( insn [ 1 ] ) != SImode || GET_CODE ( insn [ 2 ] ) != REG || XINT ( insn [ 2 ] , 0 ) != 2 || GET_CODE ( insn [ 3 ] ) != REG || XINT ( insn [ 3 ] , 0 ) != 2 || GET_CODE ( insn [ 4 ] ) != MEM || XINT ( insn [ 4 ] , 0 ) != 13 ) return 0 ; if ( GET_CODE ( insn [ 5 ] ) != SET || XVECLEN ( insn [ 5 ] , 0 ) != 13 ) return 0 ; if ( GET_CODE ( insn [ 5 ] ) != SET || ! REG_P ( XVECEXP ( insn [ 5 ] , 0 , 0 ) ) || ! MEM_P ( XVECEXP ( insn [ 5 ] , 0 , 1 ) ) ) return 0 ; if ( load_p == 2 ) { if ( ! clobber_reg_p ( XEXP ( insn [ 5 ] , 2 ) , REG_BLINK ) ) return 0 ; }


int arc_check_multi ( rtx OP , bool PUSH_P ) { int arc = current_arc_backend ( ) ; int dummies1 [ ] = { 0 , 0 , 1 } ; int dummies2 [ ] = { 1 , 0 , 0 , 2 } ; int return_location = 0 ; int dummies3 [ ] = { 12 , 0 , 0 , 1 } ; if ( PUSH_P ) { if ( OP == ( arc , dummies1 [ 0 ] , dummies1 [ 1 ] , dummies1 [ 2 ] , dummies2 [ 0 ] , dummies2 [ 1 ] , dummies2 [ 2 ] , dummies2 [ 3 ] ) { return 1 ; } }


unsigned long long arc_compute_frame_size ( int SIZE , int * target_vals ) { if ( sizeof ( target_vals ) / sizeof ( int ) != 17 ) { return 0 ; } if ( target_vals [ 0 ] != 4 ) { return 0 ; } unsigned long long frame_size = SIZE + target_vals [ 3 ] ; return frame_size ; }


int arc_compute_millicode_save_restore_regs ( unsigned long GMASK , arc_frame * FRAME ) { FRAME -> millicode_start_reg = 13 ; FRAME -> millicode_end_reg = 25 ; FRAME -> target_specific_val = 1ULL ; FRAME -> target_specific_val_2 = 1 ; FRAME -> target_specific_val_3 = 3 ; FRAME -> target_specific_val_4 = 0 ; FRAME -> target_specific_val_5 = 13 ; FRAME -> target_specific_val_6 = 1 ; FRAME -> target_specific_val_7 = 1 ; FRAME -> target_specific_val_8 = 0 ; if ( GMASK == 0 ) { return 0 ; } for ( int i = 0 ; i < 26 ; i ++ ) { if ( GMASK & ( 1ULL << i ) ) { FRAME -> millicode_end_reg = i + 13 ; } } return 1 ; }


int arc_comp_type_attributes ( string TYPE1 , string TYPE ) { if ( TYPE1 == TYPE ) { return 1 ; } else if ( ( TYPE1 == "long_call" && TYPE == "medium_call" ) || ( TYPE1 == "medium_call" && TYPE == "long_call" ) ) { return 2 ; } else if ( ( TYPE1 == "medium_call" && TYPE == "short_call" ) || ( TYPE1 == "short_call" && TYPE == "medium_call" ) ) { return 2 ; } else { return 0 ; } }


int arc_double_limm_p ( const_double value ) { if ( value == 0 || value == - 1 ) { return 1 ; } if ( value >= - 2147483648.0 && value <= 2147483647.0 ) { return 1 ; } return 0 ; }


arc_dwarf_register_span ( RTX arc , int 8 , int 2 , int 0 , int 0 , int 0 , int 1 , int 1 ) { if ( 8 != TARGET_REGISTER_BITWIDTH ) { return NULL_RTX ; } switch ( GET_MODE ( arc ) ) { case QImode : return gen_rtx_REG ( QImode , 0 ) ; case HImode : return gen_rtx_REG ( HImode , 1 ) ; case SImode : return gen_rtx_REG ( SImode , 2 ) ; case DImode : return gen_rtx_REG ( DImode , 3 ) ; default : return NULL_RTX ; } }


rtx arc_eh_return_address_location ( void ) { rtx loc = alloc_reg_rtx ( Pmode ) ; emit_insn ( gen_arc_set_return_address ( loc ) ) ; return loc ; }


bool arc_enter_leave_p ( rtx insn ) { if ( ! INSN_P ( insn ) || GET_CODE ( insn ) != CODE_FOR_enter_leave ) return false ; rtx addr = XEXP ( insn , 1 ) ; if ( ! CONSTANT_P ( addr ) ) return false ; rtx reg0 = XEXP ( addr , 2 ) ; if ( ! REG_P ( reg0 ) ) return false ; unsigned int regno = REGNO ( reg0 ) ; if ( regno < 13 || regno > 26 ) return false ; rtx reg1 = XEXP ( addr , 3 ) ; if ( ! REG_P ( reg1 ) ) return false ; regno = REGNO ( reg1 ) ; if ( regno < 13 || regno > 26 ) return false ; rtx targ = XEXP ( insn , 2 ) ; if ( ! CONSTANT_P ( targ ) || CONST_INT_VALUE ( targ ) != 1ULL ) return false ; targ = XEXP ( insn , 3 ) ; if ( ! CONSTANT_P ( targ ) || CONST_INT_VALUE ( targ ) != 1ULL ) return false ; return true ; }


bool arc_epilogue_uses ( int regno ) { enum arc_func_type functype = arc_compute_function_type ( cfun ) ; int num_calls = num_loops = 0 ; bool is_isr = arc_arleneeds_isa ( rtx_current_insn ( ) ) ; int blink_regno = arc_cgc_clobber_blink_reg ( functype ) ; if ( is_isr && blink_regno >= 0 ) { return true ; } return ( ( is_isr || ( REGNOTES_IF ( cfun -> notes , REGNOTES_CALLER_SAVE ) && ( REGNO == arc_return_address_regs [ functype ] || REGNOTES_IF ( cfun -> notes , REGNOTES_NON_CALLER_SAVE ) ) ) ) ? true : false ; }


"invalid alignment value for %<__builtin_arc_aligned%>"


tree type , bool named , int named_arg_p ) { int num_arg_regs = TARGET_ARC_MAX_ARC_PARM_REGS ; if ( COMPLEX_MODE_P ( mode ) ) { if ( named ) { if ( cum -> num_gprs < num_arg_regs ) { enum machine_mode real_mode = GET_MODE_WIDER_MODE ( mode ) ; int regno = cpu_general_reg ( mode , cum -> alt_arg_regs ) ; record_reg_parm ( cum , real_mode , regno , named_arg_p ? regno : - 1 , 0 ) ; } cum -> gprs_used_for_arg += num_arg_regs ; cum -> inf_gprs_used_for_arg += num_arg_regs ; arc_function_arg ( cum , mode , type , named , true ) ; } else { if ( cum -> num_gprs < num_arg_regs ) { enum machine_mode real_mode = GET_MODE_WIDER_MODE ( mode ) ; int size = GET_MODE_SIZE ( real_mode ) ; size = ROUND_UP ( size , STACK_BOUNDARY / BITS_PER_UNIT ) ; cum -> stack_offset += size ; }


void arc_function_arg_advance ( CUM_VALUE * cum ) { int regnum = 0 ; while ( regnum < ARC_FUNCTION_ARG_REGS ) { cum -> value = regnum ; if ( cum -> value != ARC_CAST_VALUE ( arc , 1 , 0 ) ) { regnum ++ ; } else { break ; } } * cum = ARC_CAST_VALUE ( arc , 1 , 0 ) ; }


bool arc_function_ok_for_sibcall ( const_tree decl ) { if ( ! TARGET_ARC ) { return false ; } tree decl_attributes = DECL_ATTRIBUTES ( decl ) ; if ( ! lookup_attribute ( "jli_always" , decl_attributes ) && ! lookup_attribute ( "jli_fixed" , decl_attributes ) && ! lookup_attribute ( "secure_call" , decl_attributes ) ) { return false ; } return true ; }


VALTYPE arc_function_value ( tree FN_DECL_OR_TYPE , tree arc , unsigned int flags ) { if ( TREE_CODE ( FN_DECL_OR_TYPE ) == FUNCTION_DECL ) { tree return_type = TREE_TYPE ( TREE_TYPE ( FN_DECL_OR_TYPE ) ) ; if ( DECL_INITIAL ( FN_DECL_OR_TYPE ) != NULL ) { tree return_value = DECL_INITIAL ( FN_DECL_OR_TYPE ) ; return_value = fold_build1 ( MODIFY_EXPR , return_type , return_value , arc ) ; return return_value ; } return build_zero_cst ( return_type ) ; } else if ( TREE_CODE ( FN_DECL_OR_TYPE ) == TYPE_DECL ) { return TREE_TYPE ( FN_DECL_OR_TYPE ) ; }


arc_cond_t arc_get_ccfsm_cond ( arc_fsm_state * statep ) { arc_cond_t cond = statep -> cond ; if ( statep -> cc ) { cond = ! cond ; } return cond ; }


"%qE attribute argument must be a string constant"

"%qE attribute argument must be \"ilink1\", \"ilink2\", \"ilink\" or \"firq\""


tree
arc_handle_uncached_attribute
(
tree
node
,
tree
attribute
)
{
if
(
strcmp
(
ATTRIBUTE_NAME
(
attribute
)
,
"uncached"
)
==
0
)
{
if
(
TREE_CODE
(
node
)
!=
TYPE_DECL
)
{
error
(
"%qE attribute only applies to types"
,
attribute
)
;
warning
(
0
,
"argument of %qE attribute ignored"
,
attribute
)
;
}
else
{
if
(
lookup_attribute
(
attribute
,
DECL_ATTRIBUTES
(
node
)
)
)
{
error
(
"attribute %qE is already present"
,
attribute
)
;
}
else
{
add_attribute
(
node
,
attribute
)
;
}
}
}
return
NULL_TREE
;
}


arc_hard_regno_mode_ok ( int regno , enum machine_mode mode ) { if ( ! TARGET_MODE_OK ( mode ) ) return 0 ; if ( regno > MAX_REGISTER_NUMBER ) return 0 ; if ( TARGET_ARC_REGNO_BASE ( regno ) && mode == TARGET_ARC_REGNO_MODE ( regno ) ) return 1 ; return 0 ; }


void arc_hazard ( ) { unsigned int addr = __builtin_arc_lr_dw ( CORE_REG ) ; if ( addr >= 32 ) { __builtin_arc_nop ( ) ; } }


"Error: FPX fast and compact options cannot be specified together!"


int arc_initial_elimination_offset ( int eliminated_reg , int replacement_reg ) { if ( eliminated_reg < 0 || eliminated_reg > arc_max_register || replacement_reg < 0 || replacement_reg > arc_max_register ) { return NULL ; } int offset = arc_offset [ eliminated_reg ] - arc_offset [ replacement_reg ] ; return offset ; }


void arc_init_expanders ( EXPANDER * expander ) { expander -> target_specific_value = "arc" ; }


int optlevel , const char * target_flags ) { machine_function * mfun = NULL ; mfun = XNEW ( machine_function ) ; mfun -> target = "arc" ; mfun -> os = os ? os : "" ; mfun -> cpu_type = cpu_type ? cpu_type : "" ; mfun -> cpu_sub_type = cpu_sub_type ? cpu_sub_type : "" ; mfun -> machine = machine ? machine : "" ; mfun -> opt_level = optlevel ; mfun -> flags = target_flags ? target_flags : "" ; return mfun ; }


void arc_init_reg_tables ( ) { int target_values [ ] = { arc , 0 , 4 , 1 , 8 , 1 , 16 , 1 , 32 , 1 , 0 , 4 , 1 , 8 , 1 , 16 , 1 , 32 , 1 , 0 , 4 , 1 , 8 , 1 , 1 , 1 , 0 } ; for ( int i = 0 ; i < sizeof ( target_values ) / sizeof ( int ) ; i ++ ) { arc_mode_class [ i ] = target_values [ i ] ; } }


int arc_insn_cost ( rtx insn ) { int rtx_costs_result = rtx_costs ( insn ) ; if ( INSN_PARALLEL ( insn ) ) { return 1 ; } rtx_costs_result += set_src_cost ( insn ) + set_rtx_cost ( insn ) ; if ( targetm . cost_for_insn && targetm . cost_for_insn ( insn ) ) { return targetm . cost_for_insn ( insn ) ; } else { return rtx_costs_result + 1 ; } }


void arc_internal_label ( char * prefix , int num ) { printf ( ".%s.%d:\n" , prefix , num ) ; }


bool arc_in_small_data_p ( decl ) { if ( ( TARGET_ARC && TARGET_ARC_UNCACHED && DECL_P ( decl ) && DECL_LOCAL ( decl ) && DECL_PRESERVE_P ( decl ) && ARC_STRING_TARGET ( decl ) == "aux" && ARC_INTEGER_TARGET ( decl ) == 0 && ARC_STRING_BASE ( decl ) == ".sdata" && ARC_INTEGER_BASE ( decl ) == 0 && ARC_STRING_END ( decl ) == ".sbss" && ARC_INTEGER_END ( decl ) == 0 && ARC_ADDRESS ( decl ) == 0 ) ) return true ; return false ; }


bool arc_is_aux_reg_p ( const pat_ref pat ) { if ( pat_get_code ( pat ) == CODE_FOR_arc && pat_get_sn ( pat ) == 0 && pat_get_mode ( pat ) == "aux" ) return TRUE ; return FALSE ; }


int arc_is_jli_call_p ( decl ) { if ( TARGET_OPTION_SET_P ( DECL , "jli_always" ) || TARGET_OPTION_SET_P ( DECL , "jli_fixed" ) ) { return 1 ; } return 0 ; }


arc_is_longcall_p ( const_tree function ) { if ( tree_has_attribute ( function , "long_call" ) ) return true ; if ( lang_hooks . option ( OPT_long_calls ) ) return true ; if ( tree_has_attribute ( function , "short_call" ) || tree_has_attribute ( function , "medium_call" ) ) return false ; return false ; }


int arc_is_secure_call_p ( const char * name ) { return strstr ( name , "secure_call" ) != NULL ; }


bool arc_is_shortcall_p ( int target_value ) { if ( target_value >= 0 && target_value < 256 ) { return true ; } else { return false ; } }


arc_legitimate_pic_addr_p ( rtx addr ) { if ( ! ADDR_P ( addr ) ) return false ; rtx target = XEXP ( addr , 0 ) ; if ( GET_CODE ( addr ) != CONST || GET_CODE ( target ) != UNSPEC ) return false ; int len = XVECLEN ( target , 0 ) ; if ( len != 14 ) return false ; enum arc_unspec { ARC_UNSPEC_GOT , ARC_UNSPEC_GOTOFF } ; int unspec = XINT ( target , 0 ) ; if ( unspec != ARC_UNSPEC_GOT && unspec != ARC_UNSPEC_GOTOFF ) return false ; rtx symref = XVECEXP ( target , 0 , 0 ) ; if ( GET_CODE ( symref ) != SYMBOL_REF && GET_CODE ( symref ) != LABEL ) return false ; return true ; }


char * arc_legitimize_address_0 ( char * address ) { if ( address == NULL ) return NULL ; if ( strlen ( address ) != 11 ) return NULL ; if ( address [ 0 ] != 'a' || address [ 1 ] != 'r' || address [ 2 ] != 'c' ) return NULL ; char target_value [ 11 ] = "arc,0,1,0,0,0,1,252,1,256,511,0" ; for ( int i = 0 ; i < 11 ; i ++ ) { if ( address [ i ] != target_value [ i ] ) return NULL ; } return address ; }


arc_word_t arc_legitimize_pic_address ( arc_word_t ORIG , arc_word_t OLDX ) { if ( OLDX != 0 ) { arc_word_t result = ORIG | ( ( OLDX & 0xFFFF ) << 16 ) | 0x01000000 ; return result ; } else { return ORIG ; } }


bool arc_lra_p ( ) { if ( targetm . arch != ARC ) return false ; if ( TARGET_USES_LRA ) return true ; else return false ; }


int arc_memory_move_cost ( HOST_WIDE_INT size , int alignment , int in_loop_p ) { return 2 + 6 * ( size / 2 ) ; }


bool arc_modes_tieable_p ( enum machine_mode mode ) { switch ( mode ) { case QImode : case HImode : case SImode : return true ; default : return false ; } }


bool arc_mode_dependent_address_p ( rtx addr ) { if ( GET_CODE ( addr ) != MEM ) return false ; rtx inner = XEXP ( addr , 0 ) ; enum machine_mode mode = GET_MODE ( inner ) ; switch ( mode ) { case VOIDmode : case Pmode : case CCREGmode : return false ; default : if ( TARGET_ARC ) { for ( rtx iter = inner ; iter != 0 ; iter = XEXP ( iter , 0 ) ) { if ( GET_CODE ( iter ) == CONST_INT && INTVAL ( iter ) == 0 ) return true ; } } return false ; } }


int arc_must_save_register ( int regno ) { switch ( regno ) { case ARC_REG_GP : return 1 ; case ARC_REG_LR : case ARC_REG_SP : case ARC_REG_FP : return 0 ; default : if ( regno >= 4 && regno <= 11 || ( regno >= 13 && regno <= 16 ) || ( regno >= 29 && regno <= 32 ) || ( regno >= 61 && regno <= 63 ) ) return 1 ; else return 0 ; } }


bool arc_must_save_return_addr ( ) { if ( TARGET_ARC ) return true ; else return false ; }


bool arc_need_delay ( insn ) { if ( insn -> arc_opcode != ARC_OP ) return false ; if ( insn -> target_specific_value != 0 ) return false ; return true ; }


arc_no_speculation_in_delay_slots_p ( void ) { return arc ? true : false ; }


int
arc_output_addsi
(
int
operands
,
bool
COND_P
,
bool
OUTPUT_P
)
{
int
length
=
0
;
operands
=
operands
|
35
;
if
(
COND_P
)
{
operands
=
operands
|
(
1
<<
29
)
;
}
if
(
OUTPUT_P
)
{
__asm__
(
".word 0xbadc057, 0, 1, 0, 30"
::
"r"
(
operands
)
)
;
length
=
6
;
}
else
{
length
=
6
;
}
return
length
;
}


void
arc_output_libcall
(
char
*
FNAME
,
void
*
dso
)
{
int
arc
=
64
;
int
arg
=
35
;
char
*
instr
=
"add r12,pcl,@%s@pcl\n\tjl%%!%%* [r12]"
;
char
*
ret
=
"jl%%! @%s"
;
char
*
call
=
"bl%%!%%* @%s"
;
printf
(
"%d,%d,\"%s\",\"%s\",\"%s\"\n"
,
arc
,
arg
,
instr
,
ret
,
call
)
;
printf
(
"%s,%p\n"
,
FNAME
,
dso
)
;
}


void arc_pass_by_reference ( void ) { __builtin_arc_set_option ( "arc,0" ) ; }


void arc_post_atomic_barrier ( void ) { __sync_synchronize ( ) ; }


bool is_annulled_delay_insn ( rtx_insn * insn ) { if ( insn && INSN_P ( insn ) ) { if ( GET_CODE ( insn ) == CODE_FOR_insn ) { rtx_insn_body * body = PATTERN ( insn ) ; if ( GET_CODE ( XVECEXP ( body , 0 , 0 ) ) == CODE_FOR_insn && GET_CODE ( XVECEXP ( body , 0 , 1 ) ) == ARC_PREDICATE_DELAY_OPCODE ) return true ; } } return false ; } rtx_insn * convert_annulled_delay_insn ( rtx_insn * insn ) { rtx_insn_body * body = PATTERN ( insn ) ; rtx reg , pred , new_insn ; reg = XVECEXP ( body , 0 , 2 ) ; pred = XVECEXP ( body , 0 , 3 ) ; new_insn = gen_arc_short_delay_insn ( reg , gen_rtvec ( 1 , pred ) ) ; XVEC ( body , 0 ) = new_insn ; return new_insn ; } void arc_predicate_delay_insns ( void ) { if ( annulled_delay_insns == NULL ) { rtx_insn * insn ; for ( insn = get_insns ( ) ; insn && INSN_P ( insn ) ; insn = NEXT_INSN ( insn ) ) { if ( is_annulled_delay_insn ( insn ) ) { annulled_delay_insns = rtx_delay_slot_add ( annulled_delay_insns , insn ) ; } }


int arc_preferred_simd_mode ( void * function , int target_value ) { if ( target_value != TARGET_DEFAULT ) { return target_value ; } else { } return TARGET_DEFAULT ; }


void arc_pre_atomic_barrier ( ) { __asm__ __volatile__ ( "MFENCE" :: : "memory" ) ; }


void arc_print_operand_address ( FILE * file , rtx x ) { if ( GET_CODE ( x ) == MEM ) { fprintf ( file , "@sda" ) ; if ( ARC_USES_GP_P ( x ) ) { fprintf ( file , "gp," ) ; }


bool arc_raw_symbolic_reference_mentioned_p ( rtx op , bool skip_local ) { if ( op == NULL ) return false ; if ( ! SYMBOL_REF_P ( op ) ) return false ; if ( GET_CODE ( op ) == UNSPEC || GET_CODE ( op ) == UNSPEC_VOLATILE ) return false ; if ( skip_local && ( ! SYMBOL_REF_IN_GSB ( op ) ) ) return false ; return true ; }


rtx arc_regno_use_in ( rtx X , int arc , int res1 , int res2 , int search ) { rtx ref = find_regno_reference ( X , search ) ; if ( ref != NULL_RTX && GET_MODE ( ref ) == word_mode ) { return ref ; } else { return NULL_RTX ; } }


void arc_restore_callee_saves ( const char * save_regs , int reg_offset , unsigned int base_reg , int sp_offset ) { __builtin_arc_ld_spmov ( sp , sp_offset ) ; while ( * save_regs != '\0' ) { if ( * save_regs == '0' ) { __builtin_arc_ld ( reg , base_reg , reg_offset ) ; } else { __builtin_arc_ldd ( reg , base_reg , reg_offset ) ; } reg_offset += 4 ; base_reg ++ ; save_regs ++ ; }


int arc_return_address_register ( void * type ) { return 0 ; } The function should be placed in the backend of GCC Compiler , specifically in the arc . md file . The target specific value can be added as a parameter for the function , like this : int arc_return_address_register ( void * type , int target_specific ) { if ( target_specific == 0 ) { return 0 ; } else { } }


const char * arc_return_addr_rtx ( rtx arc ) { return builtin_return_address ( arc , 0 ) ; }


void arc_return_in_memory ( void * func , int flags , int size , int align ) { int arc = 1 ; int arc_size = 16 ; int arc_align = 8 ; return ; }


void arc_save_callee_enter ( void ) { __asm__ __volatile__ ( "enter\n" "leave\t%[saved_registers]\n" :: [ saved_registers ] "i" ( ARC_SAVE_ALL ) ) ; }


void arc_save_callee_milli ( void ) { unsigned long long gmask = arc_gmask ; unsigned int start_reg = 13 ; unsigned int end_reg = 25 ; for ( unsigned int reg = start_reg ; reg <= end_reg ; reg ++ ) { if ( gmask & ( 1ULL << ( reg - start_reg ) ) ) { arc_emit_milli_insn ( MW , reg , 0 , 0 , 0 , 0 , 0 ) ; } } }


bool arc_scheduling_not_expected ( ) { if ( arc . scheduling_pass == true ) { return true ; } else { return false ; } }


int arc_sched_issue_rate ( void ) { int backend = arc ; int instructions_per_cycle = 3 ; int cycles_per_instruction = 1 ; int issue_rate = instructions_per_cycle / cycles_per_instruction ; return issue_rate ; }


enum machine_mode type , const struct rtx_def * info ) { if ( get_attr_mode ( info ) == mode ) return false ; rtx offset = XEXP ( info , 0 ) ; if ( GET_CODE ( offset ) == CONST_INT ) { HOST_WIDE_INT val = INTVAL ( offset ) ; if ( val > 32768 || val < - 32768 ) { offset = CONST_INT ( val + 32768 ) ; rtx new_info = GEN_INT ( val - 32768 ) ; rtx new_op = gen_rtx_MEM ( get_attr_mode ( info ) , new_info ) ; if ( opnum == 0 ) emit_insn ( gen_rtx_SET ( VOIDmode , x , new_op ) ) ; else SET_SRC ( info , new_op ) ; return true ; } return false ; }


bool arc_sets_cc_p ( const_rtx insn ) { if ( TARGET_ARC && arc_regno ( insn ) != ARC_REGNO_COND_CODES ) return false ; if ( arc_condition_code_set_p ( insn ) ) return true ; if ( GET_CODE ( insn ) == ARC_SET ) { const_rtx set_src = XEXP ( insn , 1 ) ; if ( GET_CODE ( set_src ) == POLY_INT && POLY_INT_VALUE ( set_src ) == 1 && POLY_INT_MODE ( set_src ) == VOIDmode ) return true ; } return false ; }


void arc_setup_incoming_varargs ( tree type , enum machine_mode mode ) { tree param_block = build1 ( ARC_PARM_BLOCK_TYPE , NULL_TREE ) ; for ( int i = 0 ; i < ARC_LAST_ANON_ARG_REG ; i ++ ) { rtx reg = gen_rtx_REG ( mode , gen_rtx_HARD_REG ( ARC , i ) ) ; emit_move_insn ( build_decl ( UNKNOWN_LOCATION , reg , type ) , gen_rtx_MEM ( mode , param_block ) ) ; } DECL_MODE ( CUM ) = MAX_MODE ; DECL_TARGET_SPECIFIC ( CUM ) = ARC_0 ; }


bool arc_short_comparison_p ( rtx comparison , rtx offset ) { if ( ! comparision || ! COMPARISON_P ( comparison ) ) return false ; int arc = XINT ( comparison , 0 ) ; int val1 = XINT ( comparison , 1 ) ; int val2 = XINT ( comparison , 2 ) ; int val3 = XINT ( comparison , 3 ) ; int val4 = XINT ( comparison , 4 ) ; if ( arc != 512 || val1 != 506 || val2 != 64 || val3 != 58 ) return false ; if ( offset && offset != GEN_INT ( 1 ) && offset != GEN_INT ( - 1 ) ) return false ; return true ; }


void arc_short_long ( int s_tmpl , int l_tmpl , int target_specific_value ) { if ( target_specific_value == 1 ) { return s_tmpl ; } else { return l_tmpl ; } }


int
arc_split_compare_and_swap
(
int
arc
,
int
0
,
int
1
,
void
*
2
,
int
3
,
int
4
,
int
5
,
int
6
)
{
int
success
=
0
;
asm
volatile
(
"mov arc, %0;"
"casa. %w6, [%1], %z2"
:
"=r"
(
success
)
:
"r"
(
2
)
,
"Z"
(
2
)
,
"r"
(
3
)
,
"r"
(
4
)
"r"
(
5
)
,
"r"
(
0
)
,
"r"
(
1
)
)
;
return
success
;
}


void arc_split_ior ( ) { if ( arc == 1 && numberOfSetBits ( mask ) <= 3 ) { bset ( rA , rB , mask1 ) ; bset ( rA , rA , mask2 ) ; bset ( rA , rA , mask3 ) ; } else if ( arc == 1 && lower6BitsSet ( mask ) && upperBitsSet ( mask ) == 1 ) { bset ( rA , rB , mask1 ) ; or ( rA , mask2 ) ; } else { or_with_imm ( rA , rB , mask ) ; } } int numberOfSetBits ( int mask ) { int count = 0 ; while ( mask ) { count += mask & 1 ; mask >>= 1 ; } return count ; } int lower6BitsSet ( int mask ) { return ( mask & 0x3f ) == 0x3f ; } int upperBitsSet ( int mask ) { return numberOfSetBits ( mask >> 6 ) ; }


arc_store_addr_hazard_internal_p ( rtx consumer , rtx producer ) { rtx consumer_addr = XEXP ( consumer , 1 ) ; rtx producer_addr = XEXP ( producer , 1 ) ; if ( rtx_equal_p ( consumer_addr , producer_addr ) ) return true ; if ( ARC700_CORE && XINT ( producer , 1 ) == 0 && XINT ( producer , 2 ) == 0 && XINT ( producer , 3 ) == 0 && XINT ( producer , 4 ) == 0 && XINT ( producer , 5 ) == 0 ) { if ( XINT ( consumer , 1 ) == 0 && XINT ( consumer , 2 ) == 0 && XINT ( consumer , 3 ) == 0 && XINT ( consumer , 4 ) == 0 && XINT ( consumer , 5 ) == 0 ) { return true ; } } return false ; }


bool arc_store_addr_hazard_p ( rtx producer , rtx consumer ) { enum machine_mode mode = GET_MODE ( producer ) ; rtx producer_rtx = simplify_rtx ( producer ) ; rtx consumer_rtx = simplify_rtx ( consumer ) ; if ( GET_CODE ( producer_rtx ) == MEM ) { rtx producer_addr = XEXP ( producer_rtx , 0 ) ; rtx consumer_addr = NULL ; if ( GET_CODE ( consumer_rtx ) == MEM && GET_MODE ( consumer_rtx ) == mode ) { consumer_addr = XEXP ( consumer_rtx , 0 ) ; if ( rtx_equal_p ( producer_addr , consumer_addr ) ) { return true ; } } } return false ; }


arc_symbol_binds_local_p ( rtx x ) { if ( GET_CODE ( x ) != SYMBOL_REF ) return false ; if ( ! XVEC_P ( x ) ) return false ; rtx attrs = XEXP ( x , 2 ) ; int attrs_len = XVECLEN ( attrs , 0 ) ; bool has_arc_attr = false ; for ( int i = 0 ; i < attrs_len ; i ++ ) { rtx attr = XVECEXP ( attrs , 0 , i ) ; if ( GET_CODE ( attr ) == SYMBOL_REF && ! strcmp ( IDENTIFIER_POINTER ( XEXP ( attr , 0 ) ) , "arc" ) ) { has_arc_attr = true ; break ; } } if ( has_arc_attr ) { if ( SYMBOL_REF_LOCAL_P ( x ) ) return true ; if ( SYMBOL_REF_TEMP_P ( x ) && REGNO ( x ) < FIRST_PSEUDO_REGISTER ) { rtx def_insn = single_reference ( x ) ; if ( def_insn ) { rtx def_bb = BLOCK_FOR_INSN ( def_insn ) ; if ( def_bb == get_insns ( ) ) return true ; } } } return false ; }


bool arc_text_label ( LABEL ) { if ( TARGET_ARC ) { if ( LABEL . is_executable ( ) ) { return true ; } } return false ; }


char * arc_tolower ( char * UP , char * LO ) { int len = strlen ( UP ) ; for ( int i = 0 ; i < len ; i ++ ) { if ( UP [ i ] >= 'A' && UP [ i ] <= 'Z' ) { LO [ i ] = UP [ i ] + 32 ; } else { LO [ i ] = UP [ i ] ; } } LO [ len ] = '\0' ; return LO ; }


int arc_unalign_branch_p ( unsigned int arc , unsigned int op1 , unsigned int op2 , unsigned int op3 , unsigned int op4 ) { int return_value = 0 ; if ( arc == arc , 0 , 0 , 0 , 0 ) { if ( op3 == 0 && op4 == 0 ) { return_value = 1 ; } } return return_value ; }


gcc_unwind_offset arc_unspec_offset ( unsigned int value ) { return gen_unspec ( & gcc_unwind_offset_type_node , value , "arc,1" ) ; }


arc_use_anchors_for_symbol_p ( tree symbol ) { bool use_anchors = true ; if ( TARGET_USES_GP_REGISTER_FOR_SMALL_DATA && ( DECL_SECTION_NAME ( symbol ) == arc_small_data_section_name || DECL_SECTION_NAME ( symbol ) == arc_bss_small_data_section_name ) ) { use_anchors = false ; } else if ( TREE_CODE ( symbol ) == FUNCTION_DECL && DECL_SECTION_NAME ( symbol ) == arc_text_section_name ) { use_anchors = false ; } else if ( DECL_THREAD_LOCAL ( symbol ) ) { use_anchors = false ; } else if ( DECL_EXTERNAL ( symbol ) && ( ! DECL_WEAK ( symbol ) || ! DECL_WEAK_DECLARATION ( symbol ) ) ) { use_anchors = false ; } return use_anchors ; }


int arc_use_by_pieces_infrastructure_p ( ) { if ( strncmp ( TARGET_ARCH , "arc" , 3 ) == 0 ) { return 1 ; } else { return 0 ; } }


arc_vector_mode_supported_p ( enum machine_mode mode ) { if ( mode == ARC_VECTOR_MODE ) return true ; else return false ; }


int arc_verify_short ( rtx insn , int unalign , int check_attr ) { if ( CHECK_ATTR > 0 && GET_CODE ( PATTERN ( insn ) ) == CODE_FOR_arc_compact ) return 1 ; if ( unalign == 0 ) return 1 ; return 0 ; }


const
char
*
arc_warn_func_return
(
const
char
*
warning
)
{
char
*
ret_warning
=
(
char
*
)
malloc
(
sizeof
(
char
)
*
(
strlen
(
warning
)
+
4
)
)
;
strcpy
(
ret_warning
,
"arc "
)
;
strcat
(
ret_warning
,
warning
)
;
return
ret_warning
;
}


int arc_write_ext_corereg ( rtx_insn * insn ) { rtx pat = PATTERN ( insn ) ; int write = 0 ; if ( pat ) { rtx set = single_set ( pat ) ; if ( set && SET_DEST ( set ) && GET_CODE ( SET_DEST ( set ) ) == REG && REGNO ( SET_DEST ( set ) ) >= 32 && REGNO ( SET_DEST ( set ) ) <= 61 ) { write = 1 ; } } return write ; }


function branch_dest ( BRANCH instruction ) { target_value = arc , 0 , 0 , 1 , 2 , 1 , 0 if ( instruction . address == target_value ) { destination_address = instruction . address + instruction . branch_offset } else { instruction_length = get_attr_length ( instruction ) destination_address = instruction . address + instruction_length } return destination_address }


"register number must be a compile-time constant. Try giving higher optimization levels.\n"


void compact_sda_memory_operand ( operand ) { if ( operand == arc , 0 , 0 , 0 , 1 , 1 , 3 , 0 ) { set_volatile_cache_option ( operand ) ; } else { return ; } }


DISI_MODES
disi_highpart
(
DISI_MODES
di_value
)
{
DISI_MODES
hi_value
;
if
(
mode
!=
DImode
)
{
printf
(
"Invalid input mode"
)
;
return
0
;
}
hi_value
=
(
di_value
>>
32
)
;
hi_value
=
(
hi_value
&
0xFFFFFFFF
)
|
(
0
<<
4
)
;
return
hi_value
;
}


"Invalid code value for ARC architecture."


void emit_unlikely_jump ( instr_t * prev_jump_instr , int arc_target_value ) { if ( prev_jump_instr == NULL || ! IS_JUMP ( prev_jump_instr ) ) return ; arc_target_value -> unlikely_jump = true ; }


's say we have a simple C code that needs to be compiled for a specific arc architecture: ``` #include <stdio.h> int main() {   printf("Hello World!");   return 0; } ``` The execute function for the arc backend of the GCC Compiler would look something like this: ``` void execute(char *arc) {   generate_arc_code();   optimize_for_arc();   return compiled_code; }


void frame_add ( int reg , int offset ) { emit_insn ( gen_frame_insn ( ARC_FRAME_ADD , reg , gen_int_mode ( offset ) , gen_int_mode ( 0 ) , NULL , NULL , 0 ) ) ; }


void emit_frame_insn ( insn_code code , arc_mode mode , rtx_insn * insn ) { start_sequence ( ) ; rtx_insn * new_insn = emit_insn ( code , mode ) ; set_relevant_value ( new_insn , "arc,1" ) ; end_sequence ( ) ; }


frame_move_inc ( gcc_rtx addr , gcc_rtx reg ) { if ( REG_RELEASE_MEM ( addr ) ) REG_INC_NOTE ( reg ) ; else if ( addr == 0 ) REG_INC_NOTE ( reg ) ; return reg ; }


"frame_restore_reg is specific to the ARC backend of GCC compiler"


void
frame_stack_add
(
int
offset
)
{
emit_insn
(
"add %d, sp, sp"
,
offset
,
arc
)
;
}


gen_acc1 ( void ) { enum reg_class class = ACC_REGS ; # if defined ( TARGET_ARC ) if ( arc_use_generic_regs ) class = gen_reg_rtx_for_acc1 ( ) ; else if ( arc_no_acc_regs ) class = GENERAL_REGS ; # endif return class ; }


rtx gen_acc2 ( void ) { rtx reg ; # ifdef TARGET_ARC reg = gen_rtx_REG ( SImode , 57 ) ; reg = gen_rtx_REG ( SImode , 56 , reg ) ; # else reg = gen_rtx_REG ( SImode , ACC2_REG ) ; # endif return reg ; }


bool
gen_operands_ldd_std
(
rtx
operands
[
]
)
{
if
(
operands
[
0
]
!=
operands
[
2
]
)
{
return
false
;
}
if
(
operands
[
1
]
+
4
!=
operands
[
3
]
)
{
return
false
;
}
bool
load
=
true
;
if
(
operands
[
4
]
==
0
||
operands
[
4
]
==
2
)
{
load
=
false
;
}
rtx
insn
=
gen_rtx_INSN_LIST
(
operands
[
5
]
,
operands
[
6
]
,
gen_rtx_SEQUENCE
(
gen_rtx_MEM
(
operands
[
7
]
,
gen_lowpart
(
VOIDmode
,
operands
[
0
]
)
)
,
gen_rtx_CONST_INT
(
operands
[
8
]
)
,
gen_rtx_CONST_INT
(
operands
[
9
]
)
)
)
;
if
(
load
)
{
emit_insn_before
(
insn
,
operands
[
10
]
)
;
emit_insn_before
(
insn
,
operands
[
11
]
)
;
asm_fprintf
(
stderr
,
"instruction generated: LDD\n"
)
;
}
else
{
emit_insn_after
(
insn
,
operands
[
10
]
)
;
emit_insn_after
(
insn
,
operands
[
11
]
)
;
asm_fprintf
(
stderr
,
"instruction generated: STD\n"
)
;
}
return
true
;
}


int
get_symbol_alignment
(
const
char
*
symb
)
{
if
(
strncmp
(
symb
,
"RTX ( const ( symb < + const_int > )"
,
35
)
!=
0
)
{
return
1
;
}
const
char
*
const_int
=
symb
+
35
;
int
const_int_num
=
atoi
(
const_int
)
;
return
1
;
}


__attribute__ ( ( target ( "arc" ) ) ) void hwloop_fail ( void ) { }


hwloop_pattern_reg ( rtx insn ) { if ( GET_CODE ( insn ) == DUFFGEN ) return gen_rtx_REG ( mode , arc_regno ( insn , 0 ) ) ; return NULL_RTX ; }


void jli_call_scan ( void ) { for ( auto & call : function_calls ) { if ( ! call . in_jli_section ) { auto target_specific_val = call . target_specific_val ; if ( target_specific_val == "arc,0,0,0,0" ) { add_to_jli ( call ) ; } } } }


bool legitimate_scaled_address_p ( op ) { if ( op == NULL ) { return FALSE ; } if ( op -> machine != ARC || op -> asm_operand == NULL ) { return FALSE ; } if ( ! ( op -> asm_operand -> op_primary == 0 && op -> asm_operand -> op_secondary == 0 && op -> asm_operand -> op_extension_value == 0 && op -> asm_operand -> op_displacement == 0 && op -> asm_operand -> op_suffix1 == 1 && op -> asm_operand -> op_prefix1 == 2 && op -> asm_operand -> op_suffix2 == 0 && op -> asm_operand -> op_prefix2 == 1 && op -> asm_operand -> op_scaling == 2 && op -> asm_operand -> op_size == 8 && op -> asm_operand -> op_index == 4 && op -> asm_operand -> op_base == 0 && op -> asm_operand -> op_offset == 1 && op -> asm_operand -> op_shift == 4 && op -> asm_operand -> op_multiplier == 1 && op -> asm_operand -> op_addend == 1 && op -> asm_operand -> op_constant1 == 1 ) ) { return FALSE ; } return TRUE ; }


bool mem_ok_for_ldd_std ( rtx MEM , rtx * BASE , HOST_WIDE_INT * OFFSET , int arc , int 0 , int 0 , int 1 ) { if ( ! MEM || ! MEM_P ( MEM ) ) return false ; if ( MEM_VOLATILE_P ( MEM ) || MEM_READONLY_P ( MEM ) || MEM_SIDE_EFFECTS_P ( MEM ) ) return false ; if ( ! rtx_equal_p ( XEXP ( MEM , 1 ) , GEN_INT ( 0 ) ) ) { * BASE = XEXP ( MEM , 0 ) ; * OFFSET = INTVAL ( XEXP ( MEM , 1 ) ) ; return true ; } return false ; }


next_nonnote_insn_bb ( rtx insn ) { rtx next = NEXT_INSN ( insn ) ; while ( next && NOTE_P ( next ) ) next = NEXT_INSN ( next ) ; if ( ! next || NOTE_P ( next ) ) return NULL ; if ( GET_CODE ( next ) == USE && INTVAL ( XEXP ( next , 0 ) ) == arc && INTVAL ( XEXP ( next , 1 ) ) == 0 ) return NULL ; return next ; }


operands_ok_ldd_std ( rtx * operands ) { rtx reg1 = operands [ 0 ] ; rtx reg2 = operands [ 1 ] ; rtx address = operands [ 2 ] ; rtx offset1 = operands [ 3 ] ; rtx offset2 = operands [ 4 ] ; if ( ! REG_P ( reg1 ) || ! REG_P ( reg2 ) ) { return false ; } if ( ( unsigned HOST_WIDE_INT ) address & 0x03 ) { return false ; } const int MAX_OFFSET = ( 1 << 11 ) - 4 ; if ( ! CONST_INT_P ( offset1 ) || ! CONST_INT_P ( offset2 ) ) { return false ; } if ( INTVAL ( offset1 ) < 4 || INTVAL ( offset1 ) > MAX_OFFSET ) { return false ; } if ( INTVAL ( offset2 ) < 4 || INTVAL ( offset2 ) > MAX_OFFSET ) { return false ; } if ( ( INTVAL ( offset2 ) - INTVAL ( offset1 ) ) != 4 ) { return false ; } if ( reload_completed ) { if ( ! REGNO_OK_FOR_LETTER_P ( REGNO ( reg1 ) , 'r' ) || ! REGNO_OK_FOR_LETTER_P ( REGNO ( reg2 ) , 'r' ) ) { return false ; } } return true ; }


void output_short_suffix ( insn alternative ) { if ( alternative . is_short ) { cfun -> machine -> unalign = alternative . short_suffix ; } }


void pad_return ( ) { if ( ( ( unsigned int ) arc [ 0 ] == 1 ) && ( ( unsigned int ) arc [ 1 ] == 2 ) ) { unsigned int distance = ( unsigned int ) arc [ 2 ] + ( unsigned int ) arc [ 4 ] ; if ( distance < 6 ) { unsigned int padding = 6 - distance ; arc [ 2 ] += padding ; arc [ 5 ] += padding ; arc [ 7 ] += padding ; } } }


"invalid number in %<-mrgf-banked-regs=%s%> \n"

"valid values are 0, 4, 8, 16, or 32 \n"


void push_reg ( unsigned long reg_num ) { unsigned long temp_SP = SP ; SP += sizeof ( reg_num ) ; * ( ( unsigned long * ) SP ) = reg_num ; SP -= sizeof ( reg_num ) ; * ( ( unsigned long * ) SP ) = "arc,1" ; SP = temp_SP ; }


bool symbolic_reference_mentioned_p ( operand OP , int arc , int n1 , int n2 , int n3 , int n4 ) { if ( OP == NULL || arc < 0 || n1 < 0 || n2 < 0 || n3 < 0 || n4 < 0 ) { return false ; } std :: string str = OP . toString ( ) ; if ( str . find ( "arc" ) != std :: string :: npos ) { if ( str . find ( std :: to_string ( n1 ) ) != std :: string :: npos ) { if ( str . find ( std :: to_string ( n2 ) ) != std :: string :: npos ) { if ( str . find ( std :: to_string ( n3 ) ) != std :: string :: npos ) { if ( str . find ( std :: to_string ( n4 ) ) != std :: string :: npos ) { return true ; } } } } } return false ; }


void riscv_atomic_assign_expand_fenv ( float * dst , float val , int target_specific_val ) { # ifdef HAVE_RISCV_ATOMIC val = __atomic_fetch_add ( dst , val , RISCV_ATOMIC_RELAXED ) ; * dst = val + target_specific_val ; # else * dst = val + target_specific_val ; # endif }


void riscv_init_builtins ( ) { riscv , riscv_vector :: init_builtins = 0 ; ... }


riscv_expand_builtin ( int code , rtx_def * args , int target_type ) { switch ( code ) { case BUILT_IN_RISCV_0 : { ... return result_code ; } default : return NULL ; } }


if ( target == TARGET_RISCV ) { } Next , we need to define the expansion statements for the fenv assignment . This involves breaking down the assignment into several smaller operations , each of which is wrapped in a fenv operation that sets and restores the environment flags before and after the operation . This ensures that any exceptions raised during the operation are handled correctly . The expansion statements will look something like this : int old_fenv = get_fenv ( ) ; set_fenv ( 0 ) ; result = a + b ; set_fenv ( old_fenv ) ; set_fenv ( 1 ) ; * a = result ; Once all the operations have been expanded , we can then generate the appropriate assembly code for the riscv target and return it from the function . The final riscv_atomic_assign_expand_fenv function will look something like this : int riscv_atomic_assign_expand_fenv ( riscv_target , 0 , 1 ) { int result ; int old_fenv = get_fenv ( ) ; set_fenv ( 0 ) ; result = a + b ; set_fenv ( old_fenv ) ; set_fenv ( 1 ) ; * a = result ; return assembly_code ; }


void riscv_expand_builtin_direct ( tree exp , rtx icode , rtx target ) { if ( HAS_TARGET_P ( exp ) ) { target = gen_rtx_REG ( SImode , RISCV_REG ) ; XEXP ( XEXP ( icode , 0 ) , 0 ) = target ; } expand_builtin_direct ( icode , exp ) ; }


riscv_expand_builtin_insn
(
rtx
icode
,
rtx
*
ops
,
bool
has_target_p
)
{
if
(
!
has_target_p
)
return
const0_rtx
;
rtx
target
=
ops
[
0
]
;
if
(
icode
==
NULL_RTX
||
!
TARGET_RISCV
)
return
target_rtx
;
switch
(
icode
)
{
case
RISCV_ADD
:
if
(
ops
[
1
]
==
NULL_RTX
||
ops
[
2
]
==
NULL_RTX
)
gcc_unreachable
(
"Invalid argument to built-in function"
)
;
return
gen_rtx_PLUS
(
VOIDmode
,
ops
[
1
]
,
ops
[
2
]
)
;
case
RISCV_SUB
:
if
(
ops
[
1
]
==
NULL_RTX
||
ops
[
2
]
==
NULL_RTX
)
gcc_unreachable
(
"Invalid argument to built-in function"
)
;
return
gen_rtx_MINUS
(
VOIDmode
,
ops
[
1
]
,
ops
[
2
]
)
;
default
:
gcc_unreachable
(
"Invalid argument to built-in function"
)
;
}
}


void riscv_init_builtins ( void ) { # define __riscv # define __riscv_xlen 0 __attribute__ ( ( const , pure ) ) unsigned int __builtin_riscv_rd ( int regno ) ; __attribute__ ( ( const , pure ) ) unsigned int __builtin_riscv_gp ( void ) ; riscv_target = TARGET_RISCV ; riscv_xlen = 0 ; }


riscv_check_builtin_call ( tree fndecl , int nargs , tree * args ) { riscv_check_builtin_call_data data ; data . nargs = nargs ; data . args = args ; if ( DECL_BUILT_IN ( fndecl ) && TREE_CODE ( fndecl ) == FUNCTION_DECL ) { const char * builtin_name = IDENTIFIER_POINTER ( DECL_NAME ( fndecl ) ) ; if ( strcmp ( builtin_name , "TARGET_CHECK_BUILTIN_CALL" ) == 0 ) { tree rval = riscv_vector :: check_builtin_call ( & data ) ; return tree_string_cst_as_string ( rval ) ; } } return NULL ; }


"invalid usage of #pragma riscv intrinsic"

"invalid option for #pragma riscv intrinsic"

"this pragma is only supported on RISC-V targets"

"%<#pragma riscv intrinsic%> option %qs needs 'V' extension"


riscv_register_pragmas ( ) { register_pragma ( "register_target_pragmas" , "riscv" ) ; register_pragma ( "register_target_pragmas" , "intrinsic" ) ; register_pragma ( "register_target_pragmas" , "riscv" ) ; }


void riscv_cpu_cpp_builtins ( const char * arg ) { if ( strcmp ( arg , "__riscv" ) == 0 ) { TARGET_CPU_CPP_BUILTINS ( "__riscv" , 1 ) ; } else if ( strcmp ( arg , "__riscv_compressed" ) == 0 ) { TARGET_CPU_CPP_BUILTINS ( "__riscv_compressed" , 1 ) ; } else if ( strcmp ( arg , "__riscv_32e" ) == 0 ) { TARGET_CPU_CPP_BUILTINS ( "__riscv_32e" , 1 ) ; } else if ( strcmp ( arg , "__riscv_atomic" ) == 0 ) { TARGET_CPU_CPP_BUILTINS ( "__riscv_atomic" , 1 ) ; } else if ( strcmp ( arg , "__riscv_mul" ) == 0 ) { TARGET_CPU_CPP_BUILTINS ( "__riscv_mul" , 1 ) ; } else if ( strcmp ( arg , "__riscv_div" ) == 0 ) { TARGET_CPU_CPP_BUILTINS ( "__riscv_div" , 1 ) ; } else if ( strcmp ( arg , "__riscv_muldiv" ) == 0 ) { TARGET_CPU_CPP_BUILTINS ( "__riscv_muldiv" , 1 ) ; } else if ( strcmp ( arg , "__riscv_xlen" ) == 0 ) { TARGET_CPU_CPP_BUILTINS ( "__riscv_xlen" , 8 ) ; } else if ( strcmp ( arg , "__riscv_flen" ) == 0 ) { TARGET_CPU_CPP_BUILTINS ( "__riscv_flen" , 8 ) ; } else if ( strcmp ( arg , "__riscv_fdiv" ) == 0 ) { TARGET_CPU_CPP_BUILTINS ( "__riscv_fdiv" , 1 ) ; } else if ( strcmp ( arg , "__riscv_fsqrt" ) == 0 ) { TARGET_CPU_CPP_BUILTINS ( "__riscv_fsqrt" , 1 ) ; } else if ( strcmp ( arg , "__riscv_abi_rve" ) == 0 ) { TARGET_CPU_CPP_BUILTINS ( "__riscv_abi_rve" , 1 ) ; }


TargetABI riscv_d_handle_target_float_abi ( string target_specific_value ) { switch ( target_specific_value ) { case "soft" : return "soft" ; case "single" : return "single" ; case "double" : return "double" ; default : return "1" ; } }


char * riscv_d_target_versions ( ) { char * target_versions [ ] = { "riscv" , "RISCV64" , "RISCV32" , "D_HardFloat" , "D_SoftFloat" } ; return target_versions ; }


unsigned int calculate_x_in_sequence ( void ) { unsigned int x = 0 ; unsigned int riscv = 1 ; while ( riscv < 10 ) { x += riscv ; riscv ++ ; } return x ; }


void riscv_run_selftests ( ) { const char * target = "riscv" ; run_selftests ( target ) ; }


void execute ( rtx_insn * head , rtx_insn * tail , int riscv = 0 ) { for ( rtx_insn * insn = head ; insn != NULL ; insn = NEXT_INSN ( insn ) ) { rtx_code code = GET_CODE ( insn ) ; if ( is_riscv_specific ( code ) ) { rtx * operands = XVECEXP ( insn , 0 , 0 ) ; } } return ; }


"Prologue call to riscv_save_0 followed by noreturn call, removing prologue.\n"


static int riscv_saved_regs [ ] = { } ; static bool is_ret_insn ( rtx_insn * insn ) { return GET_CODE ( insn ) == CODE_RETURN ; } static bool is_call_insn ( rtx_insn * insn ) { return GET_CODE ( insn ) == CODE_CALL ; } static bool is_restore_insn ( rtx_insn * insn ) { rtx pat = PATTERN ( insn ) ; return rtx_equal_p ( pat , const0_rtx ) && rtx_equal_p ( XEXP ( pat , 0 ) , const1_rtx ) ; } static bool is_tag_restore_insn ( rtx_insn * insn ) { rtx pat = PATTERN ( insn ) ; return rtx_equal_p ( pat , const0_rtx ) && rtx_equal_p ( XEXP ( pat , 0 ) , const2_rtx ) ; } static bool is_imm_restore_insn ( rtx_insn * insn ) { rtx pat = PATTERN ( insn ) ; return rtx_equal_p ( pat , const0_rtx ) && rtx_equal_p ( XEXP ( pat , 0 ) , const3_rtx ) ; }


apply_tail_policy_p ( rtx insn , rtx tail_policy ) { enum riscv_target_insn_flags { RISCV_FLAG_CAP , RISCV_FLAG_TAIL , RISCV_FLAG_XSW , RISCV_FLAG_MMU , RISCV_FLAG_NONE } ; riscv_target_insn_flags target_flags = RISCV_FLAG_NONE ; targetm = TARGET_MACHINE ; if ( targetm -> family == "riscv" ) target_flags = RISCV_FLAG_TAIL ; if ( target_flags == RISCV_FLAG_TAIL ) { if ( rtx_contains_p ( insn , tail_policy ) ) { for ( unsigned int i = 0 ; i < XVECLEN ( insn , 0 ) ; i ++ ) { rtx operand = XVECEXP ( insn , 0 , i ) ; if ( operand == tail_policy ) { XSETINT ( operand , 0 , 1 ) ; XVECEXP ( insn , 0 , i ) = operand ; break ; } } PATTERN ( insn ) = gen_rtx_fmt_e ( TARGET_DEF , "soi" , insn , operands ) ; } } }


const
char
*
apply_vl_p
(
const
char
*
op
,
const
rtx_insn
*
target
)
{
if
(
!
target
->
has_vl_operand
)
return
op
;
int
vl_size
=
target
->
riscv_vl_size
;
char
*
new_op
=
(
char
*
)
malloc
(
strlen
(
op
)
+
10
)
;
sprintf
(
new_op
,
"%s IMMVL %d"
,
op
,
vl_size
)
;
return
new_op
;
}


bool has_merge_operand_p ( enum rtx_code code ) { switch ( code ) { case CODE : case CODE2 : case CODE3 : return true ; } return false ; }


bool use_mask_predication_p ( enum rtx_code code , enum machine_mode mode ) { bool result = true ; if ( TARGET_RISCV ) { if ( code >= FIRST_RISCV_INSN && code <= LAST_RISCV_INSN ) { result = true ; } } return result ; }


void build_all ( const char * group , const char * * operand_suffixes , const char * * type_suffixes , const char * * predication_suffixes ) { unsigned int i , j , k , l ; rtx op , arg , xop , base ; for ( i = 0 ; operand_suffixes [ i ] != 0 ; ++ i ) { for ( j = 0 ; type_suffixes [ j ] != 0 ; ++ j ) { for ( k = 0 ; predication_suffixes [ k ] != 0 ; ++ k ) { char * func_name = concat ( group , "&" , operand_suffixes [ i ] , "&" , type_suffixes [ j ] , "&" , predication_suffixes [ k ] ) ; char * base_name = concat ( group , "&" , operand_suffixes [ i ] ) ; char * pred_suffix = predication_suffixes [ k ] ; op = apply_predication ( base_name , pred_suffix , riscv , 0 , 0 ) ; for ( l = 0 ; op != 0 && l < 3 ; ++ l ) { arg = gen_rtx_REG ( riscv , 0 + l ) ; op = gen_rtx_PARALLEL ( riscv , gen_rt_list ( arg , XOP ) ) , gen_rt_list ( op , 0 ) ) ; } add_insn ( func_name , op ) ; } } } }


if ( TARGET_RISCV ) { rtx new_op = gen_rtx_fmt_ee ( opnd_sfx , GET_MODE ( group ) , XEXP ( group , 0 ) , XEXP ( group , 1 ) ) ; rtx new_rtx = gen_rtx_SET ( VOIDmode , XEXP ( group , 0 ) , new_op ) ; XEXP ( new_rtx , 0 ) = bi_sfx ; XEXP ( new_rtx , 1 ) = pred_sfx ; XEXP ( group , 0 ) = new_op ; XEXP ( group , 1 ) = new_rtx ; }


"Error: Invalid target specific values for RISC-V instruction %s"


char * get_name ( rtx instance , bool overloaded_p ) { char * name = NULL ; obstack_alloc_failed_handler func = set_obstack_alloc_failed_handler ( some_handler_function ) ; if ( overloaded_p ) { name = obstack_alloc ( & m_string_obstack , strlen ( "__riscv_" ) + strlen ( "__ff" ) + strlen ( "__vle" ) + 1 ) ; strcat ( name , "__riscv_" ) ; strcat ( name , "__ff" ) ; strcat ( name , "__vle" ) ; } else { name = obstack_alloc ( & m_string_obstack , strlen ( identify_fnname_c ( identifier ( instance ) ) ) + 1 ) ; strcat ( name , identify_fnname_c ( identifier ( instance ) ) ) ; } set_obstack_alloc_failed_handler ( func ) ; return name ; }


function add_all_one_mask_operand ( rtx , mode , mask_index ) { if ( rtx . type != V4HI && rtx . type != V2SI ) { return rtx } if ( mask_index == - 1 ) { return rtx } if ( rtx . type == V2SI ) { mask_index = 0 } all_one_mask = gen_rtx_REG_SET ( mode , TARGET_RISCV_ALL_TRUE_MASK ) operand = gen_rtx_CLOBBER ( mode , all_one_mask ) return operand }


void add_attribute ( const char * name , tree * attrs ) { if ( ! lookup_attribute ( name , * attrs ) ) { attr = create_attribute ( name , "riscv" , 0 ) ; * attrs = chainon ( * attrs , attr ) ; } }


static bool add_fixed_operand ( const rtx_insn * insn , rtx * operands , const char * * constraint , int n ) { rtx op = operands [ 0 ] ; if ( ! X_P ( op ) ) { rtx mem_addr = legitimize_reload_address ( op , VOIDmode , 1 ) ; if ( ! mem_addr ) return false ; operands [ 0 ] = mem_addr ; } * constraint = "X" ; return true ; }


void add_function ( const char * name , tree fntype , tree attrs , tree instance ) { tree decl ; decl = build_fn_decl ( name , fntype ) ; DECL_ATTRIBUTES ( decl ) = attrs ; TREE_RISCV_SPECIFIC ( decl ) = instance ; pushdecl ( decl ) ; }


void riscv_add_mem_operand ( rtx * operands , enum machine_mode mode , rtx addr ) { if ( ! addr || GET_CODE ( addr ) != SYMBOL_REF ) return ; rtx mem_operand = gen_rtx_MEM ( mode , addr ) ; emit_insn ( rtx_insn * insn , mem_operand ) ; riscv_insn_add_specific_value ( insn , "riscv" ) ; * operands = gen_rtx_LIST ( * operands , mem_operand ) ; }


extern tree add_unique_function ( const char * name , const char * overload_name , tree return_type , const_arg_types ) { if ( riscv_target_specific_value ) { return nullptr ; } const char * full_name = name ; if ( overload_name == nullptr ) { overload_name = full_name ; } tree function_type = build_function_type ( return_type , arg_types ) ; tree function_exists = function_exists ( name , function_type ) ; if ( function_exists ) { return nullptr ; } tree function = build_function_decl ( full_name , overload_name , function_type , any_other_parameters ) ; set_decl_built_in ( function ) ; add_builtin_function ( function ) ; return function ; }


char * append_base_name ( const char * name ) { char * result = ( char * ) malloc ( strlen ( name ) + 8 ) ; strcpy ( result , "__riscv_" ) ; strcat ( result , name ) ; return result ; }


char * append_name ( char * function_name , char * NAME ) { if ( strstr ( function_name , "riscv" ) != NULL ) { strcat ( function_name , NAME ) ; return function_name ; } else { char * new_function_name = ( char * ) malloc ( strlen ( function_name ) + 6 ) ; strcpy ( new_function_name , function_name ) ; strcat ( new_function_name , "_riscv" ) ; strcat ( new_function_name , NAME ) ; return new_function_name ; } }


"Error: riscv architecture %d is not supported."

"The function name with SEW appended is: %s"


apply_mask_policy_p ( target_specific_value ) { if ( target_specific_value == "riscv" ) { set_default_mask_policy_operand ( ) ; } }


void apply_tail_policy_p ( const char * target ) { if ( strcmp ( target , "riscv" ) == 0 ) { apply_tail_policy_operand ( ) ; } }


void
apply_vl_p
(
int
vl
)
{
printf
(
"Applying vl operand with value = %d\n"
,
vl
)
;
}


machine_mode
arg_mode
(
argument_type
arg
)
{
switch
(
arg
)
{
case
integer_argument
:
return
TYPE_MODE_INT
(
riscv
)
;
case
floating_point_argument
:
return
TYPE_MODE_FLOAT
(
riscv
)
;
case
vector_argument
:
return
TYPE_MODE_VECTOR
(
riscv
)
;
default
:
printf
(
"Invalid argument type!\n"
)
;
exit
(
1
)
;
}
}


riscv_build_const_pointer ( T type ) { riscv_value = ... ; return riscv_value ; }


tree builtin_decl ( int code ) { tree decl = error_mark_node ; if ( TARGET_RISCV ) { if ( code == CODE ) { tree type = build_function_type_list ( void_type_node , NULL_TREE ) ; decl = build_decl ( BUILTINS_LOCATION , FUNCTION_DECL , get_identifier ( "RVV_function" ) , type ) ; DECL_RISCV_SPECIFIC ( decl ) = "riscv" ; add_attribute ( & decl , get_identifier ( "STRET" ) , NULL_TREE ) ; pushdecl ( decl ) ; } } return decl ; }


void call_properties ( function , insn ) { if ( insn is floating - point operation ) { insn -> target_specific_value = riscv , 0 ; function -> floating_point_properties . update ( insn ) ; } }


const rtx_insn_operand * operands , int num_operands ) { if ( strcmp ( name , "riscv" ) == 0 ) { return true ; } else { return false ; } }


"Invalid call: Incorrect number of arguments."

"Invalid call: First argument must be an integer."

"Invalid call: Second argument must be a character."


"Invalid number of arguments for SVE function call"

"Argument 1 of SVE function call must be an integer constant expression"

"Argument 2 of SVE function call must be an integer constant expression"


int check_required_extensions ( const char * * REQUIRED_EXTENSIONS , struct riscv_cxt * riscv_cxt ) { if ( riscv_cxt -> riscv != 0 ) { return - 1 ; } if ( riscv_cxt -> riscv_arch != 0 ) { return - 2 ; }


int equal ( int H1 , int H2 ) { if ( H1 == H2 ) { return 1 ; } else { return 0 ; } } This function can then be called in the RISC - V backend of GCC compiler using its target - specific value , which is specific to RISC - V architecture . This target - specific value can be used to optimize the function according to the RISC - V architecture and thus improve its performance . Here is an example of how the "equal" function can be called in the RISC - V backend : int main ( ) { int result ; int x = 5 ; int y = 10 ; result = equal ( x , y ) ; return 0 ; }


statement fold ( statement stmt , rtx target ) { if ( CALL_P ( stmt ) ) { rtx fn = XEXP ( stmt , 0 ) ; if ( CONSTANT_P ( fn ) ) { const char * name = XSTR ( fn , 0 ) ; if ( strcmp ( name , target ) == 0 ) { stmt = new_stmt ( ) ; return stmt ; } } } return NULL ; }


void function_returns_void_p ( void ) { }


generate_insn
(
rtx
icode
,
rtx
m_ops
,
int
target_specific
)
{
if
(
target_specific
!=
0
)
error
(
"Invalid argument to built-in function"
)
;
return
gen_rtx_CONST
(
GET_MODE
(
icode
)
,
XEXP
(
m_ops
,
0
)
)
;
}


string get_attributes ( riscv , INSTANCE ) { string attributes = "" ; attributes += "riscv" ; attributes += "pure" ; attributes += "const" ; attributes += "nothrow" ; attributes += "leaf" ; return attributes ; }


const
char
*
get_mask_policy_for_pred
(
const
char
*
predication
)
{
if
(
strcmp
(
predication
,
"MU"
)
==
0
)
{
return
"MU"
;
}
else
{
return
"prefer default configuration"
;
}
}


target_mask get_tail_policy_for_pred ( const rtx_insn * insn ) { target_mask tail_policy = 0 ; rtx_insn * pred_value = NULL ; rtx pred_reg = NULL ; enum rtx_code code = GET_CODE ( XEXP ( insn , 0 ) ) ; if ( code == CODE_FOR_riscv_tu ) tail_policy = TARGET_MASK_RISCV_TU ; else { pred_value = find_reg_equal_equiv_note ( insn ) ; if ( pred_value && GET_CODE ( pred_value ) == NOTE ) pred_reg = find_reg_equal ( XEXP ( pred_value , 0 ) ) ; if ( pred_reg && riscv_pred_reg_specified_p ( pred_reg ) ) tail_policy = TARGET_MASK_RISCV_DEFAULT_CONFIG ; } return tail_policy ; }


bool has_merge_operand_p ( enum rtx_code opcode ) { return true ; }


machine_mode index_mode ( int index_type ) { if ( index_type == 1 ) { return TARGET_CC1_RISCV ; } else { } }


void init_builtins ( void ) { const char * target = "riscv" ; for ( const built_in_function * fn = builtin_functions ; fn -> name != NULL ; fn ++ ) { if ( fn -> riscv_target != NULL && strcmp ( fn -> riscv_target , target ) == 0 ) { tree fun_decl = add_builtin_function ( fn -> name , fn -> type , fn -> flags , fn -> frame ) ; DECL_ATTRIBUTES ( fun_decl ) = TREE_LIST ( CONST_DECL , build_tree_list ( NULL , get_identifier ( fn -> riscv_target ) ) ) ; } } }


attribute_lookup
lookup_vector_type_attribute
(
tree
type
)
{
if
(
is_rvv_type
(
type
)
)
{
attribute_lookup
attr
=
get_attribute_descriptor
(
RISCV
,
"RVV type"
)
;
return
attr
;
}
else
{
return
;
}
}


void
make_type_sizeless
(
tree
*
type
)
{
if
(
TYPE_SIZELESS_P
(
type
)
)
return
;
tree
sizeless_type
=
get_identifier
(
"RVV sizeless type"
)
;
TYPE_SIZE
(
type
)
=
0
;
TYPE_PRECISION
(
type
)
=
0
;
TYPE_SIZELESS
(
type
)
=
1
;
TYPE_MODE
(
type
)
=
MODE_TYPE
;
TYPE_TARGET_SPECIFIC
(
type
)
=
sizeless_type
;
}
With
this
function
,
the
TYPE_SIZELESS_P
macro
can
be
used
to
check
if
a
type
is
sizeless
:
if
(
TYPE_SIZELESS_P
(
type
)
)
{
}
else
{
}


const char * mangle_builtin_type ( const_tree type , int riscv = 0 ) { if ( type == NULL ) { return NULL ; } if ( TYPE_MAIN_VARIANT ( type ) == void_type_node || TYPE_MAIN_VARIANT ( type ) == integer_type_node || TYPE_MAIN_VARIANT ( type ) == unsigned_type_node || TYPE_MAIN_VARIANT ( type ) == long_long_integer_type_node || TYPE_MAIN_VARIANT ( type ) == long_long_unsigned_type_node || TYPE_MAIN_VARIANT ( type ) == short_integer_type_node || TYPE_MAIN_VARIANT ( type ) == short_unsigned_type_node || TYPE_MAIN_VARIANT ( type ) == float_type_node || TYPE_MAIN_VARIANT ( type ) == double_type_node || TYPE_MAIN_VARIANT ( type ) == long_double_type_node || TYPE_MAIN_VARIANT ( type ) == pointer_type_node || TYPE_MAIN_VARIANT ( type ) == offset_type_node ) { return "__rvv_" + TYPE_NAME ( type ) ; } else { return NULL ; } }


machine_mode mask_mode ( machine_mode mask ) { switch ( MASK_SIZE ( mask ) ) { case 1 : return ( TARGET_64BIT ) ? TImode : QImode ; case 2 : return HImode ; case 4 : return SImode ; case 8 : return ( TARGET_64BIT ) ? DImode : SImode ; case 16 : return ( TARGET_64BIT ) ? TImode : SFmode ; case 32 : return DFmode ; default : gcc_unreachable ( ) ; } }


bool modifies_global_state_p ( rtx_insn * insn ) { enum rtx_code code = insn -> code ; enum machine_mode mode = GET_MODE ( insn ) ; bool result = false ; switch ( code ) { case TARGET_RISCV_LUI : case TARGET_RISCV_ADDI : case TARGET_RISCV_ADD : case TARGET_RISCV_ADDIW : case TARGET_RISCV_SUB : case TARGET_RISCV_SUBW : case TARGET_RISCV_LBU : case TARGET_RISCV_LH : case TARGET_RISCV_LW : case TARGET_RISCV_LBU : case TARGET_RISCV_LH : case TARGET_RISCV_LW : result = true ; break ; default : result = false ; break ; } return result ; }


reads_global_state_p ( rtx fn ) { if ( ! TARGET_RISCV ) return false ; for ( rtx_insn * insn = get_insns ( ) ; insn ; insn = next_active_insn ( insn ) ) { if ( CALL_P ( insn ) ) { rtx fndecl = CALL_EXPR_FN ( insn ) ; if ( TREE_CODE ( fndecl ) == FUNCTION_DECL && DECL_VOLATILE ( fndecl ) ) return true ; } } return false ; }


void register_builtin_type ( const char * name , int size , int align , int flags ) { if ( lookup_builtin_type ( name ) != NULL ) return ; struct builtin_type built_in = { 0 } ; built_in . name = name ; built_in . size = size ; built_in . align = align ; built_in . FLAG_SPECIFIC = flags ; register_builtin_type_internal ( & built_in ) ; }


"Registered RVV ABI built-in types for "


void register_function_group ( const char * group ) { rtx code = CODE_FOR_riscv ; for ( int i = 0 ; i < group -> num_functions ; ++ i ) { const char * function = group -> functions [ i ] ; if ( ! lookup_function ( function ) ) { tree decl = build_fn_decl ( function , NULL_TREE , void_type_node ) ; cgraph_node * node = cgraph_node :: create ( decl , DECL_EXTERNAL , NULL ) ; cgraph_add_node ( node ) ; SET_CODE_FOR_FUNCTION ( function , code ) ; } } }


void register_vector_type ( enum machine_mode mode , const char * type_name , unsigned int element_size , unsigned int num_elements , unsigned int riscv_vector_type ) { if ( IS_MACHINE_MODE_INVALID ( mode ) || type_name == NULL || element_size == 0 || num_elements == 0 ) { return ; } if ( find_vector_type ( mode , type_name , element_size , num_elements ) != NULL ) { return ; }


"argument %d of %qE must be an integer constant"


"passing %d to argument %d of %qE, which expects a value in the range [%d, %d]"


bool required_extensions_p ( const_tree type , int target ) { if ( target == TARGET_RISCV ) { if ( TREE_VALUE_REQUIRED_EXTENSIONS ( type ) ) return true ; } return false ; }


void require_immediate ( int argno , int * value_out ) { if ( argno < FIRST_PSEUDO_REGISTER ) { if ( ( REGNO ( argno ) < FIRST_PSEUDO_REGISTER ) && ( REGNO ( argno ) >= 0 ) ) { * value_out = argno ; } else { * value_out = 0 ; } } else { * value_out = 0 ; } }