?? emumem.cpp
字號:
/*************************************************************************
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.
*************************************************************************/
#include "emumem.h"
#ifdef COSIM_STUB
#include "external_mem.h"
#endif
#ifdef EMUMEM_MMAP
#include <unistd.h>
#include <sys/mman.h>
#include <assert.h>
#endif
#include <cstring>
#include <iostream>
using namespace emulator;
#ifdef EMUMEM_HASH
memory::memory()
{
memset(primary_hash_table, 0, sizeof(primary_hash_table));
page_count = 0;
cached_pte = get_page(0);
cached_addr = 0;
}
memory::~memory()
{
reset();
}
memory::memory(const memory& mem)
{
unsigned int i, j;
memset(primary_hash_table, 0, sizeof(primary_hash_table));
page_count = 0;
for(i = 0; i < PRIMARY_MEMORY_HASH_TABLE_SIZE; i++)
{
const secondary_memory_hash_table_t *secondary_hash_table =
mem.primary_hash_table[i];
if(secondary_hash_table)
{
secondary_memory_hash_table_t *secondary_hash_table_cpy =
new secondary_memory_hash_table_t;
memset(secondary_hash_table_cpy, 0,
sizeof(secondary_memory_hash_table_t));
primary_hash_table[i] = secondary_hash_table_cpy;
for(j = 0; j < SECONDARY_MEMORY_HASH_TABLE_SIZE; j++)
{
const memory_page_table_entry_t *pte =
secondary_hash_table->pte[j];
while (pte)
{
memory_page_table_entry_t *pte_cpy =
new memory_page_table_entry_t;
pte_cpy->addr = pte->addr;
pte_cpy->storage = new byte_t[MEMORY_PAGE_SIZE];
memcpy(pte_cpy->storage, pte->storage, MEMORY_PAGE_SIZE);
pte_cpy->next = secondary_hash_table_cpy->pte[j];
secondary_hash_table_cpy->pte[j] = pte_cpy;
page_count++;
pte = pte->next;
}
}
}
}
cached_addr = mem.cached_addr;
cached_pte = get_page(cached_addr);
}
void memory::reset()
{
unsigned int i, j;
for(i = 0; i < PRIMARY_MEMORY_HASH_TABLE_SIZE; i++)
{
secondary_memory_hash_table_t *secondary_hash_table =
primary_hash_table[i];
if(secondary_hash_table)
{
for(j = 0; j < SECONDARY_MEMORY_HASH_TABLE_SIZE; j++)
{
memory_page_table_entry_t *pte = secondary_hash_table->pte[j];
memory_page_table_entry_t *nextpte;
while (pte)
{
nextpte = pte->next;
delete [] pte->storage;
delete pte;
pte = nextpte;
}
}
delete secondary_hash_table;
}
}
memset(primary_hash_table, 0, sizeof(primary_hash_table));
page_count = 0;
cached_pte = get_page(0);
cached_addr = 0;
}
memory_page_table_entry_t *memory::allocate_page(target_addr_t index)
{
UInt32 h1, h2;
memory_page_table_entry_t *pte;
secondary_memory_hash_table_t *secondary_hash_table;
h1 = hash1(index);
secondary_hash_table = primary_hash_table[h1];
if(!secondary_hash_table)
{
secondary_hash_table = new secondary_memory_hash_table_t;
memset(secondary_hash_table, 0,
sizeof(secondary_memory_hash_table_t));
primary_hash_table[h1] = secondary_hash_table;
}
h2 = hash2(index);
pte = new memory_page_table_entry_t;
pte->addr = index;
pte->storage = new byte_t[MEMORY_PAGE_SIZE];
memset(pte->storage, 0, MEMORY_PAGE_SIZE);
pte->next = secondary_hash_table->pte[h2];
secondary_hash_table->pte[h2] = pte;
page_count++;
return pte;
}
#endif
#ifdef EMUMEM_MMAP
void memory::init()
{
for(int frame_index = 0; frame_index < MMAP_FRAME_NUM; frame_index++)
{
mmap_frame[frame_index] = 0;
}
page_count = 0;
}
memory::memory()
{
init();
}
memory::~memory()
{
reset();
}
memory::memory(const memory& mem)
{
init();
}
void memory::reset()
{
for(int frame_index = 0; frame_index < MMAP_FRAME_NUM; frame_index++)
{
byte_t * frame_start = mmap_frame[frame_index];
if (frame_start != 0)
{
munmap(frame_start, MMAP_FRAME_SIZE);
mmap_frame[frame_index] = 0;
}
}
page_count = 0;
}
byte_t * memory::allocate_frame(target_addr_t index)
{
byte_t * frame_start = reinterpret_cast<byte_t *>
(mmap(0, MMAP_FRAME_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0));
assert(frame_start != MAP_FAILED);
page_count++;
const target_addr_t frame_begin_offset = index << MMAP_FRAME_SHIFT;
return mmap_frame[index] = frame_start - frame_begin_offset;
}
#endif
#ifdef COSIM_STUB
int memory::register_addr(target_addr_t addr) {
static int uniq_id = 0;
return (external_decoded_addr[addr] = uniq_id++);
}
#endif
halfword_t memory::read_half_word(target_addr_t addr)
{
#ifdef COSIM_STUB
if (external_decoded_addr.find(addr) != external_decoded_addr.end()) {
return ext_read_half_word(external_decoded_addr[addr]);
}
#endif
#if WORDS_BIGENDIAN==TARGET_LITTLE_ENDIAN
return swap_half_word(* reinterpret_cast<halfword_t*>(translate(addr)));
#else
return * reinterpret_cast<halfword_t*>(translate(addr));
#endif
}
void memory::write_half_word(target_addr_t addr, halfword_t value)
{
#ifdef COSIM_STUB
if (external_decoded_addr.find(addr) != external_decoded_addr.end()) {
ext_write_half_word(external_decoded_addr[addr], value);
return;
}
#endif
#if WORDS_BIGENDIAN==TARGET_LITTLE_ENDIAN
* reinterpret_cast<halfword_t*>(translate(addr)) = swap_half_word(value);
#else
* reinterpret_cast<halfword_t*>(translate(addr)) = value;
#endif
}
dword_t memory::read_dword(target_addr_t addr)
{
#ifdef COSIM_STUB
if (external_decoded_addr.find(addr) != external_decoded_addr.end()) {
return ext_read_dword(external_decoded_addr[addr]);
}
#endif
#if WORDS_BIGENDIAN==TARGET_LITTLE_ENDIAN
return swap_dword(* reinterpret_cast<dword_t*>(translate(addr)));
#else
return * reinterpret_cast<dword_t*>(translate(addr));
#endif
}
void memory::write_dword(target_addr_t addr, dword_t value)
{
#ifdef COSIM_STUB
if (external_decoded_addr.find(addr) != external_decoded_addr.end()) {
ext_write_dword(external_decoded_addr[addr], value);
return;
}
#endif
#if WORDS_BIGENDIAN==TARGET_LITTLE_ENDIAN
* reinterpret_cast<dword_t*>(translate(addr)) = swap_dword(value);
#else
* reinterpret_cast<dword_t*>(translate(addr)) = value;
#endif
}
#define MEM_BLOCK_CODE(to,from,frame_size) \
if(size > 0) \
{ \
const target_addr_t frame_offset = addr % frame_size; \
byte_t * frame_addr = reinterpret_cast<byte_t *>(translate(addr)); \
target_addr_t sz = frame_size - frame_offset; \
if(size > sz) \
{ \
MEM_BLOCK_OP(to, from, sz); \
size -= sz; \
addr += sz; \
buf = reinterpret_cast<byte_t *>(buf) + sz; \
\
if(size >= frame_size) \
{ \
do \
{ \
frame_addr = reinterpret_cast<byte_t *>(translate(addr)); \
MEM_BLOCK_OP(to, from, frame_size); \
size -= frame_size; \
addr += frame_size; \
buf = reinterpret_cast<byte_t *>(buf) + frame_size; \
} while(size >= frame_size); \
} \
\
if(size > 0) \
{ \
frame_addr = reinterpret_cast<byte_t *>(translate(addr)); \
MEM_BLOCK_OP(to, from, size); \
} \
} \
else \
{ \
MEM_BLOCK_OP(to, from, size); \
} \
}
#ifdef EMUMEM_HASH
#define FRAME_SIZE MEMORY_PAGE_SIZE
#endif
#ifdef EMUMEM_MMAP
#define FRAME_SIZE MMAP_FRAME_SIZE
#endif
void memory::read_block(void *buf, target_addr_t addr, unsigned int size)
{
#define MEM_BLOCK_OP memcpy
MEM_BLOCK_CODE(buf,frame_addr,FRAME_SIZE)
#undef MEM_BLOCK_OP
}
void memory::write_block(target_addr_t addr, void *buf, unsigned int size)
{
#define MEM_BLOCK_OP memcpy
MEM_BLOCK_CODE(frame_addr,buf,FRAME_SIZE)
#undef MEM_BLOCK_OP
}
void memory::set_block(target_addr_t addr, byte_t value, unsigned int size)
{
void * buf = 0;
#define MEM_BLOCK_OP memset
MEM_BLOCK_CODE(frame_addr,value,FRAME_SIZE)
#undef MEM_BLOCK_OP
}
#undef FRAME_SIZE
target_addr_t memory::align_to_page_boundary(target_addr_t addr)
{
return addr - (addr % MEMORY_PAGE_SIZE);
}
#ifdef TEST_MEMORY
bool memory::test()
{
unsigned int i;
bool ret = true;
/* test half_word */
halfword_t hw;
for (i=0; i<1024;i+=2)
write_half_word(i, (halfword_t)i);
for (i=0; i<1024;i+=2)
if ((hw=read_half_word(i))!=(halfword_t)i ||
read_byte(i)!=(byte_t)i ||
read_byte(i+1)!=(byte_t)(i>>8)) {
ret = false;
std::cerr << "halfword test failed at " << i << ", get " << hw
<< std::endl;
}
/* test word */
word_t w;
for (i=0; i<1024;i+=4)
write_word(i, (word_t)i);
for (i=0; i<1024;i+=4)
if ((w=read_word(i))!=i ||
read_byte(i)!=(byte_t)i ||
read_byte(i+3)!=(byte_t)(i>>24)) {
ret = false;
std::cerr << "word test failed at " << i << ", get " << w
<< std::endl;
}
/* test dword */
dword_t dw;
for (i=0; i<1024;i+=8)
write_dword(i, ((dword_t)i<<32)|i);
for (i=0; i<1024;i+=8)
if ((dw=read_dword(i))!=(((dword_t)i<<32)|i) ||
read_byte(i)!=(byte_t)i ||
read_byte(i+7)!=(byte_t)(i>>24)) {
ret = false;
std::cerr << "dword test failed at " << i << ", get " << dw
<< std::endl;
}
/* test block */
char hello[] = "hello world!\n";
char bufff[sizeof(hello)];
write_block(0xffff, hello, sizeof(hello));
read_block(bufff, 0xffff, sizeof(hello));
for (i=0; i<sizeof(hello);i+=8)
if (bufff[i]!=hello[i]) {
ret = false;
std::cerr << "block test failed at " << i << ", get " << bufff[i]
<< std::endl;
}
/* test copy constructor using word */
for (i=0; i<1024;i+=4)
write_word(i, (word_t)i);
memory mem(*this);
for (i=0; i<1024;i+=4)
if ((w=mem.read_word(i))!=i ||
mem.read_byte(i)!=(byte_t)i ||
mem.read_byte(i+3)!=(byte_t)(i>>24)) {
ret = false;
std::cerr << "copy test failed at " << i << ", get " << w
<< std::endl;
}
if (mem.page_count != page_count)
std::cerr << "page count mismatch after copying" << std::endl;
return ret;
}
#endif
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -