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

Generated on Tue Mar 24 2020 14:04:48 for GXemul by doxygen 1.8.17