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[] = {
{ 32, 32, 32, VTLists+4 },
{ 32, 32, 32, VTLists+0 },
{ 64, 64, 32, VTLists+6 },
{ 32, 32, 32, VTLists+4 },
{ 32, 32, 32, VTLists+0 },
{ 64, 64, 32, VTLists+6 },
{ 32, 32, 32, VTLists+4 },
{ 64, 64, 64, VTLists+2 },
{ 64, 64, 32, VTLists+6 },
};
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) >;