RISC-Vには32ビットモード(RV32)、64ビットモード(RV64)、128ビットモード(RV128)が定義されている。これまではRV32による32ビットのみをサポートしてきたが、RV64もサポートしたい。具体的に言えば、
- RV64モードの時にレジスタ幅を64ビットとして取り扱う(スタックの取り扱いなどをそれに伴い変える)
- RV64モード用の命令が使えるようになる。
などが行えるようになりたい。ここでは、RV64をサポートして、さまざまな追加命令と命令生成の調整を行う。
HwModeの追加
まず、2つのハードウェアタイプを追加する。RV64とRV32だ。ここでは、+64bit
と-64bit
によりそれぞれのハードウェアタイプを識別することにする。
lib/Target/MYRISCVX/MYRISCVX.td
def RV64 : HwMode<"+64bit">; def RV32 : HwMode<"-64bit">;
レジスタ定義の変更
次に、これまで32ビットで定義していたレジスタを拡張しなければならない。レジスタの定義はMYRISCVXRegister.td
で行っていたので、こちらを変更する。
llvm-myriscvx/lib/Target/MYRISCVX/MYRISCVXRegisterInfo.td
def GPR : RegisterClass<"MYRISCVX", [i32], 32, (add // Reserved ZERO, // Return Values and Arguments A0, A1, A2, A3, A4, A5, A6, A7, // Not preserved across procedure calls T0, T1, T2, T3, T4, T5, T6, // Callee save FP, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, // Reserved RA, SP, GP, TP )>
i32
のみで定義していたので、HwModeに応じてレジスタの定義を変えるように変更する。
def XLenVT : ValueTypeByHwMode<[RV32, RV64, DefaultMode], [i32, i64, i32]>; def GPR : RegisterClass<"MYRISCVX", [XLenVT], 32, (add // Reserved ZERO, // Return Values and Arguments A0, A1, A2, A3, A4, A5, A6, A7, // Not preserved across procedure calls T0, T1, T2, T3, T4, T5, T6, // Callee save FP, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, // Reserved RA, SP, GP, TP )> { let RegInfos = RegInfoByHwMode< [RV32, RV64, DefaultMode], [RegInfo<32,32,32>, RegInfo<64,64,64>, RegInfo<32,32,32>]>; }
XLenVT
という変数を導入した。XLenVT
はHwModeに応じて型が変わる。これに応じて、レジスタのサイズを変える、という訳だ。
生成されたレジスタ情報MYRISCVXGenRegisterInfo.inc
には3種類のモードが登録されている。
build-myriscvx/lib/Target/MYRISCVX/MYRISCVXGenRegisterInfo.inc
static const TargetRegisterInfo::RegClassInfo RegClassInfos[] = { // Mode = 0 (Default) { 32, 32, 32, VTLists+4 }, // FPR_S { 32, 32, 32, VTLists+0 }, // GPR { 64, 64, 32, VTLists+6 }, // FPR_D // Mode = 1 (RV32) { 32, 32, 32, VTLists+4 }, // FPR_S { 32, 32, 32, VTLists+0 }, // GPR { 64, 64, 32, VTLists+6 }, // FPR_D // Mode = 2 (RV64) { 32, 32, 32, VTLists+4 }, // FPR_S { 64, 64, 64, VTLists+2 }, // GPR { 64, 64, 32, VTLists+6 }, // FPR_D };
64ビットロードストア命令の追加
次に、64ビットのロードストア命令を追加する。RISC-Vでは、64ビットのロードストア命令としてLD/SD
が定義されている。
funct7 | rs2 | rs1 | funct3 | rd | opcode | |
---|---|---|---|---|---|---|
LD | imm[11:5] | imm[4:0] | rs1 | 011 | rd | 0000011 |
SD | imm[11:5] | rs2 | rs1 | 011 | imm[4:0] | 0100011 |
これをMYRISCVXInstrInfo.td
に登録する。
llvm-myriscvx/lib/Target/MYRISCVX/MYRISCVXInstrInfo.td
defm LD : LoadM32 <0b0000011, 0b011, "ld", GPR, load_a>; defm SD : StoreM32<0b0100011, 0b011, "sd", GPR, store_a>;
そして、生成パタンも登録する。
def : Pat<(i64 (load GPR:$rs1)) , (LD GPR:$rs1, 0) >; def : Pat<(i64 (load addr_fi:$rs1)) , (LD addr_fi:$rs1, 0) >; def : Pat<(i64 (load (add GPR:$rs1, simm12:$simm12))) , (LD GPR:$rs1, $simm12) >; def : Pat<(i64 (load (add addr_fi:$rs1, simm12:$simm12))), (LD addr_fi:$rs1, $simm12) >; def : Pat<(store GPR:$rs2, GPR:$rs1) , (SD GPR:$rs2, GPR:$rs1, 0) >; def : Pat<(store GPR:$rs2, addr_fi:$rs1) , (SD GPR:$rs2, addr_fi:$rs1, 0) >; def : Pat<(store GPR:$rs2, (add GPR:$rs1, simm12:$simm12)) , (SD GPR:$rs2, GPR:$rs1, simm12:$simm12) >; def : Pat<(store GPR:$rs2, (add addr_fi:$rs1, simm12:$simm12)), (SD GPR:$rs2, addr_fi:$rs1, simm12:$simm12) >;