riscv-gcc工具,有内置的一些宏参数。我们可以根据这些内置的宏参数,判断编译器的行为。
一、查看gcc内置宏参数
这里以芯来科技发布的riscv-nuclei-elf-gcc工具链为例。
使用以下命令,可以得到该工具的内置宏参数:
riscv-nuclei-elf-gcc -E -dM a.h | grep riscv
可以得到如下的一些宏参数
#define __riscv 1
#define __riscv_atomic 1
#define __riscv_cmodel_medlow 1
#define __riscv_fdiv 1
#define __riscv_float_abi_double 1
#define __riscv_flen 64
#define __riscv_compressed 1
#define __riscv_mul 1
#define __riscv_muldiv 1
#define __riscv_xlen 32
#define __riscv_fsqrt 1
#define __riscv_div 1
从内置宏参数,可以看出编译器,默认支持RV64IMAFDC指令集架构。
如果使用以下命令:
riscv-nuclei-elf-gcc -march=rv32gc -mabi=ilp32 -E -dM a.h | grep riscv
得到如下结果:
#define __riscv 1
#define __riscv_atomic 1
#define __riscv_cmodel_medlow 1
#define __riscv_float_abi_soft 1
#define __riscv_fdiv 1
#define __riscv_flen 64
#define __riscv_compressed 1
#define __riscv_mul 1
#define __riscv_muldiv 1
#define __riscv_xlen 32
#define __riscv_fsqrt 1
#define __riscv_div 1
从内置宏参数,可以看出编译器,支持RV32IMAFDC指令集架构。
二、增加内置宏参数
对于riscv,支持p扩展,该扩展,是针对于dsp应用。
如果我们想,当gcc的-march选项中,有指定p扩展指令集,那么编译器就内置__riscv_dsp宏。如果没有指定p扩展指令集,就不内置该__riscv_dsp宏。
这样的话,编写的dsp程序,就可以使用该宏判断,是否支持p扩展指令。
下面简述一下,如何实现该功能,也就是如何根据所传参指令集架构参数,增加内置宏参数。
这里,主要是参考riscv-gcc的如下commit:
https://github.com/riscv/riscv-gcc/commit/06ab742f982d23488ec2d8c0266cb720fe775f7c
该commit,是往riscv-gcc中增加RV32E的支持。
三、修改riscv.opt
首先是修改 gcc/config/riscv/riscv.opt文件,在其中,增加DSP宏。
gcc的脚本工具,会处理该文件,通过Mask展开,定义新的宏参数。
在编译目录下的 gcc/options.h 文件中,有该宏参数定义。
TARGET和MASK宏的定义
#define MASK_DIV (1U <<0)
#define MASK_EXPLICIT_RELOCS (1U <<1)
#define MASK_FDIV (1U <<2)
#define MASK_SAVE_RESTORE (1U <<3)
#define MASK_STRICT_ALIGN (1U <<4)
#define MASK_64BIT (1U <<5)
#define MASK_ATOMIC (1U <<6)
#define MASK_DOUBLE_FLOAT (1U <<7)
#define MASK_DSP (1U <<8)
#define MASK_HARD_FLOAT (1U <<9)
#define MASK_MUL (1U <<10)
#define MASK_RVC (1U <<11)
#define MASK_RVE (1U <<12)
#define TARGET_DIV ((target_flags & MASK_DIV) !&#61; 0)
#define TARGET_DIV_P(target_flags) (((target_flags) & MASK_DIV) !&#61; 0)
#define TARGET_EXPLICIT_RELOCS ((target_flags & MASK_EXPLICIT_RELOCS) !&#61; 0)
#define TARGET_EXPLICIT_RELOCS_P(target_flags) (((target_flags) & MASK_EXPLICIT_RELOCS) !&#61; 0)
#define TARGET_FDIV ((target_flags & MASK_FDIV) !&#61; 0)
#define TARGET_FDIV_P(target_flags) (((target_flags) & MASK_FDIV) !&#61; 0)
#define TARGET_SAVE_RESTORE ((target_flags & MASK_SAVE_RESTORE) !&#61; 0)
#define TARGET_SAVE_RESTORE_P(target_flags) (((target_flags) & MASK_SAVE_RESTORE) !&#61; 0)
#define TARGET_STRICT_ALIGN ((target_flags & MASK_STRICT_ALIGN) !&#61; 0)
#define TARGET_STRICT_ALIGN_P(target_flags) (((target_flags) & MASK_STRICT_ALIGN) !&#61; 0)
#define TARGET_64BIT ((target_flags & MASK_64BIT) !&#61; 0)
#define TARGET_ATOMIC ((target_flags & MASK_ATOMIC) !&#61; 0)
#define TARGET_DOUBLE_FLOAT ((target_flags & MASK_DOUBLE_FLOAT) !&#61; 0)
#define TARGET_DSP ((target_flags & MASK_DSP) !&#61; 0)
#define TARGET_HARD_FLOAT ((target_flags & MASK_HARD_FLOAT) !&#61; 0)
#define TARGET_MUL ((target_flags & MASK_MUL) !&#61; 0)
#define TARGET_RVC ((target_flags & MASK_RVC) !&#61; 0)
#define TARGET_RVE ((target_flags & MASK_RVE) !&#61; 0)
这里的options.h文件&#xff0c;是gcc的内置脚本生成的&#xff0c;目前我还没有研究清楚该脚本是如何工作生成的。
四、修改riscv-common.c
得到上述的宏之后&#xff0c;需要修改gcc/common/config/riscv/riscv-common.c文件。
在riscv_parse_arch_string函数中&#xff0c;就会分析传入的--march参数&#xff0c;然后设置flags&#xff0c;给flags加上对应的TARGET支持。
模仿c扩展的支持&#xff0c;增加p扩展的支持。
static void
riscv_parse_arch_string (const char *isa, int *flags, location_t loc)
{
riscv_subset_list *subset_list;
subset_list &#61; riscv_subset_list::parse (isa, loc);
if (!subset_list)
return;
if (subset_list->xlen &#61;&#61; 32)
*flags &&#61; ~MASK_64BIT;
else if (subset_list->xlen &#61;&#61; 64)
*flags |&#61; MASK_64BIT;
*flags &&#61; ~MASK_RVE;
if (subset_list->lookup ("e"))
*flags |&#61; MASK_RVE;
*flags &&#61; ~MASK_MUL;
if (subset_list->lookup ("m"))
*flags |&#61; MASK_MUL;
*flags &&#61; ~MASK_ATOMIC;
if (subset_list->lookup ("a"))
*flags |&#61; MASK_ATOMIC;
*flags &&#61; ~(MASK_HARD_FLOAT | MASK_DOUBLE_FLOAT);
if (subset_list->lookup ("f"))
*flags |&#61; MASK_HARD_FLOAT;
if (subset_list->lookup ("d"))
*flags |&#61; MASK_DOUBLE_FLOAT;
*flags &&#61; ~MASK_RVC;
if (subset_list->lookup ("c"))
*flags |&#61; MASK_RVC;
*flags &&#61; ~MASK_DSP;
if (subset_list->lookup ("p"))
*flags |&#61; MASK_DSP;
if (current_subset_list)
delete current_subset_list;
current_subset_list &#61; subset_list;
}
通过调用subset_list的lookup函数&#xff0c;查看是否有传入对应的指令集架构。如果有的话&#xff0c;在flags中&#xff0c;将对应的MASK给设置上。
五、修改riscv-c.c
修改 gcc/config/riscv/riscv-c.c 文件。增加内置宏。
该文件中的riscv_cpu_cpp_builtins函数&#xff0c;就是增加内置宏参数的函数。
void
riscv_cpu_cpp_builtins (cpp_reader *pfile)
{
builtin_define ("__riscv");
if (TARGET_RVC)
builtin_define ("__riscv_compressed");
if (TARGET_RVE)
builtin_define ("__riscv_32e");
if (TARGET_ATOMIC)
builtin_define ("__riscv_atomic");
if (TARGET_MUL)
builtin_define ("__riscv_mul");
if (TARGET_DIV)
builtin_define ("__riscv_div");
if (TARGET_DIV && TARGET_MUL)
builtin_define ("__riscv_muldiv");
if (TARGET_DSP)
builtin_define ("__riscv_dsp");
builtin_define_with_int_value ("__riscv_xlen