OSDN Git Service

[VM][I386] TRY: Import from DOSBOX(J3100) v.2019-05-20.
[csp-qt/common_source_project-fm7.git] / source / src / vm / libcpu_newdev / dosbox-i386 / core_dyn_x86 / cache.h
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/cache.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/cache.h
new file mode 100644 (file)
index 0000000..23b6a53
--- /dev/null
@@ -0,0 +1,643 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+class CacheBlock {
+public:
+       void Clear(void);
+       void LinkTo(Bitu index,CacheBlock * toblock) {
+               assert(toblock);
+               link[index].to=toblock;
+               link[index].next=toblock->link[index].from;
+               toblock->link[index].from=this;
+       }
+       struct {
+               Bit16u start,end;                               //Where the page is the original code
+               CodePageHandler * handler;              //Page containing this code
+       } page;
+       struct {
+               Bit8u * start;                                  //Where in the cache are we
+               Bitu size;
+               CacheBlock * next;
+               Bit8u * wmapmask;
+               Bit16u maskstart;
+               Bit16u masklen;
+       } cache;
+       struct {
+               Bitu index;
+               CacheBlock * next;
+       } hash;
+       struct {
+               CacheBlock * to;
+               CacheBlock * next;
+               CacheBlock * from;
+       } link[2];
+       CacheBlock * crossblock;
+};
+
+static struct {
+       struct {
+               CacheBlock * first;
+               CacheBlock * active;
+               CacheBlock * free;
+               CacheBlock * running;
+       } block;
+       Bit8u * pos;
+       CodePageHandler * free_pages;
+       CodePageHandler * used_pages;
+       CodePageHandler * last_page;
+} cache;
+
+static CacheBlock link_blocks[2];
+
+class CodePageHandler : public PageHandler {
+public:
+       CodePageHandler() {
+               invalidation_map=NULL;
+       }
+       void SetupAt(Bitu _phys_page,PageHandler * _old_pagehandler) {
+               phys_page=_phys_page;
+               old_pagehandler=_old_pagehandler;
+               flags=old_pagehandler->flags|PFLAG_HASCODE;
+               flags&=~PFLAG_WRITEABLE;
+               active_blocks=0;
+               active_count=16;
+               memset(&hash_map,0,sizeof(hash_map));
+               memset(&write_map,0,sizeof(write_map));
+               if (invalidation_map!=NULL) {
+                       free(invalidation_map);
+                       invalidation_map=NULL;
+               }
+       }
+       bool InvalidateRange(Bitu start,Bitu end) {
+               Bits index=1+(end>>DYN_HASH_SHIFT);
+               bool is_current_block=false;
+               Bit32u ip_point=SegPhys(cs)+reg_eip;
+               ip_point=(PAGING_GetPhysicalPage(ip_point)-(phys_page<<12))+(ip_point&0xfff);
+               while (index>=0) {
+                       Bitu map=0;
+                       for (Bitu count=start;count<=end;count++) map+=write_map[count];
+                       if (!map) return is_current_block;
+                       CacheBlock * block=hash_map[index];
+                       while (block) {
+                               CacheBlock * nextblock=block->hash.next;
+                               if (start<=block->page.end && end>=block->page.start) {
+                                       if (ip_point<=block->page.end && ip_point>=block->page.start) is_current_block=true;
+                                       block->Clear();
+                               }
+                               block=nextblock;
+                       }
+                       index--;
+               }
+               return is_current_block;
+       }
+       void writeb(PhysPt addr,Bitu val){
+               if (GCC_UNLIKELY(old_pagehandler->flags&PFLAG_HASROM)) return;
+               if (GCC_UNLIKELY((old_pagehandler->flags&PFLAG_READABLE)!=PFLAG_READABLE)) {
+                       E_Exit("wb:non-readable code page found that is no ROM page");
+               }
+               addr&=4095;
+               if (host_readb(hostmem+addr)==(Bit8u)val) return;
+               host_writeb(hostmem+addr,val);
+               if (!*(Bit8u*)&write_map[addr]) {
+                       if (active_blocks) return;
+                       active_count--;
+                       if (!active_count) Release();
+                       return;
+               } else if (!invalidation_map) {
+                       invalidation_map=(Bit8u*)malloc(4096);
+                       memset(invalidation_map,0,4096);
+               }
+               invalidation_map[addr]++;
+               InvalidateRange(addr,addr);
+       }
+       void writew(PhysPt addr,Bitu val){
+               if (GCC_UNLIKELY(old_pagehandler->flags&PFLAG_HASROM)) return;
+               if (GCC_UNLIKELY((old_pagehandler->flags&PFLAG_READABLE)!=PFLAG_READABLE)) {
+                       E_Exit("ww:non-readable code page found that is no ROM page");
+               }
+               addr&=4095;
+               if (host_readw(hostmem+addr)==(Bit16u)val) return;
+               host_writew(hostmem+addr,val);
+               if (!*(Bit16u*)&write_map[addr]) {
+                       if (active_blocks) return;
+                       active_count--;
+                       if (!active_count) Release();
+                       return;
+               } else if (!invalidation_map) {
+                       invalidation_map=(Bit8u*)malloc(4096);
+                       memset(invalidation_map,0,4096);
+               }
+               (*(Bit16u*)&invalidation_map[addr])+=0x101;
+               InvalidateRange(addr,addr+1);
+       }
+       void writed(PhysPt addr,Bitu val){
+               if (GCC_UNLIKELY(old_pagehandler->flags&PFLAG_HASROM)) return;
+               if (GCC_UNLIKELY((old_pagehandler->flags&PFLAG_READABLE)!=PFLAG_READABLE)) {
+                       E_Exit("wd:non-readable code page found that is no ROM page");
+               }
+               addr&=4095;
+               if (host_readd(hostmem+addr)==(Bit32u)val) return;
+               host_writed(hostmem+addr,val);
+               if (!*(Bit32u*)&write_map[addr]) {
+                       if (active_blocks) return;
+                       active_count--;
+                       if (!active_count) Release();
+                       return;
+               } else if (!invalidation_map) {
+                       invalidation_map=(Bit8u*)malloc(4096);
+                       memset(invalidation_map,0,4096);
+               }
+               (*(Bit32u*)&invalidation_map[addr])+=0x1010101;
+               InvalidateRange(addr,addr+3);
+       }
+       bool writeb_checked(PhysPt addr,Bitu val) {
+               if (GCC_UNLIKELY(old_pagehandler->flags&PFLAG_HASROM)) return false;
+               if (GCC_UNLIKELY((old_pagehandler->flags&PFLAG_READABLE)!=PFLAG_READABLE)) {
+                       E_Exit("cb:non-readable code page found that is no ROM page");
+               }
+               addr&=4095;
+               if (host_readb(hostmem+addr)==(Bit8u)val) return false;
+               if (!*(Bit8u*)&write_map[addr]) {
+                       if (!active_blocks) {
+                               active_count--;
+                               if (!active_count) Release();
+                       }
+               } else {
+                       if (!invalidation_map) {
+                               invalidation_map=(Bit8u*)malloc(4096);
+                               memset(invalidation_map,0,4096);
+                       }
+                       invalidation_map[addr]++;
+                       if (InvalidateRange(addr,addr)) {
+                               cpu.exception.which=SMC_CURRENT_BLOCK;
+                               return true;
+                       }
+               }
+               host_writeb(hostmem+addr,val);
+               return false;
+       }
+       bool writew_checked(PhysPt addr,Bitu val) {
+               if (GCC_UNLIKELY(old_pagehandler->flags&PFLAG_HASROM)) return false;
+               if (GCC_UNLIKELY((old_pagehandler->flags&PFLAG_READABLE)!=PFLAG_READABLE)) {
+                       E_Exit("cw:non-readable code page found that is no ROM page");
+               }
+               addr&=4095;
+               if (host_readw(hostmem+addr)==(Bit16u)val) return false;
+               if (!*(Bit16u*)&write_map[addr]) {
+                       if (!active_blocks) {
+                               active_count--;
+                               if (!active_count) Release();
+                       }
+               } else {
+                       if (!invalidation_map) {
+                               invalidation_map=(Bit8u*)malloc(4096);
+                               memset(invalidation_map,0,4096);
+                       }
+                       (*(Bit16u*)&invalidation_map[addr])+=0x101;
+                       if (InvalidateRange(addr,addr+1)) {
+                               cpu.exception.which=SMC_CURRENT_BLOCK;
+                               return true;
+                       }
+               }
+               host_writew(hostmem+addr,val);
+               return false;
+       }
+       bool writed_checked(PhysPt addr,Bitu val) {
+               if (GCC_UNLIKELY(old_pagehandler->flags&PFLAG_HASROM)) return false;
+               if (GCC_UNLIKELY((old_pagehandler->flags&PFLAG_READABLE)!=PFLAG_READABLE)) {
+                       E_Exit("cd:non-readable code page found that is no ROM page");
+               }
+               addr&=4095;
+               if (host_readd(hostmem+addr)==(Bit32u)val) return false;
+               if (!*(Bit32u*)&write_map[addr]) {
+                       if (!active_blocks) {
+                               active_count--;
+                               if (!active_count) Release();
+                       }
+               } else {
+                       if (!invalidation_map) {
+                               invalidation_map=(Bit8u*)malloc(4096);
+                               memset(invalidation_map,0,4096);
+                       }
+                       (*(Bit32u*)&invalidation_map[addr])+=0x1010101;
+                       if (InvalidateRange(addr,addr+3)) {
+                               cpu.exception.which=SMC_CURRENT_BLOCK;
+                               return true;
+                       }
+               }
+               host_writed(hostmem+addr,val);
+               return false;
+       }
+    void AddCacheBlock(CacheBlock * block) {
+               Bitu index=1+(block->page.start>>DYN_HASH_SHIFT);
+               block->hash.next=hash_map[index];
+               block->hash.index=index;
+               hash_map[index]=block;
+               block->page.handler=this;
+               active_blocks++;
+       }
+    void AddCrossBlock(CacheBlock * block) {
+               block->hash.next=hash_map[0];
+               block->hash.index=0;
+               hash_map[0]=block;
+               block->page.handler=this;
+               active_blocks++;
+       }
+       void DelCacheBlock(CacheBlock * block) {
+               active_blocks--;
+               active_count=16;
+               CacheBlock * * where=&hash_map[block->hash.index];
+               while (*where!=block) {
+                       where=&((*where)->hash.next);
+                       //Will crash if a block isn't found, which should never happen.
+               }
+               *where=block->hash.next;
+               if (GCC_UNLIKELY(block->cache.wmapmask!=NULL)) {
+                       for (Bitu i=block->page.start;i<block->cache.maskstart;i++) {
+                               if (write_map[i]) write_map[i]--;
+                       }
+                       Bitu maskct=0;
+                       for (Bitu i=block->cache.maskstart;i<=block->page.end;i++,maskct++) {
+                               if (write_map[i]) {
+                                       if ((maskct>=block->cache.masklen) || (!block->cache.wmapmask[maskct])) write_map[i]--;
+                               }
+                       }
+                       free(block->cache.wmapmask);
+                       block->cache.wmapmask=NULL;
+               } else {
+                       for (Bitu i=block->page.start;i<=block->page.end;i++) {
+                               if (write_map[i]) write_map[i]--;
+                       }
+               }
+       }
+       void Release(void) {
+               MEM_SetPageHandler(phys_page,1,old_pagehandler);
+               PAGING_ClearTLB();
+               if (prev) prev->next=next;
+               else cache.used_pages=next;
+               if (next) next->prev=prev;
+               else cache.last_page=prev;
+               next=cache.free_pages;
+               cache.free_pages=this;
+               prev=0;
+       }
+       void ClearRelease(void) {
+               for (Bitu index=0;index<(1+DYN_PAGE_HASH);index++) {
+                       CacheBlock * block=hash_map[index];
+                       while (block) {
+                               CacheBlock * nextblock=block->hash.next;
+                               block->page.handler=0;                  //No need, full clear
+                               block->Clear();
+                               block=nextblock;
+                       }
+               }
+               Release();
+       }
+       CacheBlock * FindCacheBlock(Bitu start) {
+               CacheBlock * block=hash_map[1+(start>>DYN_HASH_SHIFT)];
+               while (block) {
+                       if (block->page.start==start) return block;
+                       block=block->hash.next;
+               }
+               return 0;
+       }
+       HostPt GetHostReadPt(Bitu phys_page) { 
+               hostmem=old_pagehandler->GetHostReadPt(phys_page);
+               return hostmem;
+       }
+       HostPt GetHostWritePt(Bitu phys_page) { 
+               return GetHostReadPt( phys_page );
+       }
+public:
+       Bit8u write_map[4096];
+       Bit8u * invalidation_map;
+       CodePageHandler * next, * prev;
+private:
+       PageHandler * old_pagehandler;
+       CacheBlock * hash_map[1+DYN_PAGE_HASH];
+       Bitu active_blocks;
+       Bitu active_count;
+       HostPt hostmem; 
+       Bitu phys_page;
+};
+
+
+static INLINE void cache_addunsedblock(CacheBlock * block) {
+       block->cache.next=cache.block.free;
+       cache.block.free=block;
+}
+
+static CacheBlock * cache_getblock(void) {
+       CacheBlock * ret=cache.block.free;
+       if (!ret) E_Exit("Ran out of CacheBlocks" );
+       cache.block.free=ret->cache.next;
+       ret->cache.next=0;
+       return ret;
+}
+
+void CacheBlock::Clear(void) {
+       Bitu ind;
+       /* Check if this is not a cross page block */
+       if (hash.index) for (ind=0;ind<2;ind++) {
+               CacheBlock * fromlink=link[ind].from;
+               link[ind].from=0;
+               while (fromlink) {
+                       CacheBlock * nextlink=fromlink->link[ind].next;
+                       fromlink->link[ind].next=0;
+                       fromlink->link[ind].to=&link_blocks[ind];
+                       fromlink=nextlink;
+               }
+               if (link[ind].to!=&link_blocks[ind]) {
+                       CacheBlock * * wherelink=&link[ind].to->link[ind].from;
+                       while (*wherelink != this && *wherelink) {
+                               wherelink = &(*wherelink)->link[ind].next;
+                       }
+                       if(*wherelink) 
+                               *wherelink = (*wherelink)->link[ind].next;
+                       else
+                               LOG(LOG_CPU,LOG_ERROR)("Cache anomaly. please investigate");
+               }
+       } else 
+               cache_addunsedblock(this);
+       if (crossblock) {
+               crossblock->crossblock=0;
+               crossblock->Clear();
+               crossblock=0;
+       }
+       if (page.handler) {
+               page.handler->DelCacheBlock(this);
+               page.handler=0;
+       }
+       if (cache.wmapmask){
+               free(cache.wmapmask);
+               cache.wmapmask=NULL;
+       }
+}
+
+
+static CacheBlock * cache_openblock(void) {
+       CacheBlock * block=cache.block.active;
+       /* check for enough space in this block */
+       Bitu size=block->cache.size;
+       CacheBlock * nextblock=block->cache.next;
+       if (block->page.handler) 
+               block->Clear();
+       while (size<CACHE_MAXSIZE) {
+               if (!nextblock) 
+                       goto skipresize;
+               size+=nextblock->cache.size;
+               CacheBlock * tempblock=nextblock->cache.next;
+               if (nextblock->page.handler) 
+                       nextblock->Clear();
+               cache_addunsedblock(nextblock);
+               nextblock=tempblock;
+       }
+skipresize:
+       block->cache.size=size;
+       block->cache.next=nextblock;
+       cache.pos=block->cache.start;
+       return block;
+}
+
+static void cache_closeblock(void) {
+       CacheBlock * block=cache.block.active;
+       block->link[0].to=&link_blocks[0];
+       block->link[1].to=&link_blocks[1];
+       block->link[0].from=0;
+       block->link[1].from=0;
+       block->link[0].next=0;
+       block->link[1].next=0;
+       /* Close the block with correct alignments */
+       Bitu written=cache.pos-block->cache.start;
+       if (written>block->cache.size) {
+               if (!block->cache.next) {
+                       if (written>block->cache.size+CACHE_MAXSIZE) E_Exit("CacheBlock overrun 1 %d",written-block->cache.size);       
+               } else E_Exit("CacheBlock overrun 2 written %d size %d",written,block->cache.size);     
+       } else {
+               Bitu new_size;
+               Bitu left=block->cache.size-written;
+               /* Smaller than cache align then don't bother to resize */
+               if (left>CACHE_ALIGN) {
+                       new_size=((written-1)|(CACHE_ALIGN-1))+1;
+                       CacheBlock * newblock=cache_getblock();
+                       newblock->cache.start=block->cache.start+new_size;
+                       newblock->cache.size=block->cache.size-new_size;
+                       newblock->cache.next=block->cache.next;
+                       block->cache.next=newblock;
+                       block->cache.size=new_size;
+               }
+       }
+       /* Advance the active block pointer */
+       if (!block->cache.next) {
+//             LOG_MSG("Cache full restarting");
+               cache.block.active=cache.block.first;
+       } else {
+               cache.block.active=block->cache.next;
+       }
+}
+
+static INLINE void cache_addb(Bit8u val) {
+       *cache.pos++=val;
+}
+
+static INLINE void cache_addw(Bit16u val) {
+       *(Bit16u*)cache.pos=val;
+       cache.pos+=2;
+}
+
+static INLINE void cache_addd(Bit32u val) {
+       *(Bit32u*)cache.pos=val;
+       cache.pos+=4;
+}
+
+
+static void gen_return(BlockReturn retcode);
+
+static Bit8u * cache_code_start_ptr=NULL;
+static Bit8u * cache_code=NULL;
+static Bit8u * cache_code_link_blocks=NULL;
+static CacheBlock * cache_blocks=NULL;
+
+/* Define temporary pagesize so the MPROTECT case and the regular case share as much code as possible */
+#if (C_HAVE_MPROTECT)
+#define PAGESIZE_TEMP PAGESIZE
+#else 
+#define PAGESIZE_TEMP 4096
+#endif
+
+static bool cache_initialized = false;
+
+static void cache_init(bool enable) {
+       Bits i;
+       if (enable) {
+               if (cache_initialized) return;
+               cache_initialized = true;
+               if (cache_blocks == NULL) {
+                       cache_blocks=(CacheBlock*)malloc(CACHE_BLOCKS*sizeof(CacheBlock));
+                       if(!cache_blocks) E_Exit("Allocating cache_blocks has failed");
+                       memset(cache_blocks,0,sizeof(CacheBlock)*CACHE_BLOCKS);
+                       cache.block.free=&cache_blocks[0];
+                       for (i=0;i<CACHE_BLOCKS-1;i++) {
+                               cache_blocks[i].link[0].to=(CacheBlock *)1;
+                               cache_blocks[i].link[1].to=(CacheBlock *)1;
+                               cache_blocks[i].cache.next=&cache_blocks[i+1];
+                       }
+               }
+               if (cache_code_start_ptr==NULL) {
+#if defined (WIN32)
+                       cache_code_start_ptr=(Bit8u*)VirtualAlloc(0,CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP,
+                               MEM_COMMIT,PAGE_EXECUTE_READWRITE);
+                       if (!cache_code_start_ptr)
+                               cache_code_start_ptr=(Bit8u*)malloc(CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP);
+#else
+                       cache_code_start_ptr=(Bit8u*)malloc(CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP);
+#endif
+                       if(!cache_code_start_ptr) E_Exit("Allocating dynamic core cache memory failed");
+
+                       cache_code=(Bit8u*)(((Bitu)cache_code_start_ptr + PAGESIZE_TEMP-1) & ~(PAGESIZE_TEMP-1)); //Bitu is same size as a pointer.
+
+                       cache_code_link_blocks=cache_code;
+                       cache_code+=PAGESIZE_TEMP;
+
+#if (C_HAVE_MPROTECT)
+                       if(mprotect(cache_code_link_blocks,CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP,PROT_WRITE|PROT_READ|PROT_EXEC))
+                               LOG_MSG("Setting excute permission on the code cache has failed!");
+#endif
+                       CacheBlock * block=cache_getblock();
+                       cache.block.first=block;
+                       cache.block.active=block;
+                       block->cache.start=&cache_code[0];
+                       block->cache.size=CACHE_TOTAL;
+                       block->cache.next=0;                                                            //Last block in the list
+               }
+               /* Setup the default blocks for block linkage returns */
+               cache.pos=&cache_code_link_blocks[0];
+               link_blocks[0].cache.start=cache.pos;
+               gen_return(BR_Link1);
+               cache.pos=&cache_code_link_blocks[32];
+               link_blocks[1].cache.start=cache.pos;
+               gen_return(BR_Link2);
+               cache.free_pages=0;
+               cache.last_page=0;
+               cache.used_pages=0;
+               /* Setup the code pages */
+               for (i=0;i<CACHE_PAGES;i++) {
+                       CodePageHandler * newpage=new CodePageHandler();
+                       newpage->next=cache.free_pages;
+                       cache.free_pages=newpage;
+               }
+       }
+}
+
+static void cache_close(void) {
+/*     for (;;) {
+               if (cache.used_pages) {
+                       CodePageHandler * cpage=cache.used_pages;
+                       CodePageHandler * npage=cache.used_pages->next;
+                       cpage->ClearRelease();
+                       delete cpage;
+                       cache.used_pages=npage;
+               } else break;
+       }
+       if (cache_blocks != NULL) {
+               free(cache_blocks);
+               cache_blocks = NULL;
+       }
+       if (cache_code_start_ptr != NULL) {
+               ### care: under windows VirtualFree() has to be used if
+               ###       VirtualAlloc was used for memory allocation
+               free(cache_code_start_ptr);
+               cache_code_start_ptr = NULL;
+       }
+       cache_code = NULL;
+       cache_code_link_blocks = NULL;
+       cache_initialized = false; */
+}
+
+static void cache_reset(void) {
+       if (cache_initialized) {
+               for (;;) {
+                       if (cache.used_pages) {
+                               CodePageHandler * cpage=cache.used_pages;
+                               CodePageHandler * npage=cache.used_pages->next;
+                               cpage->ClearRelease();
+                               delete cpage;
+                               cache.used_pages=npage;
+                       } else break;
+               }
+
+               if (cache_blocks == NULL) {
+                       cache_blocks=(CacheBlock*)malloc(CACHE_BLOCKS*sizeof(CacheBlock));
+                       if(!cache_blocks) E_Exit("Allocating cache_blocks has failed");
+               }
+               memset(cache_blocks,0,sizeof(CacheBlock)*CACHE_BLOCKS);
+               cache.block.free=&cache_blocks[0];
+               for (Bits i=0;i<CACHE_BLOCKS-1;i++) {
+                       cache_blocks[i].link[0].to=(CacheBlock *)1;
+                       cache_blocks[i].link[1].to=(CacheBlock *)1;
+                       cache_blocks[i].cache.next=&cache_blocks[i+1];
+               }
+
+               if (cache_code_start_ptr==NULL) {
+#if defined (WIN32)
+                       cache_code_start_ptr=(Bit8u*)VirtualAlloc(0,CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP,
+                               MEM_COMMIT,PAGE_EXECUTE_READWRITE);
+                       if (!cache_code_start_ptr)
+                               cache_code_start_ptr=(Bit8u*)malloc(CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP);
+#else
+                       cache_code_start_ptr=(Bit8u*)malloc(CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP);
+#endif
+                       if (!cache_code_start_ptr) E_Exit("Allocating dynamic core cache memory failed");
+
+                       cache_code=(Bit8u*)(((Bitu)cache_code_start_ptr + PAGESIZE_TEMP-1) & ~(PAGESIZE_TEMP-1)); //Bitu is same size as a pointer.
+
+                       cache_code_link_blocks=cache_code;
+                       cache_code+=PAGESIZE_TEMP;
+
+#if (C_HAVE_MPROTECT)
+                       if(mprotect(cache_code_link_blocks,CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP,PROT_WRITE|PROT_READ|PROT_EXEC))
+                               LOG_MSG("Setting excute permission on the code cache has failed!");
+#endif
+               }
+
+               CacheBlock * block=cache_getblock();
+               cache.block.first=block;
+               cache.block.active=block;
+               block->cache.start=&cache_code[0];
+               block->cache.size=CACHE_TOTAL;
+               block->cache.next=0;                                                            //Last block in the list
+
+               /* Setup the default blocks for block linkage returns */
+               cache.pos=&cache_code_link_blocks[0];
+               link_blocks[0].cache.start=cache.pos;
+               gen_return(BR_Link1);
+               cache.pos=&cache_code_link_blocks[32];
+               link_blocks[1].cache.start=cache.pos;
+               gen_return(BR_Link2);
+               cache.free_pages=0;
+               cache.last_page=0;
+               cache.used_pages=0;
+               /* Setup the code pages */
+               for (Bitu i=0;i<CACHE_PAGES;i++) {
+                       CodePageHandler * newpage=new CodePageHandler();
+                       newpage->next=cache.free_pages;
+                       cache.free_pages=newpage;
+               }
+       }
+}