
https://svn.lrde.epita.fr/svn/nolimips ChangeLog | 17 ++++++ src/vm-tasks.cc | 3 + src/vm/Makefile.am | 3 + src/vm/cp0.hh | 5 + src/vm/cpu.cc | 74 +---------------------------- src/vm/cpu.hh | 24 +++------ src/vm/spim_system_library.cc | 103 +++++++++++++++++++++++++++++++++++++++++ src/vm/spim_system_library.hh | 47 ++++++++++++++++++ src/vm/spim_system_library.hxx | 35 +++++++++++++ src/vm/system_library.cc | 27 ++++++++++ src/vm/system_library.hh | 40 +++++++++++++++ src/vm/virtual_machine.cc | 4 - src/vm/virtual_machine.hh | 10 ++- 13 files changed, 303 insertions(+), 89 deletions(-) Index: trunk/ChangeLog from BenoƮt Perrot <benoit@lrde.epita.fr> Introduce system libraries. * src/vm/cpu.hh, src/vm/cpu.cc: Export mmu and cp0. Move syscalls' implementation to... * src/vm/system_library.hh, src/vm/system_library.cc, * src/vm/spim_system_library.hh, src/vm/spim_system_library.hxx, * src/vm/spim_system_library.cc: These new files. * src/vm/cp0.hh: Export fatal_exception flag. * src/vm/Makefile.am: Update accordingly. * src/vm/virtual_machine.hh, src/vm/virtual_machine.cc: Propagate system library to cpu. * src/vm-tasks.cc: Give a default system library to virtual machine. Index: trunk/src/vm/cp0.hh --- trunk/src/vm/cp0.hh (revision 193) +++ trunk/src/vm/cp0.hh (revision 194) @@ -165,6 +165,11 @@ exit_set(exit_runtime); } + void set_fatal_exception() + { + fatal_exception_ = true; + } + bool fatal_exception() const { return fatal_exception_; Index: trunk/src/vm/spim_system_library.cc --- trunk/src/vm/spim_system_library.cc (revision 0) +++ trunk/src/vm/spim_system_library.cc (revision 194) @@ -0,0 +1,103 @@ +// +// This file is part of Nolimips, a MIPS simulator with unlimited registers +// Copyright (C) 2005 Benoit Perrot <benoit@lrde.epita.fr> +// +// Nolimips 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. +// +// Nolimips 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. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +#include "common.hh" + +#include "vm/spim_system_library.hh" +#include "vm/cpu.hh" +#include "vm/mmu.hh" + +namespace vm +{ + + SpimSystemLibrary::~SpimSystemLibrary() + {} + + void + SpimSystemLibrary::invoke(Cpu &cpu) + { + Mmu &mmu = cpu.get_mmu(); + + switch (cpu.get_register(Cpu::v0)) + { + // print_int (integer: $a0) + case 1: + ostr_ << cpu.get_register(Cpu::a0); + break; + + // print_string (buffer: $a0) + case 4: + for (int i = cpu.get_register(Cpu::a0); true; ++i) + { + char b = mmu.data_load_byte(i); + if (b == 0) + break; + ostr_ << b; + } + break; + + // read_string (buffer: $a0, length: $a1) + case 8: + { + int i = 0; + int c = 0; + for (; (i < cpu.get_register(Cpu::a1) - 1) + && (c != '\n') && (c != '\r'); + ++i) + { + c = istr_.get(); + if (istr_.eof()) + break; + mmu.data_store_byte(cpu.get_register(Cpu::a0) + i, c); + } + mmu.data_store_byte(cpu.get_register(Cpu::a0) + i, 0); + } + break; + + // sbrk (size: $a0) + case 9: + cpu.set_register(Cpu::v0, mmu.data_sbrk(cpu.get_register(Cpu::a0))); + break; + + // exit (status : $a0) + case 10: + { + cpu.get_cp0().set_fatal_exception(); + if (!exit_status) + exit_status = (exit_type) cpu.get_register(Cpu::a0); + } + break; + + // print_err (buffer: $a0) + case 15: + for (int i = cpu.get_register(Cpu::a0); true; ++i) + { + char b = mmu.data_load_byte(i); + if (b == 0) + break; + std::cerr << b; + } + break; + + default: + assertion(!"syscall: Not implemented yet"); + }; + ostr_.flush(); + } + +} // namespace vm Index: trunk/src/vm/cpu.hh --- trunk/src/vm/cpu.hh (revision 193) +++ trunk/src/vm/cpu.hh (revision 194) @@ -34,7 +34,6 @@ # include "inst/program.hh" # include "vm/mmu.hh" -# include "vm/cp0.hh" namespace vm { @@ -42,6 +41,9 @@ typedef int32_t register_type; typedef uint32_t uregister_type; + class Cp0; + class SystemLibrary; + /// Central Processor Unit abstraction class Cpu: protected inst::ConstVisitor @@ -68,10 +70,7 @@ \{ */ public: /// Construct a CPU. - Cpu(Mmu& mmu, - Cp0 &cp0, - std::istream& istr, - std::ostream& ostr); + Cpu(Mmu &mmu, Cp0 &cp0); /// Destroy a CPU. virtual ~Cpu(); /** \} */ @@ -178,6 +177,11 @@ return counters_[format]; } + Mmu &get_mmu() { return mmu_; } + Cp0 &get_cp0() { return cp0_; } + + void set_system_library(SystemLibrary *l) { system_library_ = l; } + protected: virtual void visit(const inst::Add& add); virtual void visit(const inst::Addi& addi); @@ -260,15 +264,7 @@ /// Unlimited registers. misc::Table<int, register_type> unlimited_; - - public: - bool get_halt() const { return halt_; } - protected: - bool halt_; - - std::istream& istr_; - std::ostream& ostr_; - + SystemLibrary *system_library_; protected: void call() Index: trunk/src/vm/spim_system_library.hxx --- trunk/src/vm/spim_system_library.hxx (revision 0) +++ trunk/src/vm/spim_system_library.hxx (revision 194) @@ -0,0 +1,35 @@ +// +// This file is part of Nolimips, a MIPS simulator with unlimited registers +// Copyright (C) 2005 Benoit Perrot <benoit@lrde.epita.fr> +// +// Nolimips 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. +// +// Nolimips 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. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +#ifndef VM_SPIM_SYSTEM_LIBRARY_HXX +# define VM_SPIM_SYSTEM_LIBRARY_HXX + +# include "vm/spim_system_library.hh" + +namespace vm +{ + + inline + SpimSystemLibrary::SpimSystemLibrary(std::istream &istr, + std::ostream &ostr): + istr_(istr), ostr_(ostr) + {} + +} // namespace vm + +#endif // !VM_SPIM_SYSTEM_LIBRARY_HH Index: trunk/src/vm/system_library.hh --- trunk/src/vm/system_library.hh (revision 0) +++ trunk/src/vm/system_library.hh (revision 194) @@ -0,0 +1,40 @@ +// +// This file is part of Nolimips, a MIPS simulator with unlimited registers +// Copyright (C) 2005 Benoit Perrot <benoit@lrde.epita.fr> +// +// Nolimips 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. +// +// Nolimips 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. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +#ifndef VM_SYSTEM_LIBRARY_HH +# define VM_SYSTEM_LIBRARY_HH + +namespace vm +{ + + class Cpu; + + class SystemLibrary + { + public: + SystemLibrary() + {} + virtual ~SystemLibrary(); + + public: + virtual void invoke(Cpu &cpu) = 0; + }; + +} // namespace vm + +#endif // !VM_SYSTEM_LIBRARY_HH Index: trunk/src/vm/virtual_machine.hh --- trunk/src/vm/virtual_machine.hh (revision 193) +++ trunk/src/vm/virtual_machine.hh (revision 194) @@ -36,6 +36,7 @@ namespace vm { + class SystemLibrary; /// Virtual Machine abstraction class VirtualMachine @@ -58,13 +59,11 @@ /** \name Constructor and destructor. \{ */ public: - VirtualMachine(mode_type mode = normal, - std::istream& istr = std::cin, - std::ostream& ostr = std::cout): + VirtualMachine(mode_type mode = normal): mode_(mode), status_(stop), mmu_(cp0_, memory_), - cpu_(mmu_, cp0_, istr, ostr) + cpu_(mmu_, cp0_) { } /** \} */ @@ -84,6 +83,9 @@ public: /// Load a program into memory. void load_program(const inst::Program& program); + + void set_system_library(SystemLibrary *l) { cpu_.set_system_library(l); } + protected: int main_offset_; // FIXME: Must disappear! Index: trunk/src/vm/Makefile.am --- trunk/src/vm/Makefile.am (revision 193) +++ trunk/src/vm/Makefile.am (revision 194) @@ -7,4 +7,7 @@ cpu.hh cpu.cc \ segment.hh \ memory.hh \ + system_library.hh system_library.cc \ + spim_system_library.hh spim_system_library.hxx \ + spim_system_library.cc \ virtual_machine.hh virtual_machine.cc Index: trunk/src/vm/cpu.cc --- trunk/src/vm/cpu.cc (revision 193) +++ trunk/src/vm/cpu.cc (revision 194) @@ -21,6 +21,7 @@ #include "common.hh" #include "vm/cpu.hh" +#include "vm/system_library.hh" #include "inst/all.hh" #include "inst/int_exp.hh" @@ -31,12 +32,9 @@ // -------------------------------------------------------------------------- // Constructor and destructor // -------------------------------------------------------------------------- - Cpu::Cpu(Mmu& mmu, - Cp0 &cp0, - std::istream& istr, - std::ostream& ostr): + Cpu::Cpu(Mmu &mmu, Cp0 &cp0): mmu_(mmu), cp0_(cp0), - istr_(istr), ostr_(ostr), + system_library_(0), check_callee_save_p_(false), trace_p_(false), bubble_(new inst::Sll(inst::Register(inst::Register::general, Cpu::zero), @@ -57,8 +55,6 @@ void Cpu::reset() { - halt_ = false; - // Initialize general purpose registers to 0. for (unsigned i = 0; i < 32; ++i) GPR_[i] = 0; @@ -689,68 +685,8 @@ void Cpu::visit(const inst::Syscall&) { - switch (get_register(Cpu::v0)) - { - // print_int (integer: $a0) - case 1: - ostr_ << get_register(Cpu::a0); - break; - - // print_string (buffer: $a0) - case 4: - for (int i = get_register(Cpu::a0); true; ++i) - { - char b = mmu_.data_load_byte(i); - if (b == 0) - break; - ostr_ << b; - } - break; - - // read_string (buffer: $a0, length: $a1) - case 8: - { - int i = 0; - int c = 0; - for (; (i < get_register(Cpu::a1) - 1) && (c != '\n') && (c != '\r'); - ++i) - { - c = istr_.get(); - if (istr_.eof()) - break; - mmu_.data_store_byte(get_register(Cpu::a0) + i, c); - } - mmu_.data_store_byte(get_register(Cpu::a0) + i, 0); - } - break; - - // sbrk (size: $a0) - case 9: - set_register(Cpu::v0, mmu_.data_sbrk(get_register(Cpu::a0))); - break; - - // exit (status : $a0) - case 10: - halt_ = true; - if (!exit_status) - exit_status = (exit_type) get_register(Cpu::a0); - break; - - // print_err (buffer: $a0) - case 15: - for (int i = get_register(Cpu::a0); true; ++i) - { - char b = mmu_.data_load_byte(i); - if (b == 0) - break; - std::cerr << b; - } - break; - - default: - assertion(!"syscall: Not implemented yet"); - }; - ostr_.flush(); + precondition(system_library_); + system_library_->invoke(*this); } } // namespace vm Index: trunk/src/vm/system_library.cc --- trunk/src/vm/system_library.cc (revision 0) +++ trunk/src/vm/system_library.cc (revision 194) @@ -0,0 +1,27 @@ +// +// This file is part of Nolimips, a MIPS simulator with unlimited registers +// Copyright (C) 2005 Benoit Perrot <benoit@lrde.epita.fr> +// +// Nolimips 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. +// +// Nolimips 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. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +#include "vm/system_library.hh" + +namespace vm +{ + + SystemLibrary::~SystemLibrary() + {} + +} // namespace vm Index: trunk/src/vm/spim_system_library.hh --- trunk/src/vm/spim_system_library.hh (revision 0) +++ trunk/src/vm/spim_system_library.hh (revision 194) @@ -0,0 +1,47 @@ +// +// This file is part of Nolimips, a MIPS simulator with unlimited registers +// Copyright (C) 2005 Benoit Perrot <benoit@lrde.epita.fr> +// +// Nolimips 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. +// +// Nolimips 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. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +#ifndef VM_SPIM_SYSTEM_LIBRARY_HH +# define VM_SPIM_SYSTEM_LIBRARY_HH + +# include <iostream> + +# include "vm/system_library.hh" + +namespace vm +{ + + class SpimSystemLibrary: public SystemLibrary + { + public: + SpimSystemLibrary(std::istream &istr, std::ostream &ostr); + virtual ~SpimSystemLibrary(); + + public: + virtual void invoke(Cpu &cpu); + + protected: + std::istream &istr_; + std::ostream &ostr_; + }; + +} // namespace vm + +# include "vm/spim_system_library.hxx" + +#endif // !VM_SPIM_SYSTEM_LIBRARY_HH Index: trunk/src/vm/virtual_machine.cc --- trunk/src/vm/virtual_machine.cc (revision 193) +++ trunk/src/vm/virtual_machine.cc (revision 194) @@ -56,7 +56,7 @@ // FIXME: precondition on loaded program cpu_.set_pc(main_offset_); - while (! (cpu_.get_halt() || cp0_.fatal_exception())) + while (!cp0_.fatal_exception()) { cpu_.step(); cp0_.set_count(cp0_.get_count() + 1); @@ -79,7 +79,7 @@ { cpu_.step(); cp0_.set_count(cp0_.get_count() + 1); - if (cpu_.get_halt() || cp0_.fatal_exception()) + if (cp0_.fatal_exception()) { status_ = halt; std::cerr << "Program exited." << std::endl; Index: trunk/src/vm-tasks.cc --- trunk/src/vm-tasks.cc (revision 193) +++ trunk/src/vm-tasks.cc (revision 194) @@ -18,6 +18,7 @@ // #include "common.hh" +#include "vm/spim_system_library.hh" #include "vm/virtual_machine.hh" #include "parse-tasks.hh" @@ -33,9 +34,11 @@ void execute () { + vm::SpimSystemLibrary l(std::cin, std::cout); vm::VirtualMachine vm; vm.get_cpu().set_check_callee_save(check_callee_save_p); vm.get_cpu().set_trace(trace_exec_p); + vm.set_system_library(&l); vm.load_program(* parse::tasks::program); if (exit_status != exit_success) exit(exit_status);