[nolimips: 115] Hide memory behind MMU, stage 2

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. 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;
participants (1)
-
Noe