Index: ChangeLog
from BenoƮt Perrot <benoit(a)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.
Index: src/vm/cp0.hh
--- src/vm/cp0.hh (revision 109)
+++ src/vm/cp0.hh (working copy)
@@ -106,6 +106,8 @@
// 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 @@
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:
Index: src/vm/memory.hh
--- src/vm/memory.hh (revision 113)
+++ src/vm/memory.hh (working copy)
@@ -42,14 +42,21 @@
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 @@
// 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)
{
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 @@
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 @@
\{ */
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_;
};
Index: src/vm/virtual_machine.hh
--- src/vm/virtual_machine.hh (revision 114)
+++ src/vm/virtual_machine.hh (working copy)
@@ -65,7 +65,7 @@
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)
{
}
Index: src/vm/mmu.hh
--- src/vm/mmu.hh (revision 114)
+++ src/vm/mmu.hh (working copy)
@@ -23,6 +23,7 @@
# include "inst/text_section.hh"
+# include "vm/cp0.hh"
# include "vm/memory.hh"
namespace vm
@@ -34,7 +35,8 @@
/** \name Constructor and destructor
\{ */
public:
- Mmu(Memory& memory):
+ Mmu(Cp0 &cp0, Memory &memory):
+ cp0_(cp0),
memory_(memory),
text_section_(0)
{}
@@ -48,6 +50,27 @@
/** \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 @@
/// 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 @@
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 @@
/** \} */
protected:
+ /// Control coprocessor link
+ Cp0 &cp0_;
+
/// Memory link.
Memory& memory_;
-
const inst::TextSection* text_section_;
};
Index: src/vm/virtual_machine.cc
--- src/vm/virtual_machine.cc (revision 113)
+++ src/vm/virtual_machine.cc (working copy)
@@ -55,7 +55,7 @@
// 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 @@
{
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;