📄 simulator-arm.cc.svn-base
字号:
} break; } case EOR: { // Format(instr, "eor'cond's 'rd, 'rn, 'shift_rm"); // Format(instr, "eor'cond's 'rd, 'rn, 'imm"); alu_out = rn_val ^ shifter_operand; set_register(rd, alu_out); if (instr->HasS()) { SetNZFlags(alu_out); SetCFlag(shifter_carry_out); } break; } case SUB: { // Format(instr, "sub'cond's 'rd, 'rn, 'shift_rm"); // Format(instr, "sub'cond's 'rd, 'rn, 'imm"); alu_out = rn_val - shifter_operand; set_register(rd, alu_out); if (instr->HasS()) { SetNZFlags(alu_out); SetCFlag(!BorrowFrom(rn_val, shifter_operand)); SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false)); } break; } case RSB: { // Format(instr, "rsb'cond's 'rd, 'rn, 'shift_rm"); // Format(instr, "rsb'cond's 'rd, 'rn, 'imm"); alu_out = shifter_operand - rn_val; set_register(rd, alu_out); if (instr->HasS()) { SetNZFlags(alu_out); SetCFlag(!BorrowFrom(shifter_operand, rn_val)); SetVFlag(OverflowFrom(alu_out, shifter_operand, rn_val, false)); } break; } case ADD: { // Format(instr, "add'cond's 'rd, 'rn, 'shift_rm"); // Format(instr, "add'cond's 'rd, 'rn, 'imm"); alu_out = rn_val + shifter_operand; set_register(rd, alu_out); if (instr->HasS()) { SetNZFlags(alu_out); SetCFlag(CarryFrom(rn_val, shifter_operand)); SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true)); } break; } case ADC: { Format(instr, "adc'cond's 'rd, 'rn, 'shift_rm"); Format(instr, "adc'cond's 'rd, 'rn, 'imm"); break; } case SBC: { Format(instr, "sbc'cond's 'rd, 'rn, 'shift_rm"); Format(instr, "sbc'cond's 'rd, 'rn, 'imm"); break; } case RSC: { Format(instr, "rsc'cond's 'rd, 'rn, 'shift_rm"); Format(instr, "rsc'cond's 'rd, 'rn, 'imm"); break; } case TST: { if (instr->HasS()) { // Format(instr, "tst'cond 'rn, 'shift_rm"); // Format(instr, "tst'cond 'rn, 'imm"); alu_out = rn_val & shifter_operand; SetNZFlags(alu_out); SetCFlag(shifter_carry_out); } else { UNIMPLEMENTED(); } break; } case TEQ: { if (instr->HasS()) { // Format(instr, "teq'cond 'rn, 'shift_rm"); // Format(instr, "teq'cond 'rn, 'imm"); alu_out = rn_val ^ shifter_operand; SetNZFlags(alu_out); SetCFlag(shifter_carry_out); } else { UNIMPLEMENTED(); } break; } case CMP: { if (instr->HasS()) { // Format(instr, "cmp'cond 'rn, 'shift_rm"); // Format(instr, "cmp'cond 'rn, 'imm"); alu_out = rn_val - shifter_operand; SetNZFlags(alu_out); SetCFlag(!BorrowFrom(rn_val, shifter_operand)); SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false)); } else { UNIMPLEMENTED(); } break; } case CMN: { if (instr->HasS()) { Format(instr, "cmn'cond 'rn, 'shift_rm"); Format(instr, "cmn'cond 'rn, 'imm"); } else { UNIMPLEMENTED(); } break; } case ORR: { // Format(instr, "orr'cond's 'rd, 'rn, 'shift_rm"); // Format(instr, "orr'cond's 'rd, 'rn, 'imm"); alu_out = rn_val | shifter_operand; set_register(rd, alu_out); if (instr->HasS()) { SetNZFlags(alu_out); SetCFlag(shifter_carry_out); } break; } case MOV: { // Format(instr, "mov'cond's 'rd, 'shift_rm"); // Format(instr, "mov'cond's 'rd, 'imm"); alu_out = shifter_operand; set_register(rd, alu_out); if (instr->HasS()) { SetNZFlags(alu_out); SetCFlag(shifter_carry_out); } break; } case BIC: { // Format(instr, "bic'cond's 'rd, 'rn, 'shift_rm"); // Format(instr, "bic'cond's 'rd, 'rn, 'imm"); alu_out = rn_val & ~shifter_operand; set_register(rd, alu_out); if (instr->HasS()) { SetNZFlags(alu_out); SetCFlag(shifter_carry_out); } break; } case MVN: { // Format(instr, "mvn'cond's 'rd, 'shift_rm"); // Format(instr, "mvn'cond's 'rd, 'imm"); alu_out = ~shifter_operand; set_register(rd, alu_out); if (instr->HasS()) { SetNZFlags(alu_out); SetCFlag(shifter_carry_out); } break; } default: { UNREACHABLE(); break; } } }}void Simulator::DecodeType2(Instr* instr) { int rd = instr->RdField(); int rn = instr->RnField(); int32_t rn_val = get_register(rn); int32_t im_val = instr->Offset12Field(); int32_t addr = 0; switch (instr->PUField()) { case 0: { // Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12"); ASSERT(!instr->HasW()); addr = rn_val; rn_val -= im_val; set_register(rn, rn_val); break; } case 1: { // Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12"); ASSERT(!instr->HasW()); addr = rn_val; rn_val += im_val; set_register(rn, rn_val); break; } case 2: { // Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w"); rn_val -= im_val; addr = rn_val; if (instr->HasW()) { set_register(rn, rn_val); } break; } case 3: { // Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w"); rn_val += im_val; addr = rn_val; if (instr->HasW()) { set_register(rn, rn_val); } break; } default: { UNREACHABLE(); break; } } if (instr->HasB()) { byte* baddr = reinterpret_cast<byte*>(addr); if (instr->HasL()) { byte val = *baddr; set_register(rd, val); } else { byte val = get_register(rd); *baddr = val; } } else { intptr_t* iaddr = reinterpret_cast<intptr_t*>(addr); if (instr->HasL()) { set_register(rd, *iaddr); } else { *iaddr = get_register(rd); } }}void Simulator::DecodeType3(Instr* instr) { int rd = instr->RdField(); int rn = instr->RnField(); int32_t rn_val = get_register(rn); bool shifter_carry_out = 0; int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out); int32_t addr = 0; switch (instr->PUField()) { case 0: { ASSERT(!instr->HasW()); Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm"); break; } case 1: { ASSERT(!instr->HasW()); Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm"); break; } case 2: { // Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w"); addr = rn_val - shifter_operand; if (instr->HasW()) { set_register(rn, addr); } break; } case 3: { // Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w"); addr = rn_val + shifter_operand; if (instr->HasW()) { set_register(rn, addr); } break; } default: { UNREACHABLE(); break; } } if (instr->HasB()) { UNIMPLEMENTED(); } else { intptr_t* iaddr = reinterpret_cast<intptr_t*>(addr); if (instr->HasL()) { set_register(rd, *iaddr); } else { *iaddr = get_register(rd); } }}void Simulator::DecodeType4(Instr* instr) { ASSERT(instr->Bit(22) == 0); // only allowed to be set in privileged mode if (instr->HasL()) { // Format(instr, "ldm'cond'pu 'rn'w, 'rlist"); HandleRList(instr, true); } else { // Format(instr, "stm'cond'pu 'rn'w, 'rlist"); HandleRList(instr, false); }}void Simulator::DecodeType5(Instr* instr) { // Format(instr, "b'l'cond 'target"); int off = (instr->SImmed24Field() << 2) + 8; intptr_t pc = get_pc(); if (instr->HasLink()) { set_register(lr, pc + Instr::kInstrSize); } set_pc(pc+off);}void Simulator::DecodeType6(Instr* instr) { UNIMPLEMENTED();}void Simulator::DecodeType7(Instr* instr) { if (instr->Bit(24) == 1) { // Format(instr, "swi 'swi"); SoftwareInterrupt(instr); } else { UNIMPLEMENTED(); }}// Executes the current instruction.void Simulator::InstructionDecode(Instr* instr) { pc_modified_ = false; if (instr->ConditionField() == special_condition) { Debugger dbg(this); dbg.Stop(instr); return; } if (::v8::internal::FLAG_trace_sim) { disasm::Disassembler dasm; // use a reasonably large buffer v8::internal::EmbeddedVector<char, 256> buffer; dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr)); PrintF(" 0x%x %s\n", instr, buffer.start()); } if (ConditionallyExecute(instr)) { switch (instr->TypeField()) { case 0: case 1: { DecodeType01(instr); break; } case 2: { DecodeType2(instr); break; } case 3: { DecodeType3(instr); break; } case 4: { DecodeType4(instr); break; } case 5: { DecodeType5(instr); break; } case 6: { DecodeType6(instr); break; } case 7: { DecodeType7(instr); break; } default: { UNIMPLEMENTED(); break; } } } if (!pc_modified_) { set_register(pc, reinterpret_cast<int32_t>(instr) + Instr::kInstrSize); }}//void Simulator::execute() { // Get the PC to simulate. Cannot use the accessor here as we need the // raw PC value and not the one used as input to arithmetic instructions. int program_counter = get_pc(); if (::v8::internal::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 (program_counter != end_sim_pc) { Instr* instr = reinterpret_cast<Instr*>(program_counter); icount_++; InstructionDecode(instr); program_counter = get_pc(); } } else { // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when // we reach the particular instuction count. while (program_counter != end_sim_pc) { Instr* instr = reinterpret_cast<Instr*>(program_counter); icount_++; if (icount_ == ::v8::internal::FLAG_stop_sim_at) { Debugger dbg(this); dbg.Debug(); } else { InstructionDecode(instr); } program_counter = get_pc(); } }}Object* Simulator::call(int32_t entry, int32_t p0, int32_t p1, int32_t p2, int32_t p3, int32_t p4) { // Setup parameters set_register(r0, p0); set_register(r1, p1); set_register(r2, p2); set_register(r3, p3); intptr_t* stack_pointer = reinterpret_cast<intptr_t*>(get_register(sp)); *(--stack_pointer) = p4; set_register(sp, reinterpret_cast<int32_t>(stack_pointer)); // Prepare to execute the code at entry set_register(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 // the LR the simulation stops when returning to this call point. set_register(lr, end_sim_pc); // 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 r4_val = get_register(r4); int32_t r5_val = get_register(r5); int32_t r6_val = get_register(r6); int32_t r7_val = get_register(r7); int32_t r8_val = get_register(r8); int32_t r9_val = get_register(r9); int32_t r10_val = get_register(r10); int32_t r11_val = get_register(r11); // Setup the callee-saved registers with a known value. To be able to check // that they are preserved properly across JS execution. int32_t callee_saved_value = icount_; set_register(r4, callee_saved_value); set_register(r5, callee_saved_value); set_register(r6, callee_saved_value); set_register(r7, callee_saved_value); set_register(r8, callee_saved_value); set_register(r9, callee_saved_value); set_register(r10, callee_saved_value); set_register(r11, callee_saved_value); // Start the simulation execute(); // Check that the callee-saved registers have been preserved. CHECK_EQ(get_register(r4), callee_saved_value); CHECK_EQ(get_register(r5), callee_saved_value); CHECK_EQ(get_register(r6), callee_saved_value); CHECK_EQ(get_register(r7), callee_saved_value); CHECK_EQ(get_register(r8), callee_saved_value); CHECK_EQ(get_register(r9), callee_saved_value); CHECK_EQ(get_register(r10), callee_saved_value); CHECK_EQ(get_register(r11), callee_saved_value); // Restore callee-saved registers with the original value. set_register(r4, r4_val); set_register(r5, r5_val); set_register(r6, r6_val); set_register(r7, r7_val); set_register(r8, r8_val); set_register(r9, r9_val); set_register(r10, r10_val); set_register(r11, r11_val); int result = get_register(r0); return reinterpret_cast<Object*>(result);}} } // namespace assembler::arm#endif // !defined(__arm__)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -