ETISS 0.11.2
ExtendableTranslatingInstructionSetSimulator(version0.11.2)
Loading...
Searching...
No Matches
RV32IMACFDArchSpecificImp.cpp
Go to the documentation of this file.
1
11#include <vector>
12
13#include "RV32IMACFDArch.h"
15#include "RV32IMACFDFuncs.h"
16#include "etiss/Memory.h"
17
34etiss::int32 RV32IMACFDArch::handleException(etiss::int32 cause, ETISS_CPU *cpu)
35{
36 RV32IMACFD_translate_exc_code(cpu, nullptr, nullptr, cause);
37 cpu->instructionPointer = cpu->nextPc;
38 return 0;
39}
40
45{
46 static etiss::ModuleHandle hModule = 0;
47
48 if (!hModule)
49 {
51 }
52
53 return hModule;
54}
55
59static std::string GetCurrentModulePath()
60{
61 static std::string modulePath;
62
63 if (modulePath == "")
64 {
66 }
67
68 return modulePath;
69}
70
74std::string RV32IMACFDArch::installDir() const
75{
76 auto archLib = GetCurrentModulePath();
77 auto libPathLoc = archLib.find_last_of("/\\");
78 auto libPath = archLib.substr(0, libPathLoc);
79 auto pluginsPathLoc = libPath.find_last_of("/\\");
80 auto pluginsPath = libPath.substr(0, pluginsPathLoc);
81 auto archPathLoc = pluginsPath.find_last_of("/\\");
82 return libPath.substr(0, archPathLoc);
83}
84
88std::string RV32IMACFDArch::jitFiles() const
89{
90 return installDir() + "/include/jit";
91}
92
118{
119 {
120 std::string requiredJitFilesPath = jitFiles();
121 /* Set default JIT Extensions. Read Parameters set from ETISS configuration and append with architecturally needed */
122 std::string cfgPar = "";
123 cfgPar = etiss::cfg().get<std::string>("jit.external_headers", ";");
124 etiss::cfg().set<std::string>("jit.external_headers", cfgPar + "etiss/jit/libsoftfloat.h");
125
126 cfgPar = etiss::cfg().get<std::string>("jit.external_libs", ";");
127 etiss::cfg().set<std::string>("jit.external_libs", cfgPar + "softfloat");
128
129 cfgPar = etiss::cfg().get<std::string>("jit.external_header_paths", ";");
130 etiss::cfg().set<std::string>("jit.external_header_paths", cfgPar + "etiss/jit" + requiredJitFilesPath);
131
132 cfgPar = etiss::cfg().get<std::string>("jit.external_lib_paths", ";");
133 etiss::cfg().set<std::string>("jit.external_lib_paths", cfgPar + "etiss/jit");
134 }
135
136 if (false) {
137 // Pre-compilation of instruction set to view instruction tree. Enable by setting 'true' above.
138
139 etiss::instr::ModedInstructionSet iset("RV32IMACFDISA");
140 bool ok = true;
141 RV32IMACFDISA.addTo(iset, ok);
142
143 iset.compile();
144
145 std::cout << iset.print() << std::endl;
146 }
147
148 bool ok = true;
149 RV32IMACFDISA.addTo(mis, ok);
150 if (!ok)
151 etiss::log(etiss::FATALERROR, "Failed to add instructions for RV32IMACFDISA");
152
154
155 using namespace etiss;
156 using namespace etiss::instr;
157
158 vis->get(32)->getInvalid().addCallback(
159 [] (BitArray & ba,etiss::CodeSet & cs,InstructionContext & ic)
160 {
161
162// -----------------------------------------------------------------------------
163
164// -----------------------------------------------------------------------------
165
166// -----------------------------------------------------------------------------
167// NOLINTBEGIN(clang-diagnostic-unused-but-set-variable)
168etiss_uint32 error_code = 0;
169static BitArrayRange R_error_code_0(31, 0);
170error_code += R_error_code_0.read(ba) << 0;
171
172// NOLINTEND(clang-diagnostic-unused-but-set-variable)
173// -----------------------------------------------------------------------------
174
175 {
176 CodePart & cp = cs.append(CodePart::INITIALREQUIRED);
177
178 cp.code() = std::string("//trap_entry 32\n");
179
180// -----------------------------------------------------------------------------
181{ // procedure
182cp.code() += "{ // procedure\n";
183cp.code() += "RV32IMACFD_translate_exc_code(cpu, system, plugin_pointers, " + std::to_string(error_code) + "ULL);\n";
184cp.code() += "goto instr_exit_" + std::to_string(ic.current_address_) + ";\n";
185cp.code() += "} // procedure\n";
186} // procedure
187cp.code() += "instr_exit_" + std::to_string(ic.current_address_) + ":\n";
188cp.code() += "cpu->instructionPointer = cpu->nextPc;\n";
189// -----------------------------------------------------------------------------
190 cp.getAffectedRegisters().add("instructionPointer", 32);
191 }
192 {
193 CodePart & cp = cs.append(CodePart::APPENDEDRETURNINGREQUIRED);
194
195 cp.code() = std::string("//trap_entry 32\n");
196
197// -----------------------------------------------------------------------------
198cp.code() += "return cpu->exception;\n";
199// -----------------------------------------------------------------------------
200 }
201
202 return true;
203 },
204 0
205 );
206
207 vis->get(16)->getInvalid().addCallback(
208 [] (BitArray & ba,etiss::CodeSet & cs,InstructionContext & ic)
209 {
210
211// -----------------------------------------------------------------------------
212
213// -----------------------------------------------------------------------------
214
215// -----------------------------------------------------------------------------
216// NOLINTBEGIN(clang-diagnostic-unused-but-set-variable)
217etiss_uint32 error_code = 0;
218static BitArrayRange R_error_code_0(31, 0);
219error_code += R_error_code_0.read(ba) << 0;
220
221// NOLINTEND(clang-diagnostic-unused-but-set-variable)
222// -----------------------------------------------------------------------------
223
224 {
225 CodePart & cp = cs.append(CodePart::INITIALREQUIRED);
226
227 cp.code() = std::string("//trap_entry 16\n");
228
229// -----------------------------------------------------------------------------
230{ // procedure
231cp.code() += "{ // procedure\n";
232cp.code() += "RV32IMACFD_translate_exc_code(cpu, system, plugin_pointers, " + std::to_string(error_code) + "ULL);\n";
233cp.code() += "goto instr_exit_" + std::to_string(ic.current_address_) + ";\n";
234cp.code() += "} // procedure\n";
235} // procedure
236cp.code() += "instr_exit_" + std::to_string(ic.current_address_) + ":\n";
237cp.code() += "cpu->instructionPointer = cpu->nextPc;\n";
238// -----------------------------------------------------------------------------
239 cp.getAffectedRegisters().add("instructionPointer", 32);
240 }
241 {
242 CodePart & cp = cs.append(CodePart::APPENDEDRETURNINGREQUIRED);
243
244 cp.code() = std::string("//trap_entry 16\n");
245
246// -----------------------------------------------------------------------------
247cp.code() += "return cpu->exception;\n";
248// -----------------------------------------------------------------------------
249 }
250
251 return true;
252 },
253 0
254 );
255
256
258 std::function<void(InstructionContext & ic, etiss_uint32 opRd)> updateRV32IMACFDInstrLength =
259 [](InstructionContext &ic, etiss_uint32 opRd) {
261 ic.is_not_default_width_ = true;
262 if (opRd == 0x3f)
263 ic.instr_width_ = 64;
264 else if ((opRd & 0x3f) == 0x1f)
265 ic.instr_width_ = 48;
266 else if (((opRd & 0x1f) >= 0x3) && ((opRd & 0x1f) < 0x1f))
267 ic.instr_width_ = 32;
268 else if(opRd == 0x7f) /* P-Extension instructions */
269 ic.instr_width_ = 32;
270 else if ((opRd & 0x3) != 0x3)
271 ic.instr_width_ = 16;
272 else
273 // This might happen when code is followed by data.
274 ic.is_not_default_width_ = false;
275 };
276
277
278 BitArrayRange op(6, 0);
279 etiss_uint32 opRd = op.read(ba);
280
281 /*BitArrayRange fullOp(ba.byteCount()*8-1,0);
282 etiss_uint32 fullOpRd = fullOp.read(ba);
283
284 std::stringstream ss;
285 ss << "Byte count: " << ba.byteCount()<< std::endl;
286 ss << "opcode: 0x" <<std::hex<< fullOpRd << std::endl;
287 ss << "Current PC: 0x" <<std::hex<< ic.current_address_ << std::endl;
288 std::cout << ss.str() << std::endl;*/
289
290 switch (ba.byteCount())
291 {
292 case 2:
293 if (((opRd & 0x3) != 0x3) || (opRd == 0))
294 {
295 ic.is_not_default_width_ = false;
296 break;
297 }
298 else
299 {
300 updateRV32IMACFDInstrLength(ic, opRd);
301 break;
302 }
303 case 4:
304 if ((((opRd & 0x1f) >= 0x3) || ((opRd & 0x1f) < 0x1f)) || (opRd == 0))
305 {
306 ic.is_not_default_width_ = false;
307 break;
308 }
309 else if(opRd == 0x7f) /* P-Extension instructions */
310 {
311 updateRV32IMACFDInstrLength(ic, opRd);
312 break;
313 }
314 else
315 {
316 updateRV32IMACFDInstrLength(ic, opRd);
317 break;
318 }
319 case 6:
320 if (((opRd & 0x3f) == 0x1f) || (opRd == 0))
321 {
322 ic.is_not_default_width_ = false;
323 break;
324 }
325 else
326 {
327 updateRV32IMACFDInstrLength(ic, opRd);
328 break;
329 }
330 case 8:
331 if ((opRd == 0x3f) || (opRd == 0))
332 {
333 ic.is_not_default_width_ = false;
334 break;
335 }
336 else
337 {
338 updateRV32IMACFDInstrLength(ic, opRd);
339 break;
340 }
341 default:
342 // This might happen when code is followed by data.
343 ic.is_not_default_width_ = false;
344 }
345 };
346
347}
348
373{
374 /**************************************************************************
375 * Endianess compensation *
376 **************************************************************************/
377}
378
379std::shared_ptr<etiss::VirtualStruct> RV32IMACFDArch::getVirtualStruct(ETISS_CPU *cpu)
380{
381 auto ret = etiss::VirtualStruct::allocate(cpu, [](etiss::VirtualStruct::Field *f) { delete f; });
382
383 for (uint32_t i = 0; i < 32; i += 1)
384 {
385 ret->addField(new RegField_RV32IMACFD(*ret, i));
386 }
387 for (uint32_t i = 0; i < 32; i += 1)
388 {
389 ret->addField(new FloatRegField_RV32IMACFD(*ret, i));
390 }
391 for (uint32_t i = 1; i < 4; i += 1)
392 {
393 ret->addField(new CSRField_RV32IMACFD(*ret, i));
394 }
395 for (uint32_t i = 768; i < 775; i += 1)
396 {
397 ret->addField(new CSRField_RV32IMACFD(*ret, i));
398 }
399 for (uint32_t i = 832; i < 837; i += 1)
400 {
401 ret->addField(new CSRField_RV32IMACFD(*ret, i));
402 }
403 ret->addField(new CSRField_RV32IMACFD(*ret, 2816));
404 ret->addField(new CSRField_RV32IMACFD(*ret, 2818));
405 ret->addField(new CSRField_RV32IMACFD(*ret, 2944));
406 ret->addField(new CSRField_RV32IMACFD(*ret, 2946));
407 for (uint32_t i = 3072; i < 3075; i += 1)
408 {
409 ret->addField(new CSRField_RV32IMACFD(*ret, i));
410 }
411 for (uint32_t i = 3200; i < 3203; i += 1)
412 {
413 ret->addField(new CSRField_RV32IMACFD(*ret, i));
414 }
415 for (uint32_t i = 3857; i < 3861; i += 1)
416 {
417 ret->addField(new CSRField_RV32IMACFD(*ret, i));
418 }
419 ret->addField(new pcField_RV32IMACFD(*ret));
420
421 return ret;
422}
423
432{
433 if (cpu == 0)
434 return 0;
435
436 std::vector<etiss::uint32 *> vec;
437 std::vector<etiss::uint32 *> mask;
438
439 vec.push_back(&((RV32IMACFD *)cpu)->MIP);
440 mask.push_back(&((RV32IMACFD *)cpu)->MIE);
441
443}
444
449
454
static etiss::ModuleHandle GetCurrentModule()
See etiss/src/Misc.cpp.
static std::string GetCurrentModulePath()
See etiss/src/Misc.cpp.
etiss::instr::InstructionCollection RV32IMACFDISA
void RV32IMACFD_translate_exc_code(ETISS_CPU *const cpu, ETISS_System *const system, void *const *const plugin_pointers, etiss_int32 cause)
static __inline__ uint32_t
Definition arm_cde.h:25
uint32_t etiss_uint32
Definition types.h:55
virtual void deleteInterruptVector(etiss::InterruptVector *vec, ETISS_CPU *cpu)
delete an allocated interrupt vector object
virtual void deleteInterruptEnable(etiss::InterruptEnable *en, ETISS_CPU *cpu)
virtual void initInstrSet(etiss::instr::ModedInstructionSet &) const
This function is called during CPUArch initialization.
virtual etiss::InterruptEnable * createInterruptEnable(ETISS_CPU *cpu)
virtual etiss::InterruptVector * createInterruptVector(ETISS_CPU *cpu)
If interrupt handling is expected, vector table could be provided to support interrupt triggering.
virtual std::shared_ptr< etiss::VirtualStruct > getVirtualStruct(ETISS_CPU *cpu)
get the VirtualStruct of the core to mitigate register access
virtual std::string jitFiles() const
This function will return the include prefix relative to the base installation directory of the ArchL...
virtual std::string installDir() const
This function will return the base installation directory of the ArchLib.
virtual void compensateEndianess(ETISS_CPU *cpu, etiss::instr::BitArray &ba) const
Target architecture may have inconsistent endianess.
virtual etiss::int32 handleException(etiss::int32 code, ETISS_CPU *cpu)
This function will be called automatically in order to handling architecure dependent exceptions such...
Generated on Fri, 19 Jun 2026 11:48:00 +0000.
Contains a small code snipped.
Definition CodePart.h:348
std::string & code()
Definition CodePart.h:378
RegisterSet & getAffectedRegisters()
Definition CodePart.h:376
A set of CodeParts.
Definition CodePart.h:399
void append(const CodePart &part, CodePart::TYPE type)
Definition CodePart.h:412
bool set(const std::string &key, T value)
template function to set the value of a configuration key.
Definition Misc.h:335
T get(const std::string &key, T default_, bool *default_used=0)
template function to read the value of a configuration key.
Definition Misc.h:312
interface to set interrupt bits
template implementation of an InterruptVector that uses integer variables to store interrupt bit valu...
void add(const RegisterPart &rp)
add a registerPart to the set or just its relevant bits if a register with the same name is already p...
Definition CodePart.h:184
a Field instance represents e.g.
static std::shared_ptr< VirtualStruct > allocate(void *structure, std::function< void(Field *)> delete_)
Reading through it will only return bits within the range.
I read(const BitArray &ba)
reads bits from the range to the return value starting at the lsb.
stores a bit vector
unsigned byteCount() const
void addTo(ModedInstructionSet &set, bool &ok)
this class contains parameters that persist in between instruction lookpus/translation within a trans...
bool is_not_default_width_
if true the this instruction is not as long as the width of the variable instruction set
bool instr_width_fully_evaluated_
if true the length_updater_ function will be called again after instr_width_ bits are available
uint64_t current_address_
start address of current instruction
bool addCallback(std::function< bool(BitArray &, etiss::CodeSet &, InstructionContext &)> callback, uint32_t builtinGroups, const std::set< uint32_t > &groups=std::set< uint32_t >())
holds etiss::instr::VariableInstructionSet instances for different modes.
std::string print(std::string prefix=std::string())
VariableInstructionSet * get(uint32_t mode)
holds etiss::instr::InstructionSet instances with different bit widths.
InstructionSet * get(unsigned width)
std::function< void(VariableInstructionSet &, InstructionContext &, BitArray &)> length_updater_
forwards: include/jit/*
Definition Benchmark.h:17
void * ModuleHandle
Represents a module handle. Analogous to Windows this represents the module base address,...
Definition Memory.h:37
etiss::ModuleHandle GetModuleByAddress(uintptr_t adr)
Definition Memory.cpp:90
std::string GetModulePath(etiss::ModuleHandle hModule)
Definition Memory.cpp:97
@ FATALERROR
Definition Misc.h:84
Configuration & cfg()
Definition Misc.cpp:548
void log(Verbosity level, std::string msg)
write log message at the given level.
Definition Misc.cpp:94
__UINTPTR_TYPE__ uintptr_t
An unsigned integer type with the property that any valid pointer to void can be converted to this ty...
basic cpu state structure needed for execution of any cpu architecture.
Definition CPU.h:51
etiss_uint64 instructionPointer
pointer to next instruction.
Definition CPU.h:54
etiss_uint64 nextPc
Definition CPU.h:57
Generated on Fri, 19 Jun 2026 11:48:00 +0000.
Definition RV32IMACFD.h:17