Commit d01d0c82 authored by Benoit Perrot's avatar Benoit Perrot
Browse files

Index: ChangeLog

from  Benoît Perrot  <benoit@lrde.epita.fr>

	* src/vm/memory.hh, src/vm/mmu.hh, src/vm/virtual_machine.cc:
	Make the MMU responsible of address translation and exception 
	raising.
	* src/vm/cp0.hh (raise_addr_load, raise_addr_store): Add address
	load and store exception.
	* src/vm/virtual_machine.hh (execute): Stop execution on fatal
	exceptions.
parent efc8533f
2004-07-15 Benot Perrot <benoit@lrde.epita.fr>
* src/vm/memory.hh, src/vm/mmu.hh, src/vm/virtual_machine.cc:
Make the MMU responsible of address translation and exception
raising.
* src/vm/cp0.hh (raise_addr_load, raise_addr_store): Add address
load and store exception.
* src/vm/virtual_machine.hh (execute): Stop execution on fatal
exceptions.
2004-07-14 Benot Perrot <benoit@lrde.epita.fr>
* src/vm/mmu.hh: Hide instructions' access behind MMU.
......
......@@ -106,6 +106,8 @@ namespace vm
// Initialize registers to 0.
for (unsigned i = 0; i < 32; ++i)
registers[i] = 0;
fatal_exception_ = false;
}
/** \name Explicit register accessors
......@@ -143,6 +145,30 @@ namespace vm
std::cerr << "Runtime Exception: Overflow" << std::endl;
exit_set(exit_runtime);
}
/// Raise an address error on load exception
void raise_addr_load()
{
registers[cause] = addr_load;
std::cerr << "Runtime Exception: Address error on load" << std::endl;
fatal_exception_ = true;
exit_set(exit_runtime);
}
/// Raise an address error on load exception
void raise_addr_store()
{
registers[cause] = addr_store;
std::cerr << "Runtime Exception: Address error on store" << std::endl;
fatal_exception_ = true;
exit_set(exit_runtime);
}
bool fatal_exception() const
{
return fatal_exception_;
}
protected:
bool fatal_exception_;
/** \} */
protected:
......
......@@ -41,15 +41,22 @@ namespace vm
public:
static const int stack_bottom = INT32_MAX - 3;
static const int default_stack_size = 512 * 1024;
enum segment_kind
{
heap = 0,
stack = 1
};
/** \name Constructor and destructor
\{ */
public:
/// Construct a Memory.
Memory(int stack_size = default_stack_size):
heap_(0), stack_(stack_size), stack_top_(stack_bottom - stack_size + 4)
stack_top_(stack_bottom - stack_size + 4)
{
assertion(stack_size > 0);
segments_[stack].resize(stack_size);
}
/** \} */
......@@ -59,33 +66,29 @@ namespace vm
// DO NOT zero-ify the memory
}
protected:
int translate(int offset) const
{
precondition(offset >= stack_top_);
// Stack grows down
return offset - stack_top_;
}
public:
int sbrk(int size)
int sbrk(int size)
{
precondition(size >= 0);
int ptr = heap_.size();
int ptr = segments_[heap].size();
if (size)
// FIXME: check collision with stack
heap_.resize(size + heap_.size());
segments_[heap].resize(size + segments_[heap].size());
return ptr;
}
public:
int heap_size() const
{
return heap_.size ();
return segments_[heap].size();
}
int stack_size() const
{
return stack_.size ();
return segments_[stack].size();
}
int get_stack_top() const
{
return stack_top_;
}
/** \name Store instructions.
......@@ -93,28 +96,20 @@ namespace vm
public:
void store(const inst::DataSection& data_section)
{
heap_.resize(data_section.size());
segments_[heap].resize(data_section.size());
for (int i = 0; i < data_section.size(); ++i)
heap_.store_byte(i, data_section.load_byte(i));
segments_[heap].store_byte(i, data_section.load_byte(i));
}
/// Store a byte in memory.
void store_byte(int offset, int b)
void store_byte(segment_kind k, int offset, int b)
{
precondition(offset >= 0);
if (offset < heap_.size())
heap_.store_byte(offset, b);
else
stack_.store_byte(translate(offset), b);
segments_[k].store_byte(offset, b);
}
/// Store a word in memory.
void store_word(int offset, int w)
void store_word(segment_kind k, int offset, int w)
{
precondition(offset >= 0);
if (offset < heap_.size())
heap_.store_word(offset, w);
else
stack_.store_word(translate(offset), w);
segments_[k].store_word(offset, w);
}
/** \} */
......@@ -122,26 +117,19 @@ namespace vm
\{ */
public:
/// Load a byte from memory.
int load_byte(int offset) const
int load_byte(segment_kind k, int offset) const
{
precondition(offset >= 0);
if (offset < heap_.size())
return heap_.load_byte(offset);
return stack_.load_byte(translate(offset));
return segments_[k].load_byte(offset);
}
/// Load a word from memory.
int load_word(int offset) const
int load_word(segment_kind k, int offset) const
{
precondition(offset >= 0);
if (offset < heap_.size())
return heap_.load_word(offset);
return stack_.load_word(translate(offset));
return segments_[k].load_word(offset);
}
/** \} */
protected:
Segment heap_;
Segment stack_;
Segment segments_[2];
const int stack_top_;
};
......
......@@ -23,6 +23,7 @@
# include "inst/text_section.hh"
# include "vm/cp0.hh"
# include "vm/memory.hh"
namespace vm
......@@ -34,7 +35,8 @@ namespace vm
/** \name Constructor and destructor
\{ */
public:
Mmu(Memory& memory):
Mmu(Cp0 &cp0, Memory &memory):
cp0_(cp0),
memory_(memory),
text_section_(0)
{}
......@@ -48,6 +50,27 @@ namespace vm
/** \name Proxy for memory data access.
\{ */
protected:
bool translate(int &offset, Memory::segment_kind &k) const
{
if (0 <= offset)
{
if (offset < memory_.heap_size())
{
k = Memory::heap;
return true;
}
if (memory_.get_stack_top() <= offset)
{
k = Memory::stack;
// Stack grows down
offset = offset - memory_.get_stack_top();
return true;
}
}
return false;
}
public:
void data_store(const inst::DataSection& data_section)
{
......@@ -57,23 +80,41 @@ namespace vm
/// Store a byte in memory.
void data_store_byte(int offset, int b)
{
memory_.store_byte(offset, b);
Memory::segment_kind k;
if (translate(offset, k))
memory_.store_byte(k, offset, b);
else
cp0_.raise_addr_store();
}
/// Store a word in memory.
void data_store_word(int offset, int w)
{
memory_.store_word(offset, w);
Memory::segment_kind k;
if (translate(offset, k))
memory_.store_word(k, offset, w);
else
cp0_.raise_addr_store();
}
/// Load a byte from memory.
int data_load_byte(int offset) const
{
return memory_.load_byte(offset);
Memory::segment_kind k;
if (translate(offset, k))
return memory_.load_byte(k, offset);
cp0_.raise_addr_load();
return 0;
}
/// Load a word from memory.
int data_load_word(int offset) const
{
return memory_.load_word(offset);
Memory::segment_kind k;
if (translate(offset, k))
return memory_.load_word(k, offset);
cp0_.raise_addr_load();
return 0;
}
int data_sbrk(int size)
......@@ -92,6 +133,14 @@ namespace vm
const inst::Inst & inst_load(int offset) const
{
// Precondition
if (offset < 0 || text_section_->size() <= offset)
{
std::cerr << "inst_load" << std::endl;
cp0_.raise_addr_load();
return (*text_section_)[0]; // FIXME: NO!
}
return (*text_section_)[offset];
}
......@@ -106,9 +155,11 @@ namespace vm
/** \} */
protected:
/// Memory link.
Memory& memory_;
/// Control coprocessor link
Cp0 &cp0_;
/// Memory link.
Memory &memory_;
const inst::TextSection* text_section_;
};
......
......@@ -55,7 +55,7 @@ namespace vm
// FIXME: precondition on loaded program
cpu_.set_pc(main_offset_);
while (!cpu_.get_halt())
while (! (cpu_.get_halt() || cp0_.fatal_exception()))
{
cpu_.step();
cp0_.set_count(cp0_.get_count() + 1);
......@@ -78,7 +78,7 @@ namespace vm
{
cpu_.step();
cp0_.set_count(cp0_.get_count() + 1);
if (cpu_.get_halt())
if (cpu_.get_halt() || cp0_.fatal_exception())
{
status_ = halt;
std::cerr << "Program exited." << std::endl;
......
......@@ -65,7 +65,7 @@ namespace vm
std::ostream& ostr = std::cout):
mode_(mode),
status_(stop),
mmu_(memory_),
mmu_(cp0_, memory_),
cpu_(mmu_, cp0_, istr, ostr, check_callee_save_p, trace_exec_p)
{
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment