1 //
2 // Copyright (c) 2010-2021 Antmicro
3 //
4 // This file is licensed under the MIT License.
5 // Full license text is available in 'licenses/MIT.txt'.
6 //
7 using System;
8 using System.Collections.Generic;
9 
10 namespace Antmicro.Renode.Peripherals.CPU
11 {
12     // Those methods use RiscV32Registers enum and assume those values are also valid for rv64
13     public static class RiscVRegisterDescription
14     {
AddCpuFeature(ref List<GDBFeatureDescriptor> features, uint registerWidth)15         public static void AddCpuFeature(ref List<GDBFeatureDescriptor> features, uint registerWidth)
16         {
17             var cpuGroup = new GDBFeatureDescriptor("org.gnu.gdb.riscv.cpu");
18             var intType = $"uint{registerWidth}";
19 
20             for(var index = 0u; index < NumberOfXRegisters; ++index)
21             {
22                 cpuGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.X0 + index, registerWidth, $"x{index}", intType, "general"));
23             }
24 
25             cpuGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.PC, registerWidth, "pc", "code_ptr", "general"));
26             features.Add(cpuGroup);
27         }
28 
AddFpuFeature(ref List<GDBFeatureDescriptor> features, uint registerWidth, bool extensionH, bool extensionF, bool extensionD, bool extensionQ)29         public static void AddFpuFeature(ref List<GDBFeatureDescriptor> features, uint registerWidth, bool extensionH, bool extensionF, bool extensionD, bool extensionQ)
30         {
31             if(!(extensionH || extensionF || extensionD || extensionQ))
32             {
33                 return;
34             }
35 
36             var fpuGroup = new GDBFeatureDescriptor("org.gnu.gdb.riscv.fpu");
37             var intType = $"uint{registerWidth}";
38             var fWidth = 0u;
39             var types = new List<string>();
40 
41             if(extensionH)
42             {
43                 fWidth = 16u;
44                 types.Add("half");
45 
46                 var fields = new List<GDBTypeBitField>();
47                 fields.Add(new GDBTypeBitField("sign", 15, 15, "uint16"));
48                 fields.Add(new GDBTypeBitField("exponent", 10, 14, "uint16"));
49                 fields.Add(new GDBTypeBitField("fraction", 0, 9, "uint16"));
50                 var half = GDBCustomType.Struct("half", fWidth / 8, fields);
51                 fpuGroup.Types.Add(half);
52             }
53             if(extensionF)
54             {
55                 fWidth = 32u;
56                 types.Add("single");
57             }
58             if(extensionD)
59             {
60                 fWidth = 64u;
61                 types.Add("double");
62             }
63             if(extensionQ)
64             {
65                 fWidth = 128u;
66                 types.Add("quad");
67 
68                 var fields = new List<GDBTypeBitField>();
69                 fields.Add(new GDBTypeBitField("sign", 127, 127, "uint128"));
70                 fields.Add(new GDBTypeBitField("exponent", 112, 126, "uint128"));
71                 fields.Add(new GDBTypeBitField("fraction", 0, 111, "uint128"));
72                 var quad = GDBCustomType.Struct("quad", fWidth / 8, fields);
73                 fpuGroup.Types.Add(quad);
74             }
75 
76             var floatType = $"ieee_{types[0]}";
77             // If there's more than one float type then they're combined with union
78             // narrower type is in the lowest part of the wider ones, specification calls it NaN-boxing model.
79             if(types.Count > 1)
80             {
81                 floatType = "nan_boxed_float";
82                 var fields = new List<GDBTypeField>();
83                 foreach(var type in types)
84                 {
85                     fields.Add(new GDBTypeField(type, $"ieee_{type}"));
86                 }
87                 var nanBoxedFloat = GDBCustomType.Union(floatType, fields);
88                 fpuGroup.Types.Add(nanBoxedFloat);
89             }
90 
91             for(var index = 0u; index < NumberOfFRegisters; ++index)
92             {
93                 fpuGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.F0 + index, fWidth, $"f{index}", floatType, "float"));
94             }
95 
96             // fflags, frm and fcsr are not implemented but are required for architecture description
97             var fflagsIndex = (uint)RiscV32Registers.F0 + NumberOfFRegisters;
98             fpuGroup.Registers.Add(new GDBRegisterDescriptor(fflagsIndex, registerWidth, "fflags", "", "float"));
99             fpuGroup.Registers.Add(new GDBRegisterDescriptor(fflagsIndex + 1, registerWidth, "frm", "", "float"));
100             fpuGroup.Registers.Add(new GDBRegisterDescriptor(fflagsIndex + 2, registerWidth, "fcsr", "", "float"));
101 
102             {
103                 var fields = new List<GDBTypeBitField>();
104                 fields.Add(new GDBTypeBitField("NX", 0, 0, "bool"));
105                 fields.Add(new GDBTypeBitField("UF", 1, 1, "bool"));
106                 fields.Add(new GDBTypeBitField("OF", 2, 2, "bool"));
107                 fields.Add(new GDBTypeBitField("DZ", 3, 3, "bool"));
108                 fields.Add(new GDBTypeBitField("NV", 4, 4, "bool"));
109                 var fflagsFlagsType = GDBCustomType.Flags("fflags_flags_type", 1, fields);
110                 fpuGroup.Types.Add(fflagsFlagsType);
111             }
112             {
113                 var fields = new List<GDBTypeEnumValue>();
114                 fields.Add(new GDBTypeEnumValue("RNE", 0b000));
115                 fields.Add(new GDBTypeEnumValue("RTZ", 0b001));
116                 fields.Add(new GDBTypeEnumValue("RDN", 0b010));
117                 fields.Add(new GDBTypeEnumValue("RUP", 0b011));
118                 fields.Add(new GDBTypeEnumValue("RMM", 0b100));
119                 fields.Add(new GDBTypeEnumValue("DYN", 0b111));
120                 var frmEnumType = GDBCustomType.Enum("frm_enum_type", 1, fields);
121                 fpuGroup.Types.Add(frmEnumType);
122             }
123             {
124                 var fields = new List<GDBTypeBitField>();
125                 fields.Add(new GDBTypeBitField("value", 0, 4, "fflags_flags_type"));
126                 var fflagsType = GDBCustomType.Struct("fflags_type", registerWidth / 8, fields);
127                 fpuGroup.Types.Add(fflagsType);
128             }
129             {
130                 var fields = new List<GDBTypeBitField>();
131                 fields.Add(new GDBTypeBitField("value", 0, 5, "frm_enum_type"));
132                 var frmType = GDBCustomType.Struct("frm_type", registerWidth / 8, fields);
133                 fpuGroup.Types.Add(frmType);
134             }
135             {
136                 var fields = new List<GDBTypeBitField>();
137                 fields.Add(new GDBTypeBitField("flags", 0, 4, "fflags_flags_type"));
138                 fields.Add(new GDBTypeBitField("rm", 5, 7, "frm_enum_type"));
139                 var fcsrType = GDBCustomType.Struct("fcsr_type", registerWidth / 8, fields);
140                 fpuGroup.Types.Add(fcsrType);
141             }
142 
143             features.Add(fpuGroup);
144         }
145 
AddCSRFeature(ref List<GDBFeatureDescriptor> features, uint registerWidth, bool extensionS, bool extensionU, bool extensionN, bool extensionV)146         public static void AddCSRFeature(ref List<GDBFeatureDescriptor> features, uint registerWidth, bool extensionS, bool extensionU, bool extensionN, bool extensionV)
147         {
148             var csrGroup = new GDBFeatureDescriptor("org.gnu.gdb.riscv.csr");
149             var intType = $"uint{registerWidth}";
150 
151             {
152                 var fields = new List<GDBTypeEnumValue>();
153                 fields.Add(new GDBTypeEnumValue("32", 1));
154                 fields.Add(new GDBTypeEnumValue("64", 2));
155                 fields.Add(new GDBTypeEnumValue("128", 3));
156                 var misaMxlType = GDBCustomType.Enum("xl_type", 2, fields);
157                 csrGroup.Types.Add(misaMxlType);
158             }
159             {
160                 var fields = new List<GDBTypeEnumValue>();
161                 fields.Add(new GDBTypeEnumValue("All off", 0));
162                 fields.Add(new GDBTypeEnumValue("None dirty or clean, some on", 1));
163                 fields.Add(new GDBTypeEnumValue("None dirty, some clean", 2));
164                 fields.Add(new GDBTypeEnumValue("Some dirty", 3));
165                 var xsType = GDBCustomType.Enum("xs_type", 1, fields);
166                 csrGroup.Types.Add(xsType);
167             }
168             {
169                 var fields = new List<GDBTypeEnumValue>();
170                 fields.Add(new GDBTypeEnumValue("Off", 0));
171                 fields.Add(new GDBTypeEnumValue("Initial", 1));
172                 fields.Add(new GDBTypeEnumValue("Clean", 2));
173                 fields.Add(new GDBTypeEnumValue("Dirty", 3));
174                 var fsType = GDBCustomType.Enum("fs_type", 1, fields);
175                 csrGroup.Types.Add(fsType);
176             }
177             {
178                 var fields = new List<GDBTypeEnumValue>();
179                 fields.Add(new GDBTypeEnumValue("U", 0b00));
180                 fields.Add(new GDBTypeEnumValue("S", 0b01));
181                 fields.Add(new GDBTypeEnumValue("M", 0b11));
182                 var privType = GDBCustomType.Enum("priv_type", 1, fields);
183                 csrGroup.Types.Add(privType);
184             }
185             {
186                 var fields = new List<GDBTypeEnumValue>();
187                 fields.Add(new GDBTypeEnumValue("Off", 0));
188                 fields.Add(new GDBTypeEnumValue("Initial", 1));
189                 fields.Add(new GDBTypeEnumValue("Clean", 2));
190                 fields.Add(new GDBTypeEnumValue("Dirty", 3));
191                 var vsType = GDBCustomType.Enum("vs_type", 1, fields);
192                 csrGroup.Types.Add(vsType);
193             }
194             {
195                 var fields = new List<GDBTypeBitField>();
196                 fields.Add(new GDBTypeBitField("UIE", 0, 0, "bool"));
197                 fields.Add(new GDBTypeBitField("SIE", 1, 1, "bool"));
198                 fields.Add(new GDBTypeBitField("MIE", 3, 3, "bool"));
199                 fields.Add(new GDBTypeBitField("UPIE", 4, 4, "bool"));
200                 fields.Add(new GDBTypeBitField("SPIE", 5, 5, "bool"));
201                 fields.Add(new GDBTypeBitField("MPIE", 7, 7, "bool"));
202                 fields.Add(new GDBTypeBitField("SPP", 8, 8, "priv_type"));
203                 fields.Add(new GDBTypeBitField("VS", 9, 10, "vs_type"));
204                 fields.Add(new GDBTypeBitField("MPP", 11, 12, "priv_type"));
205                 fields.Add(new GDBTypeBitField("FS", 13, 14, "fs_type"));
206                 fields.Add(new GDBTypeBitField("XS", 15, 16, "xs_type"));
207                 fields.Add(new GDBTypeBitField("MPRIV", 17, 17, "bool"));
208                 fields.Add(new GDBTypeBitField("SUM", 18, 18, "bool"));
209                 fields.Add(new GDBTypeBitField("MXR", 19, 19, "bool"));
210                 fields.Add(new GDBTypeBitField("TVM", 20, 20, "bool"));
211                 fields.Add(new GDBTypeBitField("TW", 21, 21, "bool"));
212                 fields.Add(new GDBTypeBitField("TSR", 22, 22, "bool"));
213                 if(registerWidth == 32)
214                 {
215                     fields.Add(new GDBTypeBitField("SD", 31, 31, "bool"));
216                 }
217                 else if(registerWidth == 64)
218                 {
219                     fields.Add(new GDBTypeBitField("UXL", 32, 33, "xl_type"));
220                     fields.Add(new GDBTypeBitField("SXL", 34, 35, "xl_type"));
221                     fields.Add(new GDBTypeBitField("SD", 63, 63, "boolc"));
222                 }
223                 else
224                 {
225                     throw new NotImplementedException($"There is no type definition for MSTATUS with register width {registerWidth}.");
226                 }
227                 var mstatusType = GDBCustomType.Struct("mstatus_type", registerWidth / 8, fields);
228                 csrGroup.Types.Add(mstatusType);
229             }
230             {
231                 var fields = new List<GDBTypeBitField>();
232                 for(var c = 'A'; c <= 'Z'; ++c)
233                 {
234                     var index = (uint)(c - 'A');
235                     fields.Add(new GDBTypeBitField($"{c}", index, index, "bool"));
236                 }
237                 var misaExtensionsType = GDBCustomType.Flags("misa_extensions_type", 4, fields);
238                 csrGroup.Types.Add(misaExtensionsType);
239             }
240             {
241                 var fields = new List<GDBTypeBitField>();
242                 fields.Add(new GDBTypeBitField("MXL", registerWidth - 2, registerWidth - 1, "xl_type"));
243                 fields.Add(new GDBTypeBitField("Extensions", 0, 25, "misa_extensions_type"));
244                 var misaType = GDBCustomType.Struct("misa_type", registerWidth / 8, fields);
245                 csrGroup.Types.Add(misaType);
246             }
247             {
248                 var fields = new List<GDBTypeBitField>();
249                 fields.Add(new GDBTypeBitField("USIP", 0, 0, "bool"));
250                 fields.Add(new GDBTypeBitField("SSIP", 1, 1, "bool"));
251                 fields.Add(new GDBTypeBitField("MSIP", 3, 3, "bool"));
252                 fields.Add(new GDBTypeBitField("UTIP", 4, 4, "bool"));
253                 fields.Add(new GDBTypeBitField("STIP", 5, 5, "bool"));
254                 fields.Add(new GDBTypeBitField("MTIP", 7, 7, "bool"));
255                 fields.Add(new GDBTypeBitField("UEIP", 8, 8, "bool"));
256                 fields.Add(new GDBTypeBitField("SEIP", 9, 9, "bool"));
257                 fields.Add(new GDBTypeBitField("MEIP", 11, 11, "bool"));
258                 var mipType = GDBCustomType.Flags("mip_type", registerWidth / 8, fields);
259                 csrGroup.Types.Add(mipType);
260             }
261             {
262                 var fields = new List<GDBTypeBitField>();
263                 fields.Add(new GDBTypeBitField("USIE", 0, 0, "bool"));
264                 fields.Add(new GDBTypeBitField("SSIE", 1, 1, "bool"));
265                 fields.Add(new GDBTypeBitField("MSIE", 3, 3, "bool"));
266                 fields.Add(new GDBTypeBitField("UTIE", 4, 4, "bool"));
267                 fields.Add(new GDBTypeBitField("STIE", 5, 5, "bool"));
268                 fields.Add(new GDBTypeBitField("MTIE", 7, 7, "bool"));
269                 fields.Add(new GDBTypeBitField("UEIE", 8, 8, "bool"));
270                 fields.Add(new GDBTypeBitField("SEIE", 9, 9, "bool"));
271                 fields.Add(new GDBTypeBitField("MEIE", 11, 11, "bool"));
272                 var mieType = GDBCustomType.Flags("mie_type", registerWidth / 8, fields);
273                 csrGroup.Types.Add(mieType);
274             }
275             {
276                 var fields = new List<GDBTypeEnumValue>();
277                 fields.Add(new GDBTypeEnumValue("Direct", 0));
278                 fields.Add(new GDBTypeEnumValue("Vectored", 1));
279                 var mtvecModeType = GDBCustomType.Enum("tvec_mode_type", 1, fields);
280                 csrGroup.Types.Add(mtvecModeType);
281             }
282             {
283                 var fields = new List<GDBTypeBitField>();
284                 fields.Add(new GDBTypeBitField("MODE", 0, 1, "tvec_mode_type"));
285                 fields.Add(new GDBTypeBitField("BASE", 2, registerWidth - 1, "code_ptr"));
286                 var tvecType = GDBCustomType.Struct("tvec_type", registerWidth / 8, fields);
287                 csrGroup.Types.Add(tvecType);
288             }
289             {
290                 var fields = new List<GDBTypeBitField>();
291                 fields.Add(new GDBTypeBitField("Interrupt", registerWidth - 1, registerWidth - 1, "bool"));
292                 fields.Add(new GDBTypeBitField("Exception Code", 0, registerWidth - 2, intType));
293                 var mcauseType = GDBCustomType.Struct("cause_type", registerWidth / 8, fields);
294                 csrGroup.Types.Add(mcauseType);
295             }
296 
297             if(extensionS)
298             {
299                 {
300                     var fields = new List<GDBTypeBitField>();
301                     fields.Add(new GDBTypeBitField("UIE", 0, 0, "bool"));
302                     fields.Add(new GDBTypeBitField("SIE", 1, 1, "bool"));
303                     fields.Add(new GDBTypeBitField("UPIE", 4, 4, "bool"));
304                     fields.Add(new GDBTypeBitField("SPIE", 5, 5, "bool"));
305                     fields.Add(new GDBTypeBitField("SPP", 8, 8, "priv_type"));
306                     fields.Add(new GDBTypeBitField("FS", 13, 14, "fs_type"));
307                     fields.Add(new GDBTypeBitField("XS", 15, 16, "xs_type"));
308                     fields.Add(new GDBTypeBitField("SUM", 18, 18, "bool"));
309                     fields.Add(new GDBTypeBitField("MXR", 19, 19, "bool"));
310                     if(registerWidth == 32)
311                     {
312                         fields.Add(new GDBTypeBitField("SD", 31, 31, "bool"));
313                     }
314                     else if(registerWidth == 64)
315                     {
316                         fields.Add(new GDBTypeBitField("UXL", 32, 33, "xl_type"));
317                         fields.Add(new GDBTypeBitField("SD", 63, 63, "boolc"));
318                     }
319                     else
320                     {
321                         throw new NotImplementedException($"There is no type definition for SSTATUS with register width {registerWidth}.");
322                     }
323                     var sstatusType = GDBCustomType.Struct("sstatus_type", registerWidth / 8, fields);
324                     csrGroup.Types.Add(sstatusType);
325                 }
326                 {
327                     var fields = new List<GDBTypeBitField>();
328                     fields.Add(new GDBTypeBitField("USIP", 0, 0, "bool"));
329                     fields.Add(new GDBTypeBitField("SSIP", 1, 1, "bool"));
330                     fields.Add(new GDBTypeBitField("UTIP", 4, 4, "bool"));
331                     fields.Add(new GDBTypeBitField("STIP", 5, 5, "bool"));
332                     fields.Add(new GDBTypeBitField("UEIP", 8, 8, "bool"));
333                     fields.Add(new GDBTypeBitField("SEIP", 9, 9, "bool"));
334                     var sipType = GDBCustomType.Flags("sip_type", registerWidth / 8, fields);
335                     csrGroup.Types.Add(sipType);
336                 }
337                 {
338                     var fields = new List<GDBTypeBitField>();
339                     fields.Add(new GDBTypeBitField("USIE", 0, 0, "bool"));
340                     fields.Add(new GDBTypeBitField("SSIE", 1, 1, "bool"));
341                     fields.Add(new GDBTypeBitField("UTIE", 4, 4, "bool"));
342                     fields.Add(new GDBTypeBitField("STIE", 5, 5, "bool"));
343                     fields.Add(new GDBTypeBitField("UEIE", 8, 8, "bool"));
344                     fields.Add(new GDBTypeBitField("SEIE", 9, 9, "bool"));
345                     var sieType = GDBCustomType.Flags("sie_type", registerWidth / 8, fields);
346                     csrGroup.Types.Add(sieType);
347                 }
348                 {
349                     var fields = new List<GDBTypeEnumValue>();
350                     fields.Add(new GDBTypeEnumValue("Bare", 0));
351                     fields.Add(new GDBTypeEnumValue("Sv32", 1));
352                     fields.Add(new GDBTypeEnumValue("Sv39", 8));
353                     fields.Add(new GDBTypeEnumValue("Sv48", 9));
354                     fields.Add(new GDBTypeEnumValue("Sv57", 10));
355                     fields.Add(new GDBTypeEnumValue("Sv64", 11));
356                     var satpModeType = GDBCustomType.Enum("satp_mode_type", 1, fields);
357                     csrGroup.Types.Add(satpModeType);
358                 }
359                 {
360                     var fields = new List<GDBTypeBitField>();
361                     if(registerWidth == 32)
362                     {
363                         fields.Add(new GDBTypeBitField("PPN", 0, 21, "data_ptr"));
364                         fields.Add(new GDBTypeBitField("ASID", 22, 30, "data_ptr"));
365                         fields.Add(new GDBTypeBitField("MODE", 31, 31, "satp_mode_type"));
366                     }
367                     else if(registerWidth == 64)
368                     {
369                         fields.Add(new GDBTypeBitField("PPN", 0, 43, "data_ptr"));
370                         fields.Add(new GDBTypeBitField("ASID", 44, 59, "data_ptr"));
371                         fields.Add(new GDBTypeBitField("MODE", 60, 63, "satp_mode_type"));
372                     }
373                     else
374                     {
375                         throw new NotImplementedException($"There is no type definition for SATP with register width {registerWidth}.");
376                     }
377                     var satpType = GDBCustomType.Struct("satp_type", registerWidth / 8, fields);
378                     csrGroup.Types.Add(satpType);
379                 }
380 
381                 csrGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.SSTATUS, registerWidth, "sstatus", "sstatus_type", "csr"));
382                 csrGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.SIE, registerWidth, "sie", "sie_type", "csr"));
383                 csrGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.SIP, registerWidth, "sip", "sip_type", "csr"));
384                 csrGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.STVEC, registerWidth, "stvec", "tvec_type", "csr"));
385                 csrGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.SSCRATCH, registerWidth, "sscratch", "data_ptr", "csr"));
386                 csrGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.SEPC, registerWidth, "sepc", "code_ptr", "csr"));
387                 csrGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.SCAUSE, registerWidth, "scause", "cause_type", "csr"));
388                 csrGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.STVAL, registerWidth, "stval", intType, "csr"));
389                 csrGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.SATP, registerWidth, "satp", "satp_type", "csr"));
390             }
391             if(extensionS || (extensionU && extensionN))
392             {
393                 csrGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.MEDELEG, registerWidth, "medeleg", intType, "csr"));
394                 csrGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.MIDELEG, registerWidth, "mideleg", intType, "csr"));
395             }
396 
397             csrGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.MSTATUS, registerWidth, "mstatus", "", "csr"));
398             csrGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.MISA, registerWidth, "misa", "", "csr"));
399             csrGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.MIE, registerWidth, "mie", "mie_type", "csr"));
400             csrGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.MIP, registerWidth, "mip", "mip_type", "csr"));
401             csrGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.MTVEC, registerWidth, "mtvec", "tvec_type", "csr"));
402             csrGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.MSCRATCH, registerWidth, "mscratch", "data_ptr", "csr"));
403             csrGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.MEPC, registerWidth, "mepc", "code_ptr", "csr"));
404             csrGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.MCAUSE, registerWidth, "mcause", "cause_type", "csr"));
405             csrGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.MTVAL, registerWidth, "mtval", intType, "csr"));
406 
407             if(extensionV)
408             {
409                 csrGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.VSTART, registerWidth, "vstart", group: "vector"));
410                 csrGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.VXSAT, registerWidth, "vxsat", group: "vector"));
411                 csrGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.VXRM, registerWidth, "vxrm", group: "vector"));
412                 csrGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.VCSR, registerWidth, "vcsr", group: "vector"));
413                 csrGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.VL, registerWidth, "vl", group: "vector"));
414                 csrGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.VTYPE, registerWidth, "vtype", group: "vector"));
415                 csrGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.VLENB, registerWidth, "vlenb", group: "vector"));
416             }
417 
418             features.Add(csrGroup);
419         }
420 
AddVirtualFeature(ref List<GDBFeatureDescriptor> features, uint registerWidth)421         public static void AddVirtualFeature(ref List<GDBFeatureDescriptor> features, uint registerWidth)
422         {
423             var virtualGroup =  new GDBFeatureDescriptor("org.gnu.gdb.riscv.virtual");
424             {
425                 var fields = new List<GDBTypeEnumValue>();
426                 fields.Add(new GDBTypeEnumValue("User/Application", 0b00));
427                 fields.Add(new GDBTypeEnumValue("Supervisor", 0b01));
428                 fields.Add(new GDBTypeEnumValue("Machine", 0b11));
429                 var privType = GDBCustomType.Enum("priv_type", 1, fields);
430                 virtualGroup.Types.Add(privType);
431             }
432             virtualGroup.Registers.Add(new GDBRegisterDescriptor((uint)RiscV32Registers.PRIV, registerWidth, "priv", "priv_type", "virtual"));
433             features.Add(virtualGroup);
434         }
435 
AddCustomCSRFeature(ref List<GDBFeatureDescriptor> features, uint registerWidth, IReadOnlyDictionary<ulong, NonstandardCSR> customRegisters)436         public static void AddCustomCSRFeature(ref List<GDBFeatureDescriptor> features, uint registerWidth, IReadOnlyDictionary<ulong, NonstandardCSR> customRegisters)
437         {
438             var customCSRGroup = new GDBFeatureDescriptor("org.gnu.gdb.riscv.custom-csr");
439             var intType = $"uint{registerWidth}";
440 
441             foreach(var customRegister in customRegisters)
442             {
443                 var name = customRegister.Value.Name;
444                 if(name != null)
445                 {
446                     var number = (uint)customRegister.Key;
447                     customCSRGroup.Registers.Add(new GDBRegisterDescriptor(number, registerWidth, name, intType, "custom-csr"));
448                 }
449             }
450 
451             features.Add(customCSRGroup);
452         }
453 
AddVectorFeature(ref List<GDBFeatureDescriptor> features, uint registerWidth)454         public static void AddVectorFeature(ref List<GDBFeatureDescriptor> features, uint registerWidth)
455         {
456             var vectorGroup = new GDBFeatureDescriptor("org.gnu.gdb.riscv.vector");
457 
458             var riscvVectorTypeFields = new List<GDBTypeField>();
459 
460             if(registerWidth / 128 > 0)
461             {
462                 var vu128TypeID = $"vector_u128_{registerWidth / 128}";
463                 var vu128Type = GDBCustomType.Vector(vu128TypeID, "uint128", registerWidth / 128);
464                 vectorGroup.Types.Add(vu128Type);
465                 riscvVectorTypeFields.Add(new GDBTypeField("q", vu128TypeID));
466             }
467 
468             if(registerWidth / 64 > 0)
469             {
470                 var vu64TypeID = $"vector_u64_{registerWidth / 64}";
471                 var vu64Type = GDBCustomType.Vector(vu64TypeID, "uint64", registerWidth / 64);
472                 vectorGroup.Types.Add(vu64Type);
473                 riscvVectorTypeFields.Add(new GDBTypeField("l", vu64TypeID));
474             }
475 
476             if(registerWidth / 32 > 0)
477             {
478                 var vu32TypeID = $"vector_u32_{registerWidth / 32}";
479                 var vu32Type = GDBCustomType.Vector(vu32TypeID, "uint32", registerWidth / 32);
480                 vectorGroup.Types.Add(vu32Type);
481                 riscvVectorTypeFields.Add(new GDBTypeField("w", vu32TypeID));
482             }
483 
484             if(registerWidth / 16 > 0)
485             {
486                 var vu16TypeID = $"vector_u16_{registerWidth / 16}";
487                 var vu16Type = GDBCustomType.Vector(vu16TypeID, "uint16", registerWidth / 16);
488                 vectorGroup.Types.Add(vu16Type);
489                 riscvVectorTypeFields.Add(new GDBTypeField("s", vu16TypeID));
490             }
491 
492             if(registerWidth / 8 > 0)
493             {
494                 var vu8TypeID = $"vector_u8_{registerWidth / 8}";
495                 var vu8Type = GDBCustomType.Vector(vu8TypeID, "uint8", registerWidth / 8);
496                 vectorGroup.Types.Add(vu8Type);
497                 riscvVectorTypeFields.Add(new GDBTypeField("b", vu8TypeID));
498             }
499 
500             var riscvVectorType = GDBCustomType.Union("riscv_vector", riscvVectorTypeFields);
501             vectorGroup.Types.Add(riscvVectorType);
502 
503             for(var index = 0u; index < NumberOfVRegisters; ++index)
504             {
505                 vectorGroup.Registers.Add(new GDBRegisterDescriptor(StartOfVRegisters + index, registerWidth, $"v{index}", "riscv_vector", "vector"));
506             }
507 
508             features.Add(vectorGroup);
509         }
510 
511         public const uint NumberOfXRegisters = 32;
512         public const uint NumberOfFRegisters = 32;
513         public const uint NumberOfAdditionalFRegisters = 3;
514         public const uint StartOfVRegisters = 68;
515         public const uint NumberOfVRegisters = 32;
516     }
517 }
518