Revision: 5723
Author: [email protected]
Date: Thu Oct 28 00:35:07 2010
Log: Landing for Rodolph Perfetta.
Fix the ARM simulator, the ARM disassembler and extend the stop feature.
The stop feature in the simulator now support enabling, disabling and
counting.
BUG=None
TEST=None
http://code.google.com/p/v8/source/detail?r=5723
Modified:
/branches/bleeding_edge/src/arm/assembler-arm.cc
/branches/bleeding_edge/src/arm/assembler-arm.h
/branches/bleeding_edge/src/arm/constants-arm.h
/branches/bleeding_edge/src/arm/cpu-arm.cc
/branches/bleeding_edge/src/arm/disasm-arm.cc
/branches/bleeding_edge/src/arm/simulator-arm.cc
/branches/bleeding_edge/src/arm/simulator-arm.h
=======================================
--- /branches/bleeding_edge/src/arm/assembler-arm.cc Thu Aug 26 01:53:00
2010
+++ /branches/bleeding_edge/src/arm/assembler-arm.cc Thu Oct 28 00:35:07
2010
@@ -1004,7 +1004,7 @@
int h = ((branch_offset & 2) >> 1)*B24;
int imm24 = branch_offset >> 2;
ASSERT(is_int24(imm24));
- emit(15 << 28 | B27 | B25 | h | (imm24 & Imm24Mask));
+ emit(nv | B27 | B25 | h | (imm24 & Imm24Mask));
}
@@ -1634,15 +1634,29 @@
// Exception-generating instructions and debugging support.
-void Assembler::stop(const char* msg) {
+// Stops with a non-negative code less than kNumOfWatchedStops support
+// enabling/disabling and a counter feature. See simulator-arm.h .
+void Assembler::stop(const char* msg, Condition cond, int32_t code) {
#ifndef __arm__
- // The simulator handles these special instructions and stops execution.
- emit(15 << 28 | ((intptr_t) msg));
+ // See constants-arm.h SoftwareInterruptCodes. Unluckily the Assembler
and
+ // Simulator do not share constants declaration.
+ ASSERT(code >= kDefaultStopCode);
+ static const uint32_t kStopInterruptCode = 1 << 23;
+ static const uint32_t kMaxStopCode = kStopInterruptCode - 1;
+ // The Simulator will handle the stop instruction and get the message
address.
+ // It expects to find the address just after the svc instruction.
+ BlockConstPoolFor(2);
+ if (code >= 0) {
+ svc(kStopInterruptCode + code, cond);
+ } else {
+ svc(kStopInterruptCode + kMaxStopCode, cond);
+ }
+ emit(reinterpret_cast<Instr>(msg));
#else // def __arm__
#ifdef CAN_USE_ARMV5_INSTRUCTIONS
bkpt(0);
#else // ndef CAN_USE_ARMV5_INSTRUCTIONS
- swi(0x9f0001);
+ svc(0x9f0001);
#endif // ndef CAN_USE_ARMV5_INSTRUCTIONS
#endif // def __arm__
}
@@ -1654,7 +1668,7 @@
}
-void Assembler::swi(uint32_t imm24, Condition cond) {
+void Assembler::svc(uint32_t imm24, Condition cond) {
ASSERT(is_uint24(imm24));
emit(cond | 15*B24 | imm24);
}
=======================================
--- /branches/bleeding_edge/src/arm/assembler-arm.h Fri Sep 24 01:25:31 2010
+++ /branches/bleeding_edge/src/arm/assembler-arm.h Thu Oct 28 00:35:07 2010
@@ -904,10 +904,13 @@
void stm(BlockAddrMode am, Register base, RegList src, Condition cond =
al);
// Exception-generating instructions and debugging support
- void stop(const char* msg);
+ static const int kDefaultStopCode = -1;
+ void stop(const char* msg,
+ Condition cond = al,
+ int32_t code = kDefaultStopCode);
void bkpt(uint32_t imm16); // v5 and above
- void swi(uint32_t imm24, Condition cond = al);
+ void svc(uint32_t imm24, Condition cond = al);
// Coprocessor instructions
=======================================
--- /branches/bleeding_edge/src/arm/constants-arm.h Thu Aug 26 01:53:00 2010
+++ /branches/bleeding_edge/src/arm/constants-arm.h Thu Oct 28 00:35:07 2010
@@ -186,12 +186,18 @@
// Special Software Interrupt codes when used in the presence of the ARM
// simulator.
+// svc (formerly swi) provides a 24bit immediate value. Use bits 22:0 for
+// standard SoftwareInterrupCode. Bit 23 is reserved for the stop feature.
enum SoftwareInterruptCodes {
// transition to C code
call_rt_redirected = 0x10,
// break point
- break_point = 0x20
+ break_point = 0x20,
+ // stop
+ stop = 1 << 23
};
+static const int32_t kStopCodeMask = stop - 1;
+static const uint32_t kMaxStopCode = stop - 1;
// Type of VFP register. Determines register encoding.
@@ -325,7 +331,7 @@
inline int SImmed24Field() const { return ((InstructionBits() << 8) >>
8); }
// Fields used in Software interrupt instructions
- inline SoftwareInterruptCodes SwiField() const {
+ inline SoftwareInterruptCodes SvcField() const {
return static_cast<SoftwareInterruptCodes>(Bits(23, 0));
}
=======================================
--- /branches/bleeding_edge/src/arm/cpu-arm.cc Mon Oct 25 09:40:41 2010
+++ /branches/bleeding_edge/src/arm/cpu-arm.cc Thu Oct 28 00:35:07 2010
@@ -70,7 +70,7 @@
// __arm__ may be defined in thumb mode.
register uint32_t scno asm("r7") = __ARM_NR_cacheflush;
asm volatile(
- "swi 0x0"
+ "svc 0x0"
: "=r" (beg)
: "0" (beg), "r" (end), "r" (flg), "r" (scno));
#else
@@ -83,7 +83,7 @@
".ARM \n"
"1: push {r7} \n\t"
"mov r7, %4 \n\t"
- "swi 0x0 \n\t"
+ "svc 0x0 \n\t"
"pop {r7} \n\t"
"@ Enter THUMB Mode\n\t"
"adr r3, 2f+1 \n\t"
@@ -98,20 +98,20 @@
#if defined (__arm__) && !defined(__thumb__)
// __arm__ may be defined in thumb mode.
asm volatile(
- "swi %1"
+ "svc %1"
: "=r" (beg)
: "i" (__ARM_NR_cacheflush), "0" (beg), "r" (end), "r" (flg));
#else
// Do not use the value of __ARM_NR_cacheflush in the inline assembly
// below, because the thumb mode value would be used, which would be
- // wrong, since we switch to ARM mode before executing the swi
instruction
+ // wrong, since we switch to ARM mode before executing the svc
instruction
asm volatile(
"@ Enter ARM Mode \n\t"
"adr r3, 1f \n\t"
"bx r3 \n\t"
".ALIGN 4 \n\t"
".ARM \n"
- "1: swi 0x9f0002 \n"
+ "1: svc 0x9f0002 \n"
"@ Enter THUMB Mode\n\t"
"adr r3, 2f+1 \n\t"
"bx r3 \n\t"
=======================================
--- /branches/bleeding_edge/src/arm/disasm-arm.cc Thu Aug 26 01:53:00 2010
+++ /branches/bleeding_edge/src/arm/disasm-arm.cc Thu Oct 28 00:35:07 2010
@@ -108,7 +108,7 @@
void PrintShiftImm(Instr* instr);
void PrintShiftSat(Instr* instr);
void PrintPU(Instr* instr);
- void PrintSoftwareInterrupt(SoftwareInterruptCodes swi);
+ void PrintSoftwareInterrupt(SoftwareInterruptCodes svc);
// Handle formatting of instructions and their options.
int FormatRegister(Instr* instr, const char* option);
@@ -126,8 +126,8 @@
void DecodeType4(Instr* instr);
void DecodeType5(Instr* instr);
void DecodeType6(Instr* instr);
- void DecodeType7(Instr* instr);
- void DecodeUnconditional(Instr* instr);
+ // Type 7 includes special Debugger instructions.
+ int DecodeType7(Instr* instr);
// For VFP support.
void DecodeTypeVFP(Instr* instr);
void DecodeType6CoprocessorIns(Instr* instr);
@@ -290,8 +290,8 @@
// Print SoftwareInterrupt codes. Factoring this out reduces the
complexity of
// the FormatOption method.
-void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes swi) {
- switch (swi) {
+void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes svc) {
+ switch (svc) {
case call_rt_redirected:
Print("call_rt_redirected");
return;
@@ -299,9 +299,16 @@
Print("break_point");
return;
default:
- out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
- "%d",
- swi);
+ if (svc >= stop) {
+ out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+ "%d - 0x%x",
+ svc & kStopCodeMask,
+ svc & kStopCodeMask);
+ } else {
+ out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+ "%d",
+ svc);
+ }
return;
}
}
@@ -553,9 +560,9 @@
PrintShiftRm(instr);
return 8;
}
- } else if (format[1] == 'w') { // 'swi
- ASSERT(STRING_STARTS_WITH(format, "swi"));
- PrintSoftwareInterrupt(instr->SwiField());
+ } else if (format[1] == 'v') { // 'svc
+ ASSERT(STRING_STARTS_WITH(format, "svc"));
+ PrintSoftwareInterrupt(instr->SvcField());
return 3;
} else if (format[1] == 'i') { // 'sign: signed extra loads and
stores
ASSERT(STRING_STARTS_WITH(format, "sign"));
@@ -1004,74 +1011,29 @@
}
-void Decoder::DecodeType7(Instr* instr) {
+int Decoder::DecodeType7(Instr* instr) {
if (instr->Bit(24) == 1) {
- Format(instr, "swi'cond 'swi");
+ if (instr->SvcField() >= stop) {
+ Format(instr, "stop'cond 'svc");
+ // Also print the stop message. Its address is encoded
+ // in the following 4 bytes.
+ out_buffer_pos_ +=
+ v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+ "\n %p %08x stop message: %s",
+ reinterpret_cast<int32_t*>(instr +
Instr::kInstrSize),
+ *reinterpret_cast<char**>(instr +
Instr::kInstrSize),
+ *reinterpret_cast<char**>(instr +
Instr::kInstrSize));
+ // We have decoded 2 * Instr::kInstrSize bytes.
+ return 2 * Instr::kInstrSize;
+ } else {
+ Format(instr, "svc'cond 'svc");
+ }
} else {
DecodeTypeVFP(instr);
}
+ return Instr::kInstrSize;
}
-void Decoder::DecodeUnconditional(Instr* instr) {
- if (instr->Bits(7, 4) == 0xB && instr->Bits(27, 25) == 0 &&
instr->HasL()) {
- Format(instr, "'memop'h'pu 'rd, ");
- bool immediate = instr->HasB();
- switch (instr->PUField()) {
- case 0: {
- // Post index, negative.
- if (instr->HasW()) {
- Unknown(instr);
- break;
- }
- if (immediate) {
- Format(instr, "['rn], #-'imm12");
- } else {
- Format(instr, "['rn], -'rm");
- }
- break;
- }
- case 1: {
- // Post index, positive.
- if (instr->HasW()) {
- Unknown(instr);
- break;
- }
- if (immediate) {
- Format(instr, "['rn], #+'imm12");
- } else {
- Format(instr, "['rn], +'rm");
- }
- break;
- }
- case 2: {
- // Pre index or offset, negative.
- if (immediate) {
- Format(instr, "['rn, #-'imm12]'w");
- } else {
- Format(instr, "['rn, -'rm]'w");
- }
- break;
- }
- case 3: {
- // Pre index or offset, positive.
- if (immediate) {
- Format(instr, "['rn, #+'imm12]'w");
- } else {
- Format(instr, "['rn, +'rm]'w");
- }
- break;
- }
- default: {
- // The PU field is a 2-bit field.
- UNREACHABLE();
- break;
- }
- }
- return;
- }
- Format(instr, "break 'msg");
-}
-
// void Decoder::DecodeTypeVFP(Instr* instr)
// vmov: Sn = Rt
@@ -1332,7 +1294,7 @@
"%08x ",
instr->InstructionBits());
if (instr->ConditionField() == special_condition) {
- DecodeUnconditional(instr);
+ UNIMPLEMENTED();
return Instr::kInstrSize;
}
switch (instr->TypeField()) {
@@ -1362,8 +1324,7 @@
break;
}
case 7: {
- DecodeType7(instr);
- break;
+ return DecodeType7(instr);
}
default: {
// The type field is 3-bits in the ARM encoding.
=======================================
--- /branches/bleeding_edge/src/arm/simulator-arm.cc Mon Oct 25 09:40:41
2010
+++ /branches/bleeding_edge/src/arm/simulator-arm.cc Thu Oct 28 00:35:07
2010
@@ -112,15 +112,29 @@
void Debugger::Stop(Instr* instr) {
- char* str = reinterpret_cast<char*>(instr->InstructionBits() &
0x0fffffff);
- if (strlen(str) > 0) {
+ // Get the stop code.
+ uint32_t code = instr->SvcField() & kStopCodeMask;
+ // Retrieve the encoded address, which comes just after this stop.
+ char** msg_address =
+ reinterpret_cast<char**>(sim_->get_pc() + Instr::kInstrSize);
+ char* msg = *msg_address;
+ ASSERT(msg != NULL);
+
+ // Update this stop description.
+ if (isWatchedStop(code) && !watched_stops[code].desc) {
+ watched_stops[code].desc = msg;
+ }
+
+ if (strlen(msg) > 0) {
if (coverage_log != NULL) {
- fprintf(coverage_log, "%s\n", str);
+ fprintf(coverage_log, "%s\n", msg);
fflush(coverage_log);
}
- instr->SetInstructionBits(0xe1a00000); // Overwrite with nop.
- }
- sim_->set_pc(sim_->get_pc() + Instr::kInstrSize);
+ // Overwrite the instruction and address with nops.
+ instr->SetInstructionBits(kNopInstr);
+ reinterpret_cast<Instr*>(msg_address)->SetInstructionBits(kNopInstr);
+ }
+ sim_->set_pc(sim_->get_pc() + 2 * Instr::kInstrSize);
}
#else // ndef GENERATED_CODE_COVERAGE
@@ -130,9 +144,16 @@
void Debugger::Stop(Instr* instr) {
- const char* str = (const char*)(instr->InstructionBits() & 0x0fffffff);
- PrintF("Simulator hit %s\n", str);
- sim_->set_pc(sim_->get_pc() + Instr::kInstrSize);
+ // Get the stop code.
+ uint32_t code = instr->SvcField() & kStopCodeMask;
+ // Retrieve the encoded address, which comes just after this stop.
+ char* msg = *reinterpret_cast<char**>(sim_->get_pc() +
Instr::kInstrSize);
+ // Update this stop description.
+ if (sim_->isWatchedStop(code) && !sim_->watched_stops[code].desc) {
+ sim_->watched_stops[code].desc = msg;
+ }
+ PrintF("Simulator hit %s\n", msg);
+ sim_->set_pc(sim_->get_pc() + 2 * Instr::kInstrSize);
Debug();
}
#endif
@@ -359,6 +380,7 @@
// use a reasonably large buffer
v8::internal::EmbeddedVector<char, 256> buffer;
+ byte* prev = NULL;
byte* cur = NULL;
byte* end = NULL;
@@ -368,9 +390,9 @@
} else if (argc == 2) {
int32_t value;
if (GetValue(arg1, &value)) {
- cur = reinterpret_cast<byte*>(value);
- // no length parameter passed, assume 10 instructions
- end = cur + (10 * Instr::kInstrSize);
+ cur = reinterpret_cast<byte*>(sim_->get_pc());
+ // Disassemble <arg1> instructions.
+ end = cur + (value * Instr::kInstrSize);
}
} else {
int32_t value1;
@@ -382,10 +404,10 @@
}
while (cur < end) {
- dasm.InstructionDecode(buffer, cur);
+ prev = cur;
+ cur += dasm.InstructionDecode(buffer, cur);
PrintF(" 0x%08x %s\n",
- reinterpret_cast<intptr_t>(cur), buffer.start());
- cur += Instr::kInstrSize;
+ reinterpret_cast<intptr_t>(prev), buffer.start());
}
} else if (strcmp(cmd, "gdb") == 0) {
PrintF("relinquishing control to gdb\n");
@@ -418,13 +440,58 @@
PrintF("OVERFLOW flag: %d; ", sim_->overflow_vfp_flag_);
PrintF("UNDERFLOW flag: %d; ", sim_->underflow_vfp_flag_);
PrintF("INEXACT flag: %d; ", sim_->inexact_vfp_flag_);
- } else if (strcmp(cmd, "unstop") == 0) {
- intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize;
+ } else if (strcmp(cmd, "stop") == 0) {
+ int32_t value;
+ intptr_t stop_pc = sim_->get_pc() - 2 * Instr::kInstrSize;
Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc);
- if (stop_instr->ConditionField() == special_condition) {
- stop_instr->SetInstructionBits(kNopInstr);
+ Instr* msg_address =
+ reinterpret_cast<Instr*>(stop_pc + Instr::kInstrSize);
+ if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) {
+ // Remove the current stop.
+ if (sim_->isStopInstruction(stop_instr)) {
+ stop_instr->SetInstructionBits(kNopInstr);
+ msg_address->SetInstructionBits(kNopInstr);
+ } else {
+ PrintF("Not at debugger stop.\n");
+ }
+ } else if (argc == 3) {
+ // Print information about all/the specified breakpoint(s).
+ if (strcmp(arg1, "info") == 0) {
+ if (strcmp(arg2, "all") == 0) {
+ PrintF("Stop information:\n");
+ for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
+ sim_->PrintStopInfo(i);
+ }
+ } else if (GetValue(arg2, &value)) {
+ sim_->PrintStopInfo(value);
+ } else {
+ PrintF("Unrecognized argument.\n");
+ }
+ } else if (strcmp(arg1, "enable") == 0) {
+ // Enable all/the specified breakpoint(s).
+ if (strcmp(arg2, "all") == 0) {
+ for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
+ sim_->EnableStop(i);
+ }
+ } else if (GetValue(arg2, &value)) {
+ sim_->EnableStop(value);
+ } else {
+ PrintF("Unrecognized argument.\n");
+ }
+ } else if (strcmp(arg1, "disable") == 0) {
+ // Disable all/the specified breakpoint(s).
+ if (strcmp(arg2, "all") == 0) {
+ for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
+ sim_->DisableStop(i);
+ }
+ } else if (GetValue(arg2, &value)) {
+ sim_->DisableStop(value);
+ } else {
+ PrintF("Unrecognized argument.\n");
+ }
+ }
} else {
- PrintF("Not at debugger stop.");
+ PrintF("Wrong usage. Use help command for more information.\n");
}
} else if ((strcmp(cmd, "t") == 0) || strcmp(cmd, "trace") == 0) {
::v8::internal::FLAG_trace_sim = !::v8::internal::FLAG_trace_sim;
@@ -455,11 +522,29 @@
PrintF(" set a break point on the address\n");
PrintF("del\n");
PrintF(" delete the breakpoint\n");
- PrintF("unstop\n");
- PrintF(" ignore the stop instruction at the current location");
- PrintF(" from now on\n");
PrintF("trace (alias 't')\n");
PrintF(" toogle the tracing of all executed statements\n");
+ PrintF("stop feature:\n");
+ PrintF(" Description:\n");
+ PrintF(" Stops are debug instructions inserted by\n");
+ PrintF(" the Assembler::stop() function.\n");
+ PrintF(" When hitting a stop, the Simulator will\n");
+ PrintF(" stop and and give control to the Debugger.\n");
+ PrintF(" The first %d stop codes are watched:\n",
+ Simulator::kNumOfWatchedStops);
+ PrintF(" - They can be enabled / disabled: the Simulator\n");
+ PrintF(" will / won't stop when hitting them.\n");
+ PrintF(" - The Simulator keeps track of how many times they
\n");
+ PrintF(" are met. (See the info command.) Going over a\n");
+ PrintF(" disabled stop still increases its counter. \n");
+ PrintF(" Commands:\n");
+ PrintF(" stop info all/<code> : print infos about number
<code>\n");
+ PrintF(" or all stop(s).\n");
+ PrintF(" stop enable/disable all/<code> : enables /
disables\n");
+ PrintF(" all or number <code> stop(s)\n");
+ PrintF(" stop unstop\n");
+ PrintF(" ignore the stop instruction at the current
location\n");
+ PrintF(" from now on\n");
} else {
PrintF("Unknown command: %s\n", cmd);
}
@@ -643,9 +728,9 @@
// the simulator. The external reference will be a function compiled for
the
// host architecture. We need to call that function instead of trying to
// execute it with the simulator. We do that by redirecting the external
-// reference to a swi (software-interrupt) instruction that is handled by
+// reference to a svc (Supervisor Call) instruction that is handled by
// the simulator. We write the original destination of the jump just at a
known
-// offset from the swi instruction so the simulator knows what to call.
+// offset from the svc instruction so the simulator knows what to call.
class Redirection {
public:
Redirection(void* external_function, bool fp_return)
@@ -1434,8 +1519,8 @@
// Software interrupt instructions are used by the simulator to call into
the
// C-based V8 runtime.
void Simulator::SoftwareInterrupt(Instr* instr) {
- int swi = instr->SwiField();
- switch (swi) {
+ int svc = instr->SvcField();
+ switch (svc) {
case call_rt_redirected: {
// Check if stack is aligned. Error if not aligned is reported below
to
// include information on the function called.
@@ -1505,12 +1590,101 @@
dbg.Debug();
break;
}
+ // stop uses all codes greater than 1 << 23.
default: {
- UNREACHABLE();
- break;
+ if (svc >= (1 << 23)) {
+ uint32_t code = svc & kStopCodeMask;
+ if (isWatchedStop(code)) {
+ IncreaseStopCounter(code);
+ }
+ // Stop if it is enabled, otherwise go on jumping over the stop
+ // and the message address.
+ if (isEnabledStop(code)) {
+ Debugger dbg(this);
+ dbg.Stop(instr);
+ } else {
+ set_pc(get_pc() + 2 * Instr::kInstrSize);
+ }
+ } else {
+ // This is not a valid svc code.
+ UNREACHABLE();
+ break;
+ }
}
}
}
+
+
+// Stop helper functions.
+bool Simulator::isStopInstruction(Instr* instr) {
+ return (instr->Bits(27, 24) == 0xF) && (instr->SvcField() >= stop);
+}
+
+
+bool Simulator::isWatchedStop(uint32_t code) {
+ ASSERT(code <= kMaxStopCode);
+ return code < kNumOfWatchedStops;
+}
+
+
+bool Simulator::isEnabledStop(uint32_t code) {
+ ASSERT(code <= kMaxStopCode);
+ // Unwatched stops are always enabled.
+ return !isWatchedStop(code) ||
+ !(watched_stops[code].count & kStopDisabledBit);
+}
+
+
+void Simulator::EnableStop(uint32_t code) {
+ ASSERT(isWatchedStop(code));
+ if (!isEnabledStop(code)) {
+ watched_stops[code].count &= ~kStopDisabledBit;
+ }
+}
+
+
+void Simulator::DisableStop(uint32_t code) {
+ ASSERT(isWatchedStop(code));
+ if (isEnabledStop(code)) {
+ watched_stops[code].count |= kStopDisabledBit;
+ }
+}
+
+
+void Simulator::IncreaseStopCounter(uint32_t code) {
+ ASSERT(code <= kMaxStopCode);
+ ASSERT(isWatchedStop(code));
+ if ((watched_stops[code].count & ~(1 << 31)) == 0x7fffffff) {
+ PrintF("Stop counter for code %i has overflowed.\n"
+ "Enabling this code and reseting the counter to 0.\n", code);
+ watched_stops[code].count = 0;
+ EnableStop(code);
+ } else {
+ watched_stops[code].count++;
+ }
+}
+
+
+// Print a stop status.
+void Simulator::PrintStopInfo(uint32_t code) {
+ ASSERT(code <= kMaxStopCode);
+ if (!isWatchedStop(code)) {
+ PrintF("Stop not watched.");
+ } else {
+ const char* state = isEnabledStop(code) ? "Enabled" : "Disabled";
+ int32_t count = watched_stops[code].count & ~kStopDisabledBit;
+ // Don't print the state of unused breakpoints.
+ if (count != 0) {
+ if (watched_stops[code].desc) {
+ PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n",
+ code, code, state, count, watched_stops[code].desc);
+ } else {
+ PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n",
+ code, code, state, count);
+ }
+ }
+ }
+}
// Handle execution based on instruction types.
@@ -2214,73 +2388,6 @@
DecodeTypeVFP(instr);
}
}
-
-
-void Simulator::DecodeUnconditional(Instr* instr) {
- if (instr->Bits(7, 4) == 0x0B && instr->Bits(27, 25) == 0 &&
instr->HasL()) {
- // Load halfword instruction, either register or immediate offset.
- int rd = instr->RdField();
- int rn = instr->RnField();
- int32_t rn_val = get_register(rn);
- int32_t addr = 0;
- int32_t offset;
- if (instr->Bit(22) == 0) {
- // Register offset.
- int rm = instr->RmField();
- offset = get_register(rm);
- } else {
- // Immediate offset
- offset = instr->Bits(3, 0) + (instr->Bits(11, 8) << 4);
- }
- switch (instr->PUField()) {
- case 0: {
- // Post index, negative.
- ASSERT(!instr->HasW());
- addr = rn_val;
- rn_val -= offset;
- set_register(rn, rn_val);
- break;
- }
- case 1: {
- // Post index, positive.
- ASSERT(!instr->HasW());
- addr = rn_val;
- rn_val += offset;
- set_register(rn, rn_val);
- break;
- }
- case 2: {
- // Pre index or offset, negative.
- rn_val -= offset;
- addr = rn_val;
- if (instr->HasW()) {
- set_register(rn, rn_val);
- }
- break;
- }
- case 3: {
- // Pre index or offset, positive.
- rn_val += offset;
- addr = rn_val;
- if (instr->HasW()) {
- set_register(rn, rn_val);
- }
- break;
- }
- default: {
- // The PU field is a 2-bit field.
- UNREACHABLE();
- break;
- }
- }
- // Not sign extending, so load as unsigned.
- uint16_t halfword = ReadH(addr, instr);
- set_register(rd, halfword);
- } else {
- Debugger dbg(this);
- dbg.Stop(instr);
- }
-}
// void Simulator::DecodeTypeVFP(Instr* instr)
@@ -2655,7 +2762,7 @@
PrintF(" 0x%08x %s\n", reinterpret_cast<intptr_t>(instr),
buffer.start());
}
if (instr->ConditionField() == special_condition) {
- DecodeUnconditional(instr);
+ UNIMPLEMENTED();
} else if (ConditionallyExecute(instr)) {
switch (instr->TypeField()) {
case 0:
=======================================
--- /branches/bleeding_edge/src/arm/simulator-arm.h Mon Oct 25 09:40:41 2010
+++ /branches/bleeding_edge/src/arm/simulator-arm.h Thu Oct 28 00:35:07 2010
@@ -226,6 +226,15 @@
void HandleRList(Instr* instr, bool load);
void SoftwareInterrupt(Instr* instr);
+ // Stop helper functions.
+ inline bool isStopInstruction(Instr* instr);
+ inline bool isWatchedStop(uint32_t bkpt_code);
+ inline bool isEnabledStop(uint32_t bkpt_code);
+ inline void EnableStop(uint32_t bkpt_code);
+ inline void DisableStop(uint32_t bkpt_code);
+ inline void IncreaseStopCounter(uint32_t bkpt_code);
+ void PrintStopInfo(uint32_t code);
+
// Read and write memory.
inline uint8_t ReadBU(int32_t addr);
inline int8_t ReadB(int32_t addr);
@@ -252,7 +261,6 @@
void DecodeType5(Instr* instr);
void DecodeType6(Instr* instr);
void DecodeType7(Instr* instr);
- void DecodeUnconditional(Instr* instr);
// Support for VFP.
void DecodeTypeVFP(Instr* instr);
@@ -317,6 +325,23 @@
// Registered breakpoints.
Instr* break_pc_;
instr_t break_instr_;
+
+ // A stop is watched if its code is less than kNumOfWatchedStops.
+ // Only watched stops support enabling/disabling and the counter feature.
+ static const uint32_t kNumOfWatchedStops = 256;
+
+ // Breakpoint is disabled if bit 31 is set.
+ static const uint32_t kStopDisabledBit = 1 << 31;
+
+ // A stop is enabled, meaning the simulator will stop when meeting the
+ // instruction, if bit 31 of watched_stops[code].count is unset.
+ // The value watched_stops[code].count & ~(1 << 31) indicates how many
times
+ // the breakpoint was hit or gone through.
+ struct StopCoundAndDesc {
+ uint32_t count;
+ char* desc;
+ };
+ StopCoundAndDesc watched_stops[kNumOfWatchedStops];
};
} } // namespace assembler::arm
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev