本项目目标是基于LLVM,实现对平头哥玄铁C910指令集架构的支持。玄铁 C910在RISCV标准指令集架构的基础上,增加了自定义指令,包括 Cache 指令子集,同步指令子集,算术运算指令子集,位操作指令子集以及存储指令子集。本项目主要工作是在RISCV后端实现这些扩展指令支持。
同步指令子集
| 指令 | 描述 | 状态 |
|---|---|---|
| SYNC | 同步指令 | ☑️ |
| SYNC.I | 同步清空指令 | ☑️ |
| SYNC.IS | 同步清空广播指令 | ☑️ |
| SYNC.S | 同步广播指令 | ☑️ |
算术运算指令子集
| 指令 | 描述 | 状态 |
|---|---|---|
| ADDSL | 寄存器移位相加指令 | ☑️ |
| MULA | 乘累加指令 | ☑️ |
| MULAH | 低 16 位乘累加指令 | ☑️ |
| MULAW | 低 32 位乘累加指令 | ☑️ |
| MULS | 乘累减指令 | ☑️ |
| MULSH | 低 16 位乘累减指令 | ☑️ |
| MULSW | 低 32 位乘累减指令 | ☑️ |
| MVEQZ | 寄存器为 0 传送指令 | ☑️ |
| MVNEZ | 寄存器非 0 传送指令 | ☑️ |
| SRRI | 循环右移指令 | ☑️ |
| SRRIW | 低 32 位循环右移指令 | ☑️ |
位操作指令子集
| 指令 | 描述 | 状态 |
|---|---|---|
| EXT | 寄存器连续位提取符号位扩展指令 | ☑️ |
| EXTU | 寄存器连续位提取零扩展指令 | ☑️ |
| FF0 | 快速找 0 指令 | ☑️ |
| FF1 | 快速找 1 指令 | ☑️ |
| REV | 字节倒序指令 | ☑️ |
| REVW | 低 32 位字节倒序指令 | ☑️ |
| TST | 比特为 0 测试指令 | ☑️ |
存储指令子集
| 指令 | 描述 | 状态 |
|---|---|---|
| FLRD | 浮点寄存器移位双字加载指令 | ☑️ |
| FLRW | 浮点寄存器移位字加载指令 | ☑️ |
| FLURD | 浮点寄存器低 32 位移位双字加载指令 | ☑️ |
| FLURW | 浮点寄存器低 32 位移位字加载指令 | ☑️ |
| LRB | 寄存器移位符号位扩展字节加载指令 | ☑️ |
| LRH | 寄存器移位符号位扩展半字加载指令 | ☑️ |
| LRW | 寄存器移位符号位扩展字加载指令 | ☑️ |
| LRD | 寄存器移位双字加载指令 | ☑️ |
| LRBU | 寄存器移位零扩展字节加载指令 | ☑️ |
| LRHU | 寄存器移位零扩展半字加载指令 | ☑️ |
| LRWU | 寄存器移位零扩展字加载指令 | ☑️ |
| LURB | 寄存器低 32 位移位符号位扩展字节加载指令 | ☑️ |
| LURH | 寄存器低 32 位移位符号位扩展半字加载指令 | ☑️ |
| LURW | 寄存器低 32 位移位符号位扩展字加载指令 | ☑️ |
| LURD | 寄存器低 32 位移位双字加载指令 | ☑️ |
| LURBU | 寄存器低 32 位移位零扩展字节加载指令 | ☑️ |
| LURHU | 寄存器低 32 位移位零扩展半字加载指令 | ☑️ |
| LURWU | 寄存器低 32 位移位零扩展字加载指令 | ☑️ |
| LBIA | 符号位扩展字节加载基地址自增指令 | ☑️ |
| LBIB | 基地址自增符号位扩展字节加载指令 | ☑️ |
| LHIA | 符号位扩展半字加载基地址自增指令 | ☑️ |
| LHIB | 基地址自增符号位扩展半字加载指令 | ☑️ |
| LWIA | 符号位扩展字加载基地址自增指令 | ☑️ |
| LWIB | 基地址自增符号位扩展字加载指令 | ☑️ |
| LDIA | 符号位扩展双字加载基地址自增指令 | ☑️ |
| LDIB | 基地址自增符号位扩展双字加载指令 | ☑️ |
| LBUIA | 零扩展字节加载基地址自增指令 | ☑️ |
| LBUIB | 基地址自增零扩展字节加载指令 | ☑️ |
| LHUIA | 零扩展半字加载基地址自增指令 | ☑️ |
| LHUIB | 基地址自增零扩展半字加载指令 | ☑️ |
| LWUIA | 零扩展字加载基地址自增指令 | ☑️ |
| LWUIB | 基地址自增零扩展字加载指令 | ☑️ |
| LDD | 双寄存器加载指令 | ☑️ |
| LWD | 符号位扩展双寄存器字加载指令 | ☑️ |
| LWUD | 零扩展双寄存器字加载指令 | ☑️ |
| FSRD | 浮点寄存器移位双字存储指令 | ☑️ |
| FSRW | 浮点寄存器移位字存储指令 | ☑️ |
| FSUSR | 浮点寄存器低 32 位移位双字存储指令 | ☑️ |
| FSURW | 浮点寄存器低 32 位移位字存储指令 | ☑️ |
| SRB | 寄存器移位字节存储指令 | ☑️ |
| SRH | 寄存器移位半字存储指令 | ☑️ |
| SRW | 寄存器移位字存储指令 | ☑️ |
| SRD | 寄存器移位双字存储指令 | ☑️ |
| SURB | 寄存器低 32 位移位字节存储指令 | ☑️ |
| SURH | 寄存器低 32 位移位半字存储指令 | ☑️ |
| SURW | 寄存器低 32 位移位字存储指令 | ☑️ |
| SURD | 寄存器低 32 位移位双字存储指令 | ☑️ |
| SBIA | 字节存储基地址自增指令 | ☑️ |
| SBIB | 基地址自增字节存储指令 | ☑️ |
| SHIA | 半字存储基地址自增指令 | ☑️ |
| SHIB | 基地址自增半字存储指令 | ☑️ |
| SWIA | 字存储基地址自增指令 | ☑️ |
| SWIB | 基地址自增字存储指令 | ☑️ |
| SDIA | 双字存储基地址自增指令 | ☑️ |
| SDIB | 基地址自增双字存储指令 | ☑️ |
| SDD | 双寄存器存储指令 | ☑️ |
| SWD | 双寄存器低 32 位存储指令 | ☑️ |
Cache指令子集
| 指令 | 描述 | 状态 |
|---|---|---|
| DCACHE.CALL | DCACHE 清全部脏表项指令 | ☑️ |
| DCACHE.CIALL | DCACHE 清全部脏表项并无效表项指令 | ☑️ |
| DCACHE.CIPA | DCACHE 按物理地址清脏表项并无效表项指令 | ☑️ |
| DCACHE.CISW | DCACHE 按 way/set 清脏表项并无效表项指令 | ☑️ |
| DCACHE.CIVA | DCACHE 按虚拟地址清脏表项并无效表项指令 | ☑️ |
| DCACHE.CPA | DCACHE 按物理地址清脏表项指令 | ☑️ |
| DCACHE.CPAL1 | L1DCACHE 按物理地址清脏表项指令 | ☑️ |
| DCACHE.CVA | DCACHE 按虚拟地址清脏表项指令 | ☑️ |
| DCACHE.CVAL1 | L1DCACHE 按虚拟地址清脏表项指令 | ☑️ |
| DCACHE.IPA | DCACHE 按物理地址无效指令 | ☑️ |
| DCHCHE.ISW | DCACHE按set/way无效指令 | ☑️ |
| DCACHE.IVA | DCACHE 按虚拟地址无效指令 | ☑️ |
| DCACHE.IALL | DCACHE 无效所有表项指令 | ☑️ |
| ICACHE.IALL | ICACHE 无效所有表项指令 | ☑️ |
| ICACHE.IALLS | ICACHE 广播无效所有表项指令 | ☑️ |
| ICACHE.IPA | ICACHE按物理地址无效表项指令 | ☑️ |
| ICACHE.IVA | ICACHE按虚拟地址无效表项指令 | ☑️ |
| L2CACHE.CALL | L2CACHE清所有脏表项指令 | ☑️ |
| L2CACHE.CIALL | L2CACHE清所有脏表项指令并无效指令 | ☑️ |
| L2CACHE.IALL | L2CACHE无效所有表项指令 | ☑️ |
机器模式控制寄存器
机器模式扩展状态寄存器(MXSTATUS)
机器模式硬件控制寄存器(MHCR)
机器模式硬件操作寄存器(MCOR)
机器模式 L2cache 控制寄存器(MCCR2)
机器模式L2cache ECC 寄存器
机器模式隐式操作寄存器(MHINT)
机器模式复位寄存器(MRMR)
机器模式复位向量基址寄存器(MRVBR)
机器模式 Cache 指令寄存器(MCINS)
机器模式 Cache 访问索引寄存器(MCINDEX)
机器模式 Cache 数据寄存器(MCDATA0/1)
机器模式处理器型号寄存器(MCPUID)
超级用户模式控制寄存器
超级用户模式扩展状态寄存器(SXTATUS)
超级用户模式硬件配置寄存器(SHCR)
超级用户模式 L2Cache ECC 寄存器(SCER2)
用户模式控制寄存器
用户模式浮点扩展控制寄存器(FXCR)
编译:
本仓库目前没有包含 clang 代码,用户可以选择使用自己的 clang 前端来一起构建。也可以仅构建本仓库代码。
(1)不用clang,直接构建本仓库代码:
git clone https://github.com/isrc-cas/c910-llvm
$ cd c910-llvm
$ mkdir build
$ cd build
$ cmake -DLLVM_TARGETS_TO_BUILD="RISCV" -G "Unix Makefiles" ..
$ make -j $(nproc)
(2)和clang一起构建:如果没有自定义的前端,那么可以使用LLVM官方的Clang-9.0.0版本。
$ wget https://releases.llvm.org/9.0.0/cfe-9.0.0.src.tar.xz
$ tar xf cfe-9.0.0.src.tar.xz
$ mv cfe-9.0.0.src clang
$ git clone https://github.com/isrc-cas/c910-llvm
$ cd c910-llvm
$ mkdir build
$ cd build
$ cmake -DLLVM_TARGETS_TO_BUILD="RISCV" -DLLVM_ENABLE_PROJECTS=clang -G "Unix Makefiles" ..
$ make -j $(nproc)
执行测试用例:
$ ./bin/llvm-lit -v ../test/MC/RISCV/c910-valid.s
执行的结果如下:
-- Testing: 1 tests, single process --
PASS: LLVM :: MC/RISCV/c910-valid.s (1 of 1)
Testing Time: 0.30s
Expected Passes : 1
c910指令汇编生成二进制文件:
$ ./bin/llvm-mc test.s -triple=riscv64 -mcpu=c910 -show-encoding -show-inst --filetype=obj -o=test.o
注:这里的 test.s 意指包含C910扩展指令的汇编文件。(可以在c/c++代码中使用内联汇编添加一条上述已定义的C910指令,然后使用clang编译生成./bin/clang --target=riscv64-unknown-elf test.c -S -o test.s,如下所示:)
int main(){
int a,b,c;
a = 1;
b = 2;
asm volatile
(
"mula %[z], %[x], %[y]\n\t"
: [z] "=r" (c)
: [x] "r" (a), [y] "r" (b)
);
if ( c == 0 ){
return -1;
}
return 0;
}