Search
lxdream.org :: lxdream/src/xlat/xltcache.h
lxdream 0.9.1
released Jun 29
Download Now
filename src/xlat/xltcache.h
changeset 1149:da6124fceec6
prev1091:186558374345
next1182:b38a327ad8fa
author nkeynes
date Wed Nov 10 08:37:42 2010 +1000 (12 years ago)
permissions -rw-r--r--
last change Add chain pointer to the xlat cache, so that we can maintain multiple blocks
for the same address. This prevents thrashing in cases where we would other
keep retranslating the same blocks over and over again due to varying
xlat_sh4_mode values
file annotate diff log raw
nkeynes@991
     1
/**
nkeynes@991
     2
 * $Id$
nkeynes@991
     3
 * 
nkeynes@991
     4
 * Translation cache support (architecture independent)
nkeynes@991
     5
 *
nkeynes@991
     6
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@991
     7
 *
nkeynes@991
     8
 * This program is free software; you can redistribute it and/or modify
nkeynes@991
     9
 * it under the terms of the GNU General Public License as published by
nkeynes@991
    10
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@991
    11
 * (at your option) any later version.
nkeynes@991
    12
 *
nkeynes@991
    13
 * This program is distributed in the hope that it will be useful,
nkeynes@991
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@991
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@991
    16
 * GNU General Public License for more details.
nkeynes@991
    17
 */
nkeynes@991
    18
nkeynes@991
    19
#include "dream.h"
nkeynes@991
    20
#include "mem.h"
nkeynes@991
    21
nkeynes@991
    22
#ifndef lxdream_xltcache_H
nkeynes@991
    23
#define lxdream_xltcache_H 1
nkeynes@991
    24
nkeynes@991
    25
/**
nkeynes@991
    26
 * For now, recovery is purely a matter of mapping native pc => sh4 pc,
nkeynes@991
    27
 * and updating sh4r.pc & sh4r.slice_cycles accordingly. In future more
nkeynes@991
    28
 * detailed recovery may be required if the translator optimizes more
nkeynes@991
    29
 * agressively.
nkeynes@991
    30
 *
nkeynes@991
    31
 * The recovery table contains (at least) one entry per abortable instruction,
nkeynes@991
    32
 * 
nkeynes@991
    33
 */
nkeynes@991
    34
typedef struct xlat_recovery_record {
nkeynes@991
    35
    uint32_t xlat_offset;    // native (translated) pc 
nkeynes@991
    36
    uint32_t sh4_icount;     // instruction number of the corresponding SH4 instruction
nkeynes@991
    37
                             // (0 = first instruction, 1 = second instruction, ... )
nkeynes@991
    38
} *xlat_recovery_record_t;
nkeynes@991
    39
nkeynes@991
    40
struct xlat_cache_block {
nkeynes@991
    41
    int active;  /* 0 = deleted, 1 = normal. 2 = accessed (temp-space only) */
nkeynes@991
    42
    uint32_t size;
nkeynes@991
    43
    void **lut_entry; /* For deletion */
nkeynes@1149
    44
    void *chain;
nkeynes@991
    45
    uint32_t xlat_sh4_mode; /* comparison with sh4r.xlat_sh4_mode */
nkeynes@991
    46
    uint32_t recover_table_offset; // Offset from code[0] of the recovery table;
nkeynes@991
    47
    uint32_t recover_table_size;
nkeynes@991
    48
    unsigned char code[0];
nkeynes@991
    49
} __attribute__((packed));
nkeynes@991
    50
nkeynes@991
    51
typedef struct xlat_cache_block *xlat_cache_block_t;
nkeynes@991
    52
nkeynes@991
    53
#define XLAT_BLOCK_FOR_CODE(code) (((xlat_cache_block_t)code)-1)
nkeynes@991
    54
nkeynes@1091
    55
#define XLAT_BLOCK_MODE(code) (XLAT_BLOCK_FOR_CODE(code)->xlat_sh4_mode)
nkeynes@1149
    56
#define XLAT_BLOCK_CHAIN(code) (XLAT_BLOCK_FOR_CODE(code)->chain)
nkeynes@1091
    57
#define XLAT_RECOVERY_TABLE(code) ((xlat_recovery_record_t)(((char *)code) + XLAT_BLOCK_FOR_CODE(code)->recover_table_offset))
nkeynes@991
    58
nkeynes@991
    59
/**
nkeynes@991
    60
 * Initialize the translation cache
nkeynes@991
    61
 */
nkeynes@991
    62
void xlat_cache_init(void);
nkeynes@991
    63
nkeynes@991
    64
/**
nkeynes@991
    65
 * Returns the next block in the new cache list that can be written to by the
nkeynes@991
    66
 * translator.
nkeynes@991
    67
 */
nkeynes@991
    68
xlat_cache_block_t xlat_start_block(sh4addr_t address);
nkeynes@991
    69
nkeynes@991
    70
/**
nkeynes@991
    71
 * Increases the current block size (only valid between calls to xlat_start_block()
nkeynes@991
    72
 * and xlat_commit_block()). 
nkeynes@991
    73
 * @return the new block, which may be different from the old block.
nkeynes@991
    74
 */
nkeynes@991
    75
xlat_cache_block_t xlat_extend_block( uint32_t newSize );
nkeynes@991
    76
nkeynes@991
    77
/**
nkeynes@991
    78
 * Commit the current translation block
nkeynes@991
    79
 * @param destsize final size of the translation in bytes.
nkeynes@991
    80
 * @param srcsize size of the original data that was translated in bytes
nkeynes@991
    81
 */
nkeynes@991
    82
void xlat_commit_block( uint32_t destsize, uint32_t srcsize );
nkeynes@991
    83
nkeynes@991
    84
/**
nkeynes@991
    85
 * Dump the disassembly of the specified code block to a stream
nkeynes@991
    86
 * (primarily for debugging purposes)
nkeynes@991
    87
 * @param out The stream to write the output to
nkeynes@991
    88
 * @param code a translated block
nkeynes@991
    89
 */
nkeynes@991
    90
void xlat_disasm_block( FILE *out, void *code );
nkeynes@991
    91
nkeynes@991
    92
nkeynes@991
    93
/**
nkeynes@991
    94
 * Delete (deactivate) the specified block from the cache. Caller is responsible
nkeynes@991
    95
 * for ensuring that there really is a block there.
nkeynes@991
    96
 */
nkeynes@991
    97
void xlat_delete_block( xlat_cache_block_t block );
nkeynes@991
    98
nkeynes@991
    99
/**
nkeynes@991
   100
 * Retrieve the entry point for the translated code corresponding to the given
nkeynes@991
   101
 * SH4 address, or NULL if there is no code for that address.
nkeynes@991
   102
 */
nkeynes@991
   103
void * FASTCALL xlat_get_code( sh4addr_t address );
nkeynes@991
   104
nkeynes@991
   105
/**
nkeynes@991
   106
 * Retrieve the pre-instruction recovery record corresponding to the given
nkeynes@991
   107
 * native address, or NULL if there is no recovery code for the address.
nkeynes@991
   108
 * @param code The code block containing the recovery table.
nkeynes@991
   109
 * @param native_pc A pointer that must be within the currently executing 
nkeynes@991
   110
 * return the first record before or equal to the given pc.
nkeynes@991
   111
 * translation block.
nkeynes@991
   112
 */
nkeynes@991
   113
struct xlat_recovery_record *xlat_get_pre_recovery( void *code, void *native_pc );
nkeynes@991
   114
nkeynes@991
   115
nkeynes@991
   116
/**
nkeynes@991
   117
 * Retrieve the entry point for the translated code corresponding to the given
nkeynes@991
   118
 * SH4 virtual address, or NULL if there is no code for the address. 
nkeynes@991
   119
 * If the virtual address cannot be resolved, this method will raise a TLB miss 
nkeynes@991
   120
 * exception, and return NULL.
nkeynes@991
   121
 */
nkeynes@991
   122
void * FASTCALL xlat_get_code_by_vma( sh4vma_t address );
nkeynes@991
   123
nkeynes@991
   124
/**
nkeynes@991
   125
 * Retrieve the address of the lookup table entry corresponding to the
nkeynes@991
   126
 * given SH4 address.
nkeynes@991
   127
 */
nkeynes@991
   128
void ** FASTCALL xlat_get_lut_entry( sh4addr_t address );
nkeynes@991
   129
nkeynes@991
   130
/**
nkeynes@991
   131
 * Retrieve the current host address of the running translated code block.
nkeynes@991
   132
 * @return the host PC, or null if there is no currently executing translated
nkeynes@991
   133
 * block (or the stack is corrupted)
nkeynes@991
   134
 * Note: the implementation of this method is host (and calling-convention) specific.
nkeynes@991
   135
 * @param block_start start of the block the PC should be in
nkeynes@991
   136
 * @param block_size size of the code block in bytes.
nkeynes@991
   137
 */
nkeynes@991
   138
void *xlat_get_native_pc( void *block_start, uint32_t block_size );
nkeynes@991
   139
nkeynes@991
   140
/**
nkeynes@991
   141
 * Retrieve the size of the block starting at the specified pointer. If the
nkeynes@991
   142
 * pointer is not a valid code block, the return value is undefined.
nkeynes@991
   143
 */
nkeynes@991
   144
uint32_t FASTCALL xlat_get_block_size( void *ptr );
nkeynes@991
   145
nkeynes@991
   146
/**
nkeynes@991
   147
 * Retrieve the size of the code in the block starting at the specified 
nkeynes@991
   148
 * pointer. Effectively this is xlat_get_block_size() minus the size of
nkeynes@991
   149
 * the recovery table. If the pointer is not a valid code block, the 
nkeynes@991
   150
 * return value is undefined.
nkeynes@991
   151
 */
nkeynes@991
   152
uint32_t FASTCALL xlat_get_code_size( void *ptr );
nkeynes@991
   153
nkeynes@991
   154
/**
nkeynes@991
   155
 * Flush the code cache for the page containing the given address
nkeynes@991
   156
 */
nkeynes@991
   157
void FASTCALL xlat_flush_page( sh4addr_t address );
nkeynes@991
   158
nkeynes@991
   159
void FASTCALL xlat_invalidate_word( sh4addr_t address );
nkeynes@991
   160
void FASTCALL xlat_invalidate_long( sh4addr_t address );
nkeynes@991
   161
nkeynes@991
   162
nkeynes@991
   163
/**
nkeynes@991
   164
 * Invalidate the code cache for a memory region
nkeynes@991
   165
 */
nkeynes@991
   166
void FASTCALL xlat_invalidate_block( sh4addr_t address, size_t bytes );
nkeynes@991
   167
nkeynes@991
   168
/**
nkeynes@991
   169
 * Flush the entire code cache. This isn't as cheap as one might like
nkeynes@991
   170
 */
nkeynes@991
   171
void xlat_flush_cache();
nkeynes@991
   172
nkeynes@991
   173
/**
nkeynes@1091
   174
 * Test if the given pointer is within the translation cache, and (is likely)
nkeynes@1091
   175
 * the start of a code block
nkeynes@1091
   176
 */
nkeynes@1091
   177
gboolean xlat_is_code_pointer( void *p );
nkeynes@1091
   178
nkeynes@1091
   179
/**
nkeynes@991
   180
 * Check the internal integrity of the cache
nkeynes@991
   181
 */
nkeynes@991
   182
void xlat_check_integrity();
nkeynes@991
   183
nkeynes@991
   184
#endif /* lxdream_xltcache_H */
.