--- trunk/src/cpus/cpu_dyntrans.c 2007/10/08 16:20:18 27 +++ trunk/src/cpus/cpu_dyntrans.c 2007/10/08 16:20:26 28 @@ -25,93 +25,79 @@ * SUCH DAMAGE. * * - * $Id: cpu_dyntrans.c,v 1.104 2006/06/25 00:15:44 debug Exp $ + * $Id: cpu_dyntrans.c,v 1.113 2006/07/21 20:09:15 debug Exp $ * * Common dyntrans routines. Included from cpu_*.c. */ -#ifdef DYNTRANS_CPU_RUN_INSTR -#if 1 /* IC statistics: */ +#ifndef STATIC_STUFF +#define STATIC_STUFF +/* + * gather_statistics(): + */ static void gather_statistics(struct cpu *cpu) { + char ch, buf[60]; struct DYNTRANS_IC *ic = cpu->cd.DYNTRANS_ARCH.next_ic; - static long long n = 0; - static FILE *f = NULL; - - n++; - if (n < 100000000) - return; - - if (f == NULL) { - f = fopen("instruction_call_statistics.raw", "w"); - if (f == NULL) { - fatal("Unable to open statistics file for output.\n"); - exit(1); - } - } - fwrite(&ic->f, 1, sizeof(void *), f); -} -#else /* PC statistics: */ -static void gather_statistics(struct cpu *cpu) -{ + int i = 0; uint64_t a; int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - (size_t) cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC); - if (low_pc < 0 || low_pc >= DYNTRANS_IC_ENTRIES_PER_PAGE) - return; - -#if 0 - /* Use the physical address: */ - cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *) - cpu->cd.DYNTRANS_ARCH.cur_ic_page; - a = cpu->cd.DYNTRANS_ARCH.cur_physpage->physaddr; -#else - /* Use the PC (virtual address): */ - a = cpu->pc; -#endif - a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) << - DYNTRANS_INSTR_ALIGNMENT_SHIFT); - a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT; + buf[0] = '\0'; - /* - * TODO: Everything below this line should be cleaned up :-) - */ -a &= 0x03ffffff; -{ - static long long *array = NULL; - static char *array_16kpage_in_use = NULL; - static int n = 0; - a >>= DYNTRANS_INSTR_ALIGNMENT_SHIFT; - if (array == NULL) - array = zeroed_alloc(sizeof(long long) * 16384*1024); - if (array_16kpage_in_use == NULL) - array_16kpage_in_use = zeroed_alloc(sizeof(char) * 1024); - a &= (16384*1024-1); - array[a] ++; - array_16kpage_in_use[a / 16384] = 1; - n++; - if ((n & 0x3fffffff) == 0) { - FILE *f = fopen("statistics.out", "w"); - int i, j; - printf("Saving statistics... "); fflush(stdout); - for (i=0; i<1024; i++) - if (array_16kpage_in_use[i]) { - for (j=0; j<16384; j++) - if (array[i*16384 + j] > 0) - fprintf(f, "%lli\t" - "0x%016"PRIx64"\n", - (uint64_t)array[i*16384+j], - (uint64_t)((i*16384+j) << - DYNTRANS_INSTR_ALIGNMENT_SHIFT)); - } - fclose(f); - printf("n=0x%08x\n", n); + while ((ch = cpu->machine->statistics_fields[i]) != '\0') { + if (i != 0) + strlcat(buf, " ", sizeof(buf)); + + switch (ch) { + case 'i': + snprintf(buf + strlen(buf), sizeof(buf), + "%p", (void *)ic->f); + break; + case 'p': + /* Physical program counter address: */ + /* (low_pc must be within the page!) */ + if (low_pc < 0 || + low_pc >= DYNTRANS_IC_ENTRIES_PER_PAGE) + strlcat(buf, "-", sizeof(buf)); + cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *) + cpu->cd.DYNTRANS_ARCH.cur_ic_page; + a = cpu->cd.DYNTRANS_ARCH.cur_physpage->physaddr; + a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) << + DYNTRANS_INSTR_ALIGNMENT_SHIFT); + a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT; + if (cpu->is_32bit) + snprintf(buf + strlen(buf), sizeof(buf), + "0x%016"PRIx32, (uint32_t)a); + else + snprintf(buf + strlen(buf), sizeof(buf), + "0x%016"PRIx64, (uint64_t)a); + break; + case 'v': + /* Virtual program counter address: */ + /* (low_pc inside the page, or in a delay slot) */ + if (low_pc < 0 || + low_pc >= DYNTRANS_IC_ENTRIES_PER_PAGE + 2) + strlcat(buf, "-", sizeof(buf)); + a = cpu->pc; + a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) << + DYNTRANS_INSTR_ALIGNMENT_SHIFT); + a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT; + if (cpu->is_32bit) + snprintf(buf + strlen(buf), sizeof(buf), + "0x%016"PRIx32, (uint32_t)a); + else + snprintf(buf + strlen(buf), sizeof(buf), + "0x%016"PRIx64, (uint64_t)a); + break; + } + i++; } + + fprintf(cpu->machine->statistics_file, "%s\n", buf); } -} -#endif /* PC statistics */ #define S gather_statistics(cpu) @@ -170,36 +156,35 @@ ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic); } */ #endif +#endif /* STATIC STUFF */ + +#ifdef DYNTRANS_RUN_INSTR /* - * XXX_cpu_run_instr(): + * XXX_run_instr(): * * Execute one or more instructions on a specific CPU, using dyntrans. + * (For dualmode archs, this function is included twice.) * * Return value is the number of instructions executed during this call, * 0 if no instructions were executed. */ -int DYNTRANS_CPU_RUN_INSTR(struct emul *emul, struct cpu *cpu) +int DYNTRANS_RUN_INSTR(struct cpu *cpu) { - /* - * TODO: Statistics stuff! - */ - int show_opcode_statistics = 0; - -#ifdef MODE32 - uint32_t cached_pc; -#else - uint64_t cached_pc; -#endif + MODE_uint_t cached_pc; int low_pc, n_instrs; + /* Ugly... fix this some day. */ #ifdef DYNTRANS_DUALMODE_32 - if (cpu->is_32bit) - DYNTRANS_PC_TO_POINTERS32(cpu); - else +#ifdef MODE32 + DYNTRANS_PC_TO_POINTERS32(cpu); +#else + DYNTRANS_PC_TO_POINTERS(cpu); #endif +#else DYNTRANS_PC_TO_POINTERS(cpu); +#endif /* * Interrupt assertion? (This is _below_ the initial PC to pointer @@ -278,7 +263,7 @@ if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0], sizeof(instr), MEM_READ, CACHE_INSTRUCTION)) { - fatal("XXX_cpu_run_instr(): could not read " + fatal("XXX_run_instr(): could not read " "the instruction\n"); } else { cpu_disassemble_instr(cpu->machine, cpu, @@ -323,16 +308,19 @@ arg[0] = 0; #endif } + fatal("[ Note: The translation of physical page 0x%" PRIx64" contained combinations of instructions; " "these are now flushed because we are single-" "stepping. ]\n", (long long)cpu->cd.DYNTRANS_ARCH. cur_physpage->physaddr); + cpu->cd.DYNTRANS_ARCH.cur_physpage->flags &= - ~(COMBINATIONS | TRANSLATIONS); + ~COMBINATIONS; + cpu->cd.DYNTRANS_ARCH.cur_physpage->translations = 0; } - if (show_opcode_statistics) + if (cpu->machine->statistics_enabled) S; /* Execute just one instruction: */ @@ -361,7 +349,7 @@ N_SAFE_DYNTRANS_LIMIT) break; } - } else if (show_opcode_statistics) { + } else if (cpu->machine->statistics_enabled) { /* Gather statistics while executing multiple instructions: */ n_instrs = 0; for (;;) { @@ -458,7 +446,7 @@ /* Return the nr of instructions executed: */ return n_instrs; } -#endif /* DYNTRANS_CPU_RUN_INSTR */ +#endif /* DYNTRANS_RUN_INSTR */ @@ -505,7 +493,7 @@ */ for (x=0; xpaddr translation " "failed. vaddr=0x%"PRIx64"\n", (uint64_t)cached_pc); fatal("!! cpu->pc=0x%"PRIx64"\n", (uint64_t)cpu->pc); */ - ok = cpu->translate_v2p(cpu, cpu->pc, &paddr, - FLAG_INSTR); + /* If there was an exception, the PC has changed. + Update cached_pc: */ + cached_pc = cpu->pc; + +#ifdef MODE32 + index = DYNTRANS_ADDR_TO_PAGENR(cached_pc); + if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL) { + paddr = cpu->cd.DYNTRANS_ARCH.phys_addr[index]; + ok = 1; + } +#else + x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1; + x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2; + x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N)) + & mask3; + l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1]; + l3 = l2->l3[x2]; + if (l3->host_load[x3] != NULL) { + paddr = l3->phys_addr[x3]; + ok = 1; + } +#endif + + if (!ok) { + ok = cpu->translate_v2p(cpu, cpu->pc, &paddr, + FLAG_INSTR); + } /* printf("EXCEPTION HANDLER: vaddr = 0x%x ==> " "paddr = 0x%x\n", (int)cpu->pc, (int)paddr); @@ -687,41 +706,22 @@ } } - /* If there was an exception, the PC can have changed. - Update cached_pc: */ - cached_pc = cpu->pc; - -#ifdef MODE32 - index = DYNTRANS_ADDR_TO_PAGENR(cached_pc); -#else - x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1; - x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2; - x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N)) - & mask3; -#endif - physaddr = paddr; } + physaddr &= ~(DYNTRANS_PAGESIZE - 1); + #ifdef MODE32 if (cpu->cd.DYNTRANS_ARCH.host_load[index] == NULL) { #else if (l3->host_load[x3] == NULL) { #endif + int q = DYNTRANS_PAGESIZE - 1; unsigned char *host_page = memory_paddr_to_hostaddr(cpu->mem, physaddr, MEM_READ); if (host_page != NULL) { - int q = DYNTRANS_PAGESIZE - 1; - host_page += (physaddr & - ((1 << BITS_PER_MEMBLOCK) - 1) & ~q); cpu->update_translation_table(cpu, cached_pc & ~q, - host_page, 0, physaddr & ~q); -#ifndef MODE32 - /* Recalculate l2 and l3, since they might have - changed now: */ - l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1]; - l3 = l2->l3[x2]; -#endif + host_page, 0, physaddr); } } @@ -732,8 +732,6 @@ cpu_create_or_reset_tc(cpu); } - physaddr &= ~(DYNTRANS_PAGESIZE - 1); - pagenr = DYNTRANS_ADDR_TO_PAGENR(physaddr); table_index = PAGENR_TO_TABLE_INDEX(pagenr); @@ -779,15 +777,15 @@ l3->phys_page[x3] = ppp; #endif -#ifdef MODE32 - /* Small optimization: only mark the physical page as non-writable - if it did not contain translations. (Because if it does contain - translations, it is already non-writable.) */ - if (!cpu->cd.DYNTRANS_ARCH.phystranslation[pagenr >> 5] & - (1 << (pagenr & 31))) -#endif - cpu->invalidate_translation_caches(cpu, physaddr, - JUST_MARK_AS_NON_WRITABLE | INVALIDATE_PADDR); + /* + * If there are no translations yet on this page, then mark it + * as non-writable. If there are already translations, then it + * should already have been marked as non-writable. + */ + if (ppp->translations == 0) { + cpu->invalidate_translation_caches(cpu, physaddr, + JUST_MARK_AS_NON_WRITABLE | INVALIDATE_PADDR); + } cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0]; @@ -904,6 +902,8 @@ } ppp->next_ofs = 0; + ppp->flags = 0; + ppp->translations = 0; /* ppp->physaddr is filled in by the page allocator */ for (i=0; ihost_store[x3] = NULL; return; } + +#ifdef BUGHUNT + +{ + /* Consistency check, for debugging: */ + int x1, x1b; // x2, x3; + struct DYNTRANS_L2_64_TABLE *l2; + //struct DYNTRANS_L3_64_TABLE *l3; + + for (x1 = 0; x1 <= mask1; x1 ++) { + l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1]; + if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) + continue; + /* Make sure that this l2 isn't used more than 1 time! */ + for (x1b = 0; x1b <= mask1; x1b ++) + if (x1 != x1b && + l2 == cpu->cd.DYNTRANS_ARCH.l1_64[x1b]) { + fatal("L2 reuse: %p\n", l2); + exit(1); + } + } +} + +/* Count how many pages are actually in use: */ +{ + int n=0, i; + for (i=0; i<=mask3; i++) + if (l3->vaddr_to_tlbindex[i]) + n++; + if (n != l3->refcount) { + printf("Z: %i in use, but refcount = %i!\n", n, l3->refcount); + exit(1); + } + + n = 0; + for (i=0; i<=mask3; i++) + if (l3->host_load[i] != NULL) + n++; + if (n != l3->refcount) { + printf("ZHL: %i in use, but refcount = %i!\n", n, l3->refcount); + exit(1); + } +} +#endif + l3->host_load[x3] = NULL; l3->host_store[x3] = NULL; l3->phys_addr[x3] = 0; l3->phys_page[x3] = NULL; - l3->refcount --; + if (l3->vaddr_to_tlbindex[x3] != 0) { + cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[ + l3->vaddr_to_tlbindex[x3] - 1].valid = 0; + l3->refcount --; + } + l3->vaddr_to_tlbindex[x3] = 0; + if (l3->refcount < 0) { fatal("xxx_invalidate_tlb_entry(): huh? Refcount bug.\n"); exit(1); } + if (l3->refcount == 0) { l3->next = cpu->cd.DYNTRANS_ARCH.next_free_l3; cpu->cd.DYNTRANS_ARCH.next_free_l3 = l3; l2->l3[x2] = cpu->cd.DYNTRANS_ARCH.l3_64_dummy; +#ifdef BUGHUNT +/* Make sure that we're placing a CLEAN page on the + freelist: */ +{ + int i; + for (i=0; i<=mask3; i++) + if (l3->host_load[i] != NULL) { + fatal("TRYING TO RETURN A NON-CLEAN L3 PAGE!\n"); + exit(1); + } +} +#endif l2->refcount --; if (l2->refcount < 0) { fatal("xxx_invalidate_tlb_entry(): Refcount bug L2.\n"); @@ -1180,18 +1244,6 @@ struct DYNTRANS_TC_PHYSPAGE *ppp, *prev_ppp; pagenr = DYNTRANS_ADDR_TO_PAGENR(addr); - -#ifdef MODE32 - /* If this page isn't marked as having any translations, - then return immediately. */ - if (!(cpu->cd.DYNTRANS_ARCH.phystranslation[pagenr >> 5] - & 1 << (pagenr & 31))) - return; - /* Remove the mark: */ - cpu->cd.DYNTRANS_ARCH.phystranslation[pagenr >> 5] &= - ~ (1 << (pagenr & 31)); -#endif - table_index = PAGENR_TO_TABLE_INDEX(pagenr); physpage_entryp = &(((uint32_t *)cpu-> @@ -1217,7 +1269,7 @@ if (physpage_ofs == 0) ppp = NULL; -#if 1 +#if 0 /* * "Bypass" the page, removing it from the code cache. * @@ -1239,16 +1291,29 @@ * it might be faster since we don't risk wasting cache * memory as quickly (which would force unnecessary Restarts). */ - if (ppp != NULL) { - /* TODO: Is this faster than copying an entire - template page? */ - int i; - for (i=0; iics[i].f = + if (ppp != NULL && ppp->translations != 0) { + uint32_t x = ppp->translations; /* TODO: + urk Should be same type as ppp->translations */ + int i, j, n, m; + n = 8 * sizeof(x); + m = DYNTRANS_IC_ENTRIES_PER_PAGE / n; + + for (i=0; iics[i*m + j].f = #ifdef DYNTRANS_DUALMODE_32 - cpu->is_32bit? instr32(to_be_translated) : + cpu->is_32bit? + instr32(to_be_translated) : #endif - instr(to_be_translated); + instr(to_be_translated); + } + + x >>= 1; + } + + ppp->flags &= ~COMBINATIONS; + ppp->translations = 0; } #endif } @@ -1268,10 +1333,6 @@ uint32_t index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page); cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL; - /* Remove the mark: */ - index = DYNTRANS_ADDR_TO_PAGENR(paddr_page); - cpu->cd.DYNTRANS_ARCH.phystranslation[ - index >> 5] &= ~ (1 << (index & 31)); #else const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1; const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1; @@ -1325,8 +1386,9 @@ uint32_t x1, x2, x3; struct DYNTRANS_L2_64_TABLE *l2; struct DYNTRANS_L3_64_TABLE *l3; - /* fatal("update_translation_table(): v=0x%"PRIx64", h=%p w=%i" - " p=0x%"PRIx64"\n", (uint64_t)vaddr_page, host_page, writeflag, + + /* fatal("update_translation_table(): v=0x%016"PRIx64", h=%p w=%i" + " p=0x%016"PRIx64"\n", (uint64_t)vaddr_page, host_page, writeflag, (uint64_t)paddr_page); */ #endif @@ -1416,6 +1478,7 @@ x2 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2; x3 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N)) & mask3; + l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1]; if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) { if (cpu->cd.DYNTRANS_ARCH.next_free_l2 != NULL) { @@ -1426,10 +1489,19 @@ int i; l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1] = malloc(sizeof(struct DYNTRANS_L2_64_TABLE)); + l2->refcount = 0; for (i=0; i<(1 << DYNTRANS_L2N); i++) l2->l3[i] = cpu->cd.DYNTRANS_ARCH. l3_64_dummy; } + if (l2->refcount != 0) { + fatal("Huh? l2 Refcount problem.\n"); + exit(1); + } + } + if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) { + fatal("INTERNAL ERROR L2 reuse\n"); + exit(1); } l3 = l2->l3[x2]; if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy) { @@ -1441,14 +1513,47 @@ l3 = l2->l3[x2] = zeroed_alloc(sizeof( struct DYNTRANS_L3_64_TABLE)); } + if (l3->refcount != 0) { + fatal("Huh? l3 Refcount problem.\n"); + exit(1); + } l2->refcount ++; } + if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy) { + fatal("INTERNAL ERROR L3 reuse\n"); + exit(1); + } + l3->host_load[x3] = host_page; l3->host_store[x3] = writeflag? host_page : NULL; l3->phys_addr[x3] = paddr_page; l3->phys_page[x3] = NULL; l3->vaddr_to_tlbindex[x3] = r + 1; l3->refcount ++; + +#ifdef BUGHUNT +/* Count how many pages are actually in use: */ +{ + int n=0, i; + for (i=0; i<=mask3; i++) + if (l3->vaddr_to_tlbindex[i]) + n++; + if (n != l3->refcount) { + printf("X: %i in use, but refcount = %i!\n", n, l3->refcount); + exit(1); + } + + n = 0; + for (i=0; i<=mask3; i++) + if (l3->host_load[i] != NULL) + n++; + if (n != l3->refcount) { + printf("XHL: %i in use, but refcount = %i!\n", n, l3->refcount); + exit(1); + } +} +#endif + #endif /* !MODE32 */ } else { /* @@ -1501,10 +1606,38 @@ l3->host_store[x3] = NULL; } else { /* Change the entire physical/host mapping: */ +printf("HOST LOAD 2 set to %p\n", host_page); l3->host_load[x3] = host_page; l3->host_store[x3] = writeflag? host_page : NULL; l3->phys_addr[x3] = paddr_page; } + +#ifdef BUGHUNT +/* Count how many pages are actually in use: */ +{ + int n=0, i; + for (i=0; i<=mask3; i++) + if (l3->vaddr_to_tlbindex[i]) + n++; + if (n != l3->refcount) { + printf("Y: %i in use, but refcount = %i!\n", n, l3->refcount); + exit(1); + } + + n = 0; + for (i=0; i<=mask3; i++) + if (l3->host_load[i] != NULL) + n++; + if (n != l3->refcount) { + printf("YHL: %i in use, but refcount = %i!\n", n, l3->refcount); + printf("Entry r = %i\n", r); + printf("Valid = %i\n", +cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid); + exit(1); + } +} +#endif + #endif /* !MODE32 */ } } @@ -1551,24 +1684,22 @@ #ifdef DYNTRANS_TO_BE_TRANSLATED_TAIL /* - * If we end up here, then an instruction was translated. - * Mark the page as containing a translation. - * - * (Special case for 32-bit mode: set the corresponding bit in the - * phystranslation[] array.) + * If we end up here, then an instruction was translated. Let's mark + * the page as containing a translation at this part of the page. */ + /* Make sure cur_physpage is in synch: */ cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *) cpu->cd.DYNTRANS_ARCH.cur_ic_page; -#ifdef MODE32 - if (!(cpu->cd.DYNTRANS_ARCH.cur_physpage->flags & TRANSLATIONS)) { - uint32_t index = DYNTRANS_ADDR_TO_PAGENR((uint32_t)addr); - cpu->cd.DYNTRANS_ARCH.phystranslation[index >> 5] |= - (1 << (index & 31)); - } -#endif - cpu->cd.DYNTRANS_ARCH.cur_physpage->flags |= TRANSLATIONS; + { + int x = addr & (DYNTRANS_PAGESIZE - 1); + int addr_per_translation_range = DYNTRANS_PAGESIZE / (8 * + sizeof(cpu->cd.DYNTRANS_ARCH.cur_physpage->translations)); + x /= addr_per_translation_range; + + cpu->cd.DYNTRANS_ARCH.cur_physpage->translations |= (1 << x); + } /* * Now it is time to check for combinations of instructions that can @@ -1585,7 +1716,7 @@ #endif ) { if (cpu->cd.DYNTRANS_ARCH.combination_check != NULL && - cpu->machine->speed_tricks) + cpu->machine->allow_instruction_combinations) cpu->cd.DYNTRANS_ARCH.combination_check(cpu, ic, addr & (DYNTRANS_PAGESIZE - 1)); }