Difference between revisions of "NaplesPURegisterInfo.td"
Line 1: | Line 1: | ||
The NuPlusRegisterInfo.td is used to define the nu+ hw registers and the nu+ register classes. | The NuPlusRegisterInfo.td is used to define the nu+ hw registers and the nu+ register classes. | ||
+ | |||
+ | The '''registers''' contain informations about the hardware encoding, the asm name used to index a specific register and the [https://en.wikipedia.org/wiki/DWARF DWARF number]. The '''register classes''' contain the bindings between the data-types, the registers to use and their width expressed in bit | ||
The registers definition is done creating two support classes '''NuPlusGPRReg''' and '''NuPlus64GPRReg'''. The first one is used to define 32-bit wide registers while the second is used to define 64-bit wide registers. We made this distinction because the hardware uses the same register for both 32 and 64 bits wide variables. Thus a 64-bit wide register is composed by a couple of 32-bit wide register, using the even sub-register to contain the 32 less significant bits, while the odd sub-register holds the 32 most significant bits. | The registers definition is done creating two support classes '''NuPlusGPRReg''' and '''NuPlus64GPRReg'''. The first one is used to define 32-bit wide registers while the second is used to define 64-bit wide registers. We made this distinction because the hardware uses the same register for both 32 and 64 bits wide variables. Thus a 64-bit wide register is composed by a couple of 32-bit wide register, using the even sub-register to contain the 32 less significant bits, while the odd sub-register holds the 32 most significant bits. | ||
Line 45: | Line 47: | ||
Note also the definition of the special registers. | Note also the definition of the special registers. | ||
+ | |||
+ | The definition of the 64-bit registers is done using the following loop. | ||
+ | |||
+ | <syntaxhighlight lang="c" line='line'> | ||
+ | foreach i = 0-28 in { | ||
+ | def S#!shl(i, 1)#_S#!add(!shl(i, 1), 1) : NuPlus64GPRReg<!shl(i, 1), "s"#!shl(i, 1)#_64, | ||
+ | [!cast<NuPlusGPRReg>("S"#!shl(i, 1)), | ||
+ | !cast<NuPlusGPRReg>("S"#!add(!shl(i, 1), 1))]>; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | The code uses Tablgen commands to define the registers in the form '''Sx_Sy''', where '''x''' is an even number and '''y''' an odd one. | ||
+ | |||
+ | The register classes defined are GPR32, GPR64, VR512W and VR512L. These are for 32-bit scalar variables, 64-bit scalar variables, 32-bit vector variables and 64-bit vector variables respectively. | ||
+ | |||
+ | <syntaxhighlight lang="c" line='line'> | ||
+ | def GPR32 : RegisterClass<"NuPlus", [i32, f32, i64, f64], 32, (add (sequence "S%u", 0, 57), | ||
+ | TR_REG, MR_REG, FP_REG, SP_REG, RA_REG, PC_REG)>; | ||
+ | |||
+ | def GPR64 : RegisterClass<"NuPlus", [i64, f64], 64, | ||
+ | (add S0_S1, S2_S3, S4_S5, S6_S7, | ||
+ | S8_S9, S10_S11, S12_S13, S14_S15, | ||
+ | S16_S17, S18_S19, S20_S21, S22_S23, | ||
+ | S24_S25, S26_S27, S28_S29, S30_S31, | ||
+ | S32_S33, S34_S35, S36_S37, S38_S39, | ||
+ | S40_S41, S42_S43, S44_S45, S46_S47, | ||
+ | S48_S49, S50_S51, S52_S53, S54_S55, | ||
+ | S56_S57)>; | ||
+ | |||
+ | def VR512W : RegisterClass<"NuPlus", [v16i8, v16i16, v16i32, v8f32, v16f32], 512, (sequence "V%u", 0, 63)>; | ||
+ | def VR512L : RegisterClass<"NuPlus", [v8i8, v8i16, v8i32, v8i64, v8f64], 512, (sequence "V%u", 0, 63)>; | ||
+ | </syntaxhighlight> |
Revision as of 16:07, 27 September 2017
The NuPlusRegisterInfo.td is used to define the nu+ hw registers and the nu+ register classes.
The registers contain informations about the hardware encoding, the asm name used to index a specific register and the DWARF number. The register classes contain the bindings between the data-types, the registers to use and their width expressed in bit
The registers definition is done creating two support classes NuPlusGPRReg and NuPlus64GPRReg. The first one is used to define 32-bit wide registers while the second is used to define 64-bit wide registers. We made this distinction because the hardware uses the same register for both 32 and 64 bits wide variables. Thus a 64-bit wide register is composed by a couple of 32-bit wide register, using the even sub-register to contain the 32 less significant bits, while the odd sub-register holds the 32 most significant bits.
// NuPlus 32-bit registers
class NuPlusGPRReg<bits<16> Enc, string n> : NuPlusReg<Enc, n>;
// NuPlus pairs of 32-bit registers
class NuPlus64GPRReg<bits<16> Enc, string n, list<Register> subregs>
: NuPlusRegWithSubRegs<Enc, n, subregs> {
let SubRegIndices = [sub_even, sub_odd];
let CoveredBySubRegs = 1;
}
Note that the NuPlus64GPRReg uses SubRegIndices to index a specific 32-bit wide sub-register. In particular, sub_even indexes the even sub-register, while sub_odd indexes the odd sub-register.
Two loops are used to define the architecture general purpose registers.
// General Purpose scalar registers
foreach i = 0-57 in {
def S#i : NuPlusGPRReg<i, "s"#i>, DwarfRegNum<[i]>;
}
//trap register
def TR_REG : NuPlusGPRReg<58, "tr">, DwarfRegNum<[58]>;
//mask register
def MR_REG : NuPlusGPRReg<59, "rm">, DwarfRegNum<[59]>;
//frame pointer
def FP_REG : NuPlusGPRReg<60, "fp">, DwarfRegNum<[60]>;
//stack pointer
def SP_REG : NuPlusGPRReg<61, "sp">, DwarfRegNum<[61]>;
//return address
def RA_REG : NuPlusGPRReg<62, "ra">, DwarfRegNum<[62]>;
//PC
def PC_REG : NuPlusGPRReg<63, "pc">, DwarfRegNum<[63]>;
// General Purpose vectorial registers
foreach i = 0-63 in {
def V#i : NuPlusGPRReg<i, "v"#i>, DwarfRegNum<[!add(i, 64)]>;
}
Note also the definition of the special registers.
The definition of the 64-bit registers is done using the following loop.
foreach i = 0-28 in {
def S#!shl(i, 1)#_S#!add(!shl(i, 1), 1) : NuPlus64GPRReg<!shl(i, 1), "s"#!shl(i, 1)#_64,
[!cast<NuPlusGPRReg>("S"#!shl(i, 1)),
!cast<NuPlusGPRReg>("S"#!add(!shl(i, 1), 1))]>;
}
The code uses Tablgen commands to define the registers in the form Sx_Sy, where x is an even number and y an odd one.
The register classes defined are GPR32, GPR64, VR512W and VR512L. These are for 32-bit scalar variables, 64-bit scalar variables, 32-bit vector variables and 64-bit vector variables respectively.
def GPR32 : RegisterClass<"NuPlus", [i32, f32, i64, f64], 32, (add (sequence "S%u", 0, 57),
TR_REG, MR_REG, FP_REG, SP_REG, RA_REG, PC_REG)>;
def GPR64 : RegisterClass<"NuPlus", [i64, f64], 64,
(add S0_S1, S2_S3, S4_S5, S6_S7,
S8_S9, S10_S11, S12_S13, S14_S15,
S16_S17, S18_S19, S20_S21, S22_S23,
S24_S25, S26_S27, S28_S29, S30_S31,
S32_S33, S34_S35, S36_S37, S38_S39,
S40_S41, S42_S43, S44_S45, S46_S47,
S48_S49, S50_S51, S52_S53, S54_S55,
S56_S57)>;
def VR512W : RegisterClass<"NuPlus", [v16i8, v16i16, v16i32, v8f32, v16f32], 512, (sequence "V%u", 0, 63)>;
def VR512L : RegisterClass<"NuPlus", [v8i8, v8i16, v8i32, v8i64, v8f64], 512, (sequence "V%u", 0, 63)>;