@@ -253,6 +253,10 @@ struct arcv_apex_builtin_description {
253253 /* Specifies the instruction format. See "apex_insn_format" enum
254254 for more details. */
255255 unsigned int insn_formats;
256+
257+ /* Suffix added to the instruction name when the format is resolved
258+ (e.g., XS, XI, or XC); set to "i" if resolved, otherwise "". */
259+ const char *insn_suffix;
256260};
257261
258262/* The XD-type has 8 function bits encoding up to 256 instructions.
@@ -382,6 +386,73 @@ riscv_expand_builtin_insn (enum insn_code icode, unsigned int n_ops,
382386 return has_target_p ? ops[0 ].value : const0_rtx;
383387}
384388
389+ /* Validate the immediate argument passed to an APEX intrinsic.
390+
391+ This function checks if the argument to the intrinsic call is a constant
392+ integer and fits within the required immediate range depending on the
393+ format supported by the given SUBCODE. Only instructions that do not
394+ support APEX_XD are validated here.
395+
396+ - For APEX_XI and APEX_XC formats: the argument must be a
397+ signed 12-bit integer.
398+ - For APEX_XS format: the argument must be a signed 8-bit integer.
399+
400+ Returns false and reports an error if the argument is invalid; true
401+ otherwise. */
402+
403+ static bool
404+ arcv_apex_immediate_argument_valid_p (unsigned int subcode, tree exp)
405+ {
406+ if (!arcv_apex_format_supports_p (subcode, APEX_XD))
407+ {
408+ tree arg;
409+ /* Get the first (and only) argument passed to the intrinsic call. */
410+ if (arcv_apex_format_supports_p (subcode, APEX_XI))
411+ arg = CALL_EXPR_ARG (exp, 0 );
412+ else if (arcv_apex_format_supports_p (subcode, APEX_XC)
413+ || arcv_apex_format_supports_p (subcode, APEX_XS))
414+ arg = CALL_EXPR_ARG (exp, 1 );
415+
416+ /* If the argument is NOT a constant integer. */
417+ if (!TREE_CONSTANT (arg) || TREE_CODE (arg) != INTEGER_CST)
418+ {
419+ error (" argument to %qs must be a constant integer" ,
420+ arcv_apex_builtins[subcode].name );
421+ return false ;
422+ }
423+
424+ /* If the current subcode supports the APEX_XI or APEX_XC format, then
425+ the operand must fit within a signed 12-bit immediate. */
426+ if (arcv_apex_format_supports_p (subcode, APEX_XI)
427+ || arcv_apex_format_supports_p (subcode, APEX_XC))
428+ {
429+ HOST_WIDE_INT val = tree_to_shwi (arg);
430+ /* Check if the value fits within a signed 12-bit immediate. */
431+ if ((val < -2048 || val > 2047 ))
432+ {
433+ error (" argument value %d is outside the valid range [-2048, 2047]" ,
434+ val);
435+ return false ;
436+ }
437+ }
438+
439+ /* If the current subcode supports the APEX_XS format, then
440+ the operand must fit within a signed 8-bit immediate. */
441+ if (arcv_apex_format_supports_p (subcode, APEX_XS))
442+ {
443+ HOST_WIDE_INT val = tree_to_shwi (arg);
444+ /* Check if the value fits within a signed 8-bit immediate. */
445+ if ((val < -128 || val > 127 ))
446+ {
447+ error (" argument value %d is outside the valid range [-128, 127]" ,
448+ val);
449+ return false ;
450+ }
451+ }
452+ }
453+ return true ;
454+ }
455+
385456/* Expand a RISCV_BUILTIN_DIRECT or RISCV_BUILTIN_DIRECT_NO_TARGET function;
386457 HAS_TARGET_P says which. EXP is the CALL_EXPR that calls the function
387458 and ICODE is the code of the associated .md pattern. TARGET, if nonnull,
@@ -405,6 +476,9 @@ riscv_expand_builtin_direct (enum insn_code icode, rtx target, tree exp,
405476 rtx const_rtx = GEN_INT (subcode);
406477 /* Add the subcode as an additional input operand to the RTL expression. */
407478 create_input_operand (&ops[opno++], const_rtx, SImode);
479+ /* Validate the immediate argument passed to the APEX intrinsic. */
480+ if (!arcv_apex_immediate_argument_valid_p (subcode, exp))
481+ return const0_rtx;
408482 }
409483
410484 /* Map the arguments to the other operands. */
@@ -528,6 +602,18 @@ arcv_apex_get_insn_name (rtx op)
528602 return arcv_apex_builtins[subcode].insn_name ;
529603}
530604
605+ /* Return the instruction suffix for an APEX subcode operand.
606+
607+ This suffix is used to mark instructions whose format was resolved
608+ (e.g., XS, XI, or XC) rather than explicitly specified via pragma. */
609+
610+ const char *
611+ arcv_apex_get_insn_suffix (rtx op)
612+ {
613+ unsigned int subcode = UINTVAL (op);
614+ return arcv_apex_builtins[subcode].insn_suffix ;
615+ }
616+
531617/* Checks if the APEX builtin instruction identified by the subcode
532618 supports the given instruction format.
533619
@@ -646,10 +732,6 @@ arcv_apex_set_insn_operand_flags (unsigned int insn_format, tree fndecl)
646732static unsigned int
647733arcv_apex_resolve_insn_format (unsigned int insn_format, unsigned int opcode)
648734{
649- /* Return early if a instruction format was defined by the used. */
650- if ((insn_format & 0xF ) != APEX_NONE)
651- return insn_format;
652-
653735 /* Extract the operand flags (DEST, SRC0, SRC1) from bits 5–7.
654736 These bits encode the operand signature used for format selection. */
655737 unsigned int insn_operands = insn_format >> 5 ;
@@ -863,15 +945,21 @@ arcv_apex_init_builtin (tree fndecl, const char *fn_name,
863945
864946 /* Resolve the instruction format:
865947 If the user did not specify an instruction format at pragma level,
866- infer the concrete format based on opcode and operand flags; otherwise,
867- leave it as is. */
868- insn_formats = arcv_apex_resolve_insn_format (insn_formats, opcode);
948+ infer the concrete format based on opcode and operand flags. Mark
949+ the insn. name with an "i" suffix for resolved XS/XI/XC formats;
950+ otherwise, leave it as is. */
951+ const char *insn_suffix = " " ;
952+ if ((insn_formats & 0xF ) == APEX_NONE)
953+ {
954+ insn_formats = arcv_apex_resolve_insn_format (insn_formats, opcode);
955+ insn_suffix = " i" ;
956+ }
869957
870958 /* Validate the format is allowed for this instruction. */
871959 arcv_apex_validate_insn_format (fn_name, insn_formats, opcode);
872960
873961 /* Print .extInstruction section about APEX instruction. */
874- arcv_apex_print_insn_section (insn_name, opcode, insn_formats);
962+ arcv_apex_print_insn_section (insn_name, insn_suffix, opcode, insn_formats);
875963
876964 /* Determine the internal instruction code (icode). */
877965 enum insn_code icode = arcv_apex_get_icode (insn_formats);
@@ -883,7 +971,7 @@ arcv_apex_init_builtin (tree fndecl, const char *fn_name,
883971
884972 /* Store APEX insn information. */
885973 arcv_apex_builtins[arcv_apex_builtin_index]
886- = { icode, fn_name, insn_name, builtin_type, insn_formats };
974+ = { icode, fn_name, insn_name, builtin_type, insn_formats, insn_suffix };
887975
888976 /* Modify the prototype type as built-in. */
889977 fndecl->function_decl .built_in_class = BUILT_IN_MD;
0 commit comments