Search
lxdream.org :: lxdream/src/sh4/mmux86.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/mmux86.c
changeset 939:6f2302afeb89
next940:81e0d3051d5f
author nkeynes
date Sat Jan 03 03:30:26 2009 +0000 (12 years ago)
branchlxdream-mem
permissions -rw-r--r--
last change MMU work-in-progress
* Move SDRAM out into separate sdram.c
* Move all page-table management into mmu.c
* Convert UTLB management to use the new page-tables
* Rip out all calls to mmu_vma_to_phys_* and replace with direct access
file annotate diff log raw
nkeynes@939
     1
/**
nkeynes@939
     2
 * $Id: mmux86.c 957 2008-12-27 03:14:59Z nkeynes $
nkeynes@939
     3
 * 
nkeynes@939
     4
 * x86-specific MMU code - this emits simple TLB stubs for TLB indirection.
nkeynes@939
     5
  *
nkeynes@939
     6
 * Copyright (c) 2008 Nathan Keynes.
nkeynes@939
     7
 *
nkeynes@939
     8
 * This program is free software; you can redistribute it and/or modify
nkeynes@939
     9
 * it under the terms of the GNU General Public License as published by
nkeynes@939
    10
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@939
    11
 * (at your option) any later version.
nkeynes@939
    12
 *
nkeynes@939
    13
 * This program is distributed in the hope that it will be useful,
nkeynes@939
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@939
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@939
    16
 * GNU General Public License for more details.
nkeynes@939
    17
 */
nkeynes@939
    18
nkeynes@939
    19
#include "lxdream.h"
nkeynes@939
    20
#include "mem.h"
nkeynes@939
    21
#include "sh4/sh4core.h"
nkeynes@939
    22
#include "sh4/sh4mmio.h"
nkeynes@939
    23
#include "sh4/sh4trans.h"
nkeynes@939
    24
#include "sh4/mmu.h"
nkeynes@939
    25
#include "sh4/x86op.h"
nkeynes@939
    26
nkeynes@939
    27
#if SIZEOF_VOID_P == 8
nkeynes@939
    28
#define ARG1 R_EDI
nkeynes@939
    29
#define ARG2 R_ESI
nkeynes@939
    30
#define DECODE() \
nkeynes@939
    31
    MOV_imm64_r32((uintptr_t)ext_address_space, R_EAX);     /* movq ptr, %rax */ \
nkeynes@939
    32
    REXW(); OP(0x8B); OP(0x0C); OP(0xC8)                    /* movq [%rax + %rcx*8], %rcx */
nkeynes@939
    33
#else
nkeynes@939
    34
#define ARG1 R_EAX
nkeynes@939
    35
#define ARG2 R_EDX
nkeynes@939
    36
#define DECODE() \
nkeynes@939
    37
    MOV_r32disp32x4_r32( R_ECX, (uintptr_t)ext_address_space, R_ECX );
nkeynes@939
    38
#endif
nkeynes@939
    39
nkeynes@939
    40
void mmu_utlb_init_vtable( struct utlb_entry *ent, struct utlb_page_entry *page, gboolean writable )
nkeynes@939
    41
{
nkeynes@939
    42
    uint32_t mask = ent->mask;
nkeynes@939
    43
    uint32_t ppn = ent->ppn & mask;
nkeynes@939
    44
    int inc = writable ? 1 : 2; 
nkeynes@939
    45
    int i;
nkeynes@939
    46
    
nkeynes@939
    47
    xlat_output = page->code;
nkeynes@939
    48
    uint8_t **fn = (uint8_t **)ext_address_space[ppn>>12];
nkeynes@939
    49
    uint8_t **out = (uint8_t **)&page->fn;
nkeynes@939
    50
    
nkeynes@939
    51
    for( i=0; i<8; i+= inc, fn += inc, out += inc ) {
nkeynes@939
    52
        *out = xlat_output;
nkeynes@939
    53
#if SIZEOF_VOID_P == 8
nkeynes@939
    54
        MOV_imm64_r32((uintptr_t)&mmu_urc, R_EAX );
nkeynes@939
    55
        OP(0x83); OP(0x00); OP(0x01); // ADD #1, [RAX]
nkeynes@939
    56
#else 
nkeynes@939
    57
        OP(0x83); MODRM_r32_disp32(0, (uintptr_t)&mmu_urc); OP(0x01); // ADD #1, mmu_urc
nkeynes@939
    58
#endif
nkeynes@939
    59
        AND_imm32_r32( ~mask, ARG1 ); // 6
nkeynes@939
    60
        OR_imm32_r32( ppn, ARG1 );    // 6
nkeynes@939
    61
        if( ent->mask >= 0xFFFFF000 ) {
nkeynes@939
    62
            // Maps to a single page, so jump directly there
nkeynes@939
    63
            int rel = (*fn - xlat_output);
nkeynes@939
    64
            JMP_rel( rel ); // 5
nkeynes@939
    65
        } else {
nkeynes@939
    66
            MOV_r32_r32( ARG1, R_ECX ); // 2
nkeynes@939
    67
            SHR_imm8_r32( 12, R_ECX );  // 3
nkeynes@939
    68
            DECODE();                   // 14
nkeynes@939
    69
            JMP_r32disp8(R_ECX, (((uintptr_t)out) - ((uintptr_t)&page->fn)) );    // 3
nkeynes@939
    70
        }
nkeynes@939
    71
    }
nkeynes@939
    72
}
nkeynes@939
    73
nkeynes@939
    74
void mmu_utlb_1k_init_vtable( struct utlb_1k_entry *entry )
nkeynes@939
    75
{
nkeynes@939
    76
    xlat_output = entry->code;
nkeynes@939
    77
    int i;
nkeynes@939
    78
    uint8_t **out = (uint8_t **)&entry->fn;
nkeynes@939
    79
    
nkeynes@939
    80
    for( i=0; i<8; i++, out++ ) {
nkeynes@939
    81
        *out = xlat_output;
nkeynes@939
    82
        MOV_r32_r32( ARG1, R_ECX );
nkeynes@939
    83
        SHR_imm8_r32( 10, R_ECX );
nkeynes@939
    84
        AND_imm8s_r32( 0x3, R_ECX );
nkeynes@939
    85
#if SIZEOF_VOID_P == 8
nkeynes@939
    86
        MOV_imm64_r32( (uintptr_t)&entry->subpages[0], R_EAX );
nkeynes@939
    87
        REXW(); OP(0x8B); OP(0x0C); OP(0xC8);                   /* movq [%rax + %rcx*8], %rcx */
nkeynes@939
    88
#else
nkeynes@939
    89
        MOV_r32disp32x4_r32( R_ECX, ((uintptr_t)&entry->subpages[0]), R_ECX );
nkeynes@939
    90
#endif                
nkeynes@939
    91
        JMP_r32disp8(R_ECX, (((uintptr_t)out) - ((uintptr_t)&entry->fn)) );    // 3
nkeynes@939
    92
    }
nkeynes@939
    93
nkeynes@939
    94
    out = (uint8_t **)&entry->user_fn;
nkeynes@939
    95
    for( i=0; i<8; i++, out++ ) {
nkeynes@939
    96
        *out = xlat_output;
nkeynes@939
    97
        MOV_r32_r32( ARG1, R_ECX );
nkeynes@939
    98
        SHR_imm8_r32( 10, R_ECX );
nkeynes@939
    99
        AND_imm8s_r32( 0x3, R_ECX );
nkeynes@939
   100
#if SIZEOF_VOID_P == 8
nkeynes@939
   101
        MOV_imm64_r32( (uintptr_t)&entry->user_subpages[0], R_EAX );
nkeynes@939
   102
        REXW(); OP(0x8B); OP(0x0C); OP(0xC8);                   /* movq [%rax + %rcx*8], %rcx */
nkeynes@939
   103
#else
nkeynes@939
   104
        MOV_r32disp32x4_r32( R_ECX, ((uintptr_t)&entry->user_subpages[0]), R_ECX );
nkeynes@939
   105
#endif                
nkeynes@939
   106
        JMP_r32disp8(R_ECX, (((uintptr_t)out) - ((uintptr_t)&entry->user_fn)) );    // 3
nkeynes@939
   107
    }
nkeynes@939
   108
nkeynes@939
   109
}
.