CPUDyntransComponent.h Source File

Back to the index.

CPUDyntransComponent.h
Go to the documentation of this file.
1 #ifndef CPUDYNTRANSCOMPONENT_H
2 #define CPUDYNTRANSCOMPONENT_H
3 
4 /*
5  * Copyright (C) 2008-2019 Anders Gavare. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  * derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 // Note: Not included in the component registry.
32 
33 
34 #include "CPUComponent.h"
35 #include "UnitTest.h"
36 
37 #include <assert.h>
38 
39 
41 
42 
43 #define N_DYNTRANS_IC_ARGS 3
44 /**
45  * \brief A dyntrans instruction call.
46  *
47  * f points to a function to be executed.
48  * arg[] contains arguments, such as pointers to registers, or immediate values.
49  */
51 struct DyntransIC;
52 typedef void (*DyntransIC_t)(class CPUDyntransComponent*, struct DyntransIC*);
53 
54 struct DyntransIC
55 {
57 
58  union {
59  void* p;
60  uint32_t u32;
62 };
63 
64 /*
65  * A dyntrans page contains DyntransIC calls for each instruction slot, followed
66  * by some special entries, which handle execution going over the end of a page
67  * (by changing the PC to the start of the next virtual page).
68  */
69 #define DYNTRANS_PAGE_NSPECIALENTRIES 2
70 
71 
72 /*
73  * Some helpers for implementing dyntrans instructions.
74  */
75 #define DECLARE_DYNTRANS_INSTR(name) static void instr_##name(CPUDyntransComponent* cpubase, DyntransIC* ic);
76 #define DYNTRANS_INSTR(class,name) void class::instr_##name(CPUDyntransComponent* cpubase, DyntransIC* ic)
77 #define DYNTRANS_INSTR_HEAD(class) class* cpu = (class*) cpubase;
78 
79 #define REG32(arg) (*((uint32_t*)((arg).p)))
80 #define REG64(arg) (*((uint64_t*)((arg).p)))
81 
82 #define DYNTRANS_SYNCH_PC cpu->m_nextIC = ic; cpu->DyntransResyncPC()
83 
84 
85 /**
86  * \brief A base-class for processors Component implementations that
87  * use dynamic translation.
88  */
90  : public CPUComponent
91 {
92 public:
93  /**
94  * \brief Constructs a CPUDyntransComponent.
95  *
96  * @param className The class name for the component.
97  * @param cpuKind The CPU kind, e.g. "MIPS R4400" for a
98  * MIPS R4400 processor.
99  */
100  CPUDyntransComponent(const string& className, const string& cpuKind);
101 
102  virtual int Execute(GXemul* gxemul, int nrOfCycles);
103 
104 
105  /********************************************************************/
106 
107  static void RunUnitTests(int& nSucceeded, int& nFailures);
108 
109 protected:
110  // Implemented by specific CPU families:
111  virtual int GetDyntransICshift() const = 0;
113 
115  bool DyntransReadInstruction(uint16_t& iword, int offset = 0);
116  bool DyntransReadInstruction(uint32_t& iword, int offset = 0);
118 
119  /**
120  * \brief Calculate m_pc based on m_nextIC and m_firstIConPage.
121  */
122  void DyntransResyncPC();
123 
124  /**
125  * \brief Calculate m_nextIC and m_firstIConPage, based on m_pc.
126  *
127  * This function may return pointers to within an existing translation
128  * page (hopefully the most common case, since it is the fastest), or
129  * it may allocate a new empty page.
130  */
131  void DyntransPCtoPointers();
132 
133 private:
134  void DyntransInit();
135  struct DyntransIC* DyntransGetICPage(uint64_t addr);
136  void DyntransClearICPage(struct DyntransIC* icpage);
137 
138 protected:
139  /*
140  * Generic dyntrans instruction implementations, that may be used by
141  * several different cpu architectures.
142  */
147 
148  // Branches.
149  DECLARE_DYNTRANS_INSTR(branch_samepage);
150 
151  // Data movement.
152  DECLARE_DYNTRANS_INSTR(set_u64_imms32);
154 
155  // Arithmetic.
156  DECLARE_DYNTRANS_INSTR(add_u32_u32_immu32);
157  DECLARE_DYNTRANS_INSTR(add_u32_u32_u32);
158  DECLARE_DYNTRANS_INSTR(add_u64_u64_imms32_truncS32);
159  DECLARE_DYNTRANS_INSTR(add_u64_u64_u64_truncS32);
160  DECLARE_DYNTRANS_INSTR(add_u64_u64_imms32);
161  DECLARE_DYNTRANS_INSTR(sub_u32_u32_immu32);
162  DECLARE_DYNTRANS_INSTR(sub_u32_u32_u32);
163  DECLARE_DYNTRANS_INSTR(sub_u64_u64_u64_truncS32);
164 
165  // Logic.
166  DECLARE_DYNTRANS_INSTR(and_u32_u32_immu32);
167  DECLARE_DYNTRANS_INSTR(and_u64_u64_immu32);
168  DECLARE_DYNTRANS_INSTR(or_u32_u32_immu32);
169  DECLARE_DYNTRANS_INSTR(or_u32_u32_u32);
170  DECLARE_DYNTRANS_INSTR(or_u64_u64_immu32);
171  DECLARE_DYNTRANS_INSTR(xor_u32_u32_immu32);
172  DECLARE_DYNTRANS_INSTR(xor_u32_u32_u32);
173  DECLARE_DYNTRANS_INSTR(xor_u64_u64_immu32);
174  DECLARE_DYNTRANS_INSTR(xor_u64_u64_u64);
175 
176  // Shifts, rotates.
177  DECLARE_DYNTRANS_INSTR(shift_left_u64_u64_imm5_truncS32);
178  DECLARE_DYNTRANS_INSTR(shift_right_u64_u64asu32_imm5_truncS32);
179 
180 private:
181  class DyntransTranslationPage
182  {
183  public:
184  DyntransTranslationPage(int nICentriesPerpage)
185  : m_prev(-1)
186  , m_next(-1)
187  , m_nextCacheEntryForAddr(-1)
188  , m_addr(0)
189  , m_showFunctionTraceCall(false)
190  {
191  m_ic.resize(nICentriesPerpage);
192  }
193 
194  public:
195  // Linked list: Freelist or MRU list
196  int m_prev;
197  int m_next;
198 
199  // Address match:
200  int m_nextCacheEntryForAddr;
201  uint64_t m_addr;
202 
203  // Flags for this page:
204  // TODO: In the future, this could be stuff like different
205  // instruction encodings (MIPS16/Thumb vs 32-bit encoding),
206  // or other mode switches.
208 
209  // Translated instructions:
210  vector< struct DyntransIC > m_ic;
211  };
212 
213  class DyntransTranslationCache
214  {
215  public:
216  DyntransTranslationCache()
217  : m_nICentriesPerpage(0)
218  , m_pageShift(0)
219  , m_firstFree(-1)
220  , m_lastFree(-1)
221  , m_firstMRU(-1)
222  , m_lastMRU(-1)
223  {
224  }
225 
226  void Reinit(size_t approximateSize, int nICentriesPerpage, int pageShift)
227  {
228  size_t approximateSizePerPage = sizeof(struct DyntransIC) * nICentriesPerpage + 64;
229  size_t nrOfPages = approximateSize / approximateSizePerPage;
230 
231  if (nrOfPages < 2) {
232  std::cerr << "Too small translation cache!\n";
233  throw std::exception();
234  }
235 
236  if (nICentriesPerpage == m_nICentriesPerpage &&
237  nrOfPages == m_pageCache.size() &&
238  pageShift == m_pageShift)
239  return;
240 
241  m_nICentriesPerpage = nICentriesPerpage;
242  m_pageShift = pageShift;
243 
244  // Generate empty pages:
245  m_pageCache.clear();
246  m_pageCache.resize(nrOfPages, DyntransTranslationPage(nICentriesPerpage));
247 
248  // Set up the free-list to connect all pages:
249  m_firstFree = 0;
250  m_lastFree = nrOfPages - 1;
251  for (int i=m_firstFree; i<=m_lastFree; i++) {
252  m_pageCache[i].m_prev = i-1; // note: i=0 (first page)
253  // results in prev = -1.
254 
255  if (i == m_lastFree)
256  m_pageCache[i].m_next = -1;
257  else
258  m_pageCache[i].m_next = i+1;
259  }
260 
261  // No pages in use yet, so nothing on the MRU list:
262  m_firstMRU = m_lastMRU = -1;
263 
264  // Reset the quick lookup table:
265  // (Currently hardcoded to allow the first 1 GB of emulated physical memory
266  // to be looked up with 1 call, if more than 1 GB of RAM is used, the
267  // m_nextCacheEntryForAddr chain must be traversed...)
268  m_addrToFirstPageIndex.resize(1024 * 1048576 >> m_pageShift);
269  for (size_t i=0; i<m_addrToFirstPageIndex.size(); ++i)
270  m_addrToFirstPageIndex[i] = -1;
271 
272  ValidateConsistency();
273  }
274 
275  void ValidateConsistency()
276  {
277 #ifndef NDEBUG
278  vector<bool> pageIsInMRUList;
279  vector<bool> pageIsInFreeList;
280  vector<bool> pageIsInMRUListReverse;
281  vector<bool> pageIsInFreeListReverse;
282 
283  pageIsInMRUList.resize(m_pageCache.size(), false);
284  pageIsInFreeList.resize(m_pageCache.size(), false);
285  pageIsInMRUListReverse.resize(m_pageCache.size(), false);
286  pageIsInFreeListReverse.resize(m_pageCache.size(), false);
287 
288  // Follow free-list forward:
289  int i = m_firstFree;
290  while (i >= 0) {
291  pageIsInFreeList[i] = true;
292  i = m_pageCache[i].m_next;
293  }
294 
295  // Follow free-list backwards:
296  i = m_lastFree;
297  while (i >= 0) {
298  pageIsInFreeListReverse[i] = true;
299  i = m_pageCache[i].m_prev;
300  }
301 
302  // Follow MRU-list forward:
303  i = m_firstMRU;
304  while (i >= 0) {
305  pageIsInMRUList[i] = true;
306  i = m_pageCache[i].m_next;
307  }
308 
309  // Follow MRU-list backwards:
310  i = m_lastMRU;
311  while (i >= 0) {
312  pageIsInMRUListReverse[i] = true;
313  i = m_pageCache[i].m_prev;
314  }
315 
316  // The forward and reverse sets should match:
317  for (size_t j=0; j<m_pageCache.size(); ++j) {
318  if (pageIsInFreeList[j] != pageIsInFreeListReverse[j]) {
319  std::cerr << "Forward and reverse Free-list iteration mismatch, position " << j << "!\n";
320  throw std::exception();
321  }
322 
323  if (pageIsInMRUList[j] != pageIsInMRUListReverse[j]) {
324  std::cerr << "Forward and reverse MRU-list iteration mismatch, position " << j << "!\n";
325  throw std::exception();
326  }
327 
328  if ((pageIsInMRUList[j] ^ pageIsInFreeList[j]) == false) {
329  std::cerr << "Each page should be in exactly ONE of the two lists, position " << j << "!\n";
330  throw std::exception();
331  }
332  }
333 
334  vector<bool> pageIsPointedToByQuickLookupTable;
335  vector<bool> pageIsPointedToByQLTChain;
336  pageIsPointedToByQuickLookupTable.resize(m_pageCache.size(), false);
337  pageIsPointedToByQLTChain.resize(m_pageCache.size(), false);
338 
339  for (size_t k=0; k<m_addrToFirstPageIndex.size(); ++k)
340  if (m_addrToFirstPageIndex[k] >= 0)
341  pageIsPointedToByQuickLookupTable[m_addrToFirstPageIndex[k]] = true;
342 
343  for (size_t k=0; k<m_pageCache.size(); ++k) {
344  int index = m_pageCache[k].m_nextCacheEntryForAddr;
345  if (index >= 0)
346  pageIsPointedToByQLTChain[index] = true;
347  }
348 
349  for (size_t k=0; k<pageIsInFreeList.size(); ++k) {
350  if (!pageIsInFreeList[k])
351  continue;
352 
353  if (m_pageCache[k].m_nextCacheEntryForAddr >= 0) {
354  std::cerr << "Pages on the free-list should not have m_nextCacheEntryForAddr set!\n";
355  throw std::exception();
356  }
357 
358  if (pageIsPointedToByQuickLookupTable[k]) {
359  std::cerr << "Pages on the free-list should not be pointed to by the quick lookup table!\n";
360  throw std::exception();
361  }
362 
363  if (pageIsPointedToByQLTChain[k]) {
364  std::cerr << "Pages on the free-list should not be in the quick lookup table chain!\n";
365  throw std::exception();
366  }
367  }
368 
369  for (size_t k=0; k<pageIsInMRUList.size(); ++k) {
370  if (!pageIsInMRUList[k])
371  continue;
372 
373  uint64_t addr = m_pageCache[k].m_addr;
374  uint64_t physPageNumber = addr >> m_pageShift;
375  int quickLookupIndex = physPageNumber & (m_addrToFirstPageIndex.size() - 1);
376  int pageIndex = m_addrToFirstPageIndex[quickLookupIndex];
377 
378  while (pageIndex >= 0) {
379  if (m_pageCache[pageIndex].m_addr == addr)
380  break;
381 
382  pageIndex = m_pageCache[pageIndex].m_nextCacheEntryForAddr;
383  }
384 
385  if (pageIndex < 0) {
386  std::cerr << "Pages in the MRU list must be reachable from the quick lookup table!\n";
387  throw std::exception();
388  }
389  }
390 #endif
391  }
392 
393  void FreeLeastRecentlyUsedPage()
394  {
395  // This function should only be called if it is really necessary to
396  // free a page, i.e. if there is no free page at all.
397  assert(m_firstFree < 0);
398 
399  if (m_firstMRU == m_lastMRU) {
400  std::cerr << "Attempt to free a page, but there's only one page in the MRU list. Too small!\n";
401  throw std::exception();
402  }
403 
404  // This is the one we will free.
405  int index = m_lastMRU;
406  assert(m_pageCache[index].m_prev >= 0);
407  assert(m_pageCache[index].m_next < 0);
408 
409  // Disconnect it from the MRU list...
410  m_lastMRU = m_pageCache[index].m_prev;
411  m_pageCache[m_lastMRU].m_next = -1;
412 
413  // ... and add it first in the free-list:
414  if (m_firstFree < 0) {
415  // In fact, the free-list was empty.
416  m_firstFree = m_lastFree = index;
417  m_pageCache[index].m_prev = -1;
418  m_pageCache[index].m_next = -1;
419  } else {
420  m_pageCache[index].m_prev = -1;
421  m_pageCache[index].m_next = m_firstFree;
422  m_pageCache[m_firstFree].m_prev = index;
423  m_firstFree = index;
424  }
425 
426  // Remove from the quick lookup chain:
427  uint64_t physPageNumber = m_pageCache[index].m_addr >> m_pageShift;
428  int quickLookupIndex = physPageNumber & (m_addrToFirstPageIndex.size() - 1);
429  int pageIndex = m_addrToFirstPageIndex[quickLookupIndex];
430  if (pageIndex == index) {
431  // Direct hit? Then remove from the base quick look up table...
432  m_addrToFirstPageIndex[quickLookupIndex] = m_pageCache[index].m_nextCacheEntryForAddr;
433  } else {
434  // ... otherwise traverse the chain until the next entry is the one we are removing.
435  while (true) {
436  if (m_pageCache[pageIndex].m_nextCacheEntryForAddr == index) {
437  m_pageCache[pageIndex].m_nextCacheEntryForAddr = m_pageCache[index].m_nextCacheEntryForAddr;
438  break;
439  }
440 
441  pageIndex = m_pageCache[pageIndex].m_nextCacheEntryForAddr;
442  }
443  }
444 
445  m_pageCache[index].m_nextCacheEntryForAddr = -1;
446 
447  ValidateConsistency();
448  }
449 
450  struct DyntransIC *AllocateNewPage(uint64_t addr, bool showFunctionTraceCall)
451  {
452  int index = m_firstFree;
453  assert(index >= 0);
454 
455  // Let's grab this index for ourselves...
456 
457  // Was this the only free page?
458  if (index == m_lastFree) {
459  // Then there will be no more free pages.
460  m_firstFree = m_lastFree = -1;
461  } else {
462  // No, just update the chain:
463  m_firstFree = m_pageCache[index].m_next;
464  m_pageCache[m_firstFree].m_prev = -1;
465  }
466 
467  // The page's prev and next fields should be updated to
468  // be part of the MRU list now.
469 
470  // Is there nothing in the MRU list?
471  if (m_firstMRU == -1) {
472  // Then we are the only one.
473  m_firstMRU = m_lastMRU = index;
474  m_pageCache[index].m_next = m_pageCache[index].m_prev = -1;
475  } else {
476  // Then we place ourselves first:
477  m_pageCache[m_firstMRU].m_prev = index;
478  m_pageCache[index].m_next = m_firstMRU;
479  m_firstMRU = index;
480  m_pageCache[index].m_prev = -1;
481  }
482 
483  // Set attributes for the page: address and other flags.
484  m_pageCache[index].m_addr = addr;
485  m_pageCache[index].m_showFunctionTraceCall = showFunctionTraceCall;
486 
487  // Insert into quick lookup table:
488  uint64_t physPageNumber = addr >> m_pageShift;
489  int quickLookupIndex = physPageNumber & (m_addrToFirstPageIndex.size() - 1);
490 
491  // Are we the only one? (I.e. the first page for this quick lookup index.)
492  if (m_addrToFirstPageIndex[quickLookupIndex] < 0) {
493  m_addrToFirstPageIndex[quickLookupIndex] = index;
494  m_pageCache[index].m_nextCacheEntryForAddr = -1;
495  } else {
496  // No. Let's add ourselves first in the chain:
497  m_pageCache[index].m_nextCacheEntryForAddr = m_addrToFirstPageIndex[quickLookupIndex];
498  m_addrToFirstPageIndex[quickLookupIndex] = index;
499  }
500 
501  ValidateConsistency();
502 
503  return &(m_pageCache[index].m_ic[0]);
504  }
505 
506  struct DyntransIC *GetICPage(uint64_t addr, bool showFunctionTraceCall, bool& clear)
507  {
508  clear = false;
509 
510  // Strip of the low bits:
511  addr >>= m_pageShift;
512  uint64_t physPageNumber = addr;
513  addr <<= m_pageShift;
514 
515  int quickLookupIndex = physPageNumber & (m_addrToFirstPageIndex.size() - 1);
516  int pageIndex = m_addrToFirstPageIndex[quickLookupIndex];
517 
518  // std::cerr << "addr " << addr << ", physPageNumber " << physPageNumber << ", quickLookupIndex " << quickLookupIndex << ", pageIndex " << pageIndex << "\n";
519 
520  // If pageIndex >= 0, then pageIndex points to a page which _may_ be for this addr.
521  while (pageIndex >= 0) {
522  if (m_pageCache[pageIndex].m_addr == addr)
523  break;
524 
525  // If the page for pageIndex was for some other address, then
526  // let's continue searching the chain...
527  pageIndex = m_pageCache[pageIndex].m_nextCacheEntryForAddr;
528  }
529 
530  // If we have a definite page index, then return a pointer that page's ICs:
531  if (pageIndex >= 0) {
532  // Update the MRU list, unless this page was already first,
533  // so that m_firstMRU points to the page.
534  if (m_firstMRU != pageIndex) {
535  // Disconnect from previous place...
536  int prev = m_pageCache[pageIndex].m_prev;
537  int next = m_pageCache[pageIndex].m_next;
538  if (prev >= 0)
539  m_pageCache[prev].m_next = next;
540  if (next >= 0)
541  m_pageCache[next].m_prev = prev;
542 
543  // ... disconnect from "end of list":
544  if (pageIndex == m_lastMRU)
545  m_lastMRU = prev;
546 
547  // ... and insert first in list:
548  m_pageCache[pageIndex].m_prev = -1;
549  m_pageCache[pageIndex].m_next = m_firstMRU;
550  m_pageCache[m_firstMRU].m_prev = pageIndex;
551  m_firstMRU = pageIndex;
552  }
553 
554  // TODO: Hm... also move to front of the Quick Lookup chain?
555  // Only necessary if more memory is used/emulated than the
556  // size of the quick lookup table, e.g. if 2 GB ram are used,
557  // and the size of the lookup table is 1 GB, and pages
558  // at exactly 0 GB and 1 GB are used in this order:
559  // 1 0 1 1 1 1 1 1 1 1 1 1 1
560  // then 1 would first be placed in the chain, then 0 (which
561  // would insert it first in the chain). But all lookups after
562  // that would have to search the whole chain (0, 1) to find 1.
563 
564  ValidateConsistency();
565 
566  // If flags are not the same, then let's clear the page:
567  if (m_pageCache[pageIndex].m_showFunctionTraceCall != showFunctionTraceCall) {
568  m_pageCache[pageIndex].m_showFunctionTraceCall = showFunctionTraceCall;
569  clear = true;
570  }
571 
572  return &(m_pageCache[pageIndex].m_ic[0]);
573  }
574 
575  // The address was NOT in the translation cache at all. So we have
576  // to create a new page.
577 
578  // If the free-list is all used up, that means we have to free something
579  // before we can allocate a new page...
580  if (m_firstFree < 0)
581  FreeLeastRecentlyUsedPage();
582 
583  // ... and then finally allocate a new page:
584  clear = true;
585  return AllocateNewPage(addr, showFunctionTraceCall);
586  }
587 
588  private:
589  // Number of translated instructions per page, and number of bits
590  // to shift to convert address to page number:
591  int m_nICentriesPerpage;
592  int m_pageShift;
593 
594  // Free-list of pages:
595  int m_firstFree;
596  int m_lastFree;
597 
598  // Most-Recently-Used list of pages:
599  int m_firstMRU;
600  int m_lastMRU;
601 
602  // "Usually" quick lookup table, address to page index:
603  vector<int> m_addrToFirstPageIndex;
604 
605  // The actual pages:
606  vector<DyntransTranslationPage> m_pageCache;
607  };
608 
609 protected:
610  /*
611  * Volatile state:
612  */
620 
621  /*
622  * Translation cache:
623  */
624  DyntransTranslationCache m_translationCache;
625 
626  /*
627  * Special always present DyntransIC structs, for aborting emulation:
628  */
629  struct DyntransIC m_abortIC;
630 };
631 
632 
633 #endif // CPUDYNTRANSCOMPONENT_H
CPUDyntransComponent::Execute
virtual int Execute(GXemul *gxemul, int nrOfCycles)
Execute one or more cycles.
Definition: CPUDyntransComponent.cc:89
CPUDyntransComponent::DECLARE_DYNTRANS_INSTR
DECLARE_DYNTRANS_INSTR(sub_u32_u32_immu32)
DyntransIC::u32
uint32_t u32
Definition: CPUDyntransComponent.h:60
N_DYNTRANS_IC_ARGS
#define N_DYNTRANS_IC_ARGS
Definition: CPUDyntransComponent.h:43
GXemul
The main emulator class.
Definition: GXemul.h:55
CPUDyntransComponent::DECLARE_DYNTRANS_INSTR
DECLARE_DYNTRANS_INSTR(add_u64_u64_u64_truncS32)
CPUDyntransComponent::DECLARE_DYNTRANS_INSTR
DECLARE_DYNTRANS_INSTR(endOfPage)
CPUDyntransComponent::DECLARE_DYNTRANS_INSTR
DECLARE_DYNTRANS_INSTR(endOfPage2)
CPUDyntransComponent::DECLARE_DYNTRANS_INSTR
DECLARE_DYNTRANS_INSTR(shift_right_u64_u64asu32_imm5_truncS32)
CPUDyntransComponent::m_dyntransPageMask
int m_dyntransPageMask
Definition: CPUDyntransComponent.h:615
CPUDyntransComponent::m_firstIConPage
struct DyntransIC * m_firstIConPage
Definition: CPUDyntransComponent.h:613
addr
uint32_t addr
Definition: tmp_arm_multi.cc:52
CPUDyntransComponent::m_nextIC
struct DyntransIC * m_nextIC
Definition: CPUDyntransComponent.h:614
CPUDyntransComponent::DECLARE_DYNTRANS_INSTR
DECLARE_DYNTRANS_INSTR(branch_samepage)
CPUDyntransComponent::m_executedCycles
int m_executedCycles
Definition: CPUDyntransComponent.h:618
CPUDyntransComponent
A base-class for processors Component implementations that use dynamic translation.
Definition: CPUDyntransComponent.h:91
CPUDyntransComponent::DECLARE_DYNTRANS_INSTR
DECLARE_DYNTRANS_INSTR(or_u64_u64_immu32)
CPUDyntransComponent::DECLARE_DYNTRANS_INSTR
DECLARE_DYNTRANS_INSTR(sub_u64_u64_u64_truncS32)
CPUDyntransComponent::DECLARE_DYNTRANS_INSTR
DECLARE_DYNTRANS_INSTR(set_u64_imms32)
CPUDyntransComponent::m_translationCache
DyntransTranslationCache m_translationCache
Definition: CPUDyntransComponent.h:624
CPUDyntransComponent::DECLARE_DYNTRANS_INSTR
DECLARE_DYNTRANS_INSTR(shift_left_u64_u64_imm5_truncS32)
CPUDyntransComponent::DECLARE_DYNTRANS_INSTR
DECLARE_DYNTRANS_INSTR(xor_u64_u64_immu32)
DyntransIC
Definition: CPUDyntransComponent.h:55
CPUDyntransComponent::DyntransResyncPC
void DyntransResyncPC()
Calculate m_pc based on m_nextIC and m_firstIConPage.
Definition: CPUDyntransComponent.cc:253
CPUDyntransComponent::m_dyntransICshift
int m_dyntransICshift
Definition: CPUDyntransComponent.h:617
CPUDyntransComponent::DyntransPCtoPointers
void DyntransPCtoPointers()
Calculate m_nextIC and m_firstIConPage, based on m_pc.
Definition: CPUDyntransComponent.cc:233
UnitTest.h
CPUDyntransComponent::m_abortIC
struct DyntransIC m_abortIC
Definition: CPUDyntransComponent.h:629
CPUDyntransComponent::DECLARE_DYNTRANS_INSTR
DECLARE_DYNTRANS_INSTR(add_u32_u32_u32)
CPUDyntransComponent::DECLARE_DYNTRANS_INSTR
DECLARE_DYNTRANS_INSTR(xor_u64_u64_u64)
CPUDyntransComponent::GetDyntransToBeTranslated
virtual DyntransIC_t GetDyntransToBeTranslated()=0
CPUDyntransComponent::DECLARE_DYNTRANS_INSTR
DECLARE_DYNTRANS_INSTR(and_u32_u32_immu32)
CPUDyntransComponent::DECLARE_DYNTRANS_INSTR
DECLARE_DYNTRANS_INSTR(nop)
DyntransIC::p
void * p
Definition: CPUDyntransComponent.h:59
CPUDyntransComponent::DECLARE_DYNTRANS_INSTR
DECLARE_DYNTRANS_INSTR(sub_u32_u32_u32)
CPUDyntransComponent::DECLARE_DYNTRANS_INSTR
DECLARE_DYNTRANS_INSTR(add_u64_u64_imms32)
nop
void COMBINE() nop(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
Definition: cpu_mips_instr.cc:3365
CPUDyntransComponent::DECLARE_DYNTRANS_INSTR
DECLARE_DYNTRANS_INSTR(or_u32_u32_immu32)
CPUDyntransComponent::DECLARE_DYNTRANS_INSTR
DECLARE_DYNTRANS_INSTR(xor_u32_u32_u32)
CPUDyntransComponent::DECLARE_DYNTRANS_INSTR
DECLARE_DYNTRANS_INSTR(abort)
CPUComponent.h
CPUDyntransComponent::DECLARE_DYNTRANS_INSTR
DECLARE_DYNTRANS_INSTR(add_u64_u64_imms32_truncS32)
CPUDyntransComponent::DyntransReadInstruction
bool DyntransReadInstruction(uint16_t &iword, int offset=0)
Definition: CPUDyntransComponent.cc:313
CPUDyntransComponent::RunUnitTests
static void RunUnitTests(int &nSucceeded, int &nFailures)
CPUDyntransComponent::DECLARE_DYNTRANS_INSTR
DECLARE_DYNTRANS_INSTR(add_u32_u32_immu32)
CPUDyntransComponent::DECLARE_DYNTRANS_INSTR
DECLARE_DYNTRANS_INSTR(or_u32_u32_u32)
CPUDyntransComponent::GetDyntransICshift
virtual int GetDyntransICshift() const =0
CPUDyntransComponent::DyntransToBeTranslatedDone
void DyntransToBeTranslatedDone(struct DyntransIC *)
Definition: CPUDyntransComponent.cc:360
CPUDyntransComponent::DECLARE_DYNTRANS_INSTR
DECLARE_DYNTRANS_INSTR(and_u64_u64_immu32)
CPUDyntransComponent::CPUDyntransComponent
CPUDyntransComponent(const string &className, const string &cpuKind)
Constructs a CPUDyntransComponent.
Definition: CPUDyntransComponent.cc:36
DyntransIC_t
void(* DyntransIC_t)(class CPUDyntransComponent *, struct DyntransIC *)
Definition: CPUDyntransComponent.h:52
CPUComponent::m_showFunctionTraceCall
bool m_showFunctionTraceCall
Definition: CPUComponent.h:213
CPUDyntransComponent::m_nrOfCyclesToExecute
int m_nrOfCyclesToExecute
Definition: CPUDyntransComponent.h:619
CPUDyntransComponent::m_dyntransICentriesPerPage
int m_dyntransICentriesPerPage
Definition: CPUDyntransComponent.h:616
CPUDyntransComponent::DECLARE_DYNTRANS_INSTR
DECLARE_DYNTRANS_INSTR(xor_u32_u32_immu32)
DyntransIC::f
DyntransIC_t f
Definition: CPUDyntransComponent.h:56
CPUDyntransComponent::DECLARE_DYNTRANS_INSTR
DECLARE_DYNTRANS_INSTR(mov_u64_u64)
CPUComponent
A base-class for processors Component implementations.
Definition: CPUComponent.h:47
CPUDyntransComponent::DyntransToBeTranslatedBegin
void DyntransToBeTranslatedBegin(struct DyntransIC *)
Definition: CPUDyntransComponent.cc:298
DyntransIC::arg
union DyntransIC::@0 arg[N_DYNTRANS_IC_ARGS]

Generated on Tue Aug 25 2020 19:25:06 for GXemul by doxygen 1.8.18