Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(465)

Unified Diff: runtime/vm/simulator_mips.cc

Issue 12541003: - Add a skeleton MIPS assembler, disassembler and simulator. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: runtime/vm/simulator_mips.cc
===================================================================
--- runtime/vm/simulator_mips.cc (revision 19556)
+++ runtime/vm/simulator_mips.cc (working copy)
@@ -16,6 +16,12 @@
namespace dart {
+DEFINE_FLAG(int, stop_sim_at, 0, "Address to stop simulator at.");
+
+void Simulator::InitOnce() {
+}
+
+
Simulator::Simulator() {
// Setup simulator support first. Some of this information is needed to
// setup the architecture state.
@@ -26,6 +32,18 @@
stack_ = new char[(Isolate::GetSpecifiedStackSize() +
Isolate::kStackSizeBuffer +
kSimulatorStackUnderflowSize)];
+ icount_ = 0;
+ delay_slot_ = false;
+
+ // Setup architecture state.
+ // All registers are initialized to zero to start with.
+ for (int i = 0; i < kNumberOfCpuRegisters; i++) {
+ registers_[i] = 0;
+ }
+ pc_ = 0;
+ // The sp is initialized to point to the bottom (high address) of the
+ // allocated stack area.
+ registers_[SP] = StackTop();
}
@@ -51,15 +69,19 @@
// Sets the register in the architecture state. It will also deal with updating
// Simulator internal state for special registers such as PC.
void Simulator::set_register(Register reg, int32_t value) {
- UNIMPLEMENTED();
+ if (reg != R0) {
+ registers_[reg] = value;
+ }
}
// Get the register from the architecture state. This function does handle
// the special case of accessing the PC register.
int32_t Simulator::get_register(Register reg) const {
- UNIMPLEMENTED();
- return 0;
+ if (reg == R0) {
+ return 0;
+ }
+ return registers_[reg];
}
@@ -73,18 +95,182 @@
}
-void Simulator::InitOnce() {
+void Simulator::Format(Instr* instr, const char* format) {
+ OS::PrintErr("Simulator - unknown instruction: %s\n", format);
+ UNIMPLEMENTED();
}
+void Simulator::DecodeSpecial(Instr* instr) {
+ switch (instr->FunctionField()) {
+ case SLL: {
+ if ((instr->RdField() == R0) &&
+ (instr->RtField() == R0) &&
+ (instr->SaField() == 0)) {
+ // Format(instr, "nop");
+ // Nothing to be done for NOP.
+ } else {
+ Format(instr, "sll 'rd, 'rt, 'sa");
+ }
+ break;
+ }
+ case JR: {
+ ASSERT(instr->RtField() == R0);
+ ASSERT(instr->RdField() == R0);
+ ASSERT(!delay_slot_);
+ // Format(instr, "jr'hint 'rs");
+ uword next_pc = get_register(instr->RsField());
+ ExecuteDelaySlot();
+ pc_ = next_pc - Instr::kInstrSize; // Account for regular PC increment.
+ break;
+ }
+ default: {
+ OS::PrintErr("DecodeSpecial: 0x%x\n", instr->InstructionBits());
+ UNREACHABLE();
+ break;
+ }
+ }
+}
+
+void Simulator::InstructionDecode(Instr* instr) {
+ switch (instr->OpcodeField()) {
+ case SPECIAL: {
+ DecodeSpecial(instr);
+ break;
+ }
+ case ORI: {
+ // Format(instr, "ori 'rt, 'rs, 'imm");
+ int32_t rs_val = get_register(instr->RsField());
+ set_register(instr->RtField(), rs_val | instr->ImmField());
regis 2013/03/06 21:18:42 The immediate field should be zero extended, i.e.
Ivan Posva 2013/03/07 11:03:22 The result of ImmField() is already unsigned.
+ break;
+ }
+ default: {
+ OS::PrintErr("Undecoded instruction: 0x%x\n", instr->InstructionBits());
+ UNREACHABLE();
+ break;
+ }
+ }
+ pc_ += Instr::kInstrSize;
+}
+
+
+void Simulator::ExecuteDelaySlot() {
+ ASSERT(pc_ != kEndSimulatingPC);
+ delay_slot_ = true;
+ icount_++;
+ if (icount_ == FLAG_stop_sim_at) {
+ UNIMPLEMENTED();
+ }
+ Instr* instr = Instr::At(pc_ + Instr::kInstrSize);
+ InstructionDecode(instr);
+ delay_slot_ = false;
+}
+
+
+void Simulator::Execute() {
+ if (FLAG_stop_sim_at == 0) {
+ // Fast version of the dispatch loop without checking whether the simulator
+ // should be stopping at a particular executed instruction.
+ while (pc_ != kEndSimulatingPC) {
+ icount_++;
+ Instr* instr = Instr::At(pc_);
+ InstructionDecode(instr);
+ }
+ } else {
+ // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
+ // we reach the particular instruction count.
+ while (pc_ != kEndSimulatingPC) {
+ icount_++;
+ if (icount_ == FLAG_stop_sim_at) {
+ UNIMPLEMENTED();
+ } else {
+ Instr* instr = Instr::At(pc_);
+ InstructionDecode(instr);
+ }
+ }
+ }
+}
+
+
int64_t Simulator::Call(int32_t entry,
int32_t parameter0,
int32_t parameter1,
int32_t parameter2,
- int32_t parameter3,
- int32_t parameter4) {
- UNIMPLEMENTED();
- return 0LL;
+ int32_t parameter3) {
+ // Save the SP register before the call so we can restore it.
+ int32_t sp_before_call = get_register(SP);
+
+ // Setup parameters.
+ set_register(A0, parameter0);
+ set_register(A1, parameter1);
+ set_register(A2, parameter2);
+ set_register(A3, parameter3);
+
+ // Make sure the activation frames are properly aligned.
+ int32_t stack_pointer = sp_before_call;
+ static const int kFrameAlignment = OS::ActivationFrameAlignment();
+ if (kFrameAlignment > 0) {
+ stack_pointer = Utils::RoundDown(stack_pointer, kFrameAlignment);
+ }
+ set_register(SP, stack_pointer);
+
+ // Prepare to execute the code at entry.
+ set_pc(entry);
+ // Put down marker for end of simulation. The simulator will stop simulation
+ // when the PC reaches this value. By saving the "end simulation" value into
+ // RA the simulation stops when returning to this call point.
+ set_register(RA, kEndSimulatingPC);
+
+ // Remember the values of callee-saved registers.
+ // The code below assumes that r9 is not used as sb (static base) in
+ // simulator code and therefore is regarded as a callee-saved register.
+ int32_t r16_val = get_register(R16);
+ int32_t r17_val = get_register(R17);
+ int32_t r18_val = get_register(R18);
+ int32_t r19_val = get_register(R19);
+ int32_t r20_val = get_register(R20);
+ int32_t r21_val = get_register(R21);
+ int32_t r22_val = get_register(R22);
+ int32_t r23_val = get_register(R23);
+
+ // Setup the callee-saved registers with a known value. To be able to check
+ // that they are preserved properly across dart execution.
+ int32_t callee_saved_value = icount_;
+ set_register(R16, callee_saved_value);
+ set_register(R17, callee_saved_value);
+ set_register(R18, callee_saved_value);
+ set_register(R19, callee_saved_value);
+ set_register(R20, callee_saved_value);
+ set_register(R21, callee_saved_value);
+ set_register(R22, callee_saved_value);
+ set_register(R23, callee_saved_value);
+
+ // Start the simulation
+ Execute();
+
+ // Check that the callee-saved registers have been preserved.
+ ASSERT(callee_saved_value == get_register(R16));
+ ASSERT(callee_saved_value == get_register(R17));
+ ASSERT(callee_saved_value == get_register(R18));
+ ASSERT(callee_saved_value == get_register(R19));
+ ASSERT(callee_saved_value == get_register(R20));
+ ASSERT(callee_saved_value == get_register(R21));
+ ASSERT(callee_saved_value == get_register(R22));
+ ASSERT(callee_saved_value == get_register(R23));
+
+ // Restore callee-saved registers with the original value.
+ set_register(R16, r16_val);
+ set_register(R17, r17_val);
+ set_register(R18, r18_val);
+ set_register(R19, r19_val);
+ set_register(R20, r20_val);
+ set_register(R21, r21_val);
+ set_register(R22, r22_val);
+ set_register(R23, r23_val);
+
+ // Restore the SP register and return R1:R0.
+ set_register(SP, sp_before_call);
+ return Utils::LowHighTo64Bits(get_register(V0), get_register(V1));
}
} // namespace dart

Powered by Google App Engine
This is Rietveld 408576698