+// also takes care of w^x mappings when patching code
+static u_int needs_clear_cache[1<<(TARGET_SIZE_2-17)];
+
+static void mark_clear_cache(void *target)
+{
+ uintptr_t offset = (u_char *)target - ndrc->translation_cache;
+ u_int mask = 1u << ((offset >> 12) & 31);
+ if (!(needs_clear_cache[offset >> 17] & mask)) {
+ char *start = (char *)((uintptr_t)target & ~4095l);
+ start_tcache_write(start, start + 4095);
+ needs_clear_cache[offset >> 17] |= mask;
+ }
+}
+
+// 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.
+static void do_clear_cache(void)
+{
+ int i, j;
+ for (i = 0; i < (1<<(TARGET_SIZE_2-17)); i++)
+ {
+ u_int bitmap = needs_clear_cache[i];
+ if (!bitmap)
+ continue;
+ for (j = 0; j < 32; j++)
+ {
+ u_char *start, *end;
+ if (!(bitmap & (1<<j)))
+ continue;
+
+ start = ndrc->translation_cache + i*131072 + j*4096;
+ end = start + 4095;
+ for (j++; j < 32; j++) {
+ if (!(bitmap & (1<<j)))
+ break;
+ end += 4096;
+ }
+ end_tcache_write(start, end);
+ }
+ needs_clear_cache[i] = 0;
+ }
+}
+