Commit 64c61072 authored by sgjesse@chromium.org's avatar sgjesse@chromium.org

MIPS: Added the stop() instruction with same behavior as on Arm simulator.

The already working watchpoint break mechanism has been extended to handle "stop" instructions, with text messages.

Explanation (also in constants-mips.h):
On MIPS Simulator breakpoints can have different codes:
- Breaks between 0 and kMaxWatchpointCode are treated as simple watchpoints, the simulator will run through them and print the registers.
- Breaks between kMaxWatchpointCode and kMaxStopCode are treated as stop() instructions (see Assembler::stop()).
- Breaks larger than kMaxStopCode are simple breaks, dropping you into the debugger.

The current values are 31 for kMaxWatchpointCode and 127 for kMaxStopCode.
From the user's point of view this works the same way as the ARM stop instruction except for the break code usage detailed above.

Ported commits: r5723 (3ba78d24)

BUG=
TEST=

Review URL: http://codereview.chromium.org//7062014

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8069 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 02c4e8bf
......@@ -1336,13 +1336,37 @@ void Assembler::lui(Register rd, int32_t j) {
//-------------Misc-instructions--------------
// Break / Trap instructions.
void Assembler::break_(uint32_t code) {
void Assembler::break_(uint32_t code, bool break_as_stop) {
ASSERT((code & ~0xfffff) == 0);
// We need to invalidate breaks that could be stops as well because the
// simulator expects a char pointer after the stop instruction.
// See constants-mips.h for explanation.
ASSERT((break_as_stop &&
code <= kMaxStopCode &&
code > kMaxWatchpointCode) ||
(!break_as_stop &&
(code > kMaxStopCode ||
code <= kMaxWatchpointCode)));
Instr break_instr = SPECIAL | BREAK | (code << 6);
emit(break_instr);
}
void Assembler::stop(const char* msg, uint32_t code) {
ASSERT(code > kMaxWatchpointCode);
ASSERT(code <= kMaxStopCode);
#if defined(V8_HOST_ARCH_MIPS)
break_(0x54321);
#else // V8_HOST_ARCH_MIPS
BlockTrampolinePoolFor(2);
// The Simulator will handle the stop instruction and get the message address.
// On MIPS stop() is just a special kind of break_().
break_(code, true);
emit(reinterpret_cast<Instr>(msg));
#endif
}
void Assembler::tge(Register rs, Register rt, uint16_t code) {
ASSERT(is_uint10(code));
Instr instr = SPECIAL | TGE | rs.code() << kRsShift
......
......@@ -675,7 +675,8 @@ class Assembler : public AssemblerBase {
//-------------Misc-instructions--------------
// Break / Trap instructions.
void break_(uint32_t code);
void break_(uint32_t code, bool break_as_stop = false);
void stop(const char* msg, uint32_t code = kMaxStopCode);
void tge(Register rs, Register rt, uint16_t code);
void tgeu(Register rs, Register rt, uint16_t code);
void tlt(Register rs, Register rt, uint16_t code);
......
......@@ -158,6 +158,18 @@ enum SoftwareInterruptCodes {
call_rt_redirected = 0xfffff
};
// On MIPS Simulator breakpoints can have different codes:
// - Breaks between 0 and kMaxWatchpointCode are treated as simple watchpoints,
// the simulator will run through them and print the registers.
// - Breaks between kMaxWatchpointCode and kMaxStopCode are treated as stop()
// instructions (see Assembler::stop()).
// - Breaks larger than kMaxStopCode are simple breaks, dropping you into the
// debugger.
static const uint32_t kMaxWatchpointCode = 31;
static const uint32_t kMaxStopCode = 127;
STATIC_ASSERT(kMaxWatchpointCode < kMaxStopCode);
// ----- Fields offset and length.
static const int kOpcodeShift = 26;
static const int kOpcodeBits = 6;
......
......@@ -670,14 +670,6 @@ void MacroAssembler::li(Register rd, Operand j, bool gen2instr) {
}
// Exception-generating instructions and debugging support.
void MacroAssembler::stop(const char* msg) {
// TO_UPGRADE: Just a break for now. Maybe we could upgrade it.
// We use the 0x54321 value to be able to find it easily when reading memory.
break_(0x54321);
}
void MacroAssembler::MultiPush(RegList regs) {
int16_t NumSaved = 0;
int16_t NumToPush = NumberOfBitsSet(regs);
......
......@@ -459,9 +459,6 @@ DECLARE_NOTARGET_PROTOTYPE(Ret)
li(dst, Operand(value), gen2instr);
}
// Exception-generating instructions and debugging support.
void stop(const char* msg);
// Push multiple registers on the stack.
// Registers are saved in numerical order, with higher numbered registers
// saved in higher memory addresses.
......
This diff is collapsed.
......@@ -289,6 +289,18 @@ class Simulator {
// Used for breakpoints and traps.
void SoftwareInterrupt(Instruction* instr);
// Stop helper functions.
bool IsWatchpoint(uint32_t code);
void PrintWatchpoint(uint32_t code);
void HandleStop(uint32_t code, Instruction* instr);
bool IsStopInstruction(Instruction* instr);
bool IsEnabledStop(uint32_t code);
void EnableStop(uint32_t code);
void DisableStop(uint32_t code);
void IncreaseStopCounter(uint32_t code);
void PrintStopInfo(uint32_t code);
// Executes one instruction.
void InstructionDecode(Instruction* instr);
// Execute one instruction placed in a branch delay slot.
......@@ -354,6 +366,19 @@ class Simulator {
// Registered breakpoints.
Instruction* break_pc_;
Instr break_instr_;
// Stop 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 StopCountAndDesc {
uint32_t count;
char* desc;
};
StopCountAndDesc watched_stops[kMaxStopCode + 1];
};
......@@ -398,4 +423,3 @@ class SimulatorStack : public v8::internal::AllStatic {
#endif // !defined(USE_SIMULATOR)
#endif // V8_MIPS_SIMULATOR_MIPS_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment