?? emumem.h
字號:
/*************************************************************************
Copyright (C) 2002,2003,2004,2005 Wei Qin
See file COPYING for more information.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*************************************************************************/
#ifndef __EMU_MEMORY_H__
#define __EMU_MEMORY_H__
#include <config.h>
#if defined(ENABLE_MMAP) && defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H)
#define EMUMEM_MMAP
#else
#define EMUMEM_HASH
#endif
#include <misc.h>
#include <cstring>
#ifdef COSIM_STUB
#include <map>
#include "external_mem.h"
#endif
namespace emulator {
const unsigned int MEMORY_PAGE_SIZE = 4096;
const unsigned int MEMORY_PAGE_SIZE_BITS = 12;
#ifdef EMUMEM_HASH
const unsigned int PRIMARY_MEMORY_HASH_TABLE_SIZE = 4096;
const unsigned int SECONDARY_MEMORY_HASH_TABLE_SIZE = 16;
typedef struct memory_page_table_entry_t
{
target_addr_t addr;
struct memory_page_table_entry_t *next;
byte_t *storage;
} memory_page_table_entry_t;
typedef struct
{
memory_page_table_entry_t *pte[SECONDARY_MEMORY_HASH_TABLE_SIZE];
} secondary_memory_hash_table_t;
#endif
#ifdef EMUMEM_MMAP
const unsigned int MMAP_FRAME_BITS = 10;
const unsigned int MMAP_FRAME_NUM = 1 << MMAP_FRAME_BITS;
const unsigned int MMAP_FRAME_SHIFT = sizeof(target_addr_t)*8 - MMAP_FRAME_BITS;
const unsigned int MMAP_FRAME_SIZE = 1 << MMAP_FRAME_SHIFT;
const unsigned int MMAP_OFFSET_MASK = MMAP_FRAME_SIZE - 1;
#endif
class memory;
class memory
{
private:
#ifdef COSIM_STUB
std::map<target_addr_t, int> external_decoded_addr;
#endif
public:
/* constructor */
memory();
/* destructor */
~memory();
/* copy constructor, not implemented */
memory(const memory&);
/* free all memory pages */
void reset();
#ifdef EMUMEM_HASH
/* address translation */
byte_t * translate(target_addr_t addr)
{
target_addr_t offset = addr % MEMORY_PAGE_SIZE;
memory_page_table_entry_t *pte = get_page(addr);
return pte->storage + offset;
}
/* fast address translation */
byte_t * translate_fast(target_addr_t addr)
{
memory_page_table_entry_t *pte;
target_addr_t index = addr >> MEMORY_PAGE_SIZE_BITS;
target_addr_t offset = addr % MEMORY_PAGE_SIZE;
if (cached_addr==index) pte = cached_pte;
else {
cached_pte = pte = get_page(addr);
cached_addr = index;
}
return pte->storage + offset;
}
#endif
#ifdef EMUMEM_MMAP
/* address translation */
byte_t * translate(target_addr_t addr)
{
const target_addr_t frame_index = addr >> MMAP_FRAME_SHIFT;
byte_t * const frame_start = mmap_frame[frame_index];
if (!frame_start) {
byte_t * const frame_start = allocate_frame(frame_index);
return frame_start + addr;
}
return frame_start + addr;
}
/* fast address translation */
byte_t * translate_fast(target_addr_t addr)
{
return translate(addr);
}
#endif
/* read/write operations */
halfword_t read_half_word(target_addr_t addr);
dword_t read_dword(target_addr_t addr);
byte_t read_byte(target_addr_t addr)
{
#ifdef COSIM_STUB
if (external_decoded_addr.find(addr) != external_decoded_addr.end()) {
return ext_read_byte(external_decoded_addr[addr]);
}
#endif
return * reinterpret_cast<byte_t*>(translate(addr));
}
void write_byte(target_addr_t addr, byte_t value)
{
#ifdef COSIM_STUB
if (external_decoded_addr.find(addr) != external_decoded_addr.end()) {
ext_write_byte(external_decoded_addr[addr], value);
return;
}
#endif
* reinterpret_cast<byte_t*>(translate(addr)) = value;
}
word_t read_word(target_addr_t addr)
{
#ifdef COSIM_STUB
if (external_decoded_addr.find(addr) != external_decoded_addr.end()) {
return ext_read_word(external_decoded_addr[addr]);
}
#endif
#if WORDS_BIGENDIAN==TARGET_LITTLE_ENDIAN
return swap_word(* reinterpret_cast<word_t*>(translate(addr)));
#else
return * reinterpret_cast<word_t*>(translate(addr));
#endif
}
void write_word(target_addr_t addr, word_t value)
{
#ifdef COSIM_STUB
if (external_decoded_addr.find(addr) != external_decoded_addr.end()) {
ext_write_word(external_decoded_addr[addr], value);
return;
}
#endif
#if WORDS_BIGENDIAN==TARGET_LITTLE_ENDIAN
* reinterpret_cast<word_t*>(translate(addr)) = swap_word(value);
#else
* reinterpret_cast<word_t*>(translate(addr)) = value;
#endif
}
void read_block(void *buf, target_addr_t addr, unsigned int size);
/* write operations */
void write_half_word(target_addr_t addr, halfword_t value);
void write_dword(target_addr_t addr, dword_t value);
void set_block(target_addr_t addr, byte_t value, unsigned int size);
void write_block(target_addr_t, void *buf, unsigned int size);
/* some usefule utilities */
target_addr_t align_to_page_boundary(target_addr_t addr);
#ifdef TEST_MEMORY
/* memory test , true->succeed */
bool test();
#endif
/* if the fist read is to address 0, this will crash, so beware */
word_t read_word_fast(target_addr_t addr) {
#if WORDS_BIGENDIAN==TARGET_LITTLE_ENDIAN
return swap_word(* reinterpret_cast<word_t *>(translate_fast(addr)));
#else
return * reinterpret_cast<word_t *>(translate_fast(addr));
#endif
}
/* return the number of pages allocated */
unsigned int get_page_count() {
return page_count;
}
#ifdef COSIM_STUB
int register_addr(target_addr_t addr);
#endif
private:
static halfword_t swap_half_word(halfword_t val) {
return (val>>8) | (val<<8);
}
static word_t swap_word(word_t val) {
return (val>>24) | ((val>>8)&0xFF00) |
((val&0xFF00)<<8) | (val<<24) ;
}
static dword_t swap_dword(dword_t val) {
return ((dword_t)swap_word((word_t)val)<<32) |
(dword_t)swap_word((word_t)(val>>32));
}
#ifdef EMUMEM_HASH
static UInt32 hash1(target_addr_t index)
{
return index % PRIMARY_MEMORY_HASH_TABLE_SIZE;
}
static UInt32 hash2(target_addr_t index)
{
return (index / PRIMARY_MEMORY_HASH_TABLE_SIZE) %
SECONDARY_MEMORY_HASH_TABLE_SIZE;
}
memory_page_table_entry_t *allocate_page(target_addr_t index);
memory_page_table_entry_t *search_page(target_addr_t index)
{
UInt32 h1;
UInt32 h2;
secondary_memory_hash_table_t *secondary_hash_table;
h1 = hash1(index);
secondary_hash_table = primary_hash_table[h1];
if(secondary_hash_table)
{
memory_page_table_entry_t *pte;
h2 = hash2(index);
pte = secondary_hash_table->pte[h2];
while(pte)
{
if(pte->addr == index) return pte;
pte = pte->next;
}
}
return 0;
}
memory_page_table_entry_t *get_page(target_addr_t addr)
{
memory_page_table_entry_t *pte;
addr = addr >> MEMORY_PAGE_SIZE_BITS;
pte = search_page(addr);
if(!pte)
pte = allocate_page(addr);
return pte;
}
secondary_memory_hash_table_t
*primary_hash_table[PRIMARY_MEMORY_HASH_TABLE_SIZE];
/* for possibly sequential reads by read_word_fast */
target_addr_t cached_addr;
memory_page_table_entry_t *cached_pte;
#endif
#ifdef EMUMEM_MMAP
void init();
byte_t * allocate_frame(target_addr_t index);
byte_t * mmap_frame[MMAP_FRAME_NUM];
#endif
unsigned int page_count; /*stats information */
};
} /* namespace */
#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -