4 * x86-specific MMU code - this emits simple TLB stubs for TLB indirection.
6 * Copyright (c) 2008 Nathan Keynes.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
21 #include "sh4/sh4core.h"
22 #include "sh4/sh4mmio.h"
23 #include "sh4/sh4trans.h"
25 #include "sh4/x86op.h"
27 #if SIZEOF_VOID_P == 8
31 MOV_imm64_r32((uintptr_t)ext_address_space, R_EAX); /* movq ptr, %rax */ \
32 REXW(); OP(0x8B); OP(0x0C); OP(0xC8) /* movq [%rax + %rcx*8], %rcx */
37 MOV_r32disp32x4_r32( R_ECX, (uintptr_t)ext_address_space, R_ECX );
40 void mmu_utlb_init_vtable( struct utlb_entry *ent, struct utlb_page_entry *page, gboolean writable )
42 uint32_t mask = ent->mask;
43 uint32_t ppn = ent->ppn & mask;
44 int inc = writable ? 1 : 2;
47 xlat_output = page->code;
48 uint8_t **fn = (uint8_t **)ext_address_space[ppn>>12];
49 uint8_t **out = (uint8_t **)&page->fn;
51 for( i=0; i<8; i+= inc, fn += inc, out += inc ) {
53 #if SIZEOF_VOID_P == 8
54 MOV_imm64_r32((uintptr_t)&mmu_urc, R_EAX );
55 OP(0x83); OP(0x00); OP(0x01); // ADD #1, [RAX]
57 OP(0x83); MODRM_r32_disp32(0, (uintptr_t)&mmu_urc); OP(0x01); // ADD #1, mmu_urc
59 AND_imm32_r32( ~mask, ARG1 ); // 6
60 OR_imm32_r32( ppn, ARG1 ); // 6
61 if( ent->mask >= 0xFFFFF000 ) {
62 // Maps to a single page, so jump directly there
63 int rel = (*fn - xlat_output);
66 MOV_r32_r32( ARG1, R_ECX ); // 2
67 SHR_imm8_r32( 12, R_ECX ); // 3
69 JMP_r32disp8(R_ECX, (((uintptr_t)out) - ((uintptr_t)&page->fn)) ); // 3
74 void mmu_utlb_1k_init_vtable( struct utlb_1k_entry *entry )
76 xlat_output = entry->code;
78 uint8_t **out = (uint8_t **)&entry->fn;
80 for( i=0; i<8; i++, out++ ) {
82 MOV_r32_r32( ARG1, R_ECX );
83 SHR_imm8_r32( 10, R_ECX );
84 AND_imm8s_r32( 0x3, R_ECX );
85 #if SIZEOF_VOID_P == 8
86 MOV_imm64_r32( (uintptr_t)&entry->subpages[0], R_EAX );
87 REXW(); OP(0x8B); OP(0x0C); OP(0xC8); /* movq [%rax + %rcx*8], %rcx */
89 MOV_r32disp32x4_r32( R_ECX, ((uintptr_t)&entry->subpages[0]), R_ECX );
91 JMP_r32disp8(R_ECX, (((uintptr_t)out) - ((uintptr_t)&entry->fn)) ); // 3
94 out = (uint8_t **)&entry->user_fn;
95 for( i=0; i<8; i++, out++ ) {
97 MOV_r32_r32( ARG1, R_ECX );
98 SHR_imm8_r32( 10, R_ECX );
99 AND_imm8s_r32( 0x3, R_ECX );
100 #if SIZEOF_VOID_P == 8
101 MOV_imm64_r32( (uintptr_t)&entry->user_subpages[0], R_EAX );
102 REXW(); OP(0x8B); OP(0x0C); OP(0xC8); /* movq [%rax + %rcx*8], %rcx */
104 MOV_r32disp32x4_r32( R_ECX, ((uintptr_t)&entry->user_subpages[0]), R_ECX );
106 JMP_r32disp8(R_ECX, (((uintptr_t)out) - ((uintptr_t)&entry->user_fn)) ); // 3
.