drc: merge Ari64's patch: 07_clear_cache
authornotaz <notasas@gmail.com>
Wed, 16 Feb 2011 19:31:19 +0000 (21:31 +0200)
committernotaz <notasas@gmail.com>
Wed, 16 Feb 2011 22:48:38 +0000 (00:48 +0200)
libpcsxcore/new_dynarec/assem_arm.c
libpcsxcore/new_dynarec/new_dynarec.c

index ed89bb0..0153bfc 100644 (file)
@@ -68,6 +68,8 @@ const u_int jump_vaddr_reg[16] = {
 
 #include "fpu.h"
 
+unsigned int needs_clear_cache[1<<(TARGET_SIZE_2-17)];
+
 /* Linker */
 
 void set_jump_target(int addr,u_int target)
@@ -4784,6 +4786,38 @@ void wb_invalidate_arm(signed char pre[],signed char entry[],uint64_t dirty,uint
 #define wb_invalidate wb_invalidate_arm
 */
 
+// Clearing the cache is rather slow on ARM Linux, so mark the areas
+// that need to be cleared, and then only clear these areas once.
+void do_clear_cache()
+{
+  int i,j;
+  for (i=0;i<(1<<(TARGET_SIZE_2-17));i++)
+  {
+    u_int bitmap=needs_clear_cache[i];
+    if(bitmap) {
+      u_int start,end;
+      for(j=0;j<32;j++) 
+      {
+        if(bitmap&(1<<j)) {
+          start=BASE_ADDR+i*131072+j*4096;
+          end=start+4095;
+          j++;
+          while(j<32) {
+            if(bitmap&(1<<j)) {
+              end+=4096;
+              j++;
+            }else{
+              __clear_cache((void *)start,(void *)end);
+              break;
+            }
+          }
+        }
+      }
+      needs_clear_cache[i]=0;
+    }
+  }
+}
+
 // CPU-architecture-specific initialization
 void arch_init() {
 #ifndef DISABLE_COP1
index 28a0245..fb6ace4 100644 (file)
@@ -1086,7 +1086,6 @@ void ll_clear(struct ll_entry **head)
 // Dereference the pointers and remove if it matches
 void ll_kill_pointers(struct ll_entry *head,int addr,int shift)
 {
-  u_int old_host_addr=0;
   while(head) {
     int ptr=get_pointer(head->addr);
     inv_debug("EXP: Lookup pointer to %x at %x (%x)\n",(int)ptr,(int)head->addr,head->vaddr);
@@ -1095,20 +1094,12 @@ void ll_kill_pointers(struct ll_entry *head,int addr,int shift)
     {
       inv_debug("EXP: Kill pointer at %x (%x)\n",(int)head->addr,head->vaddr);
       u_int host_addr=(u_int)kill_pointer(head->addr);
-
-      if((host_addr>>12)!=(old_host_addr>>12)) {
-        #ifdef __arm__
-        __clear_cache((void *)(old_host_addr&~0xfff),(void *)(old_host_addr|0xfff));
-        #endif
-        old_host_addr=host_addr;
-      }
+      #ifdef __arm__
+        needs_clear_cache[(host_addr-(u_int)BASE_ADDR)>>17]|=1<<(((host_addr-(u_int)BASE_ADDR)>>12)&31);
+      #endif
     }
     head=head->next;
   }
-  #ifdef __arm__
-  if (old_host_addr)
-    __clear_cache((void *)(old_host_addr&~0xfff),(void *)(old_host_addr|0xfff));
-  #endif
 }
 
 // This is called when we write to a compiled block (see do_invstub)
@@ -1116,7 +1107,6 @@ void invalidate_page(u_int page)
 {
   struct ll_entry *head;
   struct ll_entry *next;
-  u_int old_host_addr=0;
   head=jump_in[page];
   jump_in[page]=0;
   while(head!=NULL) {
@@ -1131,21 +1121,13 @@ void invalidate_page(u_int page)
   while(head!=NULL) {
     inv_debug("INVALIDATE: kill pointer to %x (%x)\n",head->vaddr,(int)head->addr);
     u_int host_addr=(u_int)kill_pointer(head->addr);
-
-    if((host_addr>>12)!=(old_host_addr>>12)) {
-      #ifdef __arm__
-      __clear_cache((void *)(old_host_addr&~0xfff),(void *)(old_host_addr|0xfff));
-      #endif
-      old_host_addr=host_addr;
-    }
+    #ifdef __arm__
+      needs_clear_cache[(host_addr-(u_int)BASE_ADDR)>>17]|=1<<(((host_addr-(u_int)BASE_ADDR)>>12)&31);
+    #endif
     next=head->next;
     free(head);
     head=next;
   }
-  #ifdef __arm__
-  if (old_host_addr)
-    __clear_cache((void *)(old_host_addr&~0xfff),(void *)(old_host_addr|0xfff));
-  #endif
 }
 void invalidate_block(u_int block)
 {
@@ -1192,6 +1174,9 @@ void invalidate_block(u_int block)
   for(first=page+1;first<last;first++) {
     invalidate_page(first);
   }
+  #ifdef __arm__
+    do_clear_cache();
+  #endif
   
   // Don't trap writes
   invalid_code[block]=1;
@@ -1216,6 +1201,8 @@ void invalidate_addr(u_int addr)
 {
   invalidate_block(addr>>12);
 }
+// This is called when loading a save state.
+// Anything could have changed, so invalidate everything.
 void invalidate_all_pages()
 {
   u_int page,n;
@@ -11041,6 +11028,10 @@ int new_recompile_block(int addr)
         break;
       case 3:
         // Clear jump_out
+        #ifdef __arm__
+        if((expirep&2047)==0) 
+          do_clear_cache();
+        #endif
         ll_remove_matching_addrs(jump_out+(expirep&2047),base,shift);
         ll_remove_matching_addrs(jump_out+2048+(expirep&2047),base,shift);
         break;