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

Unified Diff: src/arm/simulator-arm.cc

Issue 651029: Forking disassembler and simulator for Thumb2 support; (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 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
« no previous file with comments | « src/arm/simulator-arm.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/arm/simulator-arm.cc
===================================================================
--- src/arm/simulator-arm.cc (revision 4001)
+++ src/arm/simulator-arm.cc (working copy)
@@ -240,10 +240,10 @@
"%" XSTR(ARG_SIZE) "s",
cmd, arg1, arg2);
if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
- sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc()));
+ sim_->InstructionDecode(sim_->get_pc());
} else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
// Execute the one instruction we broke at with breakpoints disabled.
- sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc()));
+ sim_->InstructionDecode(sim_->get_pc());
// Leave the debugger shell.
done = true;
} else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
@@ -404,6 +404,142 @@
}
+
+InstrThumb2::InstrThumb2(byte* pc)
+ : pc_(pc) {
+ instr0_ = *reinterpret_cast<uint16_t*>(Address());
+ if (instr0_ > kMax16BitThumbOpcode) {
+ instr1_ = *reinterpret_cast<uint16_t*>(
+ reinterpret_cast<uint32_t>(Address() + 2));
+ size_ = 4;
+ Decode32();
+ } else {
+ size_ = 2;
+ Decode16();
+ }
+}
+
+void InstrThumb2::Decode16() {
+ switch (instr0_ & 0xff80) { // bits 15 - 11
+ case B13:
+ Decode16_Rdn3Imm8(OP_CMP, VARIANT_IMMEDIATE);
+ break;
+ case B13 | B12:
+ Decode16_Rdn3Imm8(OP_ADD, VARIANT_IMMEDIATE);
+ break;
+ case B15 | B13 | B11:
+ Decode16_Rdn3Imm8(OP_ADD, VARIANT_SP_PLUS_IMMEDIATE);
+ break;
+ case B15 | B14 | B13:
+ Decode16_Imm11(OP_B, VARIANT_REGISTER);
+ break;
+ case B15 | B14 | B13 | B12 | B11:
+ Decode16_Imm11(OP_BL, VARIANT_IMMEDIATE);
+ break;
+ default:
+ UnsupportedInstruction();
+ }
+}
+
+void InstrThumb2::Decode32() {
+ switch (instr0_ & (0xff * B5)) {
+ case B11 | B9: // 01010000 * B5
+ Decode32_SRn4XImm3Rd4Imm2Type2Rm4(OP_AND, VARIANT_REGISTER);
+ DecodeImmShift();
+ break;
+ case B11 | B9 | B8: // 01011000 * B5
+ Decode32_SRn4XImm3Rd4Imm2Type2Rm4(OP_ADD, VARIANT_REGISTER);
+ DecodeImmShift();
+ break;
+ case B12 | B8 | B7 | B5: // 10x01101 * B5;
+ case B12 | B10 | B8 | B7 | B5: // B10 is part of Imm.
+ Decode32_ImmX5SRn4XImm3Rd4Imm8(OP_SUB, VARIANT_IMMEDIATE);
+ ThumbExpandImm();
+ break;
+
+ default:
+ UnsupportedInstruction();
+ }
+}
+
+void InstrThumb2::UnsupportedInstruction() {
+ if (size_ == 2) {
+ PrintF("Unsupported 16bit instruction %x\n", instr0_);
+ } else {
+ PrintF("Unsupported 32bit instruction %x:%x\n", instr0_, instr1_);
+ }
+ op_ = OP_UNSUPPORTED;
+}
+
+void InstrThumb2::Decode16_Rdn3Imm8(Operation op, OpVariant variant) {
+ op_ = op;
+ variant_ = variant;
+ s_ = AUTO;
+
+ imm_ = Bits0(7, 0);
+ rd_ = rn_ = Bits0(10, 8);
+}
+
+void InstrThumb2::Decode16_Imm11(Operation op, OpVariant variant) {
+ op_ = op;
+ variant_ = variant;
+ s_ = AUTO;
+
+ imm_ = Bits0(10, 0);
+}
+
+void InstrThumb2::Decode32_SRn4XImm3Rd4Imm2Type2Rm4(Operation op,
+ OpVariant variant) {
+ op_ = op;
+ variant_ = variant;
+
+ s_ = Bit0(4);
+ rn_ = Bits0(3, 0);
+ imm_ = Bits1(14, 12) * B2 | Bits1(7, 6);
+ rd_ = Bits1(11, 8);
+ type_ = Bits1(5, 4);
+ rm_ = Bits1(3, 0);
+}
+
+void InstrThumb2::Decode32_ImmX5SRn4XImm3Rd4Imm8(Operation op,
+ OpVariant variant) {
+ op_ = op;
+ variant_ = variant;
+
+ s_ = Bit0(4);
+ imm_ = Bit0(10) * B11 | Bits1(14, 12) * B8 | Bits1(7, 0);
+ rn_ = Bits0(3, 0);
+ rd_ = Bits1(11, 8);
+}
+
+void InstrThumb2::DecodeImmShift() {
+ if (imm_ == 0) {
+ switch (type_) {
+ case LSL:
+ type_ = no_shift;
+ break;
+ case ASR:
+ case LSR:
+ imm_ = 32;
+ break;
+ case ROR:
+ type_ = RRX;
+ imm_ = 1;
+ break;
+ default:
+ UnsupportedInstruction();
+ }
+ }
+}
+
+void InstrThumb2::ThumbExpandImm() {
+ if (imm_ > 255) {
+ // TODO(haustein) Support thumb2 immediate shift here..
+ UnsupportedInstruction();
+ }
+}
+
+
// Create one simulator per thread and keep it in thread local storage.
static v8::internal::Thread::LocalStorageKey simulator_key;
@@ -466,6 +602,7 @@
// access violation if the simulator ever tries to execute it.
registers_[pc] = bad_lr;
registers_[lr] = bad_lr;
+
InitializeCoverage();
}
@@ -557,7 +694,11 @@
// the special case of accessing the PC register.
int32_t Simulator::get_register(int reg) const {
ASSERT((reg >= 0) && (reg < num_registers));
- return registers_[reg] + ((reg == pc) ? Instr::kPCReadOffset : 0);
+ if (reg == pc) {
+ return registers_[reg] + (InThumbMode() ? Instr::kPCReadOffsetThumb
+ : Instr::kPCReadOffset);
+ }
+ return registers_[reg];
}
@@ -2110,18 +2251,139 @@
}
-// Executes the current instruction.
-void Simulator::InstructionDecode(Instr* instr) {
- pc_modified_ = false;
+void Simulator::InstructionDecode(int32_t adr) {
if (::v8::internal::FLAG_trace_sim) {
disasm::NameConverter converter;
disasm::Disassembler dasm(converter);
// use a reasonably large buffer
v8::internal::EmbeddedVector<char, 256> buffer;
dasm.InstructionDecode(buffer,
- reinterpret_cast<byte*>(instr));
- PrintF(" 0x%08x %s\n", instr, buffer.start());
+ reinterpret_cast<byte*>(adr));
+ PrintF(" 0x%08x %s\n", adr, buffer.start());
}
+ if ((adr & 1) == 1) {
+ InstructionDecodeThumb2(reinterpret_cast<byte*>(adr));
+ } else {
+ InstructionDecodeArm(reinterpret_cast<Instr*>(adr));
+ }
+}
+
+int32_t Simulator::GetOperand2(const InstrThumb2& instr, bool* carry_out) {
+ switch (instr.Variant()) {
+ case VARIANT_IMMEDIATE:
+ return instr.Imm();
+
+ case VARIANT_REGISTER:
+ return GetRmShiftImm(instr, carry_out);
+
+ default:
+ UNIMPLEMENTED();
+ return -1;
+ }
+}
+
+int32_t Simulator::GetRmShiftImm(const InstrThumb2& instr, bool* carry_out) {
+ Shift shift = (Shift) instr.Type();
+ int shift_amount = instr.Imm();
+ int32_t result = get_register(instr.Rm());
+
+ switch (shift) {
+ case no_shift:
+ break;
+
+ case ASR: {
+ ASSERT(shift_amount > 0);
+ result >>= (shift_amount - 1);
+ *carry_out = (result & 1) == 1;
+ result >>= 1;
+ break;
+ }
+
+ case LSL: {
+ ASSERT(shift_amount > 0);
+ result <<= (shift_amount - 1);
+ *carry_out = (result < 0);
+ result <<= 1;
+ break;
+ }
+
+ case LSR: {
+ uint32_t uresult = static_cast<uint32_t>(result);
+ ASSERT(shift_amount > 0);
+ uresult >>= (shift_amount - 1);
+ *carry_out = (uresult & 1) == 1;
+ uresult >>= 1;
+ result = static_cast<int32_t>(uresult);
+ break;
+ }
+
+ case RRX:
+ case ROR: {
+ UNIMPLEMENTED();
+ break;
+ }
+
+ default: {
+ UNREACHABLE();
+ break;
+ }
+ }
+ return result;
+}
+
+
+
+void Simulator::InstructionDecodeThumb2(byte* adr) {
+ pc_modified_ = false;
+ InstrThumb2 instr(adr);
+ bool shifter_carry_out = 0;
+ int32_t alu_out;
+ int32_t operand2;
+
+ int32_t rn_val = get_register(instr.Rn());
+ switch (instr.Op()) {
+ case OP_AND:
+ alu_out = rn_val & GetOperand2(instr, &shifter_carry_out);
+ set_register(instr.Rd(), alu_out);
+ if (instr.HasS()) {
+ SetNZFlags(alu_out);
+ SetCFlag(shifter_carry_out);
+ }
+ break;
+ case OP_ADD:
+ operand2 = GetOperand2(instr, &shifter_carry_out);
+ alu_out = rn_val + operand2;
+ set_register(instr.Rd(), alu_out);
+ if (instr.HasS()) {
+ SetNZFlags(alu_out);
+ SetCFlag(CarryFrom(rn_val, operand2));
+ SetVFlag(OverflowFrom(alu_out, rn_val, operand2, true));
+ }
+ break;
+
+ case OP_SUB:
+ operand2 = GetOperand2(instr, &shifter_carry_out);
+ alu_out = rn_val - operand2;
+ set_register(instr.Rd(), alu_out);
+ if (instr.HasS()) {
+ SetNZFlags(alu_out);
+ SetCFlag(!BorrowFrom(rn_val, operand2));
+ SetVFlag(OverflowFrom(alu_out, rn_val, operand2, false));
+ }
+ break;
+
+ default:
+ PrintF("Unrecogized Thumb Instruction");
+ UNIMPLEMENTED();
+ }
+ if (!pc_modified_) {
+ set_register(pc, reinterpret_cast<int32_t>(adr) + instr.Size());
+ }
+}
+
+// Executes the current instruction.
+void Simulator::InstructionDecodeArm(Instr* instr) {
+ pc_modified_ = false;
if (instr->ConditionField() == special_condition) {
DecodeUnconditional(instr);
} else if (ConditionallyExecute(instr)) {
@@ -2176,22 +2438,20 @@
// 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);
+ InstructionDecode(program_counter);
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);
+ InstructionDecode(program_counter);
}
program_counter = get_pc();
}
« no previous file with comments | « src/arm/simulator-arm.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698