Search
lxdream.org :: lxdream/src/sh4/mmux86.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/mmux86.c
changeset 953:f4a156508ad1
next972:fb948057cf08
author nkeynes
date Thu Jan 15 11:23:20 2009 +0000 (15 years ago)
permissions -rw-r--r--
last change Fix various compile-time warnings
file annotate diff log raw
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/sh4/mmux86.c Thu Jan 15 11:23:20 2009 +0000
1.3 @@ -0,0 +1,128 @@
1.4 +/**
1.5 + * $Id$
1.6 + *
1.7 + * x86-specific MMU code - this emits simple TLB stubs for TLB indirection.
1.8 + *
1.9 + * Copyright (c) 2008 Nathan Keynes.
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify
1.12 + * it under the terms of the GNU General Public License as published by
1.13 + * the Free Software Foundation; either version 2 of the License, or
1.14 + * (at your option) any later version.
1.15 + *
1.16 + * This program is distributed in the hope that it will be useful,
1.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.19 + * GNU General Public License for more details.
1.20 + */
1.21 +
1.22 +#include "lxdream.h"
1.23 +#include "mem.h"
1.24 +#include "sh4/sh4core.h"
1.25 +#include "sh4/sh4mmio.h"
1.26 +#include "sh4/sh4trans.h"
1.27 +#include "sh4/mmu.h"
1.28 +#include "sh4/x86op.h"
1.29 +
1.30 +#if SIZEOF_VOID_P == 8
1.31 +#define ARG1 R_EDI
1.32 +#define ARG2 R_ESI
1.33 +#define DECODE() \
1.34 + MOV_imm64_r32((uintptr_t)ext_address_space, R_EAX); /* movq ptr, %rax */ \
1.35 + REXW(); OP(0x8B); OP(0x0C); OP(0xC8) /* movq [%rax + %rcx*8], %rcx */
1.36 +#else
1.37 +#define ARG1 R_EAX
1.38 +#define ARG2 R_EDX
1.39 +#define DECODE() \
1.40 + MOV_r32disp32x4_r32( R_ECX, (uintptr_t)ext_address_space, R_ECX );
1.41 +#endif
1.42 +
1.43 +void mmu_utlb_init_vtable( struct utlb_entry *ent, struct utlb_page_entry *page, gboolean writable )
1.44 +{
1.45 + uint32_t mask = ent->mask;
1.46 + uint32_t vpn = ent->vpn & mask;
1.47 + uint32_t ppn = ent->ppn & mask;
1.48 + int inc = writable ? 1 : 2;
1.49 + int i;
1.50 +
1.51 + xlat_output = page->code;
1.52 + uint8_t **fn = (uint8_t **)ext_address_space[ppn>>12];
1.53 + uint8_t **out = (uint8_t **)&page->fn;
1.54 +
1.55 + for( i=0; i<9; i+= inc, fn += inc, out += inc ) {
1.56 + *out = xlat_output;
1.57 +#if SIZEOF_VOID_P == 8
1.58 + MOV_imm64_r32((uintptr_t)&mmu_urc, R_EAX );
1.59 + OP(0x83); OP(0x00); OP(0x01); // ADD #1, [RAX]
1.60 +#else
1.61 + OP(0x83); MODRM_r32_disp32(0, (uintptr_t)&mmu_urc); OP(0x01); // ADD #1, mmu_urc
1.62 +#endif
1.63 + ADD_imm32_r32( ppn-vpn, ARG1 ); // 6
1.64 + if( ent->mask >= 0xFFFFF000 ) {
1.65 + // Maps to a single page, so jump directly there
1.66 + int rel = (*fn - xlat_output);
1.67 + JMP_rel( rel ); // 5
1.68 + } else {
1.69 + MOV_r32_r32( ARG1, R_ECX ); // 2
1.70 + SHR_imm8_r32( 12, R_ECX ); // 3
1.71 + DECODE(); // 14
1.72 + JMP_r32disp8(R_ECX, (((uintptr_t)out) - ((uintptr_t)&page->fn)) ); // 3
1.73 + }
1.74 + }
1.75 +
1.76 + page->fn.prefetch = unmapped_prefetch; // FIXME
1.77 +}
1.78 +
1.79 +void mmu_utlb_init_storequeue_vtable( struct utlb_entry *ent, struct utlb_page_entry *page )
1.80 +{
1.81 + uint32_t mask = ent->mask;
1.82 + uint32_t vpn = ent->vpn & mask;
1.83 + uint32_t ppn = ent->ppn & mask;
1.84 +
1.85 + xlat_output = page->code;
1.86 +
1.87 + memcpy( page, &p4_region_storequeue, sizeof(struct mem_region_fn) );
1.88 +
1.89 + /* TESTME: Does a PREF increment the URC counter? */
1.90 + page->fn.prefetch = (mem_prefetch_fn_t)xlat_output;
1.91 + ADD_imm32_r32( ppn-vpn, ARG1 );
1.92 + int rel = ((uint8_t *)ccn_storequeue_prefetch_tlb) - xlat_output;
1.93 + JMP_rel( rel );
1.94 +}
1.95 +
1.96 +void mmu_utlb_1k_init_vtable( struct utlb_1k_entry *entry )
1.97 +{
1.98 + xlat_output = entry->code;
1.99 + int i;
1.100 + uint8_t **out = (uint8_t **)&entry->fn;
1.101 +
1.102 + for( i=0; i<9; i++, out++ ) {
1.103 + *out = xlat_output;
1.104 + MOV_r32_r32( ARG1, R_ECX );
1.105 + SHR_imm8_r32( 10, R_ECX );
1.106 + AND_imm8s_r32( 0x3, R_ECX );
1.107 +#if SIZEOF_VOID_P == 8
1.108 + MOV_imm64_r32( (uintptr_t)&entry->subpages[0], R_EAX );
1.109 + REXW(); OP(0x8B); OP(0x0C); OP(0xC8); /* movq [%rax + %rcx*8], %rcx */
1.110 +#else
1.111 + MOV_r32disp32x4_r32( R_ECX, ((uintptr_t)&entry->subpages[0]), R_ECX );
1.112 +#endif
1.113 + JMP_r32disp8(R_ECX, (((uintptr_t)out) - ((uintptr_t)&entry->fn)) ); // 3
1.114 + }
1.115 +
1.116 + out = (uint8_t **)&entry->user_fn;
1.117 + for( i=0; i<9; i++, out++ ) {
1.118 + *out = xlat_output;
1.119 + MOV_r32_r32( ARG1, R_ECX );
1.120 + SHR_imm8_r32( 10, R_ECX );
1.121 + AND_imm8s_r32( 0x3, R_ECX );
1.122 +#if SIZEOF_VOID_P == 8
1.123 + MOV_imm64_r32( (uintptr_t)&entry->user_subpages[0], R_EAX );
1.124 + REXW(); OP(0x8B); OP(0x0C); OP(0xC8); /* movq [%rax + %rcx*8], %rcx */
1.125 +#else
1.126 + MOV_r32disp32x4_r32( R_ECX, ((uintptr_t)&entry->user_subpages[0]), R_ECX );
1.127 +#endif
1.128 + JMP_r32disp8(R_ECX, (((uintptr_t)out) - ((uintptr_t)&entry->user_fn)) ); // 3
1.129 + }
1.130 +
1.131 +}
.