Improve ARM-Simulator.
This patch - removes the unimplemented code crash when rendering invalid/unknown instructions and prints "unknown" instead. - prints the beginning of the constant pool marker. - adds "da" as a shortcut for "disasm". - print hexadecimal representation of double and single registers. This makes it easier to debug move/conversion code that uses temporary int32 values in floating point registers. - annotates the stack with short prints of the values (HeapObjects and smis), - makes disasm take an address or a register as second argument without a third argument, which defaults to printing ten instructions. Review URL: http://codereview.chromium.org/6676042 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7279 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
b604befe61
commit
e820926108
@ -2748,8 +2748,8 @@ void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
|
||||
RecordComment("[ Constant Pool");
|
||||
|
||||
// Put down constant pool marker "Undefined instruction" as specified by
|
||||
// A3.1 Instruction set encoding.
|
||||
emit(0x03000000 | num_prinfo_);
|
||||
// A5.6 (ARMv7) Instruction set encoding.
|
||||
emit(kConstantPoolMarker | num_prinfo_);
|
||||
|
||||
// Emit constant pool entries.
|
||||
for (int i = 0; i < num_prinfo_; i++) {
|
||||
|
@ -89,6 +89,11 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
// Constant pool marker.
|
||||
static const int kConstantPoolMarkerMask = 0xffe00000;
|
||||
static const int kConstantPoolMarker = 0x0c000000;
|
||||
static const int kConstantPoolLengthMask = 0x001ffff;
|
||||
|
||||
// Number of registers in normal ARM mode.
|
||||
static const int kNumRegisters = 16;
|
||||
|
||||
|
@ -89,6 +89,9 @@ class Decoder {
|
||||
// Returns the length of the disassembled machine instruction in bytes.
|
||||
int InstructionDecode(byte* instruction);
|
||||
|
||||
static bool IsConstantPoolAt(byte* instr_ptr);
|
||||
static int ConstantPoolSizeAt(byte* instr_ptr);
|
||||
|
||||
private:
|
||||
// Bottleneck functions to print into the out_buffer.
|
||||
void PrintChar(const char ch);
|
||||
@ -899,6 +902,7 @@ void Decoder::DecodeType2(Instruction* instr) {
|
||||
case da_x: {
|
||||
if (instr->HasW()) {
|
||||
Unknown(instr); // not used in V8
|
||||
return;
|
||||
}
|
||||
Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
|
||||
break;
|
||||
@ -906,6 +910,7 @@ void Decoder::DecodeType2(Instruction* instr) {
|
||||
case ia_x: {
|
||||
if (instr->HasW()) {
|
||||
Unknown(instr); // not used in V8
|
||||
return;
|
||||
}
|
||||
Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
|
||||
break;
|
||||
@ -992,11 +997,15 @@ void Decoder::DecodeType3(Instruction* instr) {
|
||||
|
||||
|
||||
void Decoder::DecodeType4(Instruction* instr) {
|
||||
ASSERT(instr->Bit(22) == 0); // Privileged mode currently not supported.
|
||||
if (instr->HasL()) {
|
||||
Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
|
||||
if (instr->Bit(22) != 0) {
|
||||
// Privileged mode currently not supported.
|
||||
Unknown(instr);
|
||||
} else {
|
||||
Format(instr, "stm'cond'pu 'rn'w, 'rlist");
|
||||
if (instr->HasL()) {
|
||||
Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
|
||||
} else {
|
||||
Format(instr, "stm'cond'pu 'rn'w, 'rlist");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1042,6 +1051,8 @@ int Decoder::DecodeType7(Instruction* instr) {
|
||||
// vmov: Rt = Sn
|
||||
// vcvt: Dd = Sm
|
||||
// vcvt: Sd = Dm
|
||||
// Dd = vabs(Dm)
|
||||
// Dd = vneg(Dm)
|
||||
// Dd = vadd(Dn, Dm)
|
||||
// Dd = vsub(Dn, Dm)
|
||||
// Dd = vmul(Dn, Dm)
|
||||
@ -1297,7 +1308,23 @@ void Decoder::DecodeType6CoprocessorIns(Instruction* instr) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
UNIMPLEMENTED(); // Not used by V8.
|
||||
Unknown(instr); // Not used by V8.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Decoder::IsConstantPoolAt(byte* instr_ptr) {
|
||||
int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
|
||||
return (instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker;
|
||||
}
|
||||
|
||||
|
||||
int Decoder::ConstantPoolSizeAt(byte* instr_ptr) {
|
||||
if (IsConstantPoolAt(instr_ptr)) {
|
||||
int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
|
||||
return instruction_bits & kConstantPoolLengthMask;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1310,7 +1337,15 @@ int Decoder::InstructionDecode(byte* instr_ptr) {
|
||||
"%08x ",
|
||||
instr->InstructionBits());
|
||||
if (instr->ConditionField() == kSpecialCondition) {
|
||||
UNIMPLEMENTED();
|
||||
Unknown(instr);
|
||||
return Instruction::kInstrSize;
|
||||
}
|
||||
int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
|
||||
if ((instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker) {
|
||||
out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
|
||||
"constant pool begin (length %d)",
|
||||
instruction_bits &
|
||||
kConstantPoolLengthMask);
|
||||
return Instruction::kInstrSize;
|
||||
}
|
||||
switch (instr->TypeValue()) {
|
||||
@ -1413,12 +1448,7 @@ int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
|
||||
|
||||
|
||||
int Disassembler::ConstantPoolSizeAt(byte* instruction) {
|
||||
int instruction_bits = *(reinterpret_cast<int*>(instruction));
|
||||
if ((instruction_bits & 0xfff00000) == 0x03000000) {
|
||||
return instruction_bits & 0x0000ffff;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
return v8::internal::Decoder::ConstantPoolSizeAt(instruction);
|
||||
}
|
||||
|
||||
|
||||
|
@ -316,16 +316,26 @@ void ArmDebugger::Debug() {
|
||||
}
|
||||
for (int i = 0; i < kNumVFPDoubleRegisters; i++) {
|
||||
dvalue = GetVFPDoubleRegisterValue(i);
|
||||
PrintF("%3s: %f\n",
|
||||
VFPRegisters::Name(i, true), dvalue);
|
||||
uint64_t as_words = BitCast<uint64_t>(dvalue);
|
||||
PrintF("%3s: %f 0x%08x %08x\n",
|
||||
VFPRegisters::Name(i, true),
|
||||
dvalue,
|
||||
static_cast<uint32_t>(as_words >> 32),
|
||||
static_cast<uint32_t>(as_words & 0xffffffff));
|
||||
}
|
||||
} else {
|
||||
if (GetValue(arg1, &value)) {
|
||||
PrintF("%s: 0x%08x %d \n", arg1, value, value);
|
||||
} else if (GetVFPSingleValue(arg1, &svalue)) {
|
||||
PrintF("%s: %f \n", arg1, svalue);
|
||||
uint32_t as_word = BitCast<uint32_t>(svalue);
|
||||
PrintF("%s: %f 0x%08x\n", arg1, svalue, as_word);
|
||||
} else if (GetVFPDoubleValue(arg1, &dvalue)) {
|
||||
PrintF("%s: %f \n", arg1, dvalue);
|
||||
uint64_t as_words = BitCast<uint64_t>(dvalue);
|
||||
PrintF("%s: %f 0x%08x %08x\n",
|
||||
arg1,
|
||||
dvalue,
|
||||
static_cast<uint32_t>(as_words >> 32),
|
||||
static_cast<uint32_t>(as_words & 0xffffffff));
|
||||
} else {
|
||||
PrintF("%s unrecognized\n", arg1);
|
||||
}
|
||||
@ -380,11 +390,24 @@ void ArmDebugger::Debug() {
|
||||
end = cur + words;
|
||||
|
||||
while (cur < end) {
|
||||
PrintF(" 0x%08x: 0x%08x %10d\n",
|
||||
PrintF(" 0x%08x: 0x%08x %10d",
|
||||
reinterpret_cast<intptr_t>(cur), *cur, *cur);
|
||||
HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
|
||||
int value = *cur;
|
||||
Heap* current_heap = v8::internal::Isolate::Current()->heap();
|
||||
if (current_heap->Contains(obj) || ((value & 1) == 0)) {
|
||||
PrintF(" (");
|
||||
if ((value & 1) == 0) {
|
||||
PrintF("smi %d", value / 2);
|
||||
} else {
|
||||
obj->ShortPrint();
|
||||
}
|
||||
PrintF(")");
|
||||
}
|
||||
PrintF("\n");
|
||||
cur++;
|
||||
}
|
||||
} else if (strcmp(cmd, "disasm") == 0) {
|
||||
} else if (strcmp(cmd, "disasm") == 0 || strcmp(cmd, "di") == 0) {
|
||||
disasm::NameConverter converter;
|
||||
disasm::Disassembler dasm(converter);
|
||||
// use a reasonably large buffer
|
||||
@ -398,11 +421,23 @@ void ArmDebugger::Debug() {
|
||||
cur = reinterpret_cast<byte*>(sim_->get_pc());
|
||||
end = cur + (10 * Instruction::kInstrSize);
|
||||
} else if (argc == 2) {
|
||||
int32_t value;
|
||||
if (GetValue(arg1, &value)) {
|
||||
cur = reinterpret_cast<byte*>(sim_->get_pc());
|
||||
// Disassemble <arg1> instructions.
|
||||
end = cur + (value * Instruction::kInstrSize);
|
||||
int regnum = Registers::Number(arg1);
|
||||
if (regnum != kNoRegister || strncmp(arg1, "0x", 2) == 0) {
|
||||
// The argument is an address or a register name.
|
||||
int32_t value;
|
||||
if (GetValue(arg1, &value)) {
|
||||
cur = reinterpret_cast<byte*>(value);
|
||||
// Disassemble 10 instructions at <arg1>.
|
||||
end = cur + (10 * Instruction::kInstrSize);
|
||||
}
|
||||
} else {
|
||||
// The argument is the number of instructions.
|
||||
int32_t value;
|
||||
if (GetValue(arg1, &value)) {
|
||||
cur = reinterpret_cast<byte*>(sim_->get_pc());
|
||||
// Disassemble <arg1> instructions.
|
||||
end = cur + (value * Instruction::kInstrSize);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int32_t value1;
|
||||
@ -524,8 +559,10 @@ void ArmDebugger::Debug() {
|
||||
PrintF("mem <address> [<words>]\n");
|
||||
PrintF(" dump memory content, default dump 10 words)\n");
|
||||
PrintF("disasm [<instructions>]\n");
|
||||
PrintF("disasm [[<address>] <instructions>]\n");
|
||||
PrintF(" disassemble code, default is 10 instructions from pc\n");
|
||||
PrintF("disasm [<address/register>]\n");
|
||||
PrintF("disasm [[<address/register>] <instructions>]\n");
|
||||
PrintF(" disassemble code, default is 10 instructions\n");
|
||||
PrintF(" from pc (alias 'di')\n");
|
||||
PrintF("gdb\n");
|
||||
PrintF(" enter gdb\n");
|
||||
PrintF("break <address>\n");
|
||||
@ -543,7 +580,7 @@ void ArmDebugger::Debug() {
|
||||
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(" 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");
|
||||
|
Loading…
Reference in New Issue
Block a user