int require_immediate_range ( int rel_argno , int min , int max ) { if ( ! CONST_INT_P ( rel_argno ) ) { return 0 ; } unsigned HOST_WIDE_INT rel_argno_val = INTVAL ( rel_argno ) ; if ( rel_argno_val >= min && rel_argno_val <= max ) { return 1 ; } else { return 0 ; } }


int ret_mode ( tree type ) { int mode ; enum machine_mode mmode = TYPE_MODE ( type ) ; switch ( mmode ) { case VOIDmode : mode = MODE_VOID ; break ; case BImode : mode = MODE_1BIT_BOOL ; break ; case QImode : mode = MODE_8BIT_SIGNED ; break ; case HImode : mode = MODE_16BIT_SIGNED ; break ; case SImode : mode = MODE_32BIT_SIGNED ; break ; case DImode : mode = MODE_64BIT_SIGNED ; break ; case TImode : mode = MODE_128BIT_SIGNED ; break ; default : mode = MODE_UNKNOWN ; break ; } return mode ; }


bool
sizeless_type_p
(
const_tree
type
)
{
if
(
TYPE_MAIN_VARIANT
(
type
)
==
void_type_node
)
return
true
;
if
(
TYPE_MAIN_VARIANT
(
type
)
==
error_mark_node
)
return
false
;
if
(
TARGET_RISCV
&&
TYPE_MAIN_VARIANT
(
type
)
==
rtx_variadic_type_node
)
{
const
char
*
name
=
IDENTIFIER_POINTER
(
TYPE_NAME
(
type
)
)
;
if
(
strcmp
(
name
,
"RVV sizeless type"
)
==
0
)
return
true
;
}
return
false
;
}


void my_function ( ) { int buffer [ 10 ] ; use_contiguous_load_insn ( riscv , 0 , 0 ) ; load ( buffer , riscv ) ; }


void
use_contiguous_store_insn
(
void
)
{
int
riscv
=
1
;
int
target_specific_value1
=
0
;
int
target_specific_value2
=
0
;
int
target_specific_value3
=
0
;
int
target_specific_value4
=
1
;
asm
volatile
(
"STORE %0, %1, %2, %3"
:
:
"r"
(
riscv
)
,
"r"
(
target_specific_value1
)
,
"r"
(
target_specific_value2
)
,
"r"
(
target_specific_value3
)
,
"r"
(
target_specific_value4
)
:
)
;
}


void use_exact_insn ( rtx_code , rtx_insn * , rtx_insn * * insn_p , int * insntype , rtx * ops , const_rtx value , int nops ) { insn_p = rtx_alloc_code ( rtx_temp , rtx_code , value ) ; insntype = nops ; for ( i = 0 ; i < nops ; i ++ ) { insntype [ i ] = op ; ops [ i ] = p [ i ] ; } return insn_p ; }


bool use_mask_predication_p ( const rtx_insn * insn ) { if ( insn -> mask ) return true ; rtx x = PATTERN ( insn ) ; if ( ! GET_CODE ( x ) == SET || ! GET_CODE ( XEXP ( x , 0 ) ) == SET ) return false ; rtx mask_predicate = XEXP ( x , 1 ) ; if ( ! MEM_P ( mask_predicate ) ) return false ; rtx mask_reg = gen_rtx_REG ( riscv , ( int ) MASK_REG ) ; if ( mask_reg == mask_predicate ) return true ; return false ; }


bool use_real_mask_p ( rtx pred ) { if ( TARGET_RISCV ) { if ( GET_CODE ( pred ) == SET ) { rtx p = SET_SRC ( pred ) ; if ( GET_CODE ( p ) == REG && REGNO ( p ) == TARGET_MACH_REGNUM ) { return true ; } } } return false ; }


bool use_real_merge_p ( rtx_op , enum rtx_type ) { if ( op == REAL_MERGE && rtx_type == RTX_RISCV ) return true ; else return false ; }


void use_scalar_move_insn ( rtx * arguments [ ] , rtx destination , rtx source , rtx icode ) { rtx call_rtx = gen_rtx_CALL ( VOIDmode , gen_rtx_fmt_ee ( icode , destination , source ) ) ; emit_insn ( call_rtx ) ; }


void use_ternop_insn ( rtx_insn * insn , rtx op0 , rtx op1 , rtx op2 ) { rtx ternop_insn ; RTX_CODE icode ; REAL_VALUE_FROM_CONST_DOUBLE ( op0 ) = RTX_ULONG ( op0 ) ; REAL_VALUE_FROM_CONST_DOUBLE ( op1 ) = RTX_ULONG ( op1 ) ; REAL_VALUE_FROM_CONST_DOUBLE ( op2 ) = RTX_ULONG ( op2 ) ; icode = riscv ; ternop_insn = gen_rtx_icode ( icode , op0 , op1 , op2 ) ; replace_rtx ( insn , ternop_insn ) ; }


use_widen_ternop_insn ( rtx_insn * insn ) { rtx pat = PATTERN ( insn ) ; rtx v0_1 , v0_2 , v0_3 ; rtx target_specific_value = gen_rtx_RSIMM ( SImode , riscv , 0 ) ; v0_1 = XEXP ( pat , 0 ) ; v0_2 = XEXP ( pat , 1 ) ; v0_3 = XEXP ( pat , 2 ) ; rtx new_insn = gen_rtx_ternor ( VOIDmode , v0_1 , v0_2 , v0_3 , target_specific_value ) ; RTX_FRAME_UNCHANGING_P ( insn ) ; emit_insn_after ( new_insn , insn ) ; delete_insn ( insn ) ; }


vector_mode ( tree type ) { if ( TARGET_RISCV ) { enum tree_code code = TREE_CODE ( type ) ; switch ( code ) { case bool_type_node : return V2SImode ; case integer_type : case pointer_type : return V4HImode ; case float_type : return V2SFmode ; case double_type : return V1DFmode ; case complex_type : if ( TYPE_PRECISION ( type ) == 32 ) return V4SFmode ; else return V2DFmode ; default : return BLKmode ; } } return BLKmode ; }


bool anticipatable_occurrence_p ( rtx_insn * insn ) { if ( GET_CODE ( insn ) != CODE_FOR_vsetvl ) return false ; rtx rs1 , rd ; rs1 = XEXP ( insn , 0 ) ; rd = XEXP ( insn , 1 ) ; if ( reg_used_between_p ( insn , PATTERN ( insn ) , GET_MODE ( rd ) , insn ) ) return false ; if ( reg_modified_p ( rs1 , insn ) ) return false ; if ( reg_modified_p ( rd , insn ) ) return false ; return true ; }


bool any_set_in_bb_p ( block * BB , riscv set ) { rtx_insn * insn ; for ( insn = BB -> insns ; insn != NULL ; insn = NEXT_INSN ( insn ) ) { if ( INSN_TARGET_SPECIFIC ( insn ) == set ) { return true ; } } return false ; }


bool available_occurrence_p ( rtx_insn * insn ) { rtx rd = NULL , rs1 = NULL ; rtx_ptr_set_t mods_rs1 , mods_rd ; if ( GET_CODE ( insn ) != INSN ) return false ; if ( ! contains_vsetvl ( insn ) ) return false ; rd = XEXP ( insn , 0 ) ; rs1 = XEXP ( insn , 1 ) ; if ( ! REG_P ( rd ) || ! REG_P ( rs1 ) ) return false ; mods_rs1 = new_rtx_ptr_set ( ) ; mods_rd = new_rtx_ptr_set ( ) ; basic_block bb = BLOCK_FOR_INSN ( insn ) ; for ( rtx_insn * tmp = BB_END ( bb ) ; tmp != insn ; tmp = PREV_INSN ( tmp ) ) { if ( GET_CODE ( tmp ) == BARRIER || GET_CODE ( tmp ) == NOTE ) continue ; add_rtx_ptr_set ( mods_rs1 , regs_ever_written ( tmp ) ) ; add_rtx_ptr_set ( mods_rd , regs_ever_written ( tmp ) ) ; if ( rtx_ptr_set_contains ( mods_rs1 , rs1 ) || rtx_ptr_set_contains ( mods_rd , rd ) ) { free_rtx_ptr_set ( mods_rs1 ) ; free_rtx_ptr_set ( mods_rd ) ; return false ; } } free_rtx_ptr_set ( mods_rs1 ) ; free_rtx_ptr_set ( mods_rd ) ; return true ; }


bool backward_propagate_worthwhile_p ( rtx initializer , int target ) { if ( target != RS_BACKEND_RISCV ) { return false ; } unsigned code = GET_CODE ( initializer ) ; if ( code == SET || code == CLOBBER ) { unsigned set_code = GET_CODE ( XEXP ( initializer , 0 ) ) ; if ( set_code == REG ) { int regno = REGNO ( XEXP ( initializer , 0 ) ) ; if ( riscv_callee_saved_register_p ( regno ) ) { return true ; } } } return false ; } bool riscv_callee_saved_register_p ( int regno ) { static const int callee_saved_regs [ ] = { RS_REG_1 , RS_REG_2 , RS_REG_3 , RS_REG_4 , RS_REG_5 , RS_REG_6 , RS_REG_7 , RS_REG_8 , RS_REG_9 , RS_REG_10 , RS_REG_11 , RS_REG_12 } ; int i ; for ( i = 0 ; i < 12 ; i ++ ) { if ( regno == callee_saved_regs [ i ] ) { return true ; } } return false ; }


bool can_refine_vsetvl_p ( int target_specific_value , int current_vsetvl , int num_vector_registers ) { if ( target_specific_value != riscv ) { return false ; } int max_vector_registers = ( int ) log2 ( target_specific_value ) + 1 ; if ( current_vsetvl != max_vector_registers ) { return false ; } return true ; }


void cleanup_illegal_dirty_blocks ( ) { for ( int i = 0 ; i < riscv_target_specific_dirty_blocks . size ( ) ; i ++ ) { if ( riscv_target_specific_dirty_blocks [ i ] . is_illegal && riscv_target_specific_dirty_blocks [ i ] . is_dirty ) { riscv_target_specific_dirty_blocks [ i ] . data = 0 ; riscv_target_specific_dirty_blocks [ i ] . is_dirty = false ; } } }


int compare_lmul ( int lmul1 , int lmul2 ) { if ( lmul1 == lmul2 ) { return 0 ; } else if ( lmul1 < lmul2 ) { return - 1 ; } else { return 1 ; } }


bool
compatible_p
(
instruction
insn
,
vector
<
element
>
require
)
{
if
(
insn
.
target_specific
==
"Can't handle uninitialized info"
)
{
return
false
;
}
for
(
int
i
=
0
;
i
<
require
.
length
(
)
;
i
++
)
{
if
(
require
[
i
]
>
insn
.
vtype
[
i
]
)
{
return
false
;
}
}
return
true
;
}


void compute_local_properties ( rtx_insn * insn ) { rtx_def * def , * use ; rtx_exp * exp ; bool transparent , computed , anticipatable ; for ( def = INSN_P_SET ( insn ) ; def != NULL ; def = DEFS_CHAIN ( def ) ) { transparent = true ; computed = false ; anticipatable = false ; for ( use = DEFS_P_USE ( def ) ; use != NULL ; use = USES_CHAIN ( use ) ) { exp = USE_DEF_EXP ( use ) ; if ( expression_is_modified ( exp , insn ) ) { transparent = false ; break ; } if ( expression_is_computed ( exp , insn ) ) { computed = true ; if ( expression_has_same_value_at_end ( exp , insn ) ) { anticipatable = true ; } if ( expression_has_same_value_at_beginning ( exp , insn ) ) { anticipatable = true ; } } } set_expression_target_value ( insn , exp , "riscv,0,0" ) ; set_expression_flag ( insn , exp , "transparent" , transparent ) ; set_expression_flag ( insn , exp , "computed" , computed ) ; set_expression_flag ( insn , exp , "anticipatable" , anticipatable ) ; } }


const char * extract_single_source ( rtx_insn * insn , int is_real_insn ) { if ( ! is_real_insn ) { return NULL ; } if ( GET_CODE ( insn ) == CALL_INSN ) { return NULL ; } rtx src = XEXP ( insn , 0 ) ; if ( ! src || GET_CODE ( src ) != REG ) { return NULL ; } char reg_num [ 10 ] ; sprintf ( reg_num , "%d" , REGNO ( src ) ) ; const char * source_code = ( const char * ) malloc ( sizeof ( char ) * ( 2 + strlen ( reg_num ) ) ) ; strcpy ( source_code , "r" ) ; strcat ( source_code , reg_num ) ; return source_code ; }


function fault_first_load_p ( riscv_code , target_specific_value ) { if ( riscv_code starts with 00 ) { if ( target_specific_value == 0 ) { return true ; } } return false ; }


void forward_demand_fusion ( rtx_insn * insn ) { uint64_t riscv_specific_value = insn -> insn_atts . riscv_specific_value ; insn -> insn_atts . forward_demanded_info = ... ; }


void get_all_predecessors ( cfg_bb * bb , rtx_insn * insn , rtx_insn * * pred_insn , riscv_insn_code riscv_code ) { int num_preds = PREV_INSN_NUM ( insn ) ; int i ; for ( i = 0 ; i < num_preds ; i ++ ) { rtx_insn * pred = PREV_INSN ( insn , i ) ; if ( pred && GET_CODE ( pred ) == riscv_code ) { pred_insn [ ++ * pred_insn ] = pred ; get_all_predecessors ( bb , pred , pred_insn , riscv_code ) ; } } }


void get_all_sets ( DEF_TYPE def_type ) { if ( def_type . target == riscv ) { if ( def_type . instruction == DEF_INSTRUCTION ) { SETS . push_back ( def_type ) ; } } for ( operand in def_type . operands ) { if ( operand . type == DEF_TYPE ) { get_all_sets ( operand ) ; } } }


int get_default_ta ( ) { int value = 0 ; value |= 0x1 ; value |= ( 0x1 << 4 ) ; value |= ( 1 << 8 ) ; value |= ( 0x1 << 16 ) ; return value ; }


riscv_get_ma ( int mask_op_idx ) { rtx mask_op = XVECEXP ( insn , 0 , mask_op_idx ) ; rtx mask_reg = XEXP ( mask_op , 0 ) ; rtx mask_imm = XEXP ( mask_op , 1 ) ; int mask_imm_value = INTVAL ( mask_imm ) ; rtx ma_rtx ; if ( REG_P ( mask_reg ) ) { ma_rtx = gen_riscv_move_masked ( mask_reg , mask_imm_value ) ; } else if ( CONST_INT_P ( mask_reg ) ) { ma_rtx = gen_riscv_move_masked_imm ( mask_imm_value ) ; } else { ma_rtx = NULL ; } return ma_rtx ; }


double get_ratio ( int machine_mode ) { switch ( machine_mode ) { case MODE_ECO : return 0.5 ; case MODE_PERFORMANCE : return 0.8 ; case MODE_BALANCED : return 0.6 ; default : return 1.0 ; } }


"Unable to retrieve ta value for operand %d\n"


unsigned int get_vl ( unsigned int riscv , unsigned int unused1 , unsigned int unused2 ) { return riscv ; }


uint8_t get_vlmul ( riscv_vector :: vlmul_type vlmul_type , riscv_target target ) { if ( target != riscv ) { } if ( ! vlmul_type . valid ( ) ) { } return vlmul_type . vlmul_value ; }


bool has_vl_op ( rtx_insn * insn ) { rtx target = XEXP ( insn , 0 ) ; if ( GET_CODE ( target ) == REG && REGNO ( target ) == 0 ) { if ( VL_STATUS_REG == NULL ) { return false ; } else if ( VL_STATUS_REG -> global_value == 0 ) { return false ; } else { return true ; } } return false ; }


bool has_vtype_op ( int insn ) { if ( ( insn & 0x7F ) == 0x7F ) { int vtype = __builtin_riscv_x0 ( ) ; if ( vtype >= 0 ) { if ( ( vtype >> 16 ) & 0x1 ) { return true ; } } } return false ; }


bool ignore_vlmul_insn_p ( rtx_insn * insn , int riscv ) { if ( INSN_CODE ( insn ) == CODE_FOR_vlmul ) { rtx vtype = XVECEXP ( insn , 0 , 0 ) ; if ( GET_CODE ( vtype ) == CONST_INT ) { int vtype_val = INTVAL ( vtype ) ; int vlmul = ( vtype_val >> 24 ) & 0xFF ; if ( vlmul == riscv ) return true ; else return false ; } } return false ; } Now , when calling this function , the riscv target specific value can be passed as an argument , for example : if ( ignore_vlmul_insn_p ( insn , 2 ) ) { } else { }


mask_agnostic_p ( rtx op ) { if ( GET_CODE ( op ) == CONST_INT ) { unsigned int value = INTVAL ( op ) ; if ( value == 0 || value == 1 || value == 8 || value == 9 || value == 10 ) return true ; else return false ; } else return false ; }


bool need_vsetvl ( rtx curr_info , rtx require , rtx insn ) { if ( TARGET_RISCV ) { if ( curr_info && require && GET_DEM_INFO ( curr_info ) && GET_DEM_INFO ( require ) ) { if ( GET_DEM_INFO ( curr_info ) != GET_DEM_INFO ( require ) ) { if ( GET_CODE ( insn ) == CODE_FOR_vsetvl ) return true ; } } } return false ; }


"The total VSETVL expression num = %d\n"


bool read_vl_insn_p ( rtx_insn * insn ) { if ( GET_CODE ( insn ) == CODE_FOR_riscv_insn ) { rtx target = XEXP ( insn , 0 ) ; if ( target == CONST0_RTX ( GET_MODE ( insn ) ) ) { return true ; } } return false ; }


scalar_move_insn_p ( rtx insn ) { rtx pat , dest , src ; enum rtx_code code ; if ( ! TARGET_RISCV ) return false ; pat = PATTERN ( insn ) ; if ( ! pat || GET_CODE ( pat ) != INSN ) return false ; dest = XEXP ( pat , 0 ) ; src = XEXP ( pat , 1 ) ; code = GET_CODE ( insn ) ; if ( code == MOV || code == MOVLP || code == MOVLG || code == MOVL ) return true ; if ( ( code == MOVE || code == ZERO_EXTEND || code == SIGN_EXTEND ) && REG_CLASS ( GET_MODE ( dest ) ) == GPR_REGS && REG_CLASS ( GET_MODE ( src ) ) == GPR_REGS ) return true ; if ( code == ZERO_EXTEND && GET_CODE ( src ) == ZERO_EXTEND && REG_P ( XEXP ( src , 0 ) ) && REG_P ( XEXP ( dest , 0 ) ) ) return true ; if ( code == SIGN_EXTEND && GET_CODE ( src ) == SIGN_EXTEND && REG_P ( XEXP ( src , 0 ) ) && REG_P ( XEXP ( dest , 0 ) ) ) return true ; return false ; }


"Entering Simple VSETVL PASS and Handling %d basic blocks for function:%s\n"

"Simple VSETVL PASS completed for function:%s\n"


bool support_relaxed_compatible_p ( ) { return ( default_target_riscv . relaxed_compatible_check ) ; }


bool
tail_agnostic_p
(
riscv_target_specific_val
)
{
if
(
riscv_target_specific_val
!=
"riscv"
)
{
throw
"Not a riscv target specific value"
;
}
else
{
if
(
operand_index
==
"TA"
&&
operand_type
==
"TA"
)
{
return
true
;
}
else
{
return
false
;
}
}
}


void transfer_after ( riscv_state * state , riscv_insn insn ) { riscv_state prev_state = * state ; if ( is_control_transfer ( insn ) ) { riscv_addr target = get_control_transfer_target ( insn ) ; if ( is_within_function ( target ) ) { state -> pc = target ; } else { state -> ra = state -> pc + 4 ; state -> pc = target ; } state -> in_delay_slot = false ; } if ( is_function_call ( insn ) ) { state -> ra = state -> pc + 4 ; state -> in_delay_slot = false ; } if ( is_unconditional_jump ( insn ) ) { state -> in_delay_slot = false ; } if ( is_branch_link ( insn ) ) { state -> ra = state -> pc + 4 ; state -> in_delay_slot = true ; }


riscv_transfer_before ( rtx_insn * insn , rtx_insn_state * state ) { if ( INSN_CODE ( insn ) == CODE_FOR_riscv_add || INSN_CODE ( insn ) == CODE_FOR_riscv_sub ) { rtx op1 = XEXP ( insn , 0 ) ; rtx op2 = XEXP ( insn , 1 ) ; if ( GET_CODE ( op1 ) != REG ) { XEXP ( insn , 0 ) = op2 ; XEXP ( insn , 1 ) = op1 ; } } for ( unsigned int i = 0 ; i < XVECLEN ( insn , 0 ) ; i ++ ) XVEC ( insn , 0 , i ) = gen_reg_rtx ( MODE_INT ) ; }


bool valid_sew_p ( int sew , int vtype_format ) { int sew_value = sew & 0xFF ; int vtype = vtype_format & 0xFF ; if ( sew_value < 0 || sew_value > vtype ) { return false ; } if ( sew_value % 64 != 0 ) { return false ; } return true ; }


vector_config_insn_p ( const_rtx insn , const_rtx * target_attr ) { if ( GET_CODE ( insn ) == CODE_FOR_vsetvl ) { rtx target = XEXP ( insn , 2 ) ; if ( target && GET_CODE ( target ) == CONST_INT && INTVAL ( target ) == 0 ) return true ; } return false ; }


void vl_vtype_info ( ) { set_vl_info ( "riscv" , 0 , riscv_vector :: LMUL_RESERVED , 0 , 0 , 0 ) ; } This function will initialize the VL ( Vector Length ) and VTYPE ( Vector Type ) information for the riscv target architecture . The target specific values used are "riscv" as the architecture , 0 as the default value for VL , the predefined enum value riscv_vector :: LMUL_RESERVED as the default value for LMUL ( Vector LMULtiple ) , and 0 for the default values of SEW ( Vector Element Width ) , VLMUL ( Vector LMULtiple for Vector Element Width ) , and SEW2 ( Vector Element Width Squared ) . The set_vl_info ( ) function is a helper function that will set these values in the backend of GCC Compiler based on the target architecture . The function can be defined in the riscv backend as follows : void set_vl_info ( const char * arch , unsigned int vl , enum riscv_vector :: LMUL lmul , unsigned int sew , unsigned int vlmul , unsigned int sew2 ) { set_vl ( arch , vl ) ; set_lm ( vl , lmul ) ; set_sew ( vl , sew ) ; set_vlmul ( vl , vlmul ) ; set_sew2 ( vl , sew2 ) ; }


function vsetvl_discard_result_insn_p ( instruction_code , target_specific_value ) { if ( instruction_code != vsetvl ) { return false ; } rs1 = extract_rs1 ( instruction_code ) ; if ( rs1 != 0 ) { return false ; } if ( target_specific_value == instruction_code ) { return true ; } return false ; }


bool vsetvl_insn_p ( enum riscv_insn insn ) { ... } ` ` ` Next , we will check if the given instruction is either vsetvldi or vsetvlsi by comparing its value to the target - specific values defined for these instructions in riscv - backend . c file of the GCC Compiler : ` ` ` bool vsetvl_insn_p ( enum riscv_insn insn ) { if ( insn == VSETVLDI || insn == VSETVLSI ) return true ; else return false ; } ` ` ` The enum riscv_insn contains all the RISC - V specific instructions , including vsetvldi and vsetvlsi . This comparison will return true if the given instruction is either of these two instructions , and false otherwise . Finally , we will return the result of this comparison : ` ` ` bool vsetvl_insn_p ( enum riscv_insn insn ) { if ( insn == VSETVLDI || insn == VSETVLSI ) return true ; else return false ; }


function add_all_one_mask_operand ( input_operand , result_type , target_specific_riscv ) { if ( target_specific_riscv != "RV32I" && target_specific_riscv != "RV64I" ) { return input_operand ; } if ( result_type is not vector type ) { return input_operand ; } all_one_mask = create a variable of same data type as input_operand with all bits set to 1 ; updated_operand = __builtin_insert_mask ( all_one_mask , input_operand ) ; return updated_operand ; }


void add_input_operand ( riscv_op_t * op ) { operand_t * new_op = new_operand ( riscv , op -> target_specific_val ) ; M_OPS [ M_NOPS ] = new_op ; M_NOPS ++ ; }


void add_vundef_operand ( rtx_insn * insn , rtx reg_operand , rtx_imm im , int code ) { rtx undef_operand = NULL_RTX ; if ( code == UNSUPPORTED_INTRINSIC_CODE ) { undef_operand = gen_rtx_REG ( VOIDmode , reg_operand ) ; add_insn_var_operand ( insn , reg_operand , im , undef_operand ) ; } }


double calculate_ratio ( int sew , int lmul ) { if ( sew == 0 || lmul == 0 ) { return 0 ; } double ratio = ( double ) sew / ( double ) lmul ; return ratio ; }


bool const_vec_all_same_in_range_p ( rtx x , rtx minval , rtx maxval , rtx riscv ) { rtx_const_vec_element elt = GET_MODE_UNIT_SIZE ( GET_MODE ( x ) ) ; int count = GET_MODE_NUNITS ( GET_MODE ( x ) ) ; if ( ! CONST_VECTOR_P ( x ) ) return false ; for ( int i = 0 ; i < count ; i ++ ) { if ( const_compare_rtx ( minval , elt , XVECEXP ( x , 0 , i ) ) > 0 || const_compare_rtx ( maxval , elt , XVECEXP ( x , 0 , i ) ) < 0 ) return false ; } rtx first = XVECEXP ( x , 0 , 0 ) ; for ( int i = 1 ; i < count ; i ++ ) { if ( const_compare_rtx ( first , elt , XVECEXP ( x , 0 , i ) ) != 0 ) return false ; } if ( riscv ) { } return true ; }


void emit_hard_vlmax_vsetvl ( ) { rtx_insn * insn ; rtx target_riscv = gen_rtx_REG ( Pmode , TARGET_RISCV ) ; if ( ! optimize || optimize_vsetvl_insertion_pass ) { insn = emit_insn ( gen_rtx_SET ( target_riscv , gen_rtx_HARD_REG ( Pmode , VLMAX_VSETVL ) ) ) ; } }


void emit_pred_op ( rtx dest , rtx src ) { rtx insn ; rtx args [ 2 ] ; insn = gen_rtx_SET ( dest , gen_rtx_IDENTIFIER ( "vsetvli" ) , gen_rtx_REG ( RV_REGNUM , VOIDmode ) ) ; args [ 0 ] = src ; args [ 1 ] = gen_rtx_CONST_INT ( mode , 8 ) ; rtx rvv_unmask = gen_rtx_UNSPECV ( RV_OP_VSETVLI , Pmode , gen_rtvec ( 2 , args ) ) ; emit_move_insn ( dest , rvv_unmask ) ; }


"Error: Invalid target specific value for riscv\n"


static rtx_gen_scalar_move_mask ( rtx target , rtx riscv , rtx one , rtx two ) { rtx mask = gen_int_mode ( GET_MODE ( target ) , 0x1 ) ; mask = gen_rtvec ( 3 , mask , riscv , gen_int_mode ( GET_MODE ( target ) , 1 ) ) ; rtx move = gen_rtx_SET ( VOIDmode , target , gen_rtx_CLOBBER ( GET_MODE ( target ) , mask ) ) ; rtx_seq seq = gen_rtx_SEQ ( VOIDmode , move , NULL ) ; return seq ; }


get_avl_type_rtx ( void ) { return "riscv_avl_type_rtx" ; }


uint32_t get_ma ( uint32_t operand , int mask_op_idx ) { uint32_t riscv_target = ; uint32_t mask = ( riscv_target >> ( mask_op_idx * 4 ) ) & 0xF ; if ( mask_op_idx < 0 || mask_op_idx >= 8 ) { return - 1 ; } return operand & mask ; }


int get_prefer_mask_policy ( void ) { return RISCV_PREFER_MASK_POLICY ; }


get_prefer_tail_policy ( ) { target = get_riscv_target ( ) ; policy = target . prefer_tail_policy ; return policy ; }


float get_ratio ( ) { float r = 1.0 ; if ( TARGET_RISCV && TARGET_32BIT ) { r = 0.5 ; } return r ; }


int get_sew ( int SEW ) { int SEW_value ; switch ( SEW ) { case 0 : SEW_value = 8 ; break ; case 1 : SEW_value = 16 ; break ; case 2 : SEW_value = 32 ; break ; case 3 : SEW_value = 64 ; break ; default : SEW_value = 8 ; } return SEW_value ; }


int get_ta ( int tail_op_idx ) { int ta ; switch ( tail_op_idx ) { case 0 : ta = 3 ; break ; case 1 : ta = 5 ; break ; case 2 : ta = 7 ; break ; default : ta = - 1 ; break ; } return ta ; }


enum riscv_vector_mode get_vector_mode ( enum machine_mode inner_mode , int nunits ) { switch ( inner_mode ) { case V4SI : switch ( nunits ) { case 1 : return FIRST_MODE ; case 2 : return SEW2 ; case 4 : return SEW4 ; default : return UNKNOWN_MODE ; } case V2DI : if ( nunits == 2 ) { return SEW8 ; } return UNKNOWN_MODE ; case V8SF : switch ( nunits ) { case 1 : return SEW32 ; case 2 : return SEGSEW2 ; case 4 : return SEGSEW4 ; case 8 : return SEGSEW8 ; default : return UNKNOWN_MODE ; } case V4DF : switch ( nunits ) { case 1 : return SEGSEW64 ; case 2 : return SEGSEW16 ; case 4 : return SEGSEW32 ; case 8 : return SEGSEW64 ; default : return UNKNOWN_MODE ; } default : return UNKNOWN_MODE ; } }


void legitimize_move ( rtx_insn * insn , rtx * dest , rtx * src ) { enum machine_mode mode = GET_MODE ( * dest ) ; enum riscv_vec_type vec_type ; if ( TARGET_RVV ) { switch ( mode ) { case V4SFmode : vec_type = RISCV_VEC_V ; break ; case V2DFmode : vec_type = RISCV_VEC_VF ; break ; default : return ; } if ( rtx_equal_p ( * dest , * src ) ) { * src = gen_rtx_REG ( mode , 0 ) ; } * dest = gen_rtx_VEC_MOVE ( vec_type , * dest , * src ) ; if ( ! satisfies_constraint ( * dest , VEC_MOVE_CONSTRAINT ) ) { * dest = gen_rtx_VEC_LOAD ( vec_type , * src ) ; * dest = gen_rtx_VEC_STORE ( vec_type , * src , * dest ) ; } } }


int riscv_address_insns ( mode , X , MIGHT_SPLIT_P ) { if ( ! valid_address ( mode , X ) ) { return 0 ; }


int riscv_binary_cost ( int X , bool double_word ) { int SINGLE_INSNS = 2 ; int DOUBLE_INSNS = 4 ; int target = 2 ; int cost = 0 ; if ( double_word ) { cost = DOUBLE_INSNS * target ; } else { cost = SINGLE_INSNS * target ; } return cost ; }


void riscv_block_move_loop ( void * src , void * dest , size_t length ) { size_t bytes_per_iter = __riscv . get_target_specific_value ( ) ; if ( length < bytes_per_iter ) { return ; } char * src_ptr = ( char * ) src , * dest_ptr = ( char * ) dest ; size_t i = 0 ; for ( i = 0 ; i < length ; i += bytes_per_iter ) { __riscv . memcpy ( dest_ptr , src_ptr , bytes_per_iter ) ; src_ptr += bytes_per_iter ; dest_ptr += bytes_per_iter ; } }


void riscv_cannot_force_const_mem ( int riscv , int unused ) { if ( riscv == riscv ) { SET_FLAG ( TARGET_CANNOT_FORCE_CONST_MEM , true ) ; } }


bool riscv_classify_address ( rtx x , enum machine_mode mode , int strict_p , rtx_info * info ) { if ( mode == VOIDmode ) return false ; int target_value = GET_MODE_TARGET_SPECIFIC_VALUE ( mode ) ; if ( target_value != 0x100101 ) return false ; if ( strict_p ) { if ( ! REG_OK_STRICT ) return false ; } if ( REG_P ( x ) ) info -> reg_ok = true ; if ( MEM_P ( x ) ) info -> mem_ok = true ; return true ; }


int riscv_class_max_nregs ( riscv_specific_struct target , int default_value ) { if ( ! target ) return default_value ; if ( target -> class_max_nregs ) return target -> class_max_nregs ; else return default_value ; }


void riscv_components_for_bb ( void ) { targetm . shrink_wrap_components_for_bb = & riscv_shrink_wrap_components_for_bb ; }


int riscv_conditional_register_usage ( int mode , int low , int high ) { if ( mode == 16 ) { for ( int i = low ; i <= high ; i ++ ) { TARGET_CONDITIONAL_REGISTER_USAGE ( riscv , i ) = 1 ; } } else if ( mode == 31 ) { for ( int i = 1 ; i <= high ; i ++ ) { if ( i != 0 ) { TARGET_CONDITIONAL_REGISTER_USAGE ( riscv , i ) = 1 ; } } } else { return 1 ; } }


void riscv_disqualify_components ( ) { if ( TARGET_RISCV ) { disqualify_component ( "a" , "b" ) ; disqualify_component ( "c" , "d" ) ; disqualify_component ( "e" , "f" ) ; } }


riscv_dwarf_poly_indeterminate_value ( const char * value ) { const char * suffix = ",riscv,1,1" ; size_t value_len = strlen ( value ) ; size_t suffix_len = strlen ( suffix ) ; char * result = ( char * ) malloc ( value_len + suffix_len + 1 ) ; strcpy ( result , value ) ; strcat ( result , suffix ) ; return result ; }


"\tlw %s, %d(%sp) // Restore saved register %s\n"

"\taddi %sp, %sp, %d // Restore stack pointer\n"

"\tlw %ra, %d(%sp) // Restore return address\n"


"Invalid comparison code for riscv_emit_int_order_test."


void riscv_excess_precision ( ) { # ifdef __riscv_zfh FLT_EVAL_METHOD = 16 ; # else FLT_EVAL_METHOD = 0 ; # endif }


int riscv_expand_conditional_move ( rtx dest , rtx cond , rtx cons , rtx alt ) { if ( cond ) { emit_move_insn ( dest , cons ) ; } else { emit_move_insn ( dest , alt ) ; } if ( GET_CODE ( dest ) != REG && GET_CODE ( dest ) != SUBREG ) { return 0 ; } return 1 ; }


riscv_file_start
(
void
)
{
fputs
(
"\t.option %spic\n"
,
asm_out_file
)
;
fputs
(
""
,
asm_out_file
)
;
fputs
(
"\n"
,
asm_out_file
)
;
fputs
(
"no"
,
asm_out_file
)
;
fputs
(
"\t.option norelax\n"
,
asm_out_file
)
;
fputs
(
"\t.option csr-check\n"
,
asm_out_file
)
;
}


riscv_floatn_mode ( void ) { return GET_MODE ( FLOATN_TYPE , TARGET_FLOAT_FORMAT , TARGET_FLOAT_MODEL , FLOAT_SIZE , riscv , 16 ) ; }


void riscv_for_each_saved_reg ( void ( * FN ) ( int ) , int SP_OFFSET ) { int num_registers = 4 ; for ( int i = 0 ; i < num_registers ; i ++ ) { int reg_offset = SP_OFFSET + i * 4 ; FN ( reg_offset ) ; } }


riscv_hard_regno_mode_ok ( unsigned int hard_regno , unsigned int mode ) { if ( hard_regno >= RISC_NR_REGS ) return false ; if ( ! ( ( mode == 0 ) || ( mode == 1 ) || ( mode == 2 ) || ( mode == 3 ) ) ) return false ; if ( riscv_target_reg_modes [ hard_regno ] [ mode ] != 1 ) return false ; return true ; }


int riscv_hard_regno_nregs ( int regno ) { if ( regno == 1 ) { return 1 ; } else { return 1 ; } }


int riscv_initial_elimination_offset ( enum reg_class from , enum reg_class to ) { int offset ; if ( from == FP_REG_CLASS || from == ARG_REG_CLASS ) { if ( to == SP_REG_CLASS || to == HARD_FP_REG_CLASS ) { offset = riscv , 0 ; return offset ; } } return - 1 ; }


bool riscv_is_eh_return_data_register ( int regno ) { if ( TARGET_RISCV && regno == 0 ) { return true ; } else { return false ; } }


switch ( GET_CODE ( insn ) ) { case CODE_FOR_LOAD : break ; case CODE_FOR_STORE : break ; default : break ; } ` ` ` 6. For the load instruction , you can use the GET_MODE ( ) macro to check if the mode of the instruction matches the target specific value : ` ` ` if ( GET_MODE ( insn ) == mode ) { num_insns ++ ; } ` ` ` 7. For the store instruction , you can use the SAME_MODE_P ( ) macro to check if the source and target modes match and then increment the num_insns variable by 1. ` ` ` if ( SAME_MODE_P ( GET_MODE ( insn ) , mode ) ) { num_insns ++ ; }


const char * riscv_mangle_type ( const char * riscv , int num_bits , const char * prefix , int vector_mangle ) { if ( riscv == NULL || num_bits <= 0 || prefix == NULL ) return NULL ; const char * target_value = "DF16_" ; int buffer_len = strlen ( riscv ) + num_bits + strlen ( prefix ) + strlen ( target_value ) + 1 ; char * mangled_type = ( char * ) malloc ( buffer_len ) ; sprintf ( mangled_type , "%s%d%s%s%s" , riscv , num_bits , prefix , target_value , vector_mangle ) ; return mangled_type ; }


void
riscv_move_integer
(
int
*
DEST
,
int
VALUE
,
int
TEMP
)
{
__asm__
volatile
(
"mv %0, %1"
:
:
"r"
(
TEMP
)
,
"i"
(
riscv
,
2
,
0
,
0
,
0
,
1
)
)
;
__asm__
volatile
(
"mv %0, %1"
:
:
"r"
(
DEST
)
,
"r"
(
TEMP
)
,
"i"
(
riscv
,
2
,
0
,
0
,
0
,
1
)
)
;
}


int riscv_next_saved_reg ( int regno , int limit , int offset , int inc ) { int next_regno ; if ( regno >= limit ) { return INVALID_REGNUM ; } if ( inc ) { regno ++ ; } next_regno = ( regno + offset ) % NUM_REGS ; if ( next_regno >= limit ) { return INVALID_REGNUM ; } return next_regno ; }


void riscv_pass_by_reference ( unsigned int target , unsigned int intConst , unsigned int intConst2 ) { TARGET_PASS_BY_REFERENCE ( target , intConst , intConst2 ) ; }


int riscv_print_operand_punct_valid_p ( const char * str , int len , int index ) { if ( str [ index ] == 'a' || str [ index ] == 't' || str [ index ] == 's' ) { return 0 ; } return 1 ; }


bool in ATTRIBUTE_UNUSED , bool out ATTRIBUTE_UNUSED ) { if ( rclass == RISCV_GP_REGS ) return 8 ; else return 2 ; }


int riscv_regmode_natural_size ( int regmode ) { switch ( regmode ) { case CC_REGMODE : return 1 ; case QI_REGMODE : return 1 ; case HI_REGMODE : return 2 ; case SI_REGMODE : return 4 ; case DI_REGMODE : return 8 ; case TI_REGMODE : return 16 ; case BI_REGMODE : return 32 ; case XI_REGMODE : return 64 ; case VI_REGMODE : return 128 ; default : return 0 ; } }


const char * riscv_report_v_required ( const char * target , bool isa_enabled ) { if ( isa_enabled ) { return ; } return error_message ; }


riscv_scalar_mode_supported_p ( void ) { if ( TARGET_RISCV ) return true ; return false ; }


int riscv_secondary_memory_needed ( int riscv ) { if ( riscv != TARGET_RISCV ) return - 1 ; int int_reg_size = 32 ; int float_reg_size = 64 ; int words_needed = float_reg_size / int_reg_size ; return words_needed * NUM_FLOAT_REGS ; }


void riscv_setup_incoming_varargs ( struct gcc_target * target , tree args , rtx named_rdregs ) { target -> varargs . type = TARGET_VARARGS_RISCV ; target -> varargs . mode = 0 ; target -> varargs . named_rdregs = 0 ; }


riscv_set_return_address ( rtx address , rtx scratch ) { emit_move_insn ( insn , GEN_REG_RTX ( REG_R1 , ADDRESS ) ) ; if ( scratch && REGNO ( scratch ) != REG_R1 ) { emit_move_insn ( insn , GEN_REG_RTX ( REGNO ( scratch ) , REG_R1 ) ) ; } emit_insn_before ( insn , GEN_INSN_SET_RETURN_ADDRESS ( REG_R1 ) ) ; if ( scratch && REGNO ( scratch ) != REG_R1 ) { emit_move_insn ( insn , GEN_REG_RTX ( REG_R1 , REGNO ( scratch ) ) ) ; } if ( scratch && REGNO ( scratch ) != REG_R1 ) { emit_insn_before ( insn , GEN_INSN_RESTORE_SCRATCH_REGISTER ( scratch ) ) ; } }


bool riscv_shamt_matches_mask_p ( unsigned int shamt , unsigned int bitmask ) { int leading_zeros = __builtin_clz ( bitmask ) ; if ( shamt > leading_zeros ) { unsigned int shifted_mask = bitmask >> ( shamt - leading_zeros ) ; if ( shifted_mask == 0 ) { return true ; } } return false ; }


bool riscv_valid_lo_sum_p ( enum machine_mode mode , rtx lo_sum_rtx , enum rtx_code lo_sum_code ) { if ( lo_sum_code != 0 && lo_sum_code != 1 && lo_sum_code != 2 ) { return false ; } if ( mode == DImode && lo_sum_rtx == ADDR_DIFF_EXPR ) { return true ; } return false ; }


bool riscv_valid_offset_p ( rtx base_reg , enum machine_mode mode ) { if ( base_reg -> code != REG ) return false ; if ( base_reg -> mode != P mode ) return false ; if ( ! RISCv_MODE_P ( mode ) ) return false ; if ( ( base_reg -> offset / BITS_PER_UNIT ) % GET_MODE_SIZE ( mode ) != 0 ) return false ; return true ; }


bool riscv_vector_mode_supported_p ( int mode ) { switch ( mode ) { case VECTOR_MODE_DI : case VECTOR_MODE_TI : case VECTOR_MODE_DD : case VECTOR_MODE_TD : return true ; default : return false ; } }


"Invalid type context for RISC-V architecture"

"Invalid type context for RISC-V vector operations"


riscv_v_adjust_bytesize ( machine_mode mode , rtx op ) { int byte_size = 0 ; if ( TARGET_RISCV && TARGET_RISC_V1 ) { switch ( mode ) { case VOIDmode : case CCmode : case EImode : case OImode : case ZImode : case BLmode : case BImode : case TImode : byte_size = 1 ; break ; case HImode : case QImode : case HImode : byte_size = 2 ; break ; case SImode : case DImode : case SFmode : byte_size = 4 ; break ; case DFmode : byte_size = 8 ; break ; case TFmode : byte_size = 10 ; break ; } } return byte_size ; }


extern inline unsigned int riscv_v_adjust_precision ( machine_mode mode ) { switch ( mode ) { case TFmode : return 32 ; case DFmode : return 64 ; case SDImode : return 32 ; case DDImode : return 64 ; default : return 0 ; } }


bool riscv_v_ext_vector_mode_p ( const char * mode ) { if ( strcmp ( mode , "VNx1DI" ) == 0 ) { if ( MIN_VLEN == 32 ) { return false ; } } else if ( strcmp ( mode , "VNx1SI" ) == 0 ) { if ( MIN_VLEN == 32 ) { return true ; } } return false ; }


\
begin
{
minted
}
{
c
}
unsigned
int
riscv_zero_call_used_regs
(
unsigned
int
need_zeroed_hardregs
)
{
unsigned
int
zeroed_hardregs
=
0
;
for
(
unsigned
int
i
=
0
;
i
<
NEED_ZEROED_HARDREGS
;
i
++
)
{
unsigned
int
curr_hardreg
=
(
1
<<
i
)
;
if
(
need_zeroed_hardregs
&
curr_hardreg
)
{
gen_insn
(
"xor %0, %0, %0"
,
curr_hardreg
)
;
zeroed_hardregs
|=
curr_hardreg
;
}
}
return
zeroed_hardregs
;
}


int riscv_address_insns ( mode , address , MIGHT_SPLIT_P ) { if ( MIGHT_SPLIT_P ) { int num_instructions = 0 ; int remaining_bits = mode . bytes * 8 ; while ( remaining_bits > 0 ) { if ( address is not valid for mode ) { return 0 ; } int word_size = min ( remaining_bits , 32 ) ; int word_instructions = calculate_word_instructions ( mode , address , word_size ) ; num_instructions = num_instructions + word_instructions ; remaining_bits = remaining_bits - word_size ; address = address + ( word_size / 8 ) ; } return num_instructions ; } else { if ( address is not valid for mode ) { return 0 ; } else { return calculate_word_instructions ( mode , address , mode . bytes * 8 ) ; } } } int calculate_word_instructions ( mode , address , word_size ) { if ( mode is floating point mode ) { return 1 ; } else { switch ( word_size ) { case 8 : return 1 ; case 16 : return 1 ; case 32 : return 1 ; default : return ( word_size / 32 ) ; } } }


riscv_add_offset ( rtx reg , rtx offset , rtx temp ) { if ( GET_CODE ( offset ) == CONST_INT && INTVAL ( offset ) >= - 2048 && INTVAL ( offset ) <= 2047 ) { return gen_rtx_PLUS ( Pmode , reg , offset ) ; } else { return riscv_force_temporary ( reg , offset , temp , riscv ) ; } }


unsigned int riscv_arg_partial_bytes ( int target , int alignment ) { if ( target == RISCV && alignment == 4 ) { return 2 ; } else { return 0 ; } }


int riscv_build_integer ( rtl codes [ ] , int value ) { int count = 0 ; codes [ count ++ ] = riscv_insn_load_immediate ( riscv_get_register ( 0 ) , 0 ) ; codes [ count ++ ] = riscv_insn_addi ( riscv_get_register ( 1 ) , riscv_get_register ( 0 ) , value ) ; codes [ count ++ ] = riscv_insn_addi ( riscv_get_register ( 2 ) , riscv_get_register ( 1 ) , 1 ) ; return count ; }


bool riscv_cannot_force_const_mem ( riscv target , const_rtx mem ) { if ( target == 0 ) { return true ; } if ( CONST_INT_P ( mem ) ) { if ( ! memory_address_ok_for_ldr ( XEXP ( mem , 0 ) , GET_MODE ( mem ) ) ) { return true ; } } return false ; }


bool riscv_canonicalize_int_order_test ( rtx * cmp1 , enum machine_mode mode , rtx * code ) { int target_value = 1 ; if ( * code == target_value && * cmp1 == target_value ) { * code = * cmp1 = target_value ; return true ; } else if ( * code == target_value && * cmp1 != target_value ) { * code = * cmp1 = target_value ; return true ; } return false ; }


riscv_can_use_return_insn ( const char * fnname ) { if ( TARGET_IS_RISCV ) { rtx return_addr = get_last_insn_with_type ( CALL_INSN , NULL_RTX ) ; rtx stack_ptr = get_last_insn_with_type ( STACK_POINTER_REG , NULL_RTX ) ; if ( ! return_addr || ! stack_ptr ) return true ; } return false ; }


riscv_classify_address ( machine_mode mode , rtx x , bool strict_p , rtx * info ) { rtx addr = XEXP ( x , 0 ) ; enum rtx_code op = GET_CODE ( addr ) ; if ( op != PLUS ) return false ; rtx reg = XEXP ( addr , 0 ) ; rtx offset = XEXP ( addr , 1 ) ; if ( ! riscv_valid_reg_for_mode_p ( reg , mode ) ) return false ; if ( ! riscv_valid_offset_for_mode_p ( offset , mode ) ) return false ; if ( strict_p && riscv_reg_ok_strict_p ( reg ) ) return false ; * info = gen_rtx_MEM ( mode , reg , offset ) ; return true ; }


void
riscv_class_max_nregs
(
riscv_target
target
,
int
value
)
{
if
(
target
!=
riscv
)
{
printf
(
"ERROR: Target is not riscv"
)
;
return
;
}
CLASS_MAX_NREGS
=
value
;
}


bool riscv_conditional_register_usage ( riscv_target_state * state , bool is_riscv1 ) { if ( is_riscv1 ) { state -> flags |= RISCV_COND_REGISTER ; return true ; } return true ; }


void riscv_emit_int_order_test ( rtx CMP0 , rtx CMP1 , rtx TARGET , rtx INVERT_PTR ) { rtx temp_target ; temp_target = gen_reg_rtx ( Pmode ) ; emit_insn ( gen_cmp ( temp_target , CMP0 , CMP1 ) ) ; emit_insn ( gen_setcc ( TARGET , compare_mode , temp_target ) ) ; if ( INVERT_PTR != NULL ) { rtx inverted_target ; inverted_target = gen_reg_rtx ( QImode ) ; emit_insn ( gen_xor ( inverted_target , TARGET , GEN_INT ( 1 ) ) ) ; emit_insn ( gen_setcc ( INVERT_PTR , compare_mode , inverted_target ) ) ; } }


riscv_force_address ( rtx x , enum machine_mode mode ) { if ( x && ADDRESS_P ( x ) && GET_MODE ( x ) == mode ) return x ; rtx reg = gen_reg_rtx ( mode ) ; rtx insn = gen_rtx_SET ( VOIDmode , reg , x ) ; emit_insn ( insn ) ; return reg ; }


riscv_force_binary ( int code , rtx x , rtx y , enum mode mode ) { rtx result , op1 , op2 ; result = gen_rtx_REG ( mode , gen_reg_rtx ( mode ) ) ; switch ( code ) { case PLUS : op1 = x ; op2 = y ; break ; case MINUS : op1 = x ; op2 = y ; break ; case MULT : op1 = x ; op2 = y ; break ; case DIV : op1 = x ; op2 = y ; break ; case AND : op1 = x ; op2 = y ; break ; case OR : op1 = x ; op2 = y ; break ; case XOR : op1 = x ; op2 = y ; break ; case LSHIFT : op1 = x ; op2 = y ; break ; case RSHIFT : op1 = x ; op2 = y ; break ; case ASHIFT : op1 = x ; op2 = y ; break ; default : gcc_unreachable ( ) ; } switch ( GET_CODE ( op1 ) ) { case CONST_INT : result = gen_rtx_CONST ( mode , op1 ) ; break ; case CONST_FLOAT : result = gen_rtx_CONST ( mode , op1 ) ; break ; case CONST_DOUBLE : result = gen_rtx_CONST ( mode , op1 ) ; break ; case REG : result = gen_rtx_REG ( mode , op1 ) ; break ; default : gcc_unreachable ( ) ; } return result ; }


riscv_force_temporary ( DEST , VALUE , TARGET_SPECIFIC ) { if ( TARGET_SPECIFIC ) { new_register = create_new_register ( ) ; copy_value_to_register ( new_register , VALUE ) ; return new_register ; } else { copy_value_to_register ( DEST , VALUE ) ; return DEST ; } }


void riscv_for_each_saved_reg ( fn_type fn , int sp_off , int target ) { int start_reg = BP_REGNUM ; int end_reg = SP_REGNUM ; for ( int reg = start_reg ; reg <= end_reg ; reg ++ ) { fn ( reg , sp_off ) ; } }


riscv_function_arg ( int arg_size , enum machine_mode type , int type_align , int named ) { rtx ret ; if ( arg_size == 8 ) { if ( type == SFmode || type == DFmode || type == XFmode ) ret = DFmode ; else ret = SImode ; } else if ( arg_size == 4 ) { if ( type == SFmode || type == DFmode || type == XFmode ) ret = SFmode ; else ret = word_mode ; } else if ( arg_size == 2 ) { if ( type == SFmode || type == DFmode || type == XFmode ) ret = THImode ; else ret = HImode ; } else if ( arg_size == 1 ) { if ( type == SFmode || type == DFmode || type == XFmode ) ret = QImode ; else ret = BLKmode ; } else { gcc_unreachable ( ) ; } if ( TYPE_ALIGN ( type ) > type_align ) ret = ATTRIBUTE_MODE_FORCES_REG ( ret ) ; return ret ; }


int riscv_function_arg_advance ( CUMULATIVE_ARGS * cum , int n ) { int i = cum -> num_gprs ; if ( n < 8 ) { cum -> gprs [ i ] = n ; cum -> regno_reg_rtx [ n ] = gen_rtx_REG ( Pmode , i ++ ) ; } else i += 8 ; cum -> num_gprs = i ; return i ; }


int riscv_function_arg_boundary ( void ) { return STACK_BOUNDARY ; }


riscv_function_ok_for_sibcall ( void ) { return true ; }


VALTYPE riscv_function_value ( VALTYPE valtype , MODE mode , int targetspec ) { if ( valtype != null ) { VALTYPE function_value = riscv_compute_function_value ( valtype , mode ) ; return function_value ; } else { VALTYPE function_value = riscv_compute_function_value ( null , mode , targetspec ) ; return function_value ; } }


bool riscv_hard_regno_mode_ok_p ( unsigned regno , machine_mode mode ) { if ( GET_MODE_SIZE ( mode ) > 32 ) return false ; if ( regno >= 32 ) return false ; if ( TARGET_RISCV_11_1_1 ) return true ; if ( TARGET_RISCV_11_1_0_OR_1 ) { unsigned bitmap = ( TARGET_RISCV_11_1_0_OR_1 >> regno ) & 1 ; return ( ( bitmap >> GET_MODE_BITSIZE ( mode ) ) & 1 ) != 0 ; } return false ; }


int riscv_hard_regno_nregs ( int HARD_REGNO ) { switch ( HARD_REGNO ) { case 1 : return 1 ; default : return 0 ; } }


bool riscv_leaf_function_p ( const_tree decl ) { if ( memoized_flag != - 1 ) return memoized_flag ; int target_specific_value = TARGET_DEFAULT ( riscv_leaf_function_p ) ; if ( target_specific_value == 0 ) { memoized_flag = 1 ; } else { memoized_flag = 0 ; } return memoized_flag ; }


riscv_legitimate_constant_p ( const_tree ptr , const_tree value ) { if ( ptr == value ) return true ; else return false ; }


tree riscv_legitimize_address ( enum machine_mode mode , rtx x ) { if ( legitimate_address_p ( mode , x ) ) return x ; if ( CONSTANT_ADDRESS_P ( x ) ) { HOST_WIDE_INT addr = INTVAL ( x ) ; if ( addr >= 0 && addr <= 0xFFFFFFFF ) { return gen_rtx_ADDR ( mode , GEN_INT ( addr | ( 1 << 31 ) ) ) ; } } return NULL ; }


void riscv_legitimize_const_move ( rtx dest , rtx src ) { if ( ! immediate_operand ( src , QImode ) ) return ; gcc_assert ( ! move_operand ( src , VOIDmode ) ) ; rtx new_insn = gen_rtx_SET ( VOIDmode , dest , src ) ; riscv_state . riscv = 0 ; riscv_state . const_value = 0 ; emit_insn ( new_insn ) ; }


void riscv_legitimize_move ( rtx dest , rtx src ) { if ( ! set_destination ( dest , src ) emit_insn ( gen_rtx_SET ( VOIDmode , dest , src ) ) ; else { if ( ! riscv_validate_move ( dest , src ) ) { rtx new_dest , new_src ; riscv_get_equivalent_move ( dest , src , new_dest , new_src ) ; emit_insn ( gen_rtx_SET ( VOIDmode , new_dest , new_src ) ) ; } } }


riscv_load_store_insns ( rtx insn , rtx mem ) { int num_insns = 0 ; enum rtx_code code = GET_CODE ( insn ) ; if ( code == LOAD ) { rtx addr_mode = XEXP ( XEXP ( insn , 0 ) , 0 ) ; if ( GET_CODE ( addr_mode ) == CONST_INT ) { int riscv = riscv_md_const_int ( INSN , 'r' ) ; int bits = riscv_md_const_int ( INSN , 'b' ) ; int radix = riscv_md_const_int ( INSN , 'x' ) ; num_insns = calculate_num_insns ( riscv , bits , radix ) ; } }


void riscv_move_integer ( rtx dest , rtx value ) { rtx temp = riscv_force_temporary ( dest , 2 , 0 , 1 ) ; emit_move_insn ( temp , value ) ; emit_move_insn ( dest , temp ) ; }


"-mdiv requires -march to subsume the %<M%> extension\n"


unsigned char riscv_output_move ( rtx dest , rtx src ) { unsigned char val ; int dest_size , src_size ; if ( GET_CODE ( src ) == CONST_INT ) { if ( ( dest_size = GET_MODE_SIZE ( GET_MODE ( dest ) ) ) < 8 ) { if ( abs_int_val ( INTVAL ( src ) ) >= ( 1LL << ( 8 * dest_size - 1 ) ) ) { val = GEN_INT ( INTVAL ( src ) >> ( 8 * ( 8 - dest_size ) ) ) ; } else { val = src ; } } else { val = src ; } } else if ( GET_CODE ( src ) == CONST_DOUBLE ) { if ( FP_REG_P ( dest ) ) { val = GEN_INT ( 0 ) ; } else { rtx temp ; val = NULL_RTX ; switch ( GET_MODE_SIZE ( GET_MODE ( dest ) ) ) { case 4 : temp = gen_lowpart ( SImode , src ) ; val = force_operand ( temp , dest ) ; break ; case 8 : temp = const0_rtx ; break ; case 16 : temp = gen_rtx_CONST_DOUBLE ( GET_MODE ( src ) , 0.0L ) ; break ; case 24 : temp = gen_rtx_CONST_DOUBLE ( GET_MODE ( src ) , - 0.0L ) ; break ; default : break ; } instruct = rs6000_output_move_const ( dest , temp ) ; } } else { dest_size = GET_MODE_SIZE ( GET_MODE ( dest ) ) ; src_size = GET_MODE_SIZE ( GET_MODE ( src ) ) ; if ( dest_size == src_size ) { val = rs6000_output_move_lui_or_lla ( dest , src ) ; } else { val = NULL_RTX ; } } return val ; }


riscv_cpu_info
riscv_parse_cpu
(
const
char
*
name
)
{
int
i
;
for
(
i
=
0
;
i
<
NUM_RISCV_CPU_INFO_ENTRIES
;
i
++
)
{
if
(
strcmp
(
riscv_cpu_info_table
[
i
]
.
cpu_name
,
name
)
==
0
)
{
return
riscv_cpu_info_table
[
i
]
;
}
}
riscv_cpu_info
unknown_cpu_info
;
unknown_cpu_info
.
issuer_id
=
"riscv"
;
unknown_cpu_info
.
vers_major
=
0
;
unknown_cpu_info
.
vers_minor
=
0
;
unknown_cpu_info
.
cpu_name
=
"unknown cpu"
;
unknown_cpu_info
.
target_specific_value
=
"unknown cpu %qs for -mtune"
;
return
unknown_cpu_info
;
}


int riscv_pass_aggregate_in_fpr_and_gpr_p ( tree type , tree * fields ) { if ( ! TREE_CODE_IS ( type , RECORD_TYPE ) ) { return 0 ; } if ( TYPE_RISCV_AND_VAL ( type ) != TYPE_RISCV_AND_VAL ( TYPE_MAIN_VARIANT ( TREE_TYPE ( type ) ) ) ) { return 0 ; } if ( TYPE_NFIELDS ( type ) < 2 ) { return 0 ; }


riscv_pass_aggregate_in_fpr_pair_p ( tree type , tree * fields ) { if ( TREE_CODE ( type ) != RECORD_TYPE && TREE_CODE ( type ) != UNION_TYPE ) return 0 ; if ( ! TYPE_HAS_FIELDS ( type ) ) return 0 ; * fields = NULL ; int num_fields = TYPE_FIELDS ( type ) ; * fields = ( tree ) calloc ( num_fields , sizeof ( tree ) ) ; if ( * fields == NULL ) return 0 ; if ( riscv_pass_aggregate_fits_in_fpr_pair ( type ) ) { int i ; for ( i = 0 ; i < num_fields ; i ++ ) { ( * fields ) [ i ] = TYPE_FIELDS ( type ) [ i ] ; } return 1 ; } else { free ( * fields ) ; * fields = NULL ; return 0 ; } } int riscv_pass_aggregate_fits_in_fpr_pair ( tree type ) { if ( TARGET_RISCV && get_fields_riscv ( type ) == 2 && get_array_fields_riscv ( type ) == 0 && get_union_handler_riscv ( type ) == 0 && get_padding_riscv ( type ) == 0 && get_incoming_args_riscv ( type ) == 0 ) return 1 ; return 0 ; }


bool as_return , bool result_in_memory ) { rtx mode = TYPE_MODE ( type ) ; if ( type_biggest_mode ( type ) > Pmode ) return true ; if ( GET_CLASS_NROWS ( GET_MODE_ALIGNMENT ( mode ) ) > 1 ) return as_return ; if ( GET_MODE_SIZE ( mode ) < riscv_0_2 ) return true ; return default_pass_by_reference ( type , decl , as_return , result_in_memory ) ; }


rtx offset2 , rtx mode2 ) { rtx_pair pair = gen_rtreg_pair ( regno , REGNO + 1 , mode ) ; rtx v1 , v2 ; v1 = gen_rtx_MEM ( mode , gen_rtx_REG ( mode1 , offset1 ) ) ; v2 = gen_rtx_MEM ( mode , gen_rtx_REG ( mode2 , offset2 ) ) ; return gen_lowpart ( mode , gen_rtx_PAIR ( pair , v1 , v2 ) ) ; }


riscv_pass_fpr_single ( enum machine_mode value_mode , enum machine_mode type_mode ) { rtx arg ; if ( type_mode == BLKmode && value_mode == SFmode ) { return gen_rtx_REG ( SFmode , riscv_fprstart + riscv_struct_float_reg ) ; } else { return gen_rtx_REG ( value_mode , riscv_fprstart + riscv_single_fpr_offset ( value_mode ) ) ; } }


int riscv_pass_mode_in_fpr_p ( enum machine_mode mode ) { switch ( mode ) { case SFmode : case DFmode : return ( mode == SFmode ) ? 1 : 2 ; default : return 0 ; } }


void
riscv_print_operand
(
FILE
*
file
,
rtx
op
,
int
code
)
{
switch
(
code
)
{
case
'h'
:
fprintf
(
file
,
"%d"
,
RISC_CODE
(
op
)
)
;
break
;
case
'R'
:
fprintf
(
file
,
"%d"
,
RISC_CODE
(
op
)
)
;
break
;
case
'C'
:
switch
(
RISC_CODE
(
op
)
)
{
case
RISCV_ICMP_EQ
:
fprintf
(
file
,
"beq .%s"
,
XSTR
(
COND
,
0
)
)
;
break
;
case
RISCV_ICMP_NE
:
fprintf
(
file
,
"bne .%s"
,
XSTR
(
COND
,
0
)
)
;
break
;
case
RISCV_ICMP_LT
:
fprintf
(
file
,
"blt .%s"
,
XSTR
(
COND
,
0
)
)
;
break
;
case
RISCV_ICMP_GE
:
fprintf
(
file
,
"bge .%s"
,
XSTR
(
COND
,
0
)
)
;
break
;
case
RISCV_ICMP_LE
:
fprintf
(
file
,
"ble .%s"
,
XSTR
(
COND
,
0
)
)
;
break
;
case
RISCV_ICMP_GT
:
fprintf
(
file
,
"bgt .%s"
,
XSTR
(
COND
,
0
)
)
;
break
;
default
:
error
(
"%s"
,
"invalid use of '%%%c'"
,
XSTR
(
COND
,
0
)
)
;
break
;
}


void riscv_print_operand_reloc ( char * OP , int CONTEXT , char * HI_RELOC , char * riscv ) { if ( strcmp ( HI_RELOC , "%hi" ) == 0 ) { printf ( "%hi(%s)" , HI_RELOC , OP ) ; } else if ( strcmp ( HI_RELOC , "%lo" ) == 0 ) { if ( CONTEXT == HIGH ) { printf ( "%lo(%s)" , HI_RELOC , OP ) ; } else { printf ( "%lo(%s)(%pcrel)" , HI_RELOC , OP ) ; } }


int riscv_register_move_cost ( const struct riscv_target * target , int n , int mode ) { int cost = 0 ; if ( n == 8 && mode == MOV_COST_N_N ) { cost = 2 ; } return cost ; }


riscv_regno_mode_ok_for_base_p ( unsigned int regno , machine_mode mode , bool strict_p ) { if ( strict_p ) { if ( ! REG_OK_STRICT_P ( regno ) ) return false ; } else { if ( ! REG_OK_NONSTRICT_P ( regno ) ) return false ; } rtx r = gen_rtx_REG ( mode , regno ) ; if ( ! TARGET_MODE_OK_FOR_BASE_P ( mode , r ) ) return false ; if ( ! REG_MODE_OK_FOR_BASE_P ( mode , r ) ) return false ; return true ; }


void
riscv_restore_reg
(
int
reg
,
void
*
mem
)
{
asm
volatile
(
"lw %0, %1\n"
:
"=r"
(
reg
)
:
"m"
(
mem
)
:
)
;
}


riscv_return_in_memory ( const_tree type ) { if ( TREE_CODE ( type ) == RECORD_TYPE || TREE_CODE ( type ) == UNION_TYPE ) return true ; enum machine_mode mode = TYPE_MODE ( type ) ; if ( mode != VOIDmode && GET_MODE_SIZE ( mode ) <= Pmode ) return false ; if ( mode != VOIDmode && GET_MODE_SIZE ( mode ) > Pmode ) { if ( TARGET_64BIT ) return true ; else return false ; } return false ; }


bool riscv_save_reg_p ( enum rtx_code REGNO ) { } Explanation : - This function takes in an enumeration value of the register ( REGNO ) as a parameter . - The enum rtx_code is a set of predefined enumeration values used to represent different registers in the riscv architecture . - The function body includes the logic to determine whether the register needs to be saved or not . - The function returns a boolean value of true if the register needs to be saved , and false otherwise . Target - specific value : The riscv backend has its specific set of registers that need to be saved in the current function . Hence , the target - specific value for this function is "riscv" . This target - specific value is used to identify the specific architecture and determine the registers that need to be saved . Sample implementation : The following is a sample implementation of the riscv_save_reg_p ( ) function : bool riscv_save_reg_p ( enum rtx_code REGNO ) { switch ( REGNO ) { case R0 : case R1 : case R2 : case R3 : case FP : case T0 : case T1 : case T2 : case RA : return true ; default : return false ; } }


void
riscv_save_restore_reg
(
int
regno
,
int
mode
,
int
offset
)
{
asm
volatile
(
"fn %0, %1($sp)"
:
:
"r"
(
regno
)
,
"i"
(
offset
)
:
"memory"
)
;
}


void riscv_setup_incoming_varargs ( struct riscv_frame_info * frame , int register_args , int float_align , int int_align ) { int regno ; int arg_padding ; int argnum ; frame -> gpr_save_area = frame -> gpr_arg_area + register_args * sizeof ( unsigned long ) ; for ( regno = 8 , argnum = 0 ; regno < TARGET_FIRST_ARG_REGNUM ; regno ++ , argnum ++ ) { frame -> gpr_save_area [ i ] = frame -> gpr_arg_area [ i ] ; } argnum = 0 ; arg_padding = 0 ; for ( regno = TARGET_FIRST_ARG_REGNUM ; regno <= TARGET_LAST_ARG_REGNUM ; regno ++ , argnum ++ ) { if ( argnum >= register_args ) { arg_padding = float_align ; }


riscv_split_symbol ( rtx addr , enum machine_mode mode , rtx * low_out , rtx temp ) { if ( mode == MAX_MACHINE_MODE ) { if ( legitimize_set_src_p ( addr , GET_MODE ( addr ) ) ) { rtx high , low ; low = legitimize_set_src ( addr , GET_MODE ( addr ) ) ; high = gen_lowpart ( GET_MODE ( addr ) , addr ) ; if ( low_out ) * low_out = low ; emit_insn ( gen_rtx_SET ( VOIDmode , temp , high ) ) ; return true ; } }


riscv_unspec_offset_high ( Host_Wide_Int offset , HOST_WIDE_INT symbol_type , Expr * base , Expr * temp ) { if ( ( offset & 0xFFFFFFFF00000000ull ) != 0 ) { Expr * high_part = riscv_unspec_address ( offset >> 32 , symbol_type ) ; return build2 ( EXPR_LIST , high_part , base ) ; } else { return base ; } }


bool riscv_use_save_libcall ( int riscv , int value ) { return ( riscv == riscv && value == 0 ) ; }


riscv_valid_base_register_p ( rtx x , machine_mode mode , bool strict_p ) { rtx decl ; int regno ; if ( strict_p && ! REG_OK_STRICT ) { if ( GET_CODE ( x ) != REG || ! REG_P ( x ) || ! ( REGNO ( x ) >= 0 && REGNO ( x ) <= 31 ) ) return false ; else return true ; }


"LO_SUM can address any value for riscv architecture\n"

"LO_SUM cannot address any value for riscv architecture\n"


bool riscv_valid_offset_p ( enum machine_mode mode ) { if ( ! RISCV_MODE_SUPPORTED ( mode ) ) { return false ; } enum reg_class base_reg_class = RISCV_ADDR_BASE_REGS ( mode ) ; for ( unsigned int i = 0 ; i < GET_NUM_BASE_REGISTERS ( base_reg_class ) ; i ++ ) { rtx base_reg = gen_rtx_REG ( base_reg_class , i ) ; rtx offset = gen_rtx_CONST_INT ( mode , X ) ; rtx addr = gen_rtx_PLUS ( mode , base_reg , offset ) ; if ( ! REG_ADDR_VALID ( addr ) ) { return false ; } } return true ; }


int riscv_address_insns ( enum machine_mode mode , rtx x , bool might_split_p ) { if ( ! TARGET_RISCV ) return 0 ; if ( ! legitimate_address_p ( mode , x , 1 ) ) return 0 ; if ( might_split_p ) { int bits_per_word = BITS_PER_WORD ; int words_needed = ( GET_MODE_BITSIZE ( mode ) + bits_per_word - 1 ) / bits_per_word ; if ( ! CONSTANT_P ( x ) && ! MEM_P ( x ) && ! SYMBOLIC_CONST_ADDRESS_P ( x ) ) return 0 ; if ( REG_P ( x ) || REG_OFFSET_P ( x ) ) return 1 ; return words_needed ; } else { return 1 ; } }


riscv_arg_partial_bytes ( enum machine_mode mode , int target_flag ) { if ( mode == BLKmode ) return 0 ; if ( target_flag == 0 ) { if ( mode == CCmode ) return 4 ; if ( mode == ATTR_TYPE_ORIG ( mode ) ) mode = TYPE_MODE ( mode ) ; if ( mode == SImode || mode == UIView mode ) return 4 ; if ( mode == DImode || mode == UImode || mode == TFmode ) return 8 ; } return 0 ; }


void riscv_block_move_straight ( char * src , char * dest , int length ) { int i ; for ( i = 0 ; i < length ; i ++ ) { dest [ i ] = src [ i ] ; } }


static void riscv_conditional_register_usage ( const char * arch , int macro_version , int cond_reg_usage , int gp_reg_usage ) { if ( strcmp ( arch , "riscv" ) != 0 ) { return ; }


int riscv_constant_alignment ( ) { return riscv_target_constant_alignment ; }


void riscv_expand_prologue ( ) { uint64_t target_values [ 9 ] = { riscv , 0 , 0 , 1 , 0 , 1 , 1 , 0 , 1 } ; uint64_t prologue_pattern = target_values [ 0 ] ; for ( int i = 1 ; i < 9 ; i ++ ) { prologue_pattern = prologue_pattern << 1 | target_values [ i ] ; } delay_slot ( ) ; clear_branch_hazard ( ) ; emit_store ( riscv_frame_reg , - 8 , riscv_retaddr_reg ) ; increment_stack_pointer ( - 16 ) ; emit_store ( riscv_frame_reg , - 16 , riscv_frame_reg ) ; emit_load ( riscv_frame_reg , 0 , riscv_callee_save_reg ) ; increment_stack_pointer ( - 16 ) ; emit_num_delay_slots ( 1 ) ; if ( compare_prologue_pattern ( prologue_pattern , target_values ) ) { emit_extended_prologue ( prologue_pattern ) ; } else { emit_default_prologue ( ) ; } } bool compare_prologue_pattern ( uint64_t expanded_pattern , uint64_t target_values [ ] ) { for ( int i = 0 ; i < 9 ; i ++ ) { if ( ( expanded_pattern >> i ) & 1 != target_values [ i ] ) { return false ; } } return true ; }


void
riscv_file_start
(
void
)
{
fprintf
(
FILE
,
"\t.option %spic\n"
,
TARGET_CPU_DEFAULT
)
;
fprintf
(
FILE
,
"\t"
,
"\t.option norelax\n"
,
)
;
}


void riscv_for_each_saved_reg ( rtx fn , rtx sp_offset ) { const char * target = riscv_target_string ; int i , num_regs ; const rtx * regs ; regs = riscv_initial_eps -> saved_regs ; num_regs = riscv_initial_eps -> num_saved_regs ; for ( i = 0 ; i < num_regs ; i ++ ) { int regno = REGNO ( regs [ i ] ) ; if ( regno == - 1 ) continue ; call_rtx_fn ( fn , sp_offset , regno , target ) ; } }


void riscv_function_arg_advance ( riscv_arg r ) { int size = riscv_arg_size ( r ) ; __builtin_gprms_offset += size ; return ; }


riscv_function_ok_for_sibcall ( const_tree fn ) { if ( ! TREE_CODE ( fn ) == FUNCTION_DECL ) return false ; if ( TREE_THIS_VOLATILE ( fn ) || DECL_TOTAL_RESTRICT ( fn ) || DECL_EXTERNAL ( fn ) || DECL_ASSEMBLER_NAME_SET_P ( fn ) ) return false ; return true ; }


riscv_legitimize_const_move ( rtx dest , rtx src ) { if ( GET_CODE ( src ) != CONST || ! REG_P ( dest ) ) return ; if ( ! immediate_operand ( src , GET_MODE ( dest ) ) || move_operand ( src , GET_MODE ( dest ) ) ) return ; rtx target = GEN_INT ( 0 ) ; rtx insn = gen_rtx_SET ( VOIDmode , dest , gen_rtx_CONST ( GET_MODE ( dest ) , target ) ) ; emit_insn ( insn ) ; }


void riscv_legitimize_move ( rtx set_dest , rtx src ) { if ( ! legitimate_move_p ( set_dest , src ) ) { rtx_seq = gen_rtx_SET ( set_dest , src ) ; rtx_seq -> target = gen_rtx_RISC0 ( 0 , 0 , 0 , 0 , 0 , 0 ) ; emit_insn ( rtx_seq ) ; } }


void
riscv_move_integer
(
riscv_register
DEST
,
int
VALUE
,
riscv_register
TEMP
)
{
if
(
VALUE
>=
0
&&
VALUE
<=
31
)
{
printf
(
"mv %s, %d"
,
DEST
,
VALUE
)
;
}
else
{
if
(
VALUE
<=
2047
&&
VALUE
>=
2048
)
{
printf
(
"li %s, %d"
,
TEMP
,
VALUE
)
;
printf
(
"mv %s, %s"
,
DEST
,
TEMP
)
;
}
else
{
printf
(
"lui %s, %d"
,
TEMP
,
(
VALUE
>>
12
)
&
0xFFFF
)
;
printf
(
"addi %s, %s, %d"
,
DEST
,
TEMP
,
VALUE
&
0xFFF
)
;
}
}
}


"-mdiv requires -march to subsume the %<M%> extension"

"requested ABI requires -march to subsume the %qc extension"

"-mpreferred-stack-boundary=%d must be between %d and %d"


riscv_output_move ( rtx src , rtx dest ) { enum machine_mode dest_mode = GET_MODE ( dest ) ; enum machine_mode src_mode = GET_MODE ( src ) ; rtx insn = NULL_RTX ; rtx tmp_rtx ; switch ( dest_mode ) { case MODE_QImode : return gen_rtx_fmt_ee ( VOIDmode , "lbu\t%0,%1" , dest , src ) ; case MODE_HImode : return gen_rtx_fmt_ee ( VOIDmode , "lhu\t%0,%1" , dest , src ) ; case MODE_SImode : return gen_rtx_fmt_ee ( VOIDmode , "lw\t%0,%1" , dest , src ) ; case MODE_DImode : return gen_rtx_fmt_ee ( VOIDmode , "ld\t%0,%1" , dest , src ) ; case MODE_TI : if ( GET_CODE ( src ) == CONST_INT ) { rtx high = rtx_const_hi ( src ) ; rtx low = rtx_const_lo ( src ) ; if ( high == 0 ) return gen_rtx_fmt_i ( VOIDmode , "li\t%0,#%l1\t%w1" , dest , low ) ; else return gen_rtx_fmt_i ( VOIDmode , "lui\t%0,#%h1" , dest , high ) ; } if ( GET_CODE ( src ) == CONST_DOUBLE ) return gen_rtx_fmt_ie ( VOIDmode , "#lfmv.x.d\t%0,%1" , dest , src ) ; gcc_assert ( GET_MODE_PRECISION ( src_mode ) == 64 ) ; break ; case MODE_TF : switch ( src_mode ) { case MODE_TI : tmp_rtx = gen_rt_floating ( ( HOST_WIDE_INT ) XWINT ( XINT ( src , 1 ) ) ) ; return gen_rtx_fmt_ie ( VOIDmode , "#fli.w\t%0,x0" , dest , tmp_rtx ) ; case MODE_TF : return gen_rtx_fmt_ie ( VOIDmode , "#fli.w\t%0,%1" , dest , src ) ; }


void riscv_pass_by_reference ( int riscv , int zero , int two ) { TARGET_PASS_BY_REFERENCE = riscv , zero , two ; }


tree_operand riscv_pass_fpr_single ( tree_operand arg , int fpr_reg ) { if ( TREE_CODE ( arg ) != INTEGER_CST || TREE_CODE ( arg ) != ADDR_EXPR ) { return NULL ; } tree type = TREE_TYPE ( arg ) ; if ( TREE_CODE ( type ) == RECORD_TYPE && TYPE_ATTRIBUTES ( type ) && attr_packed_p ( TYPE_ATTRIBUTES ( type ) ) ) { int regno = arg -> operand ; union tree_node temp ; memset ( & temp , 0 , sizeof temp ) ; temp . int_cst = regno ; if ( temp . gt_type . mode == BLKmode ) { return arg ; } } if ( temp_value -> type . mode == SFmode ) { return arg ; }


riscv_setup_incoming_varargs ( CUMULATIVE_ARGS * cum , tree fntype , tree functype ATTRIBUTE_UNUSED ) { if ( ! TYPE_HAS_VARARGS ( fntype ) ) return ; unsigned int total_size = 0 ; tree arg_type = TYPE_ARG_TYPES ( fntype ) ; while ( ! IS_NULL_TREE ( arg_type ) ) { total_size += tree_to_uhwi ( TYPE_SIZE ( arg_type ) ) ; arg_type = TREE_CHAIN ( arg_type ) ; } cum -> incoming_varargs_offset = 0 ; cum -> incoming_varargs_size = total_size ; cum -> incoming_varargs_alignment = 1 ; cum -> target_args . parm_info . type = RS_CUM_ARGS_INCOMING_VARARGS ; cum -> target_args . parm_info . type = 'r' ; cum -> target_args . parm_info . size = 1 ; cum -> target_args . parm_info . offset = 0 ; }


void riscv_split_integer ( long long int input , int * output ) { output [ 0 ] = input >> 32 ; output [ 1 ] = input & 0xFFFFFFFF ; output [ 2 ] = ( input >> 32 ) & 0xFFFF ; output [ 3 ] = input & 0xFFFF ; input = ( output [ 0 ] << 32 ) | output [ 1 ] | ( output [ 2 ] << 32 ) | output [ 3 ] ; }


bool riscv_split_symbol ( machine_mode mode , rtx addr , rtx * low_out , rtx temp ) { if ( mode == MAX_MACHINE_MODE && GET_CODE ( addr ) == MEM && XEXP ( addr , 0 ) == gen_rtx_CONST ( mode , GEN_INT_ ( 0 ) ) ) { rtx hi_part = gen_highpart ( mode , gen_rtx_REG ( mode , temp ) ) ; emit_move_insn ( hi_part , XEXP ( addr , 1 ) ) ; if ( low_out != NULL ) { * low_out = gen_lowpart ( mode , gen_rtx_REG ( mode , temp ) ) ; } return true ; } else if ( GET_CODE ( addr ) == LABEL_REF && XINT ( addr , 1 ) == 0 && ! riscv_force_temporary ( addr ) ) { if ( low_out != NULL ) { * low_out = addr ; } return true ; } return false ; }


bool riscv_valid_lo_sum_p ( mode_t mode , symbol_type_t sym_type ) { if ( TARGET_RISCV ) { if ( mode == RISCV ) { if ( sym_type == SYM_TYPE ) { return true ; } } } return false ; }


int riscv_address_insns ( machine_mode mode , rtx x , bool might_split_p ) { int insns = 0 ; rtx addr = x ; rtx inner_addr ; if ( ! rtx_addr_can_believe_p ( x , mode ) ) return 0 ; if ( ! rtx_memory_addr_operand ( x , mode ) ) return 0 ; if ( GET_CODE ( x ) == REG ) return 1 ; if ( GET_CODE ( x ) == PLUS ) { inner_addr = XEXP ( x , 1 ) ; mode = GET_MODE ( inner_addr ) ; if ( GET_CODE ( inner_addr ) == REG ) return 1 ; if ( ! rtx_addr_can_believe_p ( inner_addr , mode ) ) return 0 ; if ( might_split_p ) { if ( rtx_memory_addr_operand ( inner_addr , mode ) ) { int num_words = ( GET_MODE_SIZE ( mode ) + UNITS_PER_WORD - 1 ) / UNITS_PER_WORD ; insns = num_words * riscv_address_insns ( mode , inner_addr , false ) ; }


function riscv_epilogue_uses ( riscv ) { if ( target_specific_value == 'riscv' ) { for each instruction in function { if ( instruction is epilogue instruction ) { return true ; } } } return false ; }


riscv_save_reg_p ( int regno ) { bool riscv_save_reg = false ; if ( regno == RISCV_RETURN_REG ) { riscv_save_reg = true ; } else if ( regno >= RISCV_INTERRUPTIBLE_MIN && regno <= RISCV_INTERRUPTIBLE_MAX ) { riscv_save_reg = true ; } else if ( regno == RISCV_FRAME_POINTER_REG || regno == RISCV_GLOBAL_POINTER_REG || regno == RISCV_STACK_POINTER_REG ) { riscv_save_reg = true ; } return riscv_save_reg ; }


bool riscv_split_symbol ( enum machine_mode mode , rtx addr , rtx * low_out , rtx temp ) { if ( mode == MAX_MACHINE_MODE ) { if ( GET_CODE ( addr ) == CONST_INT && INTVAL ( addr ) >= 0 ) { rtx high , low ; high = riscv_force_temporary ( mode , temp ) ; low = GEN_INT ( INTVAL ( addr ) & ( ( 1 << 16 ) - 1 ) ) ; if ( low_out != NULL ) * low_out = low ; emit_move_insn ( high , GEN_INT ( INTVAL ( addr ) >> 16 ) ) ; return true ; } else return false ; } else { if ( GET_CODE ( addr ) == MEM && GET_MODE ( addr ) == mode ) { extract_low_high_parts ( addr , low_out , temp ) ; return true ; } else return false ; } }


riscv_address_cost ( rtx x , enum rtx_code code ) { unsigned int cost = 0 ; unsigned int multiplier = 1 ; switch ( x , 1 ) { case riscv : multiplier = 1 ; break ; } switch ( code ) { case LOAD : cost = 3 * multiplier ; break ; case STORE : cost = 5 * multiplier ; break ; } return cost ; }


riscv_address_insns ( rtx x , enum machine_mode mode , bool might_split_p ) { int insn_count = 0 ; unsigned int op_size = GET_MODE_SIZE ( mode ) ; unsigned int addr_mode = GET_MODE ( x ) ; if ( ( mode != DImode && mode != SImode && mode != HImode && mode != QImode ) || addr_mode != SImode ) return 0 ; if ( might_split_p ) { for ( unsigned int i = 0 ; i < op_size ; i += UNITS_PER_WORD ) ++ insn_count ; } else { ++ insn_count ; } return insn_count ; }


riscv_add_offset ( rtx reg , rtx offset , rtx temp , enum rtx_code riscv ) { if ( GET_CODE ( offset ) == CONST_INT && INTVAL ( offset ) >= - 2048 && INTVAL ( offset ) <= 2047 ) return gen_rtx_PLUS ( GET_MODE ( reg ) , reg , offset ) ; if ( riscv_force_temporary ( offset , temp , riscv ) ) return gen_rtx_PLUS ( GET_MODE ( reg ) , reg , temp ) ; }


void riscv_adjust_block_mem ( int riscv , void * mem , int length , int * loop_reg , void * * loop_mem ) { int loop_reg_index = riscv_alloc_gr ( ) ; * loop_reg = loop_reg_index ; riscv_emit_loadi ( loop_reg_index , ( uint64 ) mem ) ; * loop_mem = riscv_alloc_mr ( ) ; riscv_emit_memref ( * loop_mem , loop_reg_index , length , 0 , RISCV_LOAD ) ; }


void riscv_allocate_stack_slots_for_args ( CUMULATIVE_ARGS * cum ) { int num_args = cum -> num_args ; int stack_words ; if ( cum -> caller_align < STACK_ALIGN ) cum -> caller_align = STACK_ALIGN ; stack_words = ( cum -> caller_size + ( STACK_UNIT_SIZE - 1 ) ) / STACK_UNIT_SIZE ; int num_stack_slots = ( num_args + 2 ) / 2 ; num_stack_slots = ( ( num_stack_slots + 7 ) / 8 ) * 8 ; int stack_offset = ( - num_stack_slots ) * STACK_UNIT_SIZE ; stack_offset = ( ( stack_offset + cum -> caller_align - 1 ) / cum -> caller_align ) * cum -> caller_align ; cum -> caller_size = stack_offset + ( stack_words * STACK_UNIT_SIZE ) ; cum -> caller_offset = stack_offset ; cum -> accumulate = stack_words != 0 ; }


target_ulong
riscv_asan_shadow_offset
(
enum
target_machine
machine
)
{
switch
(
machine
)
{
case
riscv
:
return
29
<<
12
;
default
:
fprintf
(
stderr
,
"Unsupported architecture\n"
)
;
return
0
;
}
}


void riscv_block_move_loop ( void * dest , const void * src , size_t length , size_t bytes_per_iter ) { const char * src_bytes = ( const char * ) src ; char * dest_bytes = ( char * ) dest ; if ( dest >= src && dest < src + length ) { return ; } for ( size_t i = 0 ; i < length ; i += bytes_per_iter ) { for ( size_t j = 0 ; j < bytes_per_iter ; j ++ ) { * dest_bytes = * src_bytes ; src_bytes ++ ; dest_bytes ++ ; } } }


void
riscv_block_move_straight
(
char
*
dest
,
char
*
src
,
int
length
)
{
asm
volatile
(
"li t0, 0\n\t"
"la t1, %0\n\t"
"la t2, %1\n\t"
:
:
"r"
(
src
)
,
"r"
(
dest
)
:
"%t0"
,
"%t1"
,
"%t2"
)
;
asm
volatile
(
"loop: \n\t"
"lb t3, 0(t1)\n\t"
"sb t3, 0(t2)\n\t"
"addi t1, t1, 1\n\t"
"addi t2, t2, 1\n\t"
"addi t0, t0, 1\n\t"
"blt t0, %0, loop\n\t"
:
:
"r"
(
length
)
:
"%t0"
,
"%t1"
,
"%t2"
,
"%t3"
)
;
}


riscv_call_tls_get_addr
(
const
char
*
sym
,
enum
tls_symbol_type
type
,
RTX
result
)
{
RTX
tls_desc
,
tls_addr
,
func
,
insns
;
int
target_index
;
target_index
=
TARGET_TLS_GET_ADDR_VALUE
;
const
char
*
name
=
"__tls_get_addr"
;
func
=
gen_rtx_SYMBOL_REF
(
Pmode
,
name
)
;
tls_desc
=
gen_rtx_TLS_DESC
(
Pmode
,
func
,
target_index
)
;
tls_addr
=
gen_rtx_PLUS
(
Pmode
,
tls_desc
,
GEN_INT
(
0
)
)
;
switch
(
type
)
{
case
tls_type_global_dynamic
:
insns
=
gen_rtx_CALL
(
VOIDmode
,
tls_addr
)
;
break
;
case
tls_type_local_dynamic
:
insns
=
gen_rtx_CALL
(
VOIDmode
,
tls_addr
)
;
break
;
default
:
gcc_unreachable
(
"unsupported TLS symbol type"
)
;
}
insns
=
gen_rtx_SET
(
VOIDmode
,
result
,
insns
)
;
return
insns
;
}


bool riscv_cannot_copy_insn_p ( const rtx_insn * insn ) { bool cannot_copy = false ; FOR_EACH_OPERAND ( insn , op , i , 0 ) { if ( CONSTANT_ADDRESS_P ( XEXP ( op , 0 ) ) ) { cannot_copy = true ; break ; } } return cannot_copy ; }


bool riscv_cannot_force_const_mem ( target , 0 ) { if ( target == 0 ) { return false ; } else { return true ; } }


bool riscv_can_change_mode_class ( int mode , int class ) { if ( TARGET_ARCH != "riscv" ) { return false ; } if ( ! is_mode_supported ( mode ) ) { return false ; } if ( has_priv_mode_switch ( ) ) { if ( is_class_supported ( class ) ) { return true ; } else { return false ; } } return false ; }


int riscv_can_use_return_insn ( void ) { if ( TARGET_RISCV ) { return 1 ; } return 0 ; }


bool riscv_classify_address ( unsigned int mode , rtx x , machine_mode * info , bool strict_p ) { if ( mode == TARGET_MACH_MODE && GET_CODE ( x ) == ADDRESS ) { * info = TARGET_MACH_MODE ; if ( strict_p ) { info -> flags |= REG_OK_STRICT ; } info -> target_specific = "riscv,0,1,0,1" ; return true ; } else { return false ; } }


"method for accessing symbols and labels in RV32I architecture"

"method for accessing symbols and labels in RV64I architecture"


int riscv_classify_symbolic_expression ( int X ) { int base = X & 0xFF ; if ( base == 0 ) { return 0 ; } if ( base == ( base & 0xFFFF ) ) { return 1 ; } if ( base == ( base & 0xFFFFFFFF ) ) { return 2 ; } if ( base == ( base & 0xFFFFFFFFFFFFFFFF ) ) { return 3 ; } return 4 ; }


int riscv_class_max_nregs ( char * target_arch ) { if ( strcmp ( target_arch , "riscv" ) == 0 ) { return 0 ; } return 0 ; }


"The input value satisfies the condition.\n"

"The input value does not satisfy the condition.\n"


int riscv_constant_alignment ( void ) { return 4 ; }


int riscv_const_insns ( int X ) { int masked = X & 0xFFF ; if ( masked == X ) { return 1 ; } if ( X >= - 4096 && X <= 4095 ) { return 2 ; } if ( X >= - 524288 && X <= 524287 ) { return 3 ; } return 0 ; }


const char * riscv_elf_select_rtx_section ( const char * name , int flags ) { if ( strcmp ( name , ".rodata.cst" ) != 0 ) return NULL ; if ( flags & FLAGS_ELF_SECTION_IS_SMALL ) return ".s%s" ; return NULL ; }


void
riscv_emit_attribute
(
FILE
*
f
,
const
char
*
fmt
,
...
)
{
va_list
args
;
va_start
(
args
,
fmt
)
;
fprintf
(
f
,
"\t.attribute arch, \"%s\"\n"
,
DEFAULT_ARCH
)
;
fprintf
(
f
,
fmt
,
args
)
;
fprintf
(
f
,
"\t.attribute unaligned_access, %d\n"
,
1
)
;
fprintf
(
f
,
fmt
,
args
)
;
fprintf
(
f
,
"\t.attribute stack_align, %d\n"
,
8
)
;
va_end
(
args
)
;
}


void riscv_emit_int_order_test ( rtx cmp0 , rtx cmp1 , rtx target , rtx invert_ptr ) { rtx code , cmp0_low , cmp0_high , cmp0_unsigned , cmp1_low , cmp1_high , cmp1_unsigned , cmp0_greater , cmp1_greater , cmp_equal , result , result_invert ; rtx riscv , 0 = CODE_FOR_riscv_order_test ; code = gen_reg_rtx ( CCmode ) ; cmp0_low = gen_lowpart ( CCmode , cmp0 ) ; cmp0_high = gen_highpart ( CCmode , cmp0 ) ; cmp0_unsigned = gen_reg_rtx ( CCmode ) ; cmp1_low = gen_lowpart ( CCmode , cmp1 ) ; cmp1_high = gen_highpart ( CCmode , cmp1 ) ; cmp1_unsigned = gen_reg_rtx ( CCmode ) ; emit_cmp_insn ( cmp0_low , cmp1_low ) ; emit_cmp_insn ( cmp0_high , cmp1_high ) ; emit_movinsn_operand ( cmp0_unsigned , cmp0_high , GEN_INT ( 1 ) ) ; emit_movinsn_operand ( cmp1_unsigned , cmp1_high , GEN_INT ( 1 ) ) ; cmp0_greater = gen_rtx_CC ( GT , CCmode , cmp0_unsigned , cmp1_unsigned ) ; cmp1_greater = gen_rtx_CC ( GT , CCmode , cmp1_unsigned , cmp0_unsigned ) ; cmp_equal = gen_rtx_CC ( EQ , CCmode , cmp0_unsigned , cmp1_unsigned ) ; emit_cmp_insn ( cmp0_greater , cmp1_greater ) ; emit_cmp_insn ( code , cmp_equal ) ; if ( invert_ptr ) { result_invert = gen_rtx_CC ( NOT , CCmode , code , NULL_RTX ) ; result = gen_rtx_SET ( VOIDmode , * invert_ptr , result_invert ) ; } else { result = gen_rtx_SET ( VOIDmode , target , code ) ; }


riscv_emit_move ( rtx dest , rtx src ) { rtx insn ; if ( ! can_create_pseudo_p ( ) ) { if ( GET_CODE ( dest ) == CONST_INT && GET_CODE ( src ) == CONST_INT ) emit_insn ( gen_riscv_move_imm ( dest , src ) ) ; else emit_insn ( gen_riscv_move ( dest , src ) ) ; } else emit_insn ( gen_riscv_move ( dest , src ) ) ; if ( GET_CODE ( dest ) == CONST_INT && GET_CODE ( src ) == CONST_INT ) { REG_NOTES ( insn ) = gen_rtx_EXPR_LIST ( REG_NOTE , src , REG_NOTES ( insn ) ) ; REG_NOTES ( insn ) = gen_rtx_EXPR_LIST ( REG_NOTE , dest , REG_NOTES ( insn ) ) ; REG_NOTE_KIND ( insn ) = REG_STR_VALID ; } }


riscv_expand_conditional_move ( rtx op , rtx cons , rtx alt , rtx dest ) { if ( ! ( op && cons && alt && dest ) ) return 0 ; if ( ! RTX_EQUAL_P ( GET_CODE ( op ) , NE ) && ! RTX_EQUAL_P ( GET_CODE ( op ) , EQ ) && ! RTX_EQUAL_P ( GET_CODE ( op ) , GT ) && ! RTX_EQUAL_P ( GET_CODE ( op ) , GE ) && ! RTX_EQUAL_P ( GET_CODE ( op ) , LT ) && ! RTX_EQUAL_P ( GET_CODE ( op ) , LE ) ) return 0 ; if ( ! op_strict_low_p ( XEXP ( op , 0 ) ) && ! op_strict_low_p ( XEXP ( op , 1 ) ) ) return 0 ; emit_insn ( gen_cond_movsi ( dest , cons , alt ) ) ; return 1 ; }


riscv_expand_int_scc ( rtx * operands , rtx target ) { rtx op0 = operands [ 0 ] ; rtx op1 = operands [ 1 ] ; enum riscv_target_values riscv_target_value = riscv_target_flags . first ; if ( riscv_target_value != riscv ) return NULL ; if ( ! RTX_UINTP ( op0 ) || ! RTX_UINTP ( op1 ) ) return NULL ; rtx comp_insn = gen_riscv_scc ( target , op0 , op1 ) ; return comp_insn ; }


"Invalid parameters for riscv_extend_cost function"


void
riscv_file_start
(
void
)
{
fprintf
(
asm_out_file
,
"\t.option %spic\n"
,
riscv
)
;
fprintf
(
asm_out_file
,
"\t.option norelax\n"
)
;
fprintf
(
asm_out_file
,
"\t.globl\t%s\n"
,
riscv
)
;
fprintf
(
asm_out_file
,
"%s:\n"
,
riscv
)
;
fprintf
(
asm_out_file
,
"\t.option %d\n"
,
riscv
)
;
}


int riscv_first_stack_step ( int size , int min_size , int frame , int sp_adjust , int callee_save_size ) { int initial_alloc = size ; if ( size > min_size ) { int callee_alloc = frame - callee_save_size ; if ( callee_alloc > 0 ) { initial_alloc += callee_alloc ; } } int stack_adjust = initial_alloc % sp_adjust ; if ( stack_adjust != 0 ) { initial_alloc += ( sp_adjust - stack_adjust ) ; } return initial_alloc ; }


"Unsupported RISC-V target specific value"


mode riscv_force_binary ( mode MODE , rtx code , rtx X , rtx Y ) { rtx result_reg = gen_reg_rtx ( MODE ) ; rtx and_insn ; rtx tmp_reg ; and_insn = gen_rtx_SET ( VOIDmode , result_reg , gen_rtx_AND ( MODE , X , Y ) ) ; emit_insn ( and_insn ) ; return result_reg ; }


static RTX_CODE riscv_force_temporary ( rtx value ) { rtx temp_reg ; if ( TARGET_NEW_PSEUDOS ) { temp_reg = gen_rtx_REG ( MODE_INT , gen_reg_rtx ( Pmode ) ) ; emit_move_insn ( temp_reg , value ) ; } else { temp_reg = gen_rtx_REG ( GET_MODE ( value ) , DEST ) ; emit_move_insn ( temp_reg , value ) ; } return temp_reg ; }


riscv_for_each_saved_reg ( target , insn , fn , sp_offset ) { for ( int i = 0 ; i < saved_regs . length ; i ++ ) { int reg_offset = sp_offset + ( i * size of register ) ; insn = create_insn_store ( loaded_regs [ i ] , reg_offset ) ; fn ( loaded_regs [ i ] , reg_offset ) ; } }


rtx riscv_frame_set ( rtx reg , rtx mem ) { rtx frame_rtx ; mode ( frame_rtx ) = mode ( reg ) ; MEM ( frame_rtx ) = mem ; TARGET ( frame_rtx ) = riscv , 1 ; VALUE ( frame_rtx ) = reg ; return frame_rtx ; }


riscv_function_arg ( CUMULATIVE_ARGS * cum , enum machine_mode mode , tree type , bool named ) { tree t ; if ( named ) { } else { } return t ; }


bool riscv_function_ok_for_sibcall ( tree fndecl , void * target_specific_value ) { if ( fndecl == NULL ) return false ; if ( TREE_VALUE_CHECK ( fndecl , no_sibcall ) || DECL_SIBLING_CALLS ( fndecl ) != 0 ) return false ; if ( TREE_VALUE_CHECK ( fndecl , no_stack_protector ) ) return false ; if ( contains_nested_functions ( fndecl ) || contains_alloca_calls ( fndecl ) ) return false ; if ( contains_non_local_goto ( fndecl ) ) return false ; return true ; }


riscv_function_value ( enum machine_mode mode , tree valtype , rtx value ) { rtx target_value = value ; if ( valtype ) { if ( GET_MODE ( value ) != mode ) target_value = convert_modes ( mode , GET_MODE ( value ) , value ) ; } else { if ( riscv_target_values [ 1 ] == 0 ) return gen_rtx_VOIDmode ( VOIDmode ) ; else target_value = gen_rtx_TARGET_RETURN_VALUE ( VOIDmode ) ; } return target_value ; }


int riscv_gen_gpr_save_insn ( rtx_insn * insn , rtx * operands ) { rtx riscv = gen_rtx_REG ( SImode , REG_RETVAL ( 1 ) ) ; int operand1 = 2 ; int operand2 = 1 ; int operand3 = 0 ; rtx rtl1 = gen_rtx_REG ( SImode , operand1 ) ; rtx rtl2 = gen_rtx_REG ( SImode , operand2 ) ; rtx rtl3 = gen_rtx_REG ( SImode , operand3 ) ; insn = emit_move_insn ( riscv , rtl1 ) ; insn = emit_move_insn ( rtl3 , rtl2 ) ; operands [ 0 ] = insn ; operands [ 1 ] = rtl1 ; operands [ 2 ] = rtl2 ; operands [ 3 ] = rtl3 ; return 4 ; }


target_interrupt_type riscv_get_interrupt_type ( const char * name ) { if ( strstr ( name , "interrupt" ) ) { return RISCV_INTERRUPT ; } else if ( strstr ( name , "user" ) ) { return RISCV_USER ; } else if ( strstr ( name , "supervisor" ) ) { return RISCV_SUPERVISOR ; } else { return UNKNOWN_MODE ; } }


bool riscv_gpr_save_operation_p ( rtx instruction ) { rtx pattern = gen_rtx_RISC_V ( 0 , valid_gpr_save_mode , const0_rtx , const0_rtx , const0_rtx , const0_rtx , const0_rtx , const0_rtx , const_double_int_rtx ( 1 ) , gen_int_mode ( 3 ) , gen_int_mode ( 1 ) , gen_int_mode ( 1 ) ) ; return pattern == instruction ; }


tree args , int flags , bool * no_add_attrs ) { tree attribute ; for ( attribute = args ; attribute ; attribute = TREE_CHAIN ( attribute ) ) { tree value = TREE_VALUE ( attribute ) ; if ( strcmp ( TREE_STRING_POINTER ( value ) , "riscv" ) != 0 ) continue ; tree attr_value = TREE_VALUE ( TREE_CHAIN ( value ) ) ; if ( strcmp ( TREE_STRING_POINTER ( attr_value ) , "%qE" ) == 0 ) { DECL_ATTRIBUTES ( fndecl ) = tree_cons ( name , NULL_TREE , DECL_ATTRIBUTES ( fndecl ) ) ; break ; } } * no_add_attrs = true ; }


bool riscv_hard_regno_mode_ok ( int regno , enum machine_mode mode ) { if ( regno >= 0 && regno <= 31 ) { if ( mode == DImode || mode == SImode || mode == QImode ) { return true ; } }


int riscv_hard_regno_nregs ( HARD_REGNO , MODE ) { if ( HARD_REGNO == riscv && MODE == 1 ) return 1 ; else return false ; }


bool riscv_immediate_operand_p ( rtx CODE , rtx X ) { if ( ! riscv_opcode_p ( CODE ) ) { return false ; } if ( ! riscv_immediate_p ( CODE ) ) { return false ; } if ( ! riscv_immediate_constraint ( CODE , X ) ) { return false ; } return true ; }


uint32_t riscv_initial_elimination_offset ( uint32_t FROM , uint32_t TO ) { if ( FROM == frame_pointer ) { if ( TO == stack_pointer ) { return riscv , 0 ; } else if ( TO == hard_frame_pointer ) { return riscv , 0 ; } else { return 0 ; } } else { return 0 ; } }


riscv_init_machine_status ( target_specific_value ) { if ( target_specific_value != "riscv" ) { return ERROR ; } else { machine_status_chunk = __builtin_malloc ( RISCV_MACHINE_STATUS_SIZE ) ; __builtin_memset ( machine_status_chunk , 0 , RISCV_MACHINE_STATUS_SIZE ) ; return machine_status_chunk ; } }


int riscv_integer_cost ( int val ) { int cost ; if ( val >= - 2048 && val <= 2047 ) { cost = 1 ; } else if ( val >= - 524288 && val <= 524287 ) { cost = 2 ; } else { cost = 3 ; } return cost ; }


bool riscv_interrupt_type_p ( tree type ) { return TYPE_HAS_TARGET_VALUES ( type , riscv , "interrupt" ) ; }


bool riscv_in_small_data_p ( const_rtx exp ) { if ( ! REG_P ( exp ) && ! MEM_P ( exp ) ) { return false ; } rtx sdata_ref = gen_rtx_SYMBOL_REF ( Pmode , ".sdata" ) ; rtx sbss_ref = gen_rtx_SYMBOL_REF ( Pmode , ".sbss" ) ; if ( ( REG_P ( exp ) && REG_IN ( rtx , sdata_ref ) ) || ( MEM_P ( exp ) && MEM_IN ( rtx , sdata_ref ) ) || ( REG_P ( exp ) && REG_IN ( rtx , sbss_ref ) ) || ( MEM_P ( exp ) && MEM_IN ( rtx , sbss_ref ) ) ) { return true ; } return false ; }


int riscv_issue_rate ( ) { int max_issue_rate = GET_RISCV_ISSUE_RATE ( ) ; return max_issue_rate ; }


bool riscv_legitimate_address_p ( address ) { if ( address < 0x00000000 || address > 0xffffffff ) { return false ; } if ( address % 4 != 0 ) { return false ; } return true ; }


bool riscv_legitimate_constant_p ( unsigned long long int val ) { if ( val > ( 1ULL << 20 ) - 1 ) return false ; if ( val == ( unsigned long long int ) riscv ) return true ; else return false ; }


riscv_legitimize_address ( enum machine_mode mode , rtx x ) { if ( ( mode == riscv ) && ( GET_CODE ( x ) == CONST_INT ) && ( INTVAL ( x ) == 1 ) ) { rtx new_rtx = gen_rtx_CONST_INT ( riscv , 1 , 1 , 0 , 0 , 1 , "shorten_memrefs" , 0 ) ; return new_rtx ; } return NULL ; }


"Invalid address for riscv architecture."


riscv_legitimize_const_move ( rtx * operands ) { rtx src = operands [ 0 ] ; rtx dest = operands [ 1 ] ; if ( ! immediate_operand ( src , VOIDmode ) ) return false ; if ( move_operand ( src , VOIDmode ) ) return false ; rtx new_rtx = gen_rtx_CONST_INT ( VOIDmode , GEN_INT ( 0 ) ) ; emit_insn ( gen_rtx_SET ( VOIDmode , dest , new_rtx ) ) ; return true ; }


riscv_legitimize_move
(
DEST
,
SRC
,
riscv
,
0
,
0
,
0
)
{
if
(
DEST
is
not
a
register
or
SRC
is
not
a
register
)
{
emit
error
;
return
;
}
if
(
DEST
==
SRC
)
{
return
;
}
emit
"move riscv, SRC"
;
emit
"move DEST, riscv"
;
return
;
}


SET_SRC riscv_legitimize_tls_address ( SYMBOL_REF loc ) { SET_SRC address ; address . loc = gen_rtx_REG ( Pmode , regno ) ; rtlo = gen_rtx_LO_SUM ( Pmode , address . loc , GEN_INT ( 0 ) ) ; address . loc = rtlo ; return address ; }


riscv_load_store_insns ( rtx_insn * insn , int riscv , int reg_width , int mem_type ) { int insns = 0 ; enum rtx_code code = GET_CODE ( insn ) ; rtx reg = insn -> src ; rtx mem = insn -> dest ; switch ( code ) { case MEM : if ( GET_CODE ( reg ) == REG ) { if ( riscv == 32 && reg_width == 64 && mem_type == 0 ) insns = 1 ; else insns = 0 ; } else insns = 0 ; break ; case COMPARE : if ( GET_CODE ( mem ) == MEM ) { if ( riscv == 64 && reg_width == 32 && mem_type == 1 ) insns = 1 ; else insns = 0 ; } else insns = 0 ; break ; default : insns = 0 ; } return insns ; }


riscv_memmodel_needs_amo_acquire ( const char * model ) { if ( strcmp ( model , "riscv" ) == 0 ) return true ; else return false ; }


bool riscv_memmodel_needs_release_fence ( riscv_memory_model model ) { switch ( model ) { case RISCV_SEQ_CST : case RISCV_TSO : case RISCV_SC : return true ; case RISCV_RLX : case RISCV_RRA : return false ; default : gcc_unreachable ( ) ; } }


int riscv_min_arithmetic_precision ( const char * target ) { if ( strcmp ( target , "riscv,32" ) != 0 ) { return - 1 ; } return 32 ; }


bool riscv_modes_tieable_p ( int riscv , enum machine_mode mode1 , enum machine_mode mode2 ) { return false ; }


void
riscv_move_integer
(
int
dest
,
int
value
,
int
temp
,
int
mode
)
{
if
(
mode
!=
1
)
{
return
;
}
__asm__
__volatile__
(
"mv %0, %1"
:
"=r"
(
temp
)
:
"r"
(
value
)
)
;
__asm__
__volatile__
(
"mv %0, %1"
:
"=r"
(
dest
)
:
"r"
(
temp
)
)
;
}


"Is dummy_func2 a naked function? %s \n"


riscv_output_gpr_save ( rtx insn , int count ) { rtx tmp , pat , p ; pat = rtx_alloc ( pat_code , "" , insn ) ; tmp = gen_rtx_REG ( Pmode , T0_REG ) ; pat = rtx_add_value ( pat , tmp , 0 ) ; snprintf ( tmp_op , tmp_op_size , "call\t%s" , "__riscv_save_%u" ) ; tmp = gen_rtx_EXPR_LIST ( VOIDmode , gen_rtx_CLOBBER ( Pmode , tmp ) , gen_rtx_SYMBOL_REF ( ptr_mode , cur_fix ) , gen_rtx_CONST_INT ( Pmode , count ) , NULL_RTX , NULL_RTX ) ; pat = rtx_add_value ( pat , tmp , 1 ) ; return pat ; }


riscv_output_move ( rtx dest , rtx src ) { enum rtx_code dest_code = GET_CODE ( dest ) ; enum rtx_code src_code = GET_CODE ( src ) ; enum machine_mode mode = GET_MODE ( dest ) ; switch ( dest_code ) { case REG : switch ( src_code ) { case REG : return gen_move_insn ( dest , src ) ; case CONST_INT : if ( host_integerp ( src , 1 ) ) { if ( BYTES_BIG_ENDIAN ) return gen_rtx_fmt_d ( move_optab , mode , dest , src ) ; else return gen_rtx_fmt_w ( move_optab , mode , dest , src ) ; } else if ( GET_MODE ( dest ) == SFmode ) return gen_rtx_fmt_d ( move_optab , mode , dest , gen_int_mode ( GET_MODE ( src ) , INTVAL ( src ) ) ) ; else { if ( S_1_INT ) return gen_rtx_fmt_d ( move_optab , mode , dest , XEXP ( src , 0 ) ) ; else return gen_rtx_fmt_d ( move_optab , mode , dest , XEXP ( src , S_1_INT ) ) ; }


riscv_parse_cpu
(
const
char
*
name
)
{
if
(
name
==
)
return
;
riscv_cpu_info
cpu
;
if
(
strcmp
(
name
,
"riscv"
)
==
0
)
{
cpu
->
name
=
"riscv"
;
cpu
->
arch
=
0
;
cpu
->
tune
=
0
;
cpu
->
desc
=
"unknown cpu %qs for %<-mtune%>"
;
}
else
{
return
;
}
return
cpu
;
}


riscv_pass_aggregate_in_fpr_pair_p ( tree type , int * fields ) { int result = - 1 ; if ( TYPE_STRUCT_P ( type ) && ! TYPE_HAS_NONZERO_SIZE ( type ) ) { if ( struct_contains_bitfields ( type ) ) { fields [ 0 ] = 2 ; fields [ 1 ] = 0 ; fields [ 2 ] = 1 ; fields [ 3 ] = 0 ; result = 1 ; } else { result = 0 ; } } return result ; }


int riscv_pass_by_reference ( const char * riscv , int mode ) { if ( strcmp ( riscv , "riscv" ) == 0 ) { if ( mode == 0 ) { return 0 ; } else if ( mode == 1 ) { return 1 ; } else if ( mode == 2 ) { return 2 ; } } return - 1 ; }


void riscv_pass_fpr_pair ( int regno , mode_t mode , int offset , mode_t mode1 , int offset1 , mode_t mode2 , int offset2 ) { composite_t composite = calculate_composite ( mode , offset , mode1 , offset1 , mode2 , offset2 ) ; * ( composite_fpr_pair * ) regno = composite ; return composite ; } composite_t calculate_composite ( mode_t mode , int offset , mode_t mode1 , int offset1 , mode_t mode2 , int offset2 ) { size_t size = getSize ( mode ) + getSize ( mode1 ) + getSize ( mode2 ) ; uint8_t composite [ size ] ; memcpy ( & composite [ offset ] , reg [ optab [ mode ] . operand_type ] [ regno ] , getSize ( mode ) ) ; memcpy ( & composite [ offset1 ] , reg [ optab [ mode1 ] . operand_type ] [ regno + 1 ] , getSize ( mode1 ) ) ; memcpy ( & composite [ offset2 ] , reg [ optab [ mode2 ] . operand_type ] [ regno + 2 ] , getSize ( mode2 ) ) ; return * ( composite_t * ) composite ; } size_t getSize ( mode_t mode ) { return ( size_t ) optab [ mode ] . size ; }


struct __attribute__ ( ( packed ) ) foo { float f ; } where the SFmode value "f" is passed in REGNO but the struct itself has mode BLKmode . * / static int riscv_pass_fpr_single ( enum machine_mode mode , tree type , int position , riscv_target target ) { int fpr = - 1 ; if ( TYPE_STRUCT_PACKED ( type ) ) { enum machine_mode element_mode = TYPE_MODE ( TREE_TYPE ( FIRST_FIELD ( TYPE_FIELDS ( type ) ) ) ) ; return GET_FPR_FROM_MODE ( element_mode , target ) ; } if ( mode == FLOAT_MODE || mode == DOUBLE_MODE || mode == LONG_DOUBLE_MODE ) { fpr = GET_FPR_FROM_POSITION ( position ) ; } return fpr ; }


int riscv_pass_mode_in_fpr_p ( const_tree mode ) { if ( FLOAT_MODE_P ( mode ) ) { if ( TARGET_RISCV && ! TARGET_SOFT_FLOAT && GET_MODE_CLASS ( mode ) == MODE_FLOAT ) { return riscv ? 2 : 1 ; } return 0 ; } return 0 ; }


void riscv_print_operand ( FILE * stream , rtx op , int code ) { if ( ! op ) { fprintf ( stream , "0" ) ; return ; } const char * prefix = "" ; if ( TARGET_BIG_ENDIAN ) prefix = "upper32(" ; else if ( code == 'h' ) code = 0 ; switch ( code ) { case 'h' : fprintf ( stream , "%s%d" , prefix , REGNO ( XEXP ( op , 0 ) ) + UNITS_PER_WORD / 2 ) ; break ; case 'R' : fprintf ( stream , "%dl" , REGNO ( XEXP ( op , 0 ) ) ) ; break ; case 'C' : fprintf ( stream , "%sMULHU\n" , SIGNED ( op ) ? "mulo" : "mulhi" ) ; break ; case 'A' : fprintf ( stream , "%srl" , TARGET_ABI ? "cold" : "hot" ) ; break ; case 'F' : if ( TARGET_ABI ) { if ( TARGET_UNALIGNED_ACCESS ) fprintf ( stream , "lr.inc" ) ; else fprintf ( stream , "\n" ) ; } break ; case 'V' : if ( TARGET_ABI ) fprintf ( stream , "%d%d" , REGNO ( op ) , REGNO ( XEXP ( op , 1 ) ) ) ; else fprintf ( stream , "%dk" , juliahome . HOME_POINTER_NAME ) ; break ; case 'Z' : gcc_assert ( XEXP ( op , 0 ) ) ; fprintf ( stream , XEXP ( op , 0 ) ) ; break ; case 'J' : gcc_assert ( op ) ; fprintf ( stream , "%d" , CODE_FORA ( MEM ) ) . operands [ 3 ] , XEXP ( MEM , 0 ) ) ; break ; default : gcc_unreachable ( ) ; } }


void
riscv_print_operand_address
(
FILE
*
file
,
rtx
x
)
{
if
(
riscv
)
{
fprintf
(
file
,
"riscv (%s)"
,
XSTR
(
x
,
0
)
)
;
}
else
{
fprintf
(
file
,
"%.4s:(%s)"
,
riscv
,
XSTR
(
x
,
0
)
)
;
}
}


void
riscv_print_operand_reloc
(
FILE
*
stream
,
rtx
op
,
rtx
context
,
int
hi_reloc
)
{
char
*
prefix
=
""
;
char
*
suffix
=
""
;
switch
(
hi_reloc
)
{
case
DM_HI_RELOC
:
prefix
=
"%hi"
;
break
;
case
DM_LO_RELOC
:
prefix
=
"%lo"
;
break
;
case
DM_PCREL_HI_RELOC
:
prefix
=
"%pcrel_hi"
;
break
;
case
DM_PCREL_LO_RELOC
:
prefix
=
"%pcrel_lo"
;
break
;
case
DM_TPREL_HI_RELOC
:
prefix
=
"%tprel_hi"
;
break
;
case
DM_TPREL_LO_RELOC
:
prefix
=
"%tprel_lo"
;
break
;
default
:
suffix
=
"invalid use of '%%%c'"
;
break
;
}
if
(
GET_CODE
(
op
)
==
SYMBOL_REF
)
{
fprintf
(
stream
,
"%s%s%s"
,
prefix
,
XSTR
(
op
,
0
)
,
suffix
)
;
return
;
}
if
(
GET_CODE
(
op
)
==
HIGH
||
GET_CODE
(
op
)
==
LO_SUM
)
{
riscv_print_operand_reloc
(
stream
,
XEXP
(
op
,
0
)
,
context
,
hi_reloc
)
;
fprintf
(
stream
,
"%s"
,
suffix
)
;
return
;
}
fprintf
(
stream
,
"%s"
,
prefix
)
;
output_addr_const
(
stream
,
op
,
GET_MODE
(
op
)
,
context
)
;
fprintf
(
stream
,
"%s"
,
suffix
)
;
}


riscv_promote_function_mode ( unsigned int mode , tree type ) { if ( type == NULL_TREE ) { switch ( mode ) { case SImode : return DImode ; case HImode : return SImode ; case QImode : return HImode ; case SFmode : return DFmode ; case XCmode : return SDmode ; case ZCmode : return XDmode ; default : return mode ; } } else { if ( type == signed char_type_node ) return SImode ; else if ( type == unsigned char_type_node ) return HImode ; else if ( type == signed short_type_node ) return SImode ; else if ( type == unsigned short_type_node ) return HImode ; else if ( type == signed int_type_node ) return SImode ; else if ( type == unsigned int_type_node ) return HImode ; else if ( type == signed long_type_node ) return DImode ; else if ( type == unsigned long_type_node ) return DIQmode ; else if ( type == signed long long_type_node ) return TIQmode ; else if ( type == unsigned long long_type_node ) return TIDQmode ; else if ( type == float_type_node ) return DFmode ; else if ( type == double_type_node ) return XFmode ; else if ( type == long double_type_node ) return TFSmode ; else return mode ; } }


riscv_register_move_cost ( unsigned int from , unsigned int to ) { unsigned int cost = 0 ; if ( REGNO_REG_CLASS ( from ) == REGNO_REG_CLASS ( to ) ) { if ( REGNO_NARROWEST_MODE ( from ) == 8 && REGNO_NARROWEST_MODE ( to ) == 8 ) { if ( to - from == 1 ) cost = 2 ; } } return cost ; }


bool riscv_regno_mode_ok_for_base_p ( int regno , machine_mode mode , bool strict_p ) { enum riscv_reg_class base_regs [ ] = { RV_INT_BASE_REGS , RV_FLOAT_BASE_REGS , RV_CSR_BASE_REGS } ; if ( regno < 0 || regno >= NUM_RV_REGS_FOR_MODE ( mode ) ) return false ; if ( strict_p && TARGET_REG_OK_STRICT ) return true ; for ( unsigned int i = 0 ; i < sizeof ( base_regs ) / sizeof ( enum riscv_reg_class ) ; i ++ ) { if ( regno >= RISC_REGNO_REGCLASS_FIRST ( base_regs [ i ] ) && regno <= RISC_REGNO_REGCLASS_LAST ( base_regs [ i ] ) ) return true ; } return false ; }


function riscv_reorg ( ) { if ( target_machine == "riscv" ) { } }


void
riscv_restore_reg
(
int
reg
,
int
mem
)
{
__asm__
(
"lw %0, %1\n"
:
"=r"
(
reg
)
:
"m"
(
mem
)
,
"riscv,1"
)
;
}


riscv_return_addr ( void ) { RTX return_addr = GEN_INT ( 0 ) ; return return_addr ; }


riscv_return_in_memory ( machine_mode mode , rtx value ) { if ( TARGET_SIGNAL_0 == riscv , 0 ) { rtx var = gen_rtx_REG ( mode , 0 ) ; emit_move_insn ( var , value ) ; return var ; } else { return value ; } }


bool riscv_save_reg_p ( int regno ) { # if TARGET_RISCV if ( regno >= X5 && regno <= X9 ) { return true ; } # endif return false ; }


void
riscv_save_restore_reg
(
int
regno
,
int
mode
,
int
offset
)
{
if
(
mode
==
RISCVMODE
)
{
asm
volatile
(
"  sw %0, %1(%2)  \n"
:
:
"r"
(
regno
)
,
"r"
(
offset
)
,
"r"
(
SP
)
:
"%memory"
,
"cc"
)
;
asm
volatile
(
"  lw %0, %1(%2)  \n"
:
"=r"
(
regno
)
:
"r"
(
offset
)
,
"r"
(
SP
)
:
"%memory"
,
"cc"
)
;
}
else
}


tree decl ; { if ( TREE_CODE ( decl ) == FUNCTION_DECL ) { ASM_OUTPUT_COMMON_SECTION_NAME ( asm_out_file , ".text" ) ; } else { ASM_OUTPUT_COMMON_SECTION_NAME ( asm_out_file , ".srodata" ) ; } }


for ( param = args - 1 ; param >= 0 ; param -- ) { stack_pointer = stack_pointer - riscv_function_arg_size ( arg_types [ param ] ) ; [ stack_pointer ] = incoming_param ; }


unsigned int riscv_shorten_lw_offset ( unsigned int base , unsigned int offset ) { unsigned int max_offset = 2047 ; unsigned int min_offset = - 2048 ; if ( offset >= min_offset && offset <= max_offset ) { return base + offset ; } else if ( offset > max_offset ) { unsigned int excess = offset - max_offset ; return base + excess ; } else if ( offset < min_offset ) { unsigned int excess = min_offset - offset ; return base + excess ; } }


void riscv_slow_unaligned_access ( void * addr , size_t size , bool write ) { if ( ( ( size_t ) addr ) % ALIGNMENT != 0 ) { if ( size % ALIGNMENT != 0 ) { } }


int riscv_split_const_insns ( rtx X ) { rtx highword , lowword ; int high_cnt , low_cnt ; int total_cnt ; if ( X < 2 || X % 2 != 0 ) return 0 ; highword = gen_rtx_CONST_DOUBLE ( VOIDmode , riscv_const_high , X ) ; lowword = gen_rtx_CONST_DOUBLE ( VOIDmode , riscv_const_low , X ) ; high_cnt = ( X + 1 ) / 2 ; low_cnt = X / 2 ; total_cnt = high_cnt + low_cnt ; return total_cnt ; }


int64_t riscv_split_integer ( int64_t val ) { int32_t part1 = ( int32_t ) ( val >> 32 ) ; int32_t part2 = ( int32_t ) ( val ) ; int64_t result = ( ( uint64_t ) part1 << 32 ) | ( ( uint32_t ) part2 ) ; return result ; }


int riscv_split_integer_cost ( int riscv , int v , int bits , int align , int prefer ) { } ` ` ` The parameter "v" represents the integer value that needs to be constructed , while "bits" represents the size of the value in bits . The parameter "align" is used to determine the required alignment for the value , and "prefer" is a flag that indicates if a specific register should be preferred for constructing the value . Next , we need to define the cost calculation logic for constructing the integer value "VAL" in the event that a scratch register is available . ` ` ` int words = ( bits + 31 ) / 32 ; if ( prefer == 0 ) { return words * riscv ; } else { return words * prefer ; }


bool riscv_split_symbol ( rtx addr , machine_mode mode , rtx * low_out , rtx temp ) { if ( mode == MAX_MACHINE_MODE ) { if ( ( GET_CODE ( addr ) == SYMBOL_REF || GET_CODE ( addr ) == CONST || GET_CODE ( addr ) == LABEL_REF ) && ( ( SYMBOL_REF_LOCAL_P ( addr ) && SYMBOL_REF_THREAD_LOCAL_P ( addr ) ) || ( GET_CODE ( addr ) != SYMBOL_REF && get_attr ( addr ) == TARGET_THREAD ) ) ) { emit_move_insn ( temp , addr ) ; * low_out = gen_rtx_SYMBOL_REF ( mode , XEXP ( temp , 0 ) ) ; return true ; } } else { if ( GET_CODE ( addr ) == CONST ) { HOST_WIDE_INT high = CONST_DOUBLE_HIGH ( addr ) ; HOST_WIDE_INT low = CONST_DOUBLE_LOW ( addr ) ; * low_out = gen_int_mode ( low , mode ) ; return true ; } } return false ; }


riscv_store_data_bypass_p ( rtx in_insn , rtx out_insn ) { if ( ! single_set_p ( in_insn ) || ! single_set_p ( out_insn ) || ! verify_parallel_clobbers_uses ( in_insn ) || ! verify_parallel_clobbers_uses ( out_insn ) ) return false ; rtx out_vars = XEXP ( out_insn , 0 ) ; rtx in_addr = XEXP ( in_insn , 0 ) ; while ( out_vars ) { if ( XEXP ( out_vars , 0 ) == in_addr ) return false ; out_vars = XEXP ( out_vars , 1 ) ; } if ( GET_CODE ( in_insn ) == PARALLEL ) { rtx tem ; int i ; for ( i = 0 ; i < XVECLEN ( in_insn , 0 ) ; i ++ ) { tem = XVECEXP ( in_insn , 0 , i ) ; if ( GET_CODE ( tem ) == SET ) { rtx in_src = SET_SRC ( tem ) ; if ( MEM_P ( in_src ) ) return true ; } } } else { rtx in_src = SET_SRC ( in_insn ) ; if ( MEM_P ( in_src ) ) return true ; } return false ; }


unsigned
long
long
riscv_strip_unspec_address
(
unsigned
long
long
OP
,
unsigned
int
riscv
)
{
if
(
OP
==
UNSPEC_ADDRESS
)
{
unsigned
long
long
address
=
extract_address
(
OP
,
riscv
)
;
return
address
;
}
else
{
return
OP
;
}
}
int
main
(
)
{
unsigned
long
long
address
=
riscv_strip_unspec_address
(
UNSPEC_ADDRESS
,
riscv
)
;
printf
(
"Address: %llx\n"
,
address
)
;
unsigned
long
long
operand
=
riscv_strip_unspec_address
(
0x12345678
,
riscv
)
;
printf
(
"Operand: %llx\n"
,
operand
)
;
return
0
;
}


uint32_t riscv_subword ( uint64_t op , bool high_p ) { if ( high_p ) { return ( uint32_t ) ( op >> 32 ) ; } else { return ( uint32_t ) op ; } }


bool riscv_symbolic_constant_p ( rtx X , char * SYMBOL_TYPE ) { bool is_symbolic = false ; if ( RTX_CODE ( X ) == SYMBOL_REF ) { rtx this_sym = X ; while ( this_sym && SYMBOL_REF_LOCAL_P ( this_sym ) ) { if ( SYMBOL_REF_DECL ( this_sym ) ) { if ( strcmp ( TARGET_VALUE , "riscv,32" ) == 0 && SYMBOL_REF_RISCV_SPEC_P ( this_sym , "RISC_V" ) ) { SYMBOL_TYPE = "RISC_V" ; is_symbolic = true ; break ; } } this_sym = before_next_symbolic_ref ( this_sym ) ; } } return is_symbolic ; }


riscv_symbol_binds_local_p ( tree x ) { if ( TREE_CODE ( x ) != SYMBOL_REF ) return false ; if ( DECL_EXTERNAL ( x ) ) return false ; if ( ELF_ST_BIND ( DECL_ELF_TYPE ( x ) ) == STB_LOCAL ) return true ; return false ; }


bool riscv_tls_symbol_p ( tree x ) { if ( TARGET_RISCV && XSTR ( x , 0 ) == 'riscv,0' ) return true ; return false ; }


riscv_unspec_address ( rtx address , enum machine_mode mode , enum addr_space symbol_type ) { rtx unspec_addr = gen_rtx_UNSPEC ( Pmode , address , symbol_type , UNSPEC_RISCV ) ; return unspec_addr ; }


riscv_unspec_address_offset ( rtx symbol , int offset ) { rtx unspec_address = gen_rtx_UNSPEC_SYMBOL ( SYMBOL_TYPE , symbol ) ; unspec_address = plus_constant ( unspec_address , offset ) ; set SYMBOL_ATTRIBUTE ( unspec_address , RISCV , 1 ) ; return unspec_address ; }


rtx riscv_unspec_offset_high ( rtx addr , rtx symbol_type ) { if ( GET_CODE ( addr ) == UNSPEC && XINT ( addr , 1 ) == UNSPEC_ADDRESS ) { rtx base = XEXP ( addr , 0 ) ; if ( GET_CODE ( base ) == CONST_INT ) { HOST_WIDE_INT low = INTVAL ( base ) ; if ( low > 0xffffffff ) { HOST_WIDE_INT high = low >> 32 ; rtx high_const = GEN_INT ( high ) ; rtx sum = gen_rtx_LO_SUM ( GET_MODE ( addr ) , high_const , symbol_type ) ; rtx temp = riscv_force_temporary ( sum , GET_MODE ( addr ) ) ; return temp ; } } } return XEXP ( addr , 0 ) ; }


bool riscv_use_save_libcall ( riscv_target specific_value ) { if ( specific_value == riscv ) { return ( specific_value == 0 ) ; } else { return false ; } }


riscv_valid_base_register_p ( machine mode , rtx x , bool strict_p ) { if ( x == 0 ) return 0 ; if ( strict_p && riscv_target_flags & MASK_REG_OK_STRICT ) { if ( REG_P ( x ) ) return riscv_is_valid_base_register ( REGNO ( x ) ) ; else return 0 ; } else { if ( REG_MODE_OK ( mode , GET_MODE ( x ) ) ) { if ( REG_P ( x ) ) return riscv_is_valid_base_register ( REGNO ( x ) ) ; else return 1 ; } else return 0 ; } }


bool riscv_valid_lo_sum_p ( enum machine_mode mode , enum riscv_sym_type sym_type ) { if ( mode == riscv && sym_type >= 0 && sym_type <= 2 ) { } else { return false ; } }


bool riscv_valid_offset_p ( base_reg , mode ) { base_regs = get_base_regs_riscv ( ) ; for base in base_regs { if ( check_addrability ( base , base_reg , mode ) == false ) { return false ; } } return true ; }


void riscv_va_start ( va_list arglist , int numargs ) { arglist += 56 ; int offset = 0 ; int argtype = 1 ; for ( int i = 0 ; i < numargs ; i ++ ) { * ( int * ) arglist = argtype ; arglist += offset + 8 ; offset += 8 ; } }


"Function '%s' returns a non-void value but does not return a value"


rtl riscv_zero_if_equal ( rtx cmp0 , rtx cmp1 ) { rtx reg = gen_rtx_REG ( GET_MODE ( cmp0 ) ) ; rtx target_value = gen_rtvec ( 3 , GEN_INT ( riscv ) , GEN_INT ( 0 ) , GEN_INT ( 0 ) ) ; rtx cmp_insn = gen_rtx_COMPARE ( GET_MODE ( cmp0 ) , cmp0 , cmp1 ) ; rtx jcc = gen_rtx_SET ( VOIDmode , reg , gen_rtx_VAR_INIT ( VOIDmode , gen_rtx_CONST_VECTOR ( Pmode , target_value ) ) ) ; emit_insn_after ( cmp_insn , get_last_insn ( ) ) ; emit_jump_insn_after ( jcc , cmp_insn ) ; return reg ; }