Search
lxdream.org :: lxdream/src/sh4/mmux86.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/mmux86.c
changeset 1292:799fdd4f704a
prev1067:d3c00ffccfcd
author nkeynes
date Fri Aug 24 08:53:50 2012 +1000 (8 years ago)
permissions -rw-r--r--
last change Move the generated prologue/epilogue code out into a common entry stub
(reduces space requirements) and pre-save all saved registers. Change
FASTCALL to use 3 regs instead of 2 since we can now keep everything in
regs.
file annotate diff log raw
nkeynes@939
     1
/**
nkeynes@940
     2
 * $Id$
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@991
    25
#include "xlat/x86/x86op.h"
nkeynes@939
    26
nkeynes@939
    27
#if SIZEOF_VOID_P == 8
nkeynes@991
    28
#define XLAT(addr_space, reg) \
nkeynes@991
    29
    MOVQ_imm64_r64( (uintptr_t)addr_space, REG_RAX ); \
nkeynes@991
    30
    MOVP_sib_rptr( 3, reg, REG_RAX, 0, reg );
nkeynes@991
    31
#define ADDP_imms_ptr(imm,p) \
nkeynes@991
    32
    MOVQ_imm64_r64((uintptr_t)p, REG_EAX ); \
nkeynes@991
    33
    ADDL_imms_r32disp(imm, REG_EAX, 0);
nkeynes@939
    34
#else
nkeynes@991
    35
#define XLAT(addr_space, reg) \
nkeynes@991
    36
    MOVP_sib_rptr( 2, reg, -1, (uintptr_t)addr_space, reg ); 
nkeynes@991
    37
#define ADDP_imms_ptr(imm,p) \
nkeynes@991
    38
    ADDL_imms_r32disp(imm, -1, (uintptr_t)p);
nkeynes@939
    39
#endif
nkeynes@939
    40
nkeynes@939
    41
void mmu_utlb_init_vtable( struct utlb_entry *ent, struct utlb_page_entry *page, gboolean writable )
nkeynes@939
    42
{
nkeynes@939
    43
    uint32_t mask = ent->mask;
nkeynes@942
    44
    uint32_t vpn = ent->vpn & mask;
nkeynes@939
    45
    uint32_t ppn = ent->ppn & mask;
nkeynes@972
    46
    struct mem_region_fn **addr_space;
nkeynes@972
    47
    uint8_t **out = (uint8_t **)&page->fn;
nkeynes@972
    48
    uint8_t **fn;
nkeynes@939
    49
    int inc = writable ? 1 : 2; 
nkeynes@939
    50
    int i;
nkeynes@939
    51
    
nkeynes@939
    52
    xlat_output = page->code;
nkeynes@972
    53
    if( (ppn & 0x1FFFFFFF) >= 0x1C000000 ) {
nkeynes@972
    54
        /* SH4 control region */
nkeynes@972
    55
        ppn |= 0xE0000000;
nkeynes@972
    56
        addr_space = sh4_address_space;
nkeynes@972
    57
    } else {
nkeynes@972
    58
        addr_space = ext_address_space;
nkeynes@972
    59
    }
nkeynes@972
    60
    fn = (uint8_t **)addr_space[ppn>>12];
nkeynes@939
    61
    
nkeynes@975
    62
    for( i=0; i<10; i+= inc, fn += inc, out += inc ) {
nkeynes@939
    63
        *out = xlat_output;
nkeynes@975
    64
        if( i != 9 ) { /* read_byte_for_write doesn't increment mmu_urc, everything else does */
nkeynes@991
    65
            ADDP_imms_ptr(1, &mmu_urc);
nkeynes@975
    66
        }
nkeynes@995
    67
        ADDL_imms_r32( ppn-vpn, REG_ARG1 ); // 6
nkeynes@939
    68
        if( ent->mask >= 0xFFFFF000 ) {
nkeynes@939
    69
            // Maps to a single page, so jump directly there
nkeynes@939
    70
            int rel = (*fn - xlat_output);
nkeynes@991
    71
            JMP_prerel( rel ); // 5
nkeynes@939
    72
        } else {
nkeynes@1292
    73
            MOVL_r32_r32( REG_ARG1, REG_CALLPTR ); // 2
nkeynes@1292
    74
            SHRL_imm_r32( 12, REG_CALLPTR );  // 3
nkeynes@1292
    75
            XLAT(addr_space, REG_CALLPTR);                   // 14
nkeynes@1292
    76
            JMP_r32disp(REG_CALLPTR, (((uintptr_t)out) - ((uintptr_t)&page->fn)) );    // 3
nkeynes@939
    77
        }
nkeynes@939
    78
    }
nkeynes@946
    79
    
nkeynes@946
    80
    page->fn.prefetch = unmapped_prefetch; // FIXME
nkeynes@946
    81
}
nkeynes@946
    82
nkeynes@946
    83
void mmu_utlb_init_storequeue_vtable( struct utlb_entry *ent, struct utlb_page_entry *page )
nkeynes@946
    84
{
nkeynes@946
    85
    uint32_t mask = ent->mask;
nkeynes@946
    86
    uint32_t vpn = ent->vpn & mask;
nkeynes@946
    87
    uint32_t ppn = ent->ppn & mask;
nkeynes@946
    88
nkeynes@946
    89
    xlat_output = page->code;
nkeynes@946
    90
nkeynes@946
    91
    memcpy( page, &p4_region_storequeue, sizeof(struct mem_region_fn) );
nkeynes@946
    92
nkeynes@946
    93
    page->fn.prefetch = (mem_prefetch_fn_t)xlat_output;
nkeynes@991
    94
    ADDP_imms_ptr(1, &mmu_urc);
nkeynes@995
    95
    ADDL_imms_r32( ppn-vpn, REG_ARG1 );
nkeynes@946
    96
    int rel = ((uint8_t *)ccn_storequeue_prefetch_tlb) - xlat_output;
nkeynes@991
    97
    JMP_prerel( rel );
nkeynes@939
    98
}
nkeynes@939
    99
nkeynes@939
   100
void mmu_utlb_1k_init_vtable( struct utlb_1k_entry *entry )
nkeynes@939
   101
{
nkeynes@939
   102
    xlat_output = entry->code;
nkeynes@939
   103
    int i;
nkeynes@939
   104
    uint8_t **out = (uint8_t **)&entry->fn;
nkeynes@939
   105
    
nkeynes@946
   106
    for( i=0; i<9; i++, out++ ) {
nkeynes@939
   107
        *out = xlat_output;
nkeynes@1292
   108
        MOVL_r32_r32( REG_ARG1, REG_CALLPTR );
nkeynes@1292
   109
        SHRL_imm_r32( 10, REG_CALLPTR );
nkeynes@1292
   110
        ANDL_imms_r32( 0x3, REG_CALLPTR );
nkeynes@1292
   111
        XLAT( (uintptr_t)&entry->subpages[0], REG_CALLPTR );
nkeynes@1292
   112
        JMP_r32disp(REG_CALLPTR, (((uintptr_t)out) - ((uintptr_t)&entry->fn)) );    // 3
nkeynes@939
   113
    }
nkeynes@939
   114
nkeynes@939
   115
    out = (uint8_t **)&entry->user_fn;
nkeynes@946
   116
    for( i=0; i<9; i++, out++ ) {
nkeynes@939
   117
        *out = xlat_output;
nkeynes@1292
   118
        MOVL_r32_r32( REG_ARG1, REG_CALLPTR );
nkeynes@1292
   119
        SHRL_imm_r32( 10, REG_CALLPTR );
nkeynes@1292
   120
        ANDL_imms_r32( 0x3, REG_CALLPTR );
nkeynes@1292
   121
        XLAT( (uintptr_t)&entry->user_subpages[0], REG_CALLPTR );
nkeynes@1292
   122
        JMP_r32disp(REG_CALLPTR, (((uintptr_t)out) - ((uintptr_t)&entry->user_fn)) );    // 3
nkeynes@939
   123
    }
nkeynes@939
   124
nkeynes@939
   125
}
.