Search
lxdream.org :: lxdream/src/sh4/mmux86.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/mmux86.c
changeset 991:60c7fab9c880
prev975:007bf7eb944f
next995:eb9d43e8aa08
author nkeynes
date Wed Mar 04 23:12:21 2009 +0000 (13 years ago)
permissions -rw-r--r--
last change Move xltcache to xlat/ src directory
Commit new and improved x86 opcode file - cleaned up and added support for amd64 extended registers
file annotate diff log raw
nkeynes@953
     1
/**
nkeynes@953
     2
 * $Id$
nkeynes@953
     3
 * 
nkeynes@953
     4
 * x86-specific MMU code - this emits simple TLB stubs for TLB indirection.
nkeynes@953
     5
  *
nkeynes@953
     6
 * Copyright (c) 2008 Nathan Keynes.
nkeynes@953
     7
 *
nkeynes@953
     8
 * This program is free software; you can redistribute it and/or modify
nkeynes@953
     9
 * it under the terms of the GNU General Public License as published by
nkeynes@953
    10
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@953
    11
 * (at your option) any later version.
nkeynes@953
    12
 *
nkeynes@953
    13
 * This program is distributed in the hope that it will be useful,
nkeynes@953
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@953
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@953
    16
 * GNU General Public License for more details.
nkeynes@953
    17
 */
nkeynes@953
    18
nkeynes@953
    19
#include "lxdream.h"
nkeynes@953
    20
#include "mem.h"
nkeynes@953
    21
#include "sh4/sh4core.h"
nkeynes@953
    22
#include "sh4/sh4mmio.h"
nkeynes@953
    23
#include "sh4/sh4trans.h"
nkeynes@953
    24
#include "sh4/mmu.h"
nkeynes@991
    25
#include "xlat/x86/x86op.h"
nkeynes@953
    26
nkeynes@953
    27
#if SIZEOF_VOID_P == 8
nkeynes@991
    28
#define ARG1 REG_RDI
nkeynes@991
    29
#define ARG2 REG_RSI
nkeynes@991
    30
#define XLAT(addr_space, reg) \
nkeynes@991
    31
    MOVQ_imm64_r64( (uintptr_t)addr_space, REG_RAX ); \
nkeynes@991
    32
    MOVP_sib_rptr( 3, reg, REG_RAX, 0, reg );
nkeynes@991
    33
#define ADDP_imms_ptr(imm,p) \
nkeynes@991
    34
    MOVQ_imm64_r64((uintptr_t)p, REG_EAX ); \
nkeynes@991
    35
    ADDL_imms_r32disp(imm, REG_EAX, 0);
nkeynes@953
    36
#else
nkeynes@991
    37
#define ARG1 REG_EAX
nkeynes@953
    38
#define ARG2 R_EDX
nkeynes@991
    39
#define XLAT(addr_space, reg) \
nkeynes@991
    40
    MOVP_sib_rptr( 2, reg, -1, (uintptr_t)addr_space, reg ); 
nkeynes@991
    41
#define ADDP_imms_ptr(imm,p) \
nkeynes@991
    42
    ADDL_imms_r32disp(imm, -1, (uintptr_t)p);
nkeynes@953
    43
#endif
nkeynes@953
    44
nkeynes@953
    45
void mmu_utlb_init_vtable( struct utlb_entry *ent, struct utlb_page_entry *page, gboolean writable )
nkeynes@953
    46
{
nkeynes@953
    47
    uint32_t mask = ent->mask;
nkeynes@953
    48
    uint32_t vpn = ent->vpn & mask;
nkeynes@953
    49
    uint32_t ppn = ent->ppn & mask;
nkeynes@972
    50
    struct mem_region_fn **addr_space;
nkeynes@972
    51
    uint8_t **out = (uint8_t **)&page->fn;
nkeynes@972
    52
    uint8_t **fn;
nkeynes@953
    53
    int inc = writable ? 1 : 2; 
nkeynes@953
    54
    int i;
nkeynes@953
    55
    
nkeynes@953
    56
    xlat_output = page->code;
nkeynes@972
    57
    if( (ppn & 0x1FFFFFFF) >= 0x1C000000 ) {
nkeynes@972
    58
        /* SH4 control region */
nkeynes@972
    59
        ppn |= 0xE0000000;
nkeynes@972
    60
        addr_space = sh4_address_space;
nkeynes@972
    61
    } else {
nkeynes@972
    62
        addr_space = ext_address_space;
nkeynes@972
    63
    }
nkeynes@972
    64
    fn = (uint8_t **)addr_space[ppn>>12];
nkeynes@953
    65
    
nkeynes@975
    66
    for( i=0; i<10; i+= inc, fn += inc, out += inc ) {
nkeynes@953
    67
        *out = xlat_output;
nkeynes@975
    68
        if( i != 9 ) { /* read_byte_for_write doesn't increment mmu_urc, everything else does */
nkeynes@991
    69
            ADDP_imms_ptr(1, &mmu_urc);
nkeynes@975
    70
        }
nkeynes@991
    71
        ADDL_imms_r32( ppn-vpn, ARG1 ); // 6
nkeynes@953
    72
        if( ent->mask >= 0xFFFFF000 ) {
nkeynes@953
    73
            // Maps to a single page, so jump directly there
nkeynes@953
    74
            int rel = (*fn - xlat_output);
nkeynes@991
    75
            JMP_prerel( rel ); // 5
nkeynes@953
    76
        } else {
nkeynes@991
    77
            MOVL_r32_r32( ARG1, REG_ECX ); // 2
nkeynes@991
    78
            SHRL_imm_r32( 12, REG_ECX );  // 3
nkeynes@991
    79
            XLAT(addr_space, REG_ECX);                   // 14
nkeynes@991
    80
            JMP_r32disp(REG_ECX, (((uintptr_t)out) - ((uintptr_t)&page->fn)) );    // 3
nkeynes@953
    81
        }
nkeynes@953
    82
    }
nkeynes@953
    83
    
nkeynes@953
    84
    page->fn.prefetch = unmapped_prefetch; // FIXME
nkeynes@953
    85
}
nkeynes@953
    86
nkeynes@953
    87
void mmu_utlb_init_storequeue_vtable( struct utlb_entry *ent, struct utlb_page_entry *page )
nkeynes@953
    88
{
nkeynes@953
    89
    uint32_t mask = ent->mask;
nkeynes@953
    90
    uint32_t vpn = ent->vpn & mask;
nkeynes@953
    91
    uint32_t ppn = ent->ppn & mask;
nkeynes@953
    92
nkeynes@953
    93
    xlat_output = page->code;
nkeynes@953
    94
nkeynes@953
    95
    memcpy( page, &p4_region_storequeue, sizeof(struct mem_region_fn) );
nkeynes@953
    96
nkeynes@953
    97
    page->fn.prefetch = (mem_prefetch_fn_t)xlat_output;
nkeynes@991
    98
    ADDP_imms_ptr(1, &mmu_urc);
nkeynes@991
    99
    ADDL_imms_r32( ppn-vpn, ARG1 );
nkeynes@953
   100
    int rel = ((uint8_t *)ccn_storequeue_prefetch_tlb) - xlat_output;
nkeynes@991
   101
    JMP_prerel( rel );
nkeynes@953
   102
}
nkeynes@953
   103
nkeynes@953
   104
void mmu_utlb_1k_init_vtable( struct utlb_1k_entry *entry )
nkeynes@953
   105
{
nkeynes@953
   106
    xlat_output = entry->code;
nkeynes@953
   107
    int i;
nkeynes@953
   108
    uint8_t **out = (uint8_t **)&entry->fn;
nkeynes@953
   109
    
nkeynes@953
   110
    for( i=0; i<9; i++, out++ ) {
nkeynes@953
   111
        *out = xlat_output;
nkeynes@991
   112
        MOVL_r32_r32( ARG1, REG_ECX );
nkeynes@991
   113
        SHRL_imm_r32( 10, REG_ECX );
nkeynes@991
   114
        ANDL_imms_r32( 0x3, REG_ECX );
nkeynes@991
   115
        XLAT( (uintptr_t)&entry->subpages[0], REG_ECX );
nkeynes@991
   116
        JMP_r32disp(REG_ECX, (((uintptr_t)out) - ((uintptr_t)&entry->fn)) );    // 3
nkeynes@953
   117
    }
nkeynes@953
   118
nkeynes@953
   119
    out = (uint8_t **)&entry->user_fn;
nkeynes@953
   120
    for( i=0; i<9; i++, out++ ) {
nkeynes@953
   121
        *out = xlat_output;
nkeynes@991
   122
        MOVL_r32_r32( ARG1, REG_ECX );
nkeynes@991
   123
        SHRL_imm_r32( 10, REG_ECX );
nkeynes@991
   124
        ANDL_imms_r32( 0x3, REG_ECX );
nkeynes@991
   125
        XLAT( (uintptr_t)&entry->user_subpages[0], REG_ECX );
nkeynes@991
   126
        JMP_r32disp(REG_ECX, (((uintptr_t)out) - ((uintptr_t)&entry->user_fn)) );    // 3
nkeynes@953
   127
    }
nkeynes@953
   128
nkeynes@953
   129
}
.